我们客服系统中使用tengine+dyups+consul 解决自动扩容缩容的问题

ngx_http_dyups_module是什么

  • ngx_http_dyups_module (dyups means dynamic upstreams)是github上一个nginx相关的开源插件,而且已经merge到了淘宝的tengine中。使用它可以在不reload nginx的情况下动态更新upstream.

    rererence: https://github.com/yzprofile/ngx_http_dyups_module

ngx_http_dyups_module能解决我们客服系统中哪些问题

  • 自动化扩容和缩容还有智能化运维一直是我们努力实现的目标,我们面临的第一个问题就是每次给服务添加新实例或者升级重启服务的时候都需要人工更改upstream server list,reload nginx, dyups module可以帮助我们避免这种人工操作,实现自动化

  • 系统中使用了websocket,长连接,nginx reload操作会对影响长连接有影响,尤其是流量大的时候用户体验不好,dyups模块可以避免reload这个操作

和其他dynamic upstream update方案的对比

1. nginx + upsync 模块
å

这个方案在沙箱试了很久都没有,功能上没有任何问题。但是在线上系统并发超过50k的情况下, reload nginx后几分钟会出现页面无法访问,静态页面的请求都变成下载了,最后导致整个应用crash. 这个应该是upsync的bug导致http response content type类型改变了。没有upsync开发者的帮助这个问题很难解决。

2. 右拍云的slardar

* slardar 是基于nginx 1.9.5 然后集成了又拍云自己开发的一些lua module,还有春哥的balancer.lua 新模块 并且结合consul k/v 实现了upstream动态更新

* slardar可以通过动态更新consul的k/v存储来添加upstream,添加lua script, 非常灵活。 不过这个需要对nginx的开发流程非常了解,并且熟悉nginx lua代码

* github上 https://github.com/upyun/slardar 目前还没有人提issue和pr,估计只有又拍云自己在用了,目前来说通用性不好(虽然这个技术架构和我们的架构非常契合)

**3. tengine + ngx_http_dyups_module **

* github 上 https://github.com/yzprofile/ngx_http_dyups_module 这个模块已经开源很久el并且merge到了tengine里,说明这个模块已经相当成熟了, 这个模块都是C编写的效率肯定是超过用lua实现的
  
* ngx_http_dyups_module 提供了可以操作upstream的http restful api, 管理upstream变得非常容易

* 线上系统之前使用的nginx就是tengine, 所以使用这个方案会更容易一些,只需重新编译并加一个dyups模块,原来的配置无需改动

* 现在线上系统的nginx是通过健康监测模块主动check服务的端口号在不在,这个检测时有时间间隔的,线上的配置是

   check interval=2000 rise=2 fall=3 timeout=1000;
   
这个健康监测连续失败3次nginx才会认为后端实例不可用,即6s后,nginx才会把一个有问题的实例屏蔽掉。通过consul service自己的健康监测不需要这么长的时间,几乎是近实时的,dyups可以很快的拿掉有问题的实例,影响小了很多。

** 4. consul nginx template **

*consul template定义nginx配置文件模版,从consul上读取server信息(ip + port),然后更新nginx,并reload nginx. 这些都是consul帮助实现的,不过还是有reload操作。

上面的方案中 tengine + ngx_http_dyups_module对于我们来说是难度最小而且可以很短时间内完成的,所以我们要先测试一下这个方案。

tengine 2.1.2 + dyups在客服系统中的使用

* java程序启动后把服务信息(server_name, ip, port,tag)注册到consul上

* 使用consul watch机制监控 consul上所有服务的状态变更 (包括重启,实例的添加,删除,服务状态从passing变为critical等)

* 捕捉到服务变更后,筛选出变化的服务

* 把最新的服务实例信息持久化到nginx upstream配置文件中以防止有nginx reload操作导致内存中的upstream信息丢失

* 持久化upstream配置成功后,在内存中直接更新有变化的upsgream server信息


tengine 2.1.2 安装配置

1. sudo yum install tengine-2.1.2

2. copy 线上的nginx配置文件到tengine 安装路径/data/apps/config/nginx

   需要同步的配置文件有waf,nginx lua的第三方库 /etc/nginx/lua
   
   
3. 配置dyups

   a. http block 中配置
       dyups_upstream_conf  conf.d/sandbox.upstream.conf;
       #sandbox.upstream.conf 用来定义持久化从consul同步过来的upstream server list.
   b. 定义dyups 管理端口
     conf.d/dyups_management.conf
     
     server {
        listen  127.0.0.1:18882; 
        location / {
            dyups_interface; # 这个指令表示这边是接口站点
        }
    }
    
4. 启动check_consul.py脚本
    
   这个脚本使用长轮训watch consul里的services状态变化,如果有变更就会持久化conf.d/sandbox.upstream.conf文件,然后更新内存中的upstream server列表,这样就实现了不需要reload nginx更新nginx upsteam列表。
   
  因为reload会把dyups更新到内存中的服务列表清除,所以每次更新到内存前要做持久化。
  
  通过dyups api查看更新到内存的upstream
  
[easemob@sdb conf.d]$ curl 127.0.0.1:18882/list
WebappReadonly_a
TenantAppService
RobotChat
TicketsReadwrite
KFSystemmessage
IMgateway
AgentState
ServiceSessionAttributes
WebappReadonly_b
GatewayIMRoutewayPartner
KFRobot
WebappReadwrite_b
WebappReadwrite_a
ServiceQuality
 
 查看WebappReadonly_b的server list
[easemob@sdb conf.d]$ curl 127.0.0.1:18882/upstream/WebappReadonly_b
server 10.117.17.21:8180
  
    
5.  配置使用dyups的服务

   之前我们的upstream名字都是比较随意的,没有以服务名字名字,为了使用dyups的特性,upsteam的名字和consul中的服务名要有关联,我们把需要灰度的服务upstream name为 [serviceName]_[tag],只有一个版本的服务upsteram 定义为 [serviceName]
    (以读写webapp为例,因为webapp需要灰度,所以配置文件有2个upstream kfapp_a,kfapp_b)
      
    a. 全局更改kfapp_a为WebappReadwrite_a, kfapp_b 改为WebappReadwrite_b。
       更改完配置,reload后 nginx会自动从内存中读取WebappReadwrite upstream的server信息。
       
    b. 删除原有的upstream kfapp_a,kfapp_b 定义
    
    
配置可以参考: http://www.ttlsa.com/nginx/nginx-modules-ngx_http_dyups_module/
    

注意:在定义非灰度服务的时候,比如MessageServer,在proxy_pass的时候需要用变量替换它的upstream名字 eg: 我们不能使用proxy_pass http://MessageServer 而应该使用变量 set $message_service "MessageServer"; http://$message_service; 原因是如果直接用服务名字,nginx会一直使用原来内存中的地址,如果使用变量,nginx 会一直遍全局存储的upstream list,有变化的话都会及时更新

按照上述步骤配置后,扩容缩容就可以避免reload nginx了,运维操作步骤也会减少很多。

当然有好处也会有风险,使用dyups后nginx对consul就有依赖了,consul的异常可能会对nginx造成影响,目前能想到的几个异常比如超时,或者 consul服务挂掉,都会被python脚本catch住 然后退出,不会对nginx造成影响。

捕捉consul timeout,还用服务变更,consul本身服务的异常code:

    while True:
        try:
            (index, consul_services) = getConsulServices(index_old)
        except requests.exceptions.ConnectionError:
             print "Can't not connect to local consul agent, please check it,  will         exit program."
             sys.exit(1)
        except requests.exceptions.RequestException as err:
             print "There is http request error during calling consul agent, will             exit program"
             print err
             sys.exit(1)
        except Exception as err:
             print err
         sys.exit(1)

测试case

  1. reload nginx
    reload nginx会读取脚本更新的配置文件,重新把从consul获取的upstream更新到内存

  2. kill consul 进程
    python 脚本中会catch到这个异常并退出,不会继续更新nginx的upstream

最后把代码和demo放到了github上,有兴趣的可以自己测试一下!
https://github.com/easemob/SwallowKeeper

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容