惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Palo Alto Networks Blog
P
Proofpoint News Feed
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
罗磊的独立博客
J
Java Code Geeks
月光博客
月光博客
F
Full Disclosure
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
U
Unit 42
WordPress大学
WordPress大学
A
About on SuperTechFans
C
Cyber Attacks, Cyber Crime and Cyber Security
SecWiki News
SecWiki News
Security Latest
Security Latest
C
Check Point Blog
C
CERT Recently Published Vulnerability Notes
小众软件
小众软件
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
B
Blog RSS Feed
V
Visual Studio Blog
博客园_首页
NISL@THU
NISL@THU
I
Intezer
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
The Register - Security
The Register - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Latest news
Latest news
Project Zero
Project Zero
博客园 - 叶小钗
C
Cybersecurity and Infrastructure Security Agency CISA
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
博客园 - 【当耐特】
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threat Research - Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
T
Tor Project blog
V
Vulnerabilities – Threatpost
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网

I'm OWenT

国产大模型(GLM 5.1、Kimi K2.6)真实场景效果和 Coding Plan 额度测试 新版本libatapp的连接管理——从etcd服务发现到拓扑驱动的自动重连 新版本libatbus的设计变更——从树形路由到拓扑驱动 Protobuf又一坑 - C++标准和ABI兼容性 AI真好用-给Blog主题统一加mermaid,chart.js,excalidraw,draw.io的多种引入方式支持 给内网部署Squid-通用HTTP下载缓存 UE使用CodeChecker和clang-tidy生成静态分析报告 找出UE的循环依赖 C++小协程栈和临时变量及作用域的栈溢出问题分析 游戏服务的可观测性能力建设(C++生态) 指标上报的多线程优化和多拉取源点优化 协程(libcopp)的Channel功能和CPU命中率优化 通用RPC代码生成器 实现strong_rc_ptr(比shared_ptr更快的引用计数智能指针) 手夯一个STL allocator和对象内存分析组件 std::condition_variable 的信号丢失问题 踩坑一处(GCC)STL std::async 实现BUG导致的crash问题 GCC 14的一个warning to error BUG 给xresloader(Excel导表工具)增强UE读表支持(包含蓝图,Blueprint) Opentelemetry社区在gRPC的几个链接问题(静态库和动态库混用,musl工具链,符号裁剪) Excel转表工具(xresloader)的新验证器(验证外部Excel和文本数据,唯一性和自定义规则) protobuf v22和gRPC v1.55版本升级的依赖变化和upb适配 关于protobuf近期版本(v20/v3.20+)和 gRPC v1.54版本在某些编译环境下的一些链接和编译问题 xresloader-Excel导表工具链的近期变更汇总 打通游戏服务端框架的C++20协程改造的最后一环 Opentelemetry-cpp的Logs模块标准更新(涉及近期版本:1.8-1.9的BREAK CHANGES) 给cmake-toolset和工具链(curl等)加HTTP/2和HTTP/3支持 又开新坑之 coredns 插件: nftables和filter 关于opentelemetry-cpp社区对于C++ Head Only组件单例和符号可见性的讨论小记 填个转表工具 xresloader 去年的坑(数组尾部裁剪) 集成 upb 和 lua binding 的踩坑小记 libcopp对C++20协程的接入和接口设计 再度优化GCC、LLVM、Clang、libc++、libc++abi等套件的构建脚本 游戏服务的分布式事务优化(二)- 事务管理 游戏服务的分布式事务优化(一)- Write Ahead Log(WAL) 模块 记录一些bazel适配用编译选项 测试现代化硬件C++浮点数性能和一致性 适配Boringssl和OpenSSL 3.0 近期cmake-toolset的一些适配问题 C++20 Text Formatting/fmtlib 适配问题小记 再次重构LLVM+Clang+libcxx+libc++abi+其他相关工具的构建流程 重构基于CMake的构建工具链 新版GCC和LLVM+Clang终于Release啦 折腾一下nftables下的双拨 [C++20] Module partitions和符号交叉引用(声明和实现分离) [Rust] 实现一个线程安全且迭代器可以保存的链表 基于protobuf的代码生成 几个使用protobuf中C++接口的Arena的坑 Amazon Aurora DB存储引擎论文阅读小记 近期对libatapp的一些优化调整(增加服务发现和连接管理,支持yaml等) xresloader转表工具链增加了一些新功能(map,oneof支持,输出矩阵,基于模板引擎的加载代码生成等) 在游戏服务器中使用分布式事务 libcopp接入C++20 Coroutine和一些过渡期的设计 libatbus 的大幅优化 nftables初体验 容器配置开发环境小计 PALM Tree - 适合多核并发架构的B+树 - 论文阅读小记 跨平台协程库 - libcopp 简介 C++20 Coroutine 性能测试 (附带和libcopp/libco/libgo/goroutine/linux ucontext对比) 尝鲜Github Action 一些xresloader(转表工具)的改进 protobuf、flatbuffer、msgpack 针对小数据包的简单对比 协程框架(libcopp) 小幅优化 Excel转表工具(xresloader) 增加protobuf插件功能和集成 UnrealEngine 支持 Anna(支持任意扩展和超高性能的KV数据库系统)阅读笔记 C++20 Coroutine libcopp merge boost.context 1.69.0 Google去中心化分布式系统论文三件套(Percolator、Spanner、F1)读后感 Rust玩具-企业微信机器人通用服务 使用ELK辅助监控开发测试环境服务质量和问题定位 2018年的新通用伪随机数算法(xoshiro / xoroshiro)的C++(head only)实现 Webpack+vue+boostrap+ejs构建Web版GM工具 Rust的第二次接触-写个小服务器程序 理解和适配AEAD加密套件 atsf4g-co的进化:协程框架v2、对象路由系统和一些其他细节优化 协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比 可执行文件压缩 初识Rust 使用restructedtext编写xresloader文档 C++的backtrace ECDH椭圆双曲线(比DH快10倍的密钥交换)算法简介和封装 protobuf-net的动态Message实现 pbc的proto3接入 atgateway内置协议流程优化-加密、算法协商和ECDH 整理一波软件源镜像同步工具+DevOps工具 Blog切换到Hugo libcopp v2的第一波优化完成 libcopp(v2) vs goroutine性能测试 libcopp的线程安全、栈池和merge boost.context 1.64.0 GCC 7和LLVM+Clang+libc++abi 4.0的构建脚本 libatbus的几个藏得很深的bug 用cmake交叉编译到iOS和Android 开源项目得一些小维护 atapp的c binding和c#适配 对象路由系统设计 2016年总结 近期的一个协程流程BUG 重写了llvm+clang+libc++和libc++abi的构建脚本 atsf4g完整游戏工程示例|I'm OWenT atframework基本框架已经完成|I'm OWenT
atframework的etcd模块化重构
owent · 2018-02-21 · via I'm OWenT

blog-website

前言

最近在抽时间整理之气的游戏服务器框架和解决方案里atsf4g-co,现在的架构是使用etcd的是atproxy。简单得说就是服务集群是分组的,每个分组有分组代理服务atproxy做组间通信。然后atproxy之间使用etcd来做分组服务的服务发现和保活,并且以此来实现平行扩容。

之前做服务间通信组件libatbus的时候也提到了有一个暂时没实现的功能,就是全局路由表的自动通知。但是这个功能的实现主要也是用于后面不同种服务间感知到哪些节点是可用的,哪些是不可用的。而且我的简单实现必然是走心跳的模式,因为心跳的形式肯定不能把心跳设置得太短,同时也要考虑网络异常抖动和断线重连和丢包,所以肯定不是丢一个心跳包就认为丢失。所以故障或者扩缩容期间的感知时间就会比较长一些。另外就是因为可能有网络孤岛问题,所以可能短期内数据不一致(当然肯定会保证最终一致性)。

再加上由于libatbus是支持多级父子节点关系的,所以变化通知和同步包就要考虑自己与父节点、兄弟节点、自己与子节点的不同关系并作不同的同步流向,会比较复杂。比如:子节点下线,既要通知父节点,又要通知兄弟节点。那么这时候给兄弟节点通知就有两个通路,一个是经由父节点中转,另一种是直接发。当然这时候并不一定和兄弟节点有直接通路。所以可能兄弟节点会收到两次通知,一次来自兄弟节点,另一次来自公共父节点。然后又会有其他问题,就是万一又收到一条冲突的消息,来自父节点和来自兄弟节点的顺序是没有保证的,这里又得加入版本机制。总的来说,细节会比较复杂,具体在实现libatbus的这个功能的时候在谈吧。

上面说的libatbus的功能暂时没实现的最重要原因是etcd可以比较完美的解决上面的延迟问题和不一致问题。缺点就是请求的消耗会高于使用libatbus的通信机制。不过这玩意本身不是高频操作,而且故障和容灾本身不是一个频发的事情所以关系不大。而之前etcd的接入是直接写死在atproxy里的,那么这次重构的目的主要就是能够抽象出模块化的工具,以便后面不同的服务可以根据需要取用。

统一管理驱动管理器和模块化

按现在的功能划分,etcd的接入总共被分为3个模块,etcd_cluster、etcd_keepalive和etcd_watcher以及一个通用工具etcd_packer。etcd_packer用于对etcd的一些通用的打解包操作。

模块关系图

etcd_cluster

etcd v3版本内部的通信已经使用了grpc。本来我是想等他的grpc接口进入官方文档并且提供出的grpc的proto再接入的,可是它一直没有整理出直接grpc的proto文件列表。另外我看了一下它的proto文件里用到了一些gogoprotobuf的扩展,其他语言不一定可以无缝接入。考虑到etcd使用了grpc-gateway提供HTTP+JSON的网关层,所以我还是基于他的HTTP接入层来做。因为这里身频次不高,也没有那么在意性能。而且一组etcd服务的QPS也就在十万的级别,只要管理好连接,不要老新建立和关闭连接,HTTP的性能还是够的。

第一个上层服务就是etcd_cluster,用于和atframework里的http_request和libuv结合起来使用。统一管理etcd的请求、超时等。当然最重要的功能是做接入,也就是去读取etcd的服务器节点列表并定时刷新。这样可以适配etcd服务的容灾和扩缩容。我们使用etcd服务一般是5节点,2个同机架,3个同机房,2个异地。这样一般的应用的容灾上绰绰有余了。当然特殊的业务需要更高的容载能力还可以加,但是etcd随着节点数上升性能会下降,而且我们的atframework也不是说etcd挂了就完全不可用,只是新的服务器组暂时感知不到罢了。已有的服务器组之间还是有自己的心跳保活的,所以你要etcd和我们业务服务器同时故障的概率就非常小了。退一万步就算真的同时故障,在服务重新拉起后还是能秒级自动恢复的,问题其实不是很大。

不过由于keepalive和watcher比较特殊,所以etcd_cluster还是需要做一些额外的支持。比如etcd的节点切换和watcher的请求超时后需要自动重新发起watcher请求;etcd的服务节点切换后需要立即发起一次keepalive的数据确认和定期自动发起keepalive保活等。之前写死在atproxy里的keepalive流程是给一个path设置数据以后,不断地用PUT命令续期过期时间。这样有个坏处是会不断提升数据版本号。现在优化成了每个etcd_cluster可以申请一个lease,然后需要keepalive的数据之设置一次数据并绑定到这个lease上。然后由etcd_cluster不断地去续期这个lease的超时时间,就和zookeeper的模式一样。这样还有一个好处是如果我增加很多个keepalive的数据不需要每个数据都不断地发请求来续期超时时间。

不过有一项还没做的是认证功能,不过因为我们现在的业务可以用运维手段,通过网络手段去隔离外部请求,并且并不需要做成公共服务,所以暂时还不需要这个。当然如果以后需要接入到某个公共平台的话可以加一个这个,也不困难,就在member/list请求后面加一个认证流程拉取token,然后在setup http请求的地方统一加一个Authorization的HTTP Header就行了。

etcd_packer

etcd提供的网关层的输出大部分有统一的response header,另外比如对于数字,输出 “a”: “123”和”a”: 123都是允许的。为了简化一些通用的流程,所以加了个小工具统一处理打解包操作。另外etcd的path和value都是二进制,然后再转化过程中全部被转为了base64编码的数据,所以对于内容而言etcd_packer就是提供了一个统一的方法把数据转换出来并且和内部的JSON对象进行转换。

etcd_keepalive和etcd_watcher

这两个模块相关性比较强。之所以抽离出来,一方面是由于前面提到的,如果有多个需要keepalive的数据,不会有多余的开销。另外就是允许业务服务根据自己的需要取舍。比如邮件服务需要互相知道节点存活状态和负载Hash规则,还要同步自己的状态,所以既有邮件的watcher也有keepalive。但是邮件的客户端层面,只需要有watcher就可以知道负载规则,就可以了。这时候就不需要keepalive和lease。再比如我们现在的服务器集群中,逻辑服要关注好友服和邮件服,因为这两个服务都是按用户ID做Hash来确定服务请求应该发给哪台服务器的,所以可以只加两个watcher,订阅好友服和邮件服的服务器集群信息就行了。

etcd_keepalive要填充的数据的key已存在,还可以对已有数据做一次检查。这样如果崩溃后短时间内被拉起,可以知道现有的数据就是自己的,这时候直接覆盖即可。如果是正常启动,发现有冲突的信息,就可以打错误日志然后下线。比如在atproxy中,如果是崩溃拉起,那么listen地址和物理地址一定不会变化,那么直接副高即可。如果两个不同的atproxy使用了同一个bus id,那么后启动的atproxy就会检查不通过然后启动失败。

Etcd V3 API

最早atproxy里写死的版本还是用的v2版的HTTP接口。因为那时候V3的接口还很不完整,现在也是直接接入了V3的API。我自己也是感觉V3的API更好更灵活一点。V2里很多靠HTTP HEADER来决定是什么行为的,数据一部分在HEADER里另一部分在BODY里,数据的传递好几种方式。现在的V3都使用URL来决定行为,用JSON内容来传递数据,和protobuf的结构保持一致了。另外就是用lease简化了keepalive的行为。

大多数数据层面还只是换了位置和名字,唯一有一个不太一样的流程是watch请求。在etcd v2的API中watch请求是一个一直BLOCK住的请求,当有事件变化到来的时候返回然后带回版本号ID,然后再用这个版本号ID去发起下一个watch请求。如果版本号之后又有变化事件会立即返回,否则继续block住。而现在etcd v3中,watch请求是一个流数据的回包,不需要再不停地发起请求了。但是流数据怎么判定是一个事件消息的结束呢?grpc-gateway的文档里说它会把流数据转化为换行符结尾的JSON串。再加上所有的数据中都被base64编码过了,所以我们可以直接用换行符来分割事件消息,然后etcd_watcher把这些消息封装成事件供业务层使用。

测试和工具

因为atsf4g-co还没有加入到CI里,所以先还是写了个小工具做测试,也算一个小demo吧,封装后的接口使用起来比较简单就一个文件。测试通过以后人工构造atproxy的各种情况然后看日志。后面有空再写自动化测试吧。

这个模块其实几周前就完成了,但是春节嘛想休息一下就一直没写这篇blog。唉!也是拖延癌拖到现在才补上来。我在接入的时候,etcd的v3版API还是v3alpha,现在已经前缀改为v3beta了,等到有空我看看变化然后改成v3beta的API,也不知道啥时候才能release版本。

这几个模块都还没抽离出atsf4g-co,现在是作为模块放在 https://github.com/atframework/atsf4g-co/tree/master/atframework/service/component/etcdcli 不过要提取出啦也没太大困难就是了,也没太多依赖,主要就依赖atframe_utils里面的http_request和base64编码。我也在考虑以后怎么给atsf4g-co模块化,做成依赖管理那种服务化的东西,等到那时候再提出来吧。