接上篇,做完了标准化及标准化管理以后,我们遇到的比较棘手的问题就是这么多的应用应该怎样高效发布,这就涉及到持续集成和发布的问题。原来的 PHP 工程,只要在一个 PHP 的文件里面把代码写好,把文件推送到服务器上,然后最新的 PHP 文件就可以直接运行起来了,不用做中间环节的管控,但是对于 Java 应用来说整个环节就没有这么简单了,Java 文件涉及到编译、二方包、三方包依赖,然后编译打包后,将软件包发布到制定的机器上,然后还要重启 Java 进程,最新的文件才能得以执行,期间还会涉及服务的注册和下线问题等等。从整个过程来说,JAVA 整个发布过程是要比 PHP 复杂很多的。所以我们为什么要去做持续集成,这个持续我的理解是说我们怎样能够把中间环节它的效率尽量提升,减少人为的干预,通过发布的自动化,提升开发和运维的效率。
持续集成和发布这里面涉及到工程效率的问题,也简单做个测算,这个是 Twitter 的工程师分享的数字,在这里也给大家分享一下。假设一个工程师一年工作 2000 小时(250 天),如果说他的效率是提升 10%的话,每个月可以节省 2 天的时间,这是一个工程师。但是如果我们是 100 个或者是 1000 个工程师,这个时候效率是多少,将是几百几千人天的效率提升,可以看到效率提升的价值和意义是非常大的。
进入到我们持续集成和发布,正常的一个持续集成,就是 Java 的发布过程来说,这个图中的流程是业界比较通用的过程。首先开发同学开发完代码以后,我要提交到代码管理库,提交完以后我有一个打包的服务器,然后把二方包、三房包拖下来做编译,然后下面的过陈是发布到测试环境进行测试,测试完成还要发到预发和灰度的 Bata 环境。灰度环境发布完没有什么问题就发到线上环境,这是整个持续集成的发布这过程。
蘑菇街也是按照这一过程去做的,所以这个地方后面我们就直接去看一个例子。我们的发布都是以应有为维度去做的发布,这是进入发布系统我选择的应用,这里面它关联的 Git 库是哪一个,然后我们再来看一下配置信息,就是我们刚才提到的应用配置管理中的信息,这里简单提炼下发布的过程,朴素地讲,发布就是把软件包发布到哪个 IP 的主机上,然后主机上哪个指定的目录下,然后再通过哪个目录下的哪个脚本进行启停控制等的过程。
而上述的这些配置信息,已经存储在了我们前面所介绍到的 CMDB 和应用配置管理中,在发布系统中,我直接调用获取到响应的信息即可。
下面是发布的完整流程,通过基础的 CMDB 的应用-IP 对应关系,以及应用配置管理的基础信息,完成全部自动化发布过程。
从 0 到 1 做完以后,效率问题基本得到解决,但是系统的稳定性这个矛盾马上就凸显出来了。我们经常遇到的问题是系统慢了,系统宕了,或者是突发流量非常大,会碰到这样那样各种诡异的问题。所以这里分享一下稳定性建设这方面的内容,主要有这么几块,一个是全链路跟踪,还有一个是预案系统、开关系统、容量评估还有限流降级。
时间原因,这里只能分享一块,主要讲讲全链路跟踪系统。首先,我们为什么要做这个事情?
这整个的全链路的架构图,在前端的应用上面我们会做埋点日志,然后通过 Kafka 放到实时日志集群里面,这样我们可以快速看到实时的数据,然后对于历史的数据,放到 Hadoop 里存储。
这里面讲一下关键的技术点,其中最关键的就是 TraceID,当一个请求到达接入层,会在接入层生成全局唯一的 TraceID,由我们自研的 Nginx 的 module 实现。然后后续的后端接口或方法调用都会把这个 ID 带上,这样每一次调完会成都会输出一条日志,把本次请求花费多长时间,调用哪些接口记录下来,这样通过刚才实时的 Storm 集群就可以计算出整个的实时请求是怎样的。
这里面呼应一下前面所讲的我们为什么要做技术架构的标准化,刚提到这个 TraceID 是通过 Nginx 的 module 生成的,在 ID 透传的过程中,每一个请求都会从框架层面把这个 ID 自动带上,业务层面是不用考虑对这个 ID 单独做处理的,对于 http 请求,就是自动带上这个参数,对于 RPC 调用,通过分布式服务框架来处理的。所以,前面我们讲到的,接入层架构、分布式架构的这样一个统一的技术栈标准化之后,我们去落地这样的稳定性方案其实就非常顺利了。假设这个标准不统一,Nginx 大家有用原生版本的,有用 Openresty 的,有用 Tengine 的,或者直接用了 Apache,这个 module 是没法统一定制的,对于分布式的框架,如果有用 dubbo,HSF、Thrift 的等等,也会无法统一。
下面直接看一个样例,我们发现页面慢了我们到底怎样去做。经常有同学反映说页面慢了或者是某个页面慢了,我们根据问题反馈的时间点,我们可以筛选一下。这个时间段内,请求超过 1 秒的有哪些,筛选出来后,以 TraceId 为入口,那接下来整个请求的过程就展示出来了。从这个界面上我们可以很明显的看到,整个请求花了 1.5 秒,但是下面红色的地方有一个评价的服务,单这个服务接口的调用自己花了 1.3 秒,肯定是这个服务出了问题,这时候可以大大缩短问题范围的缩小,根据这个 IP,我们可以直接到这台主机上检查发生了什么问题,后面就可以进入到详细的问题定位阶段。
还有一个场景是调用合理性的问题,一次请求下来耗时非常长,但是看每一次的接口调用 RT 又是非常短,问题出在什么地方。比如下面这个这个请求花了 1.8 秒,但是我们看每次请求都是了正常的,不像刚才一样的有一个请求自己占了 1.3 秒。这时候我们通过全链路可以看到,这个请求在频繁的重复的调用一个 Cache 接口,很显然在调用合理性上出现了问题。这时就可以把问题反馈给开发,检查下代码的逻辑,为什么这样么调用,是不是应该优化下调用方式。
还有一块是链路分析,我们一个应用提供出去以后,一个应用又包括了很多服务化的接口,而应用仅仅是成百上千应用当中的一个,这当中有哪些应用依赖了我,然后我又依赖哪些应用的哪些服务化接口,这些应有服务的质量到底怎样等等,这就是一个服务治理的问题了。所以我们做了这样的一个链路依赖的整个分析,从这里里面可以看到我提供服务的运行情况,有哪些应用是依赖我的,我又依赖了哪些应用。
链路分析还有一个非常关键的作用,就是刚才提到稳定性中有一个限流降级系统。这里面很关键一个的点就是通过链路分析提炼出核心应用(交易链路)和非核心应用,对于核心应用优先保障,配置的并发数和优先级就高一些,非核心应用就会小一些,如果出现流量特别大的情况,就会考虑把非核心应用降级或限流掉,优先保障核心应用的调用和运行。
举个简单例子,比如交易相关的购物车下单,如果下单应用依赖了我的服务,那它的优先级就会相对较高,毕竟下单后会马上产生收入,同时可能还有商品评价也依赖我的服务,但这个与交易无关的,那它的优先级就低一些。当我的服务和应用在峰值时(比如大促),我们的策略就是要优先保证交易的应用,其他非核心的应用就降级降掉,或者是并发数限掉,宁可失败但是不可以影响到我整个交易的链路。所以它非常关键的价值就在这里,能够帮助我们梳理清楚核心和非核心的应用,不同的场景采取不同的稳定性保障策略。
这就是刚才讲的稳定性建设里面非常关键的全链路跟踪的一个技术点,其他几个因为时间原因没有办法详细讲,后面有机会再跟大家做分享。谢谢!
本文转载自成哥的世界公众号。
原文链接:https://mp.weixin.qq.com/s/RWvr0YMdEQB43Kt7sd_pvw
评论