OWenT's blog
  • Introduction
  • About Me
  • 2020
    • 近期对libatapp的一些优化调整(增加服务发现和连接管理,支持yaml等)
    • xresloader转表工具链增加了一些新功能(map,oneof支持,输出矩阵,基于模板引擎的加载代码生成等)
    • 在游戏服务器中使用分布式事务
    • libcopp接入C++20 Coroutine和一些过渡期的设计
    • libatbus 的大幅优化
    • nftables初体验
    • 容器配置开发环境小计
  • 2019
    • 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玩具-企业微信机器人通用服务
  • 2018
    • 使用ELK辅助监控开发测试环境服务质量和问题定位
    • Webpack+vue+boostrap+ejs构建Web版GM工具
    • 2018年的新通用伪随机数算法(xoshiro / xoroshiro)的C++(head only)实现
    • Rust的第二次接触-写个小服务器程序
    • 理解和适配AEAD加密套件
    • atsf4g-co的进化:协程框架v2、对象路由系统和一些其他细节优化
    • 协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比
    • 可执行文件压缩
    • 初识Rust
    • 使用restructedtext编写xresloader文档
    • atframework的etcd模块化重构
    • C++的backtrace
  • 2017
    • 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
  • 2016
    • 重写了llvm+clang+libc++和libc++abi的构建脚本
    • atsf4g完整游戏工程示例
    • atframework基本框架已经完成
    • 游戏服务器的不停服更新
    • 对atbus的小数据包的优化
    • Android和IOS的TLS问题
    • pbc的一个陈年老BUG
    • boost.context-1.61版本的设计模型变化
    • 接入letsencrypt+全面启用HTTP/2
    • 理解Raft算法
    • libatbus基本功能及单元测试终于写完啦
    • 博客文章和文档迁移到gitbook
  • 2015
    • 博客文章和文档迁移到gitbook
    • 给客户端写得LRU缓存
    • 近期活动比较零散
    • 关于BUS通信系统的一些思考(三)
    • 针对Java JIT的优化(转表工具:xresloader)
    • libcopp更新 (merge boost 1.59 context)
    • 小记最近踩得两个C++坑
    • Redis全异步(HA)Driver设计稿
    • Vim常用命令
    • 关于firewalld和systemd的一些命令速记
    • Jenkins(hudson)插件记录
    • 我们的Lua类绑定机制
    • LLVM+Clang+Libcxx+Libcxxabi(3.6)工具链编译(完成自举编译)
    • 回顾2014
    • Android NDK undefined reference to ___tls_get_addr 错误
    • gitlab腾讯企业邮箱配置
  • 2014
    • 回顾2013
    • C++11动态模板参数和type_traits
    • C++又一坑:动态链接库中的全局变量
    • tolua++内存释放坑
    • [转]类似github的框架
    • Lua性能分析
    • 集成Qt Webkit 到cocos2d-x
    • Gitlab环境搭建小计
    • 近期研究VPN的一些记录(OpenVPN,pptp,l2tp)
    • LLVM + Clang + Libcxx + Libcxxabi 工具链编译
    • 关于BUS通信系统的一些思考(二)
    • 关于BUS通信系统的一些思考(一)
    • [libiniloader] Project
    • 记录一些在线编辑器
    • [WP Code Highlight.js] Project
    • 再议 C++ 11 Lambda表达式
    • 基于Chrome插件的开发工具链
    • [ACM] HDU 1006 解题报告
    • Linux 编译安装 GCC 4.9
    • 又碰到了这个解谜游戏,顺带记下地址
    • 简单C++单元测试框架(支持一键切到GTest或Boost.Test)
    • 捣鼓一个协程库
  • 2013
    • std和boost的function与bind实现剖析
    • 不知道是哪一年的腾讯马拉松题目 照片评级 解题报告
    • Lua 挺好用的样子
    • VC和GCC成员函数指针实现的研究(三)
    • VC和GCC成员函数指针实现的研究(二)
    • VC和GCC内成员函数指针实现的研究(一)
    • 一个C++关于成员变量偏移地址的小Trick
    • ptmalloc,tcmalloc和jemalloc内存分配策略研究
    • POJ 2192 Zipper HDU 2059 龟兔赛跑
    • 从Javascript到Typescript到Node.js
    • 网络编程小结
    • 试试Boost.Asio
    • Lnmp yum 安装脚本 (for CentOS)
    • ARM 交叉编译环境搭建
    • Linux 编译安装 GCC 4.8
    • [记录]虚拟硬盘的压缩|磁盘写零
  • 2012
    • Boost.Spirit 初体验
    • “C++的90个坑”-阅读笔记
    • AC自动机
    • C++ 标准过渡期
    • 程序员修炼之道 -- 阅读笔记
    • [转载]狼与哈士奇
    • C++ 新特性学习(八) — 原子操作和多线程库[多工内存模型]
    • C++ 新特性学习(七) — 右值引用
    • 理解Protobuf的数据编码规则
    • 忆往昔ECUST的ACM时代
    • Linux编译安装GCC 4.7
    • JSON显示库 -- showJson (Javascript)
    • C++ 新特性学习(六) — 新的字符串编码和伪随机数
    • C++ 新特性学习(五) — 引用包装、元编程的类型属性和计算函数对象返回类型
    • C++ 新特性学习(四) — Bind和Function
  • 2011
    • C++ 新特性学习(三) — Regex库
    • C++ 新特性学习(二) -- Array、Tuple和Hash库
    • C++ 新特性学习(一) -- 概述+智能指针(smart_ptr)
    • Linux 和 Windows PowerShell 常用工具/命令 记录
    • 非常帅气的Linq to sql
    • 2011 Google Code Jam 小记
    • C++总是很神奇
    • 大学生创新项目[国家级]经费使用记录
    • 常用官方文档整理
    • 我们学校的IPV6很不错嘛
  • 2010
    • 线段树相关问题 (引用 PKU POJ题目) 整理
    • 2010 ACM 赛前笔记
    • POJ PKU 2596 Dice Stacking 解题报告
    • POJ PKU 3631 Cuckoo Hashing 解题报告
    • POJ PKU 1065 Wooden Sticks 3636 Nested Dolls 解题报告
    • HDU 3336 Count the string 解题报告
    • Hash模板 个人模板
    • ZOJ 3309 Search New Posts 解题报告
    • POJ PKU Let's Go to the Movies 解题报告
    • 注册表常用键值意义
    • PKU POJ 1724 ROADS 解题报告
    • 《神奇古今秘方集锦》&《民间秘术大全》
    • PKU POJ 1720 SQUARES 解题报告
    • POJ PKU 2155 Matrix 解题报告
    • PKU POJ 1141 Brackets Sequence 解题报告
    • PKU POJ 2728 Desert King 解题报告
    • PKU POJ 2976 Dropping tests 解题报告
    • PKU POJ 3757 Simple Distributed storage system 解题报告
    • GCD Determinant 解题报告
    • Southeastern European 2008 Sky Code 解题报告
    • HDU HDOJ 3400 Line belt 解题报告
    • 线性筛法求质数(素数)表 及其原理
    • HDU HDOJ 3398 String 解题报告
    • 树状数组模块(个人模板)
    • 浙江理工 省赛总结 team62 By OWenT of Coeus
    • POJ PKU 3659 Cell Phone Network 解题报告
    • USACO 2008 March Gold Cow Jogging 解题报告
    • C#格式化输出(记录)
    • 参加有道难题笔记
    • POJ PKU 2446 Chessboard 解题报告
    • POJ PKU 1986 Distance Queries 解题报告
    • 计算几何算法概览[转载]
    • 关于差分约束(转载)
    • POJ PKU 2826 An Easy Problem?! 解题报告
    • 数论模板(个人模板)
    • 简易四则运算(ACM个人模板)
    • Catalan 数
    • The 35th ACM/ICPC Asia Regional Tianjin Site —— Online Contest 1009 Convex 解题报告
    • JQuery扩展插件--提示信息
    • ACM 计算几何 个人模板
    • 解析网站字符串型参数 Javascript QueryString 操作 TQueryString类
    • POJ PKU 1474 Video Surveillance 解题报告
  • 2009
    • 模式匹配(kmp)个人模板
    • 并查集 模板
    • POJ 3267 The Cow Lexicon 解题报告
    • C/C++语言常用排序算法
    • POJ 2606 Rabbit hunt 2780 Linearity 1118 Lining Up 解题报告
    • 打造最快的Hash表(转) [以暴雪的游戏的Hash为例]
    • ECUST 09年 校赛个人赛第六,七场总结
    • ECUST 09年 校赛个人赛第三场部分解题报告(A,D,F,I)
    • 牛顿迭代解方程 ax^3+bX^2+cx+d=0
    • 09年8月9日 ECUST ACM 练习赛总结
    • 连接最多点直线 (OWenT 个人模板)
    • 点到直线距离 和 线段间最短距离 (OWenT 模板)
    • ECUST 09年 校赛个人训练赛第五场总结
    • ECUST 09年 校赛个人赛第八场(最后一场)总结
    • 09年8月14日 ECUST ACM 练习赛总结
    • 矩阵相关 (增强中)
    • Prime最小生成树(个人模板)
    • 最长单调子序列 复杂度nlog(n)
    • POJ PKU 2549 Sumsets 解题报告
    • POJ PKU 3277 City Horizon 解题报告
    • 我的ACM生涯
    • POJ PKU 2528 Mayor's posters 解题报告
    • POJ PKU 2378 Tree Cutting 解题报告
    • POJ PKU 1990 MooFest 解题报告
Powered by GitBook
On this page
  • 前言
  • 统一管理驱动管理器和模块化
  • etcd_cluster
  • etcd_packer
  • etcd_keepalive和etcd_watcher
  • Etcd V3 API
  • 测试和工具

Was this helpful?

  1. 2018

atframework的etcd模块化重构

Previous使用restructedtext编写xresloader文档NextC++的backtrace

Last updated 6 years ago

Was this helpful?

前言

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

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

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

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

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

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

etcd_cluster

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

etcd_packer

etcd_keepalive和etcd_watcher

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

Etcd V3 API

测试和工具

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

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

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

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

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

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

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

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

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

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

[9]:

etcd
gogoprotobuf
grpc-gateway
etcd
libuv
etcd
etcd
etcd
etcd
etcd
etcd
etcd
etcd
etcd
atproxy
etcd
etcd
atproxy
atproxy
atproxy
atproxy
etcd
etcd
grpc-gateway
atsf4g-co
atproxy
etcd
atsf4g-co
https://github.com/atframework/atsf4g-co/tree/master/atframework/service/component/etcdcli
atsf4g-co
https://github.com/atframework/atsf4g-co/tree/master/src/tools/etcd-watcher
atsf4g-co
etcd
atproxy
atproxy
atproxy
etcd
libatbus
libatbus
libatbus
libatbus
etcd
libatbus
etcd
atproxy
etcd
etcd
模块关系图