Botposter.com集群ETCD2.3.7升级至3.0实录[原创]
7月1日,为庆祝我党生日,ETCD隆重发布了3.0版本。Botposter.com也在第一时间对集群进行了升级。本文是升级过程的记录与总结(文中假设读者已经使用或测试过ETCD V2,如有不妥请见谅)。
Botposet.com是一款与HubSpot类似的营销自动化SAAS产品,全部使用golang开发。
说明
在Botposter.com中,ETCD主要用于以下两个职责:
- master选举
- 集群信息保存
早期曾使用ETCD的TTL来实现master心跳检测,由于性能原因在Botposter.com上个月的重构中取消了这种用法。这也恰好简化了升级难度,因为ETCD v3对TTL有重大改动。
准备
资料准备
迁移工作的主要参考以下两篇资料:
https://github.com/coreos/etcd/blob/master/Documentation/op-guide/v2-migration.md
https://github.com/coreos/etcd/blob/master/Documentation/upgrades/upgrade_3_0.md
测试环境
开始升级前需要搭建测试环境,过程非常简单,这一点ETCD做得非常好,V3版本与V2版本无论从安装方式和配置参数完全一致。
安装参考链接:https://github.com/coreos/etcd/releases
配置参考链接:https://github.com/coreos/etcd/blob/master/Documentation/op-guide/clustering.md
配置好测试环境后,使用etcdctl测试ETCD V3是否可以正常使用。这里需要注意,一定不要忘记在环境变量中加入ETCDCTL_API=3。否则在操作V3时,无论使用SET,GET都没有任何数据返回,也没有错误返回。建议ETCD V3可以提供错误提示。我在这里耽误了一些时间,因为想当然的以为,使用ETCD V3和ETCDCTL V3是默认匹配的。
ETCDCTL的文档链接:https://github.com/coreos/etcd/blob/master/etcdctl/README.md#migrate-options
注意:我在第一次使用etcdctl member list命令(所有的命令都会出错,此处以member list举例)的时候,返回下面错误代码:
grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: dial tcp 127.0.0.1:22379: getsockopt: connection refused"; Reconnecting to {"127.0.0.1:22379" <nil>}
单独运行etcdctl命令,会返回etcdctl的使用帮助,其中有一行:
--endpoints=[127.0.0.1:2379,127.0.0.1:22379,127.0.0.1:32379] gRPC endpoints
原来默认gRPC的endpoints有三个,解决这个问题的已知办法有两个:
一是在etcdctl命令行中加入--endpoints参数
etcdctl --endpoints=127.0.0.1:2379 member list
二是在etcd启动参数中增加其它端口
-listen-client-urls http://127.0.0.1:2379,http://127.0.0.1:22379,http://127.0.0.1:32379
在Botposter.com中暂时使用第二种方法。因为迁移时间有限,没有继续查看是否可以修改gRPC的默认--endpoints。
API V2与V3区别
- 事务:ETCD V3提供了多键条件事务(multi-key conditional transactions),应用各种需要使用事务代替原来的Compare-And-Swap操作。
- 平键空间(Flat key space):ETCD V3不再使用目录结构,只保留键。例如:"/a/b/c/"是一个键,而不是目录。V3中提供了前缀查询,来获取符合前缀条件的所有键值,这变向实现了V2中查询一个目录下所有子目录和节点的功能。
- 简洁的响应:像DELETE这类操作成功后将不再返回操作前的值。如果希望获得删除前的值,可以使用事务,来实现一个原子操作,先获取键值,然后再删除。
- 租约:租约代替了V2中的TTL实现,TTL绑定到一个租约上,键再附加到这个租约上。当TTL过期时,租约将被销毁,同时附加到这个租约上的键也被删除。
与Botposter.com有关的改动只有平键空间,因为系统中使用ETCD目录结构保存了master,node和task的全部信息。
从官方文档的表述看,事务和租约值得测试并用于优化V2的用法。
客户端代码升级
平键空间
将原代码中包含以下代码的部分都修改为
&client.GetOptions{Recursive: true}
都修改为
clientv3.WithPrefix()
数据类型
在V2版本中,resp.Node.ModifiedIndex的数据类型为uint64,V3中revision为int64。
因为在Botposter.com使用了resp.Node.ModifiedIndex作为全局序列标识,所以,需要将原系统中的数据类型修改为int64。
Compare-And-Swap
在V2的一种典型用法就是Compare-And-Swap,在Botposter.com中也使用这种方法实现了分布式锁,实现方法是在SET操作时增加下面的操作:
&client.SetOptions{PrevExist: "false"})
即,只有当前key不存在时,才能写入成功。
在V3中,改为由事务实现。具体代码如下:
kvc := clientv3.NewKV(&cli)
r, _ := kvc.Txn(context.Background()).
If(clientv3.Compare(clientv3.CreateRevision(key), "=", 0)).
Then(clientv3.OpPut(key, v)).
Commit()
Txn的具体用法参考:https://godoc.org/github.com/coreos/etcd/clientv3#example-KV--Txn
Node
在V2中,get操作response回来的value保存在response.node.value,如果是一个directory,返回的结果集保存在response.node.nodes中。
V3做了大幅修改,因为V3中不再有directory,所有的key都是flat key,所以,所有get操作的返回值都保存在GetResponse.Kvs(数据类型是[]*mvccpb.KeyValue)中。而且V2中,keynotfound等错误在V3中都不再保留,V3中,当查询的key不存在时,GetResponse.Count为0,len(GetResponse.Kvs)也为0,Get操作返回的error为nil。
所以在V2中的代码如
response.Node.Value
需要改为
GetResponse.Kvs[0].Value
另外值得注意的是,V3中的key和value的返回值都是[]byte类型,这可以减少很多string与[]byte的数据类型转换操作。
ETCD升级
ETCD升级很简单,先按照安装参考链接:https://github.com/coreos/etcd/releases ,下载并解压文件。
因为Bostposter.com集群有自动恢复机制,所以使用离线升级的方式,在所有服务器运行脚本:
service etcd stop
cp etcd /usr/local/bin
service etcd start
ETCD的所有启动参数都不需要修改,升级时间不超过1秒。
ETCD升级后,升级集群服务的代码,只有在升级流程容器时需要重启2000多个流程,全部恢复时间大概在1分钟左右。
至此,升级工作全部完成。对系统功能和集群都做了测试,没有出现任何问题。
感受
下面说说升级到ETCD V3后的感受,时间有限没有做精确测试,没有数据支撑略显不够严谨。
首先,V3服务器端的内存比V2占用得更高,至少高50%。尤其是压力增大时,内存占用飙升得很快,压力减小后几分钟内存会释放出来。
其次,Client使用后一定要Close,因为在V2时,Botposter.com中使用了sync.pool来保存Client。当升级到V3后,操作频繁时池化的Client会占用非常多的内存,因为没有做具体测试,还不清楚一个Client占用多少内存。目前的解决办法是Client不再池化,而且使用后立即Close。
第三,V3的API更加合理,直接的结果是代码量减少了,异常处理也变得更简单。
第四,从升级后的整体表现看,V3的性能比V2要很多。
整体来说,在有条件的情况下,我建议升级至ETCD V3。时间仓促,如有笔误请大家及时指出,谢谢。
内容为作者原创,未经允许请勿转载,谢谢合作。
关于作者:
Jesse,目前在Joygenio工作,从事golang语言开发与架构设计。
正在开发维护的产品:www.botposter.com
Botposter.com集群ETCD2.3.7升级至3.0实录[原创]的更多相关文章
- Kakfa集群(2.11-0.10.1.0)版本滚动升级方案
Kafka集群版本升级(2.11-0.10.1.0)升级(2.11-0.10.2.2) 官网升级说明: 一.系统环境Zookeeper集群:172.16.2.10172.16.2.11172.16.2 ...
- Redis集群环境使用的是redis4.0.x的版本,在用java客户端jedisCluster启动集群做数据处理时报java.lang.NumberFormatException: For input string: "7003@17003"问题解决
java.lang.NumberFormatException: For input string: "7003@17003" at java.lang.NumberFormatE ...
- Hbase 集群安装(Hadoop 2.6.0 hbase0.99.2)
一:说明 该安装是在hadoop集群安装后进行,详情可见上一篇博客虚拟机centos7系统下安装hadoop ha和yarn ha(详细) .其中涉及五台机器,两台master(机器名:master, ...
- redis集群热扩展(基于4.0.9)
1:环境说明,首先说一下要做的事情,我们要迁移redis集群槽位,现有redis集群环境如下 我们看一下集群的基本信息: > cluster nodes 8ea64a0049e0b193296a ...
- Elasticsearch集群搭建笔记(elasticsearch-6.3.0)
# 检查Java版本 java -version # 安装Elasticsearch,所有节点均安装并解压 wget https://artifacts.elastic.co/downloads/el ...
- Spark集群任务提交流程----2.1.0源码解析
Spark的应用程序是通过spark-submit提交到Spark集群上运行的,那么spark-submit到底提交了什么,集群是怎样调度运行的,下面一一详解. 0. spark-submit提交任务 ...
- Redis单机和集群配置(版本在5.0后)
摘抄并用于自己后查 单机版的配置: 1. 下载redis压缩包,然后解压缩文件(tar xzf): 2. 进入解压后的redis文件目录,编译redis源文件(make,没有c环境要gcc): 3. ...
- spring boot:使用redis cluster集群作为分布式session(redis 6.0.5/spring boot 2.3.1)
一,为什么要使用分布式session? HpptSession默认使用内存来管理Session,如果将应用横向扩展将会出现Session共享问题, 所以我们在创建web集群时,把session保存到r ...
- centos8平台redis cluster集群添加/删除node节点(redis5.0.7)
一,当前redis cluster的node情况: 我们的添加删除等操作都是以这个cluster作为demo cluster采用六台redis,3主3从 redis1 : ip: 172.17.0.2 ...
随机推荐
- 剑指offer系列26--正则表达式匹配
[题目]请实现一个函数用来匹配包括’.’和’*‘的正则表达式.模式中的字符’.’表示任意一个字符,而’‘表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符匹配整个模式.例 ...
- vue通过判断写样式(v-bind)
v-bind:style="$index % 2 > 0?'background-color:#FFF;':'background-color:#D4EAFA;'"
- Python 处理多层嵌套列表
>>> movies =[ "the holy grail", 1975,"terry jones",91, ["graham ch ...
- 黄聪:C#禁止Webbrowser中的脚本错误提示,自动屏蔽弹出窗口
using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using ...
- MyEclipse-File Serarch时报错:Problems encountered during text search
- spring学习笔记(转)
[1]搭建环境 1.添加jar包 使用spring需要 sring.jarcommons-loggin.jar 如果使用aop组件需要 aspectjweaver.jaraspectjrt.jar 如 ...
- ARM NEON编程系列1-导论
ARM NEON 编程系列1 - 导论 前言 本系列博文用于介绍ARM CPU下NEON指令优化. 博文github地址:github 相关代码github地址:github NEON历史 ARM处理 ...
- windows环境下 生成git公钥和私钥
windows环境下 生成公钥和私钥 上传代码到远程仓库的时候需要秘钥进行验证是否本人上传的.打开Git目录下的Git Bash 输入ssh-keygen,回车 可直接不输入路径,使用默认路径(c/U ...
- [复变函数]第10堂课 3.2 Cauchy 积分定理
0. 引言 (1) $\dps{\int_{|z-a|=\rho}\frac{1}{z-a}\rd z=2\pi i\neq 0}$: 有奇点 (在 $|z|>0$: 二连通区域内解析), 周线 ...
- vs2015编译boost 64位
---恢复内容开始--- step 1: 打开Developer Command Prompt for VS2015命令行窗口 step 2: 执行bootstrap.bat,产生bjam.exe s ...