干货 | 携程第四代架构探秘之运维基础架构升级(下)

作者简介

本文由携程技术中心框架研发部吴其敏、王兴朝,技术保障中心高峻、王潇俊、陈劼联合撰写。

作为国内最大的OTA公司,携程为数以亿计的海内外用户提供优质的旅游产品及服务。2014年底携程技术中心的框架、系统和运维团队共同启动了架构改造项目,历时2年,涉及所有业务线。本文回顾了携程在整个技术架构改造过程中的一些实践和收获。

本篇为该分享的下篇,上篇请戳:

携程第四代架构探秘之运维基础架构升级(上)

弹性路由(SLB)

携程部署架构采用的是单机多应用,每台服务器上部署了很多个应用。这些应用不一定存在紧密内联关系,且很可能属于不同团队,这种架构存在着明显的问题。

其实携程面临的这些问题并不是突然暴发的,而是经过十多年的演进和慢慢累积,最终大家不得不正视这些问题。

从本质上讲,这些问题的根源是应用间的耦合,最好的解决方案就是单机单应用。因为单机单应用实现了应用间的天然物理隔离(部署在不同的服务器上),从而极大地降低了运维的复杂度,部署、排障、沟通、配置和个性化等都不用再担心会对其他应用有影响。

单机单应用是业界普遍推荐和采用的一种部署架构,但对携程而言这却是个系统性的大工程,需要从底层基础设施到配套系统工具、从流程规范到开发人员的思维转变等方面投入大量的人力和时间。所以我们首先就要考虑如何在单机多应用的情况下,实现应用解耦,也就是做到应用粒度的运维。

相比应用粒度的运维目标,携程当时实际情况则是服务器的运维粒度,并且绝大多数的运维操作还是通过硬件LB来完成。虽然硬件LB的好处显而易见,例如,高吞吐量、高性能和优秀的稳定性等。但其缺点也同样明显:

(1)水平扩展成本高昂;

(2)基于规则无法建模,规则过多时就会陷入运维泥潭;

(3)无法进行高频次的变更,因为集中式管理模式中,配置数据一多,API性能就会急剧下降;

(4)只能由少数的专职运维人员做操作。当时携程所有7层路由规则都由硬件LB负责,规则约有上万条。当一个应用需要变更访问入口时,最终会需要在硬件LB上增加一条ContentSwitch,但这可能要排期一天,等专门运维人员来操作。在运维工具上将一台问题服务器拉出,有时运气好5分钟就能返回,有时会等上30分钟。

所以,硬件LB除了无法做到应用粒度外,低效也成为一个很重大缺陷。为了解决在路由运维方面的粒度和效率问题,携程决定打造自己的软负载(SLB)系统,替代掉硬件LB的七层路由职责。经过讨论,SLB确定了自己的职能目标,即可以高并发、实时、灵活、细粒度调整七层路由规则。从另一方面想,SLB还需要实现由面向机器运维到面向应用运维的转变,以及由硬件支撑到软件支撑的进化。

在携程SLB的开发过程中,最重要的几点是:

(1)面向应用建模;

(2)多次更新一次生效

(3)多并发操作的挑战;

(4)多角色运维冲突的问题;

(5)监控和告警。

1. 面向应用建模

携程经过评估最终选择了Nginx来构建软负载系统。开发前我们参考了业界内其他公司的实现方式,基本包含几个特点:

(1)开发了一个Nginx配置文件的批量管理工具;

(2)需要专业的运维人员来操作;

(3)日常操作频率较低;

(4)和现有系统接合较松散。

结合携程的现状,我们在建模时还需要考虑:

(1)和现有系统无缝接合,融入现有系统的生态体系;

(2)支持高频率的并发操作;

但如何和现有建模体系融合起来?在开发人员眼中最重要最核心的常见模型就是一个一个的应用。所以SLB要做的是如何和应用模型融合起来,换句话说,所有对SLB的操作都要被抽象为对一个应用的操作。Nginx是基于文本配置文件,其内建了一个自己的模型,一次运维操作可以导致多个Nginx模型的变更。所以我们需要创建一个模型,这个模型可以和应用模型一一对应,又能被翻译成Nginx的内建模型,而这就是Group:

(1)一个Group是一个应用在SLB的投影;

(2)SLB上所有的操作都抽象成对Group的操作;

(3)不同Group的操作互不影响。

这样只要解决一个Group的问题,就相当于解决了1000个、甚至更多个Group的问题。

2. 多次更新一次生效

建模成功地隐藏了Nginx的内存模型,并将操作转换成了对Group的操作。虽然隔离不同Group间的操作,但在SLB上对单一Group的操作仍然是一个有风险的行为(对某一具体应用而言)。为了降低这种风险性,可以引入3种机制,包括多版本系统、日志追踪和多次更新一次生效。

Group的每次变更都会产生一个新的版本;Group的所有变更都会留下日志;对Group的变更操作并不会直接对生产生效,可以在多次变更后,有一次明确的激活操作后,从而在生产环境正式生效。

3. 多并发操作

引入group后实现了应用的独立运维,但如果有上千个Group要同时进行扩容操作,那么如何做到每个Group的操作都在5秒内完成?

因为Nginx是基于一个文本配置文件的,那么这样的要求就会转换为对配置文件的上千次操作,然后再对SLB重新加载上千次配置文件。假设一次操作花费1s,那么最后一个操作可能要等1000s,这种实现方式显然对于那些排在后面的Group更新者是无法接受的,而且SLB在这种高频度更新下,自身也无法工作。所以简单地把一次Group更新转换成一次Nginx的配置更新是肯定行不通的。(携程真实情况是Nginx变更日操作达到8万次,整个软负载API日请求数达到300万次)。

为了实现Group更新的互不影响,并确保所有Group更新保持在一个稳定返回时间内,SLB确定了核心业务流程:

(1)将一段时间内所有的Group更新操作(比如2秒内)缓存在一个任务队列中;

(2)对任务队列中的所有操作进行合并,最终只对Nginx的配置文件做一次更新。

这个流程的核心逻辑就是多次操作一次更新,最大程度减少对Nginx配置文件的操作,但外部看来Group更新操作是独立且保持在稳定返回时间内的。

4. 多角色运维的冲突

一个Group可能会有多种角色进行更新,比如应用Owner、专业运维人员和发布系统人员等。这就引出了一个新的问题,即当一个角色对一个Group的服务器进行拉出操作后,另一个角色可不可以对这些服务器做拉入操作?

比如,发布系统人员在发布完成后,准备做拉入,却发现运维人员对这台服务器进行了拉出操作。这时发系统应该如何决策?这不仅造成决策的困扰,也会使不同的角色产生联系,甚至相互耦合在一起。

为了解决这个问题,我们决定采用多状态的机制:

(1)为每一种角色分配一个服务器状态;

(2)一个角色对这个状态进行了失效操作,最终也只能由这个角色进行恢复操作;

(3)SLB在所有角色都认为这台服务器有效时,才会认为这台服务器可工作。

5. 健康检测带来的瓶颈

SLB另一个核心功能是健康检测,即需要以一定频率对应用服务器进行心跳检测,连续失败多次后对服务器进行拉出操作,成功后再进行拉入恢复。大多数公司采用了节点独立检测造成了带宽浪费和服务器压力,而携程采用了节点共享检测,具体机制是一个独立的应用负责检测,然后把检测结果在SLB节点间传播共享。

【携程的健康检测效果】 携程独立健康检测的运行效果良好,目前SLB系统已经负责了携程超过5万个结点的健康检测任务。而下图是由节点独立检测变为节点共享检测时的SLB单一服务器网络连接释放状况:

6. 监控数据采集和告警

SLB负责了几乎所有的基于域名的http调度请求,所以也成为了进行请求流量统计和请求质量统计的绝佳场所。包括在有问题时进行报警;根据不同维度统计请求量;响应码分布和响应时间分布等,携程使用了分析access log的方式来获得监控数据:

(1)SLB服务器流式读取本机实时产生的access log;

(2)分析聚合log数据,产生不同的统计数据。最终使用了语法树分析实现了高效分析,一秒可以分析14万条日志;

(3)定期(1分钟)将统计数据吐到监控系统CAT等。

以此可以产生多维度的监控统计数据,如下图:

基于上述数据,可以查看整个携程或单个应用性能表现,进行相应的优化。在慢请求和非200请求的数量异常时,执行报警操作,确保及时恢复和挽回损失。

想发就发(TARS)

解决了配置和路由问题后,发布系统前置障碍已基本扫除,而从OPS角度来看,发布系统还有几个重要目标:

(1)灰度发布

(2)简单易用

(3)发布迅捷

1、灰度发布

通常发布有三种常规方法,蓝绿发布,滚动发布,金丝雀发布。对这三种发布类别做比较,可以发现:

(1)蓝绿发布:需要额外的服务器集群支持,且数量可观,同时由于携程单机多应用的部署现状,就会造成发布一个应用需要替换整台服务器的情况,实现难度巨大且成本不经济。

(2)滚动发布:虽然可以节省资源,但对应用的兼容性有较高要求,因为发布过程中同时会有两个版本对外提供服务。但这类问题相对容易解决,实际中往往会通过功能开关,dark launch等方式来解决。

(3)金丝雀发布,比较符合携程对灰度发布的预期,但可能需要精细的流控和数据的支持,同样有版本兼容的需求。

【发布相关说明】 蓝绿发布:优先将新版本发布到待发布的机器上,并进行验证,此时新版本服务器并不接入外部流量。发布和验证过程中老版本所在的服务器仍照常服务,验证通过后,经过流控处理把流量引导到新服务器,待全部流量切换完成,老版本服务器下线。

滚动发布:从老版本服务器中挑选一批,停止老版本的服务,并更新为新版本,进行验证,通过后再分批增量更新剩余服务器。 金丝雀发布:往往从集群中挑选特定服务器或一小批符合要求的特征用户,对其进行版本更新及验证,随后逐步更新剩余服务器。

结合携程的实际情况,最终挑选的方式是滚动发布和金丝雀发布的结合体,首先允许对一个较大的应用集群,特别是跨IDC的应用集群按自定义的规则进行切分,形成较固定的发布单元。每个应用的每个发布单元称为“group”,这个group与之前提到的SLB的group是一一对应的。

每个发布单元,即group在发布过程时,还可以再分批进行,完成滚动发布。而每个group中包含一台或多台堡垒机,必须先完成堡垒机的发布和验证,才能继续其他机器的发布,从而实现金丝雀发布。除堡垒机的发布外,其他机器可按照用户能接受的最大同时拉出比例来分批,分批间允许设置具体的验证等待时间。

每台机器在发布过程中都要经历拉出、下载、安装、点火和拉入这5个步骤,发布流程为:

基于以上设计,携程新一代发布系统开发完成,命名为Tars 。

【Tars源代码】 Tars已做了开源,开源版本地址:https://github.com/ctripcorp/tars

2、简单易用

发布配置必须简单易懂,绝大部分的应用发布都是固定模式,不需要个性化配置,所以Tars只提供了几个核心配置项,包括(1)允许同时拉出的最大比例;(2)批次间的等待时间;(3)启动超时时间;(4)是否忽略点火。

除此以外,用户最关心的是发布过程中可操作按钮的易用性,Tars在这方面做了充分考虑,通过状态机的控制,保证用户在操作界面上同时最多只看到两个操作按钮,绝大部分情况下用户只需在“继续”或“终止”这样的0或1的选择中做出决策。

而图形化界面的展示,Tars也确保用户可以更直观地观察到发布的进展,以及出现的问题。

有了简单操作,危机时刻就会得到放大体现,比如,因生产故障做回滚时,能快速中断当前发布,并从界面中轻松地选到所需回滚的版本,然后一键无配置地触发完成回滚。

3、发布迅捷

天下武功无坚不摧,唯快不破,而发布也一样。发布速度快了,迭代速度研发效率也就提升了;回滚速度快了,生产故障造成的影响也就减轻了;扩容速度快了,弹性计算就能实施了,这样运维效率被大幅度提升。

从上面对发布过程的描述中,不能发现在携程通常影响发布速度的步骤是下载和验证。

(1)为了提高下载速度,携程在各个机房搭建了发布包专用的存储系统,实现了类似CDN的功能,编译和打包系统在任何一个写入点写入发布包,都会尽快同步到各个IDC及各个独立存储中,这样真正发布时,服务器只需从本IDC或本网段做下载。而回滚方面,Tars则是在服务器本地保留了n个版本(n根据服务器磁盘容量计算获得),做回滚时可快速地进行目录切换,进而省略了代码下载过程。

(2)对于验证,携程在框架层面统一提供了验证入口和常规验证方法(携程称为“点火”),收口了所有应用的验证规范和标准,容错性得到提升。

(3)Tars在系统设计方面充分考虑了速度需求。每个发布单元采用quick and dirty的方式,不管成功或失败,优先尝试把版本发布完成,后续在解决个别发布失败的问题。

根据同时拉出服务的最高比率(由用户设置)进行失败率控制,一旦达到比率,立即中断当前发布,从而对quick and dirty方式做保护(携程称为“刹车”)。发布单元中只要有任何一台服务器发布失败,都会被认为是发布局部失败,允许用户重试发布。

发布过程中如发现服务器当前运行版本与发布目标版本一致,且验证通过,则直接skip。批次间可设置观察等待时长,从第3个批次起,允许设置0或较少的等待时长,以提高后几批次的速度(携程称为“尾单加速”)。

三、结果和未来

通过CMS+SLB+TARS几个系统的联动,并经历了长达一年半的项目推广阶段,终于实现了1+1+1>>3的效果。新发布系统对于研发效率和研发人员体验的提升都非常显著。

这可以通过一些数字来证明,与2年前相比,每周的发布迭代次数成长了4倍,但单次发布的平均时长从13分钟却降低到了3分钟。同时因为发布/回退效率的提升,当需要对线上代码做紧急修复时,或者将其回退到已发布的代码版本时,都会更快捷地完成,所以使得发布类故障的处理效率也得到了提升。

对2015年至2017年的发布相关故障的统计后,发现该占比下降了一半以上。

因为CMS+SLB+TARS基于良好的配置数据模型设计,及其应用级的运维支持能力,为后续的技术架构改造带来了便捷和优势。这主要体现在:

(1)高效的容量管理,实现了对应用容量的自动化监测,当发现容量不足时,无需研发介入,全自动地进行应用服务器扩容、发布、上线和投产等。

(2)在应用容灾方面,基于准确的配置数据,可以很容易的将单数据中心的业务应用“克隆”到另外的数据中心来进行部署。

(3)在应用技术栈的迁移(例如.net应用改造为java应用),用户也能自助地创建新的java应用,并通过SLB灵活实现灰度流量切换,进而自助、高效、稳定、安全地完成整个应用迁移。

原文发布于微信公众号 - 携程技术中心(ctriptech)

原文发表时间:2017-07-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SDNLAB

基于OpenFlow架构的IaaS云安全

编者按:云计算技术的服务型基础设施即服务(IaaS),以其可扩展性、高效性及弹性等特点正在成为资源利用的主导方式。在从云计算的IaaS应用获得便捷的同时,安全漏...

31730
来自专栏开源项目

用大白话聊聊分布式系统

一提起“分布式系统”,大家的第一感觉就是好高大上啊,深不可测,看各类大牛关于分布式系统的演讲或者书籍,也大多是一脸懵逼。本文期望用浅显易懂的大白话来就什么是分布...

49890
来自专栏张绍文的专栏

微信终端跨平台组件 Mars 系列:我们如约而至

网络作为微信的基础,重要性不言而喻。任何网络实现的 bug 都可能导致重大事故。例如微信的容灾实现,如果因为版本的实现差异,导致某些版本上无法进行容灾恢复,将会...

73320
来自专栏云计算D1net

云技术如何改变业务灾难恢复计划?

尽管业务灾难恢复计划转向云计算,但传统灾难恢复(DR)的关键要素,如位置和测试仍然很重要。 在过去几年中,人们已经逐渐放弃了一种被动的业务恢复计划,那就是采用...

29960
来自专栏FreeBuf

看我如何发现价值三千美金的Facebook视频缩略图信息泄露漏洞

本文我要分享的是我的一个$3000美金Facebook漏洞发现过程。在我决定对Facebook网站进行安全测试之后,我熟读了很多相关的漏洞发现writeup,发...

16600
来自专栏软件

ERP管理软件系统设计方案

【微信运营】微信公众号开发、朋友圈广告、微信运营活动、微信小程序、微商城搭建; 【电脑端网站】网站建设、网站结构、网站功能、关键字策划、UI设计、网站SEO、升...

50850
来自专栏哲学驱动设计

《架构师》反思:系统可靠性

最近系统学习了一个系统可靠性及其相关知识,今天在这总结一下。 首先,什么是系统的可靠性呢?系统的可靠性是指在规定的时间内及规定的环境下完成规定功能的能力,也...

38050
来自专栏企鹅号快讯

前后端分离实践

前后端分离并不是什么新鲜事,到处都是前后端分离的实践。然而一些历史项目在从一体化 Web 设计转向前后端分离的架构时,仍然不可避免的会遇到各种各样的问题。由于层...

45280
来自专栏精讲JAVA

前后端分离实践的架构设计

前后端分离的项目开发策略已经不是什么新鲜东西了,网上介绍这方面的文章非常多。我自己是在14年的时候接触到的,对这种开发策略一直爱不释手,不管新老项目都会首先用前...

16530
来自专栏JAVA高级架构

饿了么:日订单量超900万的架构设计及演进之路

网站在刚开始的时候大概只是一个想法:一个产业的模型,快速地将它产生出来。“快”是第一位的,不需要花太多精力在架构设计上。在网站进入扩张期才需要对架构投入更多的精...

14220

扫码关注云+社区

领取腾讯云代金券