查看原文
其他

Beetle双活实践

转转QA 转转QA 2022-11-09

作者|陈秋

简介

Beetle是转转公司测试部主导研发的一款基于gitlab,jenkins,maven为主的轻量级效率平台,主要解决编译部署测试发布流程中的效率问题,详细介绍请参考《效能提升的江湖路--转转Beetle平台百天记》。

背景

         随着全公司集群推广接入,beetle使用频率越来越高,作为单集群部署的beetle,每一次迭代,bug修复都需要停止服务。作为效能提高平台,本身停服就是在影响效率,这对使用方来讲是不可接受的。多活是在这个场景下提出的。这篇分享,主要和大家交流下beetle在多活场景下碰到的问题,和解决方案。

目标

升级或bug修复等服务重启过程中,做搭配用户无感知。为了达到这个目的,我们需要解决以下几个问题。 

概况

Beetle服务,通过向编译服务,环境部署服务,上线服务发送命令,并轮询结果。来完成交互

问题
  1. session共享问题,多台的情况下,同一个客户端请求可能落在不同的服务器上

  2. 同步锁问题,单台情况下,原子操作大多使用了synchronized关键字,在多台情况下,这个是无法保证原子的

  3. 服务停止后,进行中的编译和部署在多台的情况下如何恢复?

方案

一、session问题

session共享,一般有如下几种解决方案

  1. 服务间session同步,登录到一台服务器之后,将session同步到其他服务器

  2. memcached-session-manager,俗称MSM

  3. 使用filter方式进行拦截过滤

  4. 持久化到数据库

我们使用上面的过滤器方式,在登录拦截器中,保存session。这样session不存在于服务器上时,就自动加上了。

二、同步锁问题,使用分布式锁来解决,一般三种,数据库,缓存,zookeeper

1、 使用数据库,插入数据一条记录作为锁,使用完之后,删除就好(key唯一性约束)。

问题:

  1. 加完锁程序挂了怎么办?

  2. 没有超时时间,一直占用怎么办?

  3. 插入数据失败怎么办?

解决:

  1. 使用定时任务轮询,删除过期的锁

  2. while轮询insert?

实现起来就复杂了

2、使用缓存,比如利用redis的原子性,完成加锁,解锁,设置过期时间(setnx,del)实现分布式锁

问题:过期时间设置多少合适?

  1. 少了,没有执行完,锁就释放了

  2. 多设置一些,在处理完了之后,代码释放这个锁,但是如果这个时候进程进行更新重启呢?这个锁要等到超时,才能重新被获得。

结论:用redis控制锁的释放时间,不太靠谱。

3、使用zookeeper 基于zookeeper临时有序节点可以实现的分布式锁。

过程:

  1. 客户端连接zk,在某个父节点node上创建子节点,第一个创建临时有序节点的为/node/lock-0000000000,第二个为/node/lock-0000000001,以次类推。

  2. 客户端获取node下的子节点列表,判断自己当前是否是最小序号,是则获取到锁。否则监听自己前一个的子节点的删除消息,直到获得锁.

  3.  执行业务代码

  4. 会话结束删除这个节点,或者超时,zk会自动释放节点

结论:解决了上面死锁,锁不能自动释放,等待过长等问题。

问题:实现起来比较复杂

解决:使用第三方客户端curator。

4、使用转转zzlock(基于etcd做数据一致性协调实现的分布式锁),自动续期,进程挂掉自动回收。

3,4方案使用起来是比较简便,并能很好的解决我们的问题。

三、服务终止后,使用定时任务轮询来恢复中断的任务,任务的竞争采用上面的分布锁实现

增加节点后,beetle简要结构如下:

扩展一下

解决以上问题之后,双活的问题就已经解决了。接下来我们思考一个问题,beetle是编译-部署-上线管理平台,那么beetle能不能上线beetle本身?

是可以的,当我们向“上线服务”发送上线任务后。一台服务器从nginx摘除,请求和回调都落到剩余的机器上。“上线服务”在完成服务跟新重启后,挂会nginx。开始服务。

往期精彩回顾

人人都谈用例管理与持续集成

生成可视化数据构造工具,我只用了5分钟

数据驱动过程改进

论测试方法带来的成就感

日志插桩工具快速搞定接口测试

转转APP专项测试——静态代码

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存