vlambda博客
学习文章列表

实战 | ​基于“Nginx+Lua”组件的应用系统灰度发布



欢迎金融科技工作者积极投稿!

各抒己见!

投稿邮箱: 

[email protected]

                                 ——金融电子化

文 / 中国人寿保险股份有限公司研发中心  熊军军 彭晓刚 郑晓勇 宣军法

近年来,随着公司业务快速发展和客户要求的不断提高,中国人寿IT系统建设逐渐呈现出两个特点。一是系统版本数量增长快,由于部分版本质量不高可能影响系统可用性,研发运维人员需要在版本上线后投入大量精力保障系统稳定。二是业务创新质量要求高,系统需要将某类新特性投放给特定用户,在预定验证周期内及早获得用户反馈,快速验证产品设计理念,促进产品快速迭代优化。为做稳做优应用系统产品,支持业务快速创新,研发中心统一制订了基于“Nginx+Lua”组件的技术方案,对关键系统进行架构改造,使其具备灰度发布能力。


工作目标

制订统一灰度发布技术方案,通过技术改造,使20余个关键系统具备灰度发布条件,进而实现以下目标。


1.提高系统可用性。按部署策略,控制某类新特性的投放范围,避免该新特性的缺陷影响所有用户,避免发生全局性系统故障。


2.提升应用产品迭代能力。将某类新特性投放给特定用户,在预定验证周期内及早获得用户反馈,快速验证产品设计理念,促进产品快速迭代完善。


技术方案

1.灰度发布的含义。灰度发布是一种将特定产品功能投放给特定用户的系统版本发布方式,有利于保障系统稳定,提高产品迭代效率。应用系统灰度发布基本原理如图1所示,其中,正式环境上部署了应用系统当前版本1,灰度环境部署应用系统新版本2,服务路由控制集群上配置访问这两个环境的策略。当用户请求到达服务路由控制集群时,控制节点会根据服务访问策略,将用户请求转发至正式或灰度环境,访问灰度环境的用户将体验系统新功能。

实战 | ​基于“Nginx+Lua”组件的应用系统灰度发布

 图1  应用系统灰度发布基本原理图


2.灰度发布的主要实现方式。根据需要灰度发布的内容,我们将灰度发布分为服务端灰度和客户端灰度。服务端灰度是指应用系统的服务端程序的灰度发布;客户端灰度是指应用系统的客户端程序及静态资源的灰度发布,如APP升级包、JS文件、图片等静态资源的发布。


根据灰度发布的技术实现方式,我们进一步将灰度发布实现方式分为:“通用路由组件实现灰度”“开发框架路由组件实现灰度”“其他实现灰度方式”及“客户端升级服务组件实现灰度”。具体如图2所示。

实战 | ​基于“Nginx+Lua”组件的应用系统灰度发布

图2  应用系统灰度发布的主要技术方案


(1)“通用路由组件实现灰度”。借助Nginx、HAproxy等通用路由组件,将部分用户请求分发到灰度环境。


本文采用的Nginx,是一种轻量级的开源软件,可用来搭建反向代理服务器、Web服务器和邮件代理服务器,具有并发性能好、资源效率低的优点,其架构特点是“事件驱动、异步化和非阻塞”。即:通过事件驱动方式动态地申请或释放资源,提高CPU、内存等资源利用率,并通过高效的多路复用IO技术,显著提高程序在大量并发连接中的CPU利用率,使得多个线程可以并发执行而不被阻塞。


为扩展Nginx能力,通常会引入Lua脚本语言。Lua是一种轻量级的脚本语言,其设计目的是通过灵活地嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能,具有“功能强大、代码简洁、易于集成、运行速度快、易于扩展”等特点。一个完整的Lua解释器不超过200KB,其中LuaJIT具备即时编译能力,通过安装LuaJIT、Lua-nginx-module、nginx_devel_kit,就可以在Nginx的11个处理阶段使用Lua指令。基于Nginx+Lua的两个开源软件OpenResty和ABTestingGateway,都可以用来快速搭建灰度环境。


(2)“开发框架路由组件实现灰度”。Dubbo、Spring Cloud等开发框架均提供了支持灰度发布的路由组件。


Dubbo的灰度路由机制:服务注册服务器将服务提供者信息推送给服务消费方,服务消费方在调用服务时,先由Router根据一定的路由规则,从本地服务器列表中选择一组合适的服务提供者,然后由LoadBalance根据自定义的负载均衡策略从中选择一个服务提供者。这个自定义的策略可以通过实现LoadBalance接口或者继承AbstractLoadBalance类来重写,以实现复杂的灰度控制逻辑。


SpringCloud的灰度路由机制:用户请求统一通过API网关Zuul来访问内部服务,网关接收到请求后,从注册中心获取可用服务列表,然后通过Ribbon中的路由策略选择正式或灰度服务,将请求发送给后端服务。自定义路由策略需要集成AbstractLoadBalanceRule或其子类。


(3)“其他实现灰度方式”。在通过专用路由组件实现灰度之前,有一些较为传统的做法也实现了灰度的效果。例如:通过程序中的硬代码分支来控制被调用的服务;通过将程序分省部属、分批上线来实现灰度发布等等。


(4)“客户端升级服务组件实现灰度”。客户端的APP升级包、JS文件,以及图片等静态资源的发布,一般通过专用的升级服务来实现,升级服务器访问灰度发布配置库获取灰度发布策略。当用户在APP登录时,首先访问升级服务器,判断是否为灰度用户,若是则从内容分发服务器下载升级包或静态资源,实现客户端灰度发布。


项目实践

在对关键系统的改造过程中,我们首先进行技术选型论证,然后组织技术验证,之后分批推进项目实施,取得一定成效。


1.技术选型。为适应不同技术框架应用系统的灰度发布需求,我们采用“通用路由组件实现灰度”的方案。


具体实现上,路由组件采用基于“Nginx+lua”组件的OpenResty工具。同时,引入Keepalived组件,保障OpenResty高可用,具体原理如图3所示。

实战 | ​基于“Nginx+Lua”组件的应用系统灰度发布

图3  基于Keepalived的OpenResty高可用集群


Keepalived采用虚拟路由冗余协议,将N台相同功能的路由器组成一个路由器组。这个组里面有一个Master和多个Backup,Master上面有一个对外提供服务的VIP。Master会发组播VRRP包,用于告诉Backup自己正常工作。当Backup收不到VRRP包时就认为Master不可用,这时就需要根据VRRP的优先级来选举一个Backup当Master。以此保障路由器的高可用,保证业务的连续性,接管速度最快可以小于1秒。


2.技术验证。为确保上述方案可行,项目组采用“Keepalived+OpenResty”方案开展验证测试,主要评集群的并发性能、高可用性及对后端服务的影响。


(1)并发性能。挡板测试表明,针对单支交易,在并发用户数从50增加到1500的场景下,OpenResty集群处理能力保持在9800笔/秒以上,CPU使用率维持在17.17%左右,内存使用率维持在23.48%左右,并发性能良好,系统资源占用率较低。


(2)高可用性。以200用户并发执行两支交易(配比为100:100),待场景稳定运行几分钟之后,手动关闭一个Openresty服务器节点,观察所有用户请求能否被快速分发到剩余运行的一台Openresty服务器节点。通过查看Keepalived日志,手动关闭一个节点后,用户请求快速切换到另一节点,场景继续稳定运行。


(3)转发对后端服务的影响。选取4支典型交易,按50用户并发,分别直连或通过OpenResty访问后端服务。通过比较2组数据,可以看到OpenResty转发对后端服务的吞吐量和响应时间影响比较小,增加Open Resty转发后,后端服务性能下降在2%以内。


3.系统改造。按照上述方案,我们对20余个关键系统进行了架构改造,增加灰度路由层,灰度控制对象,主要选择用户请求的Httpheader中的“IP、角色、机构、系统来源”。


灰度发布实施的过程中,需关注以下问题。


(1)灰度控制对象从Httpheader获取,一般不解析HttpBody中的数据,因为性能消耗较大。如果Header中暂时没有需要用来控制路由的数据元素,则上下游对对服务报文头进行联动调整即可。


(2)灰度对象当前仅限客户端资源或服务端应用,不包括服务端数据库。数据库的灰度,因涉及正式与灰度数据的合并等问题,暂无较好的整体性解决方案。但针对个别字段的调整,可以通过新增字段,并使新程序逻辑同时写新、老字段的方式,使数据库能同时兼容新老应用程序,且保证数据完整性。


(3)每个应用系统独立实现各自的灰度路由控制层,并未建立一个集中的、供各系统共用的灰度路由控制服务器。因为类似集中的路由控制,可能会跟ESB等设施一样,成为性能瓶颈。


(4)Keepalived能很好地保障OpenResty集群的高可用,在业界应用也比较广泛。但部分研发人员仍担心,主备模式仅能保证某个时点只有Master一个节点在转发服务,所有服务压力靠一个节点承载,不利于扩展。事实上,一个长的服务链路中,最前端的路由设备始终无法避免单点的问题,因为其前面没有路由设备为其分流。这时,我们可以考虑另外的服务分流方式,例如:再建立一套Keepalived主从机制,从而对外虚拟出两个VIP,使两个OpenResty集群互为主备,不同的应用访问不同的VIP即可。这个路由可以通过DNS、ESB注册订阅等机制实现,实际上体现了一种多层路由分担任务的思路。


系统的灰度能力,可以应用到不同的场景,例如:服务接口扩展,Webservice服务改为ResTFUL,ResTFUL服务从虚拟机迁移到容器等等。


4.工作成效。根据各系统特点,灵活使用基于“Nginx+Lua”的灰度发布技术组件,建立统一的架构层——服务路由层,推动“可灰度”理念成为一种架构设计共识,取得了以下成效。


(1)公司20余个关键系统全部具备灰度发布条件,其中6个系统在生产环境发布灰度版本,3个系统实现常态化灰度发布。


(2)大幅提高系统稳定性,降低新版本上线影响,防范生产事件,部分系统可白天升级,减少夜间加班升级、凌晨紧急解决问题的情况。


(3)有效提高系统迭代效率,有利于快速适应一线需求,快速发布新功能,快速试错,快速获得一线反馈。


(4)通过“Keepalived+Nginx”实现Nginx集群的高可用,探索硬负载均衡向软负载均衡切换的路径,有利于降低硬件采购成本。


总结展望

通过上述实践,我们已经积累了一定经验,包括Openresty组件使用,nginx参数配置,灰度对象选择,灰度版本发布流程等方面。为进一步完善灰度发布技术,支持更多场景实现“可灰度”的目标,可以从以下几个方面考虑后续工作。


1.全链路灰度发布。当前随着分工的细化,服务的调用链逐渐加长,一个功能改造可能涉及多个服务。如何实现用户请求发出后,全链路一致灰度,需要结合服务治理统筹考虑。


2.多种灰度方式融合。在实现完备的全链路灰度方案前,要结合各系统现状,灵活选择适用的技术方案,相互融合起来达到灰度发布的效果。实时交易类服务可用Nginx等通用路由组件实现灰度;异步消息驱动的服务,可通过建立相对隔离的灰度环境来保障灰度数据仅在灰度环境流转。此外,也需注意到新技术对灰度发布带来的影响,例如ServiceMesh框架中使用Istio实现灰度发布。


3.数据库灰度。其难点是正式环境和灰度环境数据的整合,以及异常灰度数据的回滚。需要巧妙的数据库设计或者灵活的数据迁移,可以从数据库SQL解析引擎、库表设计、分区设计等角度深入分析。





往期精选:

(点击查看精彩内容)






关于仿冒我刊收费的声明





我刊自创刊以来,从未向投稿人收取过任何费用。任何以刊发文章为名向投稿人收取费用的行为,均属于对投稿人的欺诈行为。


我刊投稿邮箱为 [email protected]





《金融电子化》新媒体部:主任 / 邝源  编辑 / 潘婧 傅甜甜