赵成花名:谦益。—在华为技术有限公司,高级软件工程师。年加入蘑菇街。
前言年加入蘑菇街,很有幸,进入蘑菇街后,经历了公司业务高速发展的这样一个阶段,在技术上,我们技术团队也经历了自创建以来非常关键的一个演进过程。
同时,也是运维团从小到大的发展起来,运维体系架构也从无到有建设起来的的一个过程。这样的经历对于我和我的团队都是非常宝贵的,今天也是想把这样一个过程在这里分享给大家。
下面是蘑菇街发展的过程,不详细描述,大家可以自己看一下:
今天的分享,主要分以下几个部分:
第一部分是蘑菇街技术架构和运维体系演进历程,以及这当中我们遇到的困难和挑战。第二个是跨越篱笆,我们的运维解决方案。第三部分是运维技术管理分享。
一、蘑菇街技术架构和运维体系演进早期年,整个产品形态以导购方式上线,当时用户量和业务不大,也没有很大地并发量。当时我们整个的技术架构选择了业界最常见的LNMP结构,通过PHP快速开发,放到Linux服务器上快速让业务运行起来。当时也没有专职的运维的团队,整个开发的同学就专职去做运维工作。
年我们转型做电商,这是我们的技术架构,可以看到,整个技术架构也没有发生太大地变化,还是以LNMP架构为主。如果有同学经过业务从小到大的快速发展的过程的,可能会有相似的经历,在这个过程中,最容易出现瓶颈和问题的是DB的连接、缓存的连接等这种连接数的资源,蘑菇街在这个阶段也遇到的同样的问题,所以架构上的调整,主要是DB中间层和缓存中间层的增加为主,但整体上还是LNMP。
随着业务发展,业务也开始变得丰富和复杂起来,也就说随着业务的发展,带来的不仅仅是用户量、业务量这种体量上的增长,业务自身丰富的程度和复杂度也在发生着非常大地变化。对技术上带来的挑战和问题,我们直接看图:
可以看到PHP的工程变得异常的臃肿,因为有太多的业务需求需要开发,有太多的开发人员在同时开发。短期内PHP的代码工程就成了这个样子。
这里首先说下PHP的优势,我们一开始是选型用PHP作为主力开发语言,因为PHP上手非常快,入门门槛相对低一些,一个新手从学习到开发生产系统的代码的周期是很短的,同时,PHP部署发布的效率也相对简单,PHP文件发到线上即可运行,不用复杂的编译、打包和启停动作,在业务前期发展阶段,PHP效率上的优势就表现的很明显。
但是,刚才我们看到的图,随着业务的发展,业务类型越来越多,开发的同学也越来越多,大家都往一个工程里面去写代码,势必导致PHP的工程越来越大,越来越臃肿,给后续的代码维护带来了很高的复杂性。
举个例子,对于一个开发的同学来说,如果他要做的功能和需求涉及到其他人的开发的PHP文件,本来这个功能和需求在原有的程序上改就行了,但是因为工程太大了,这位同学可能是没有办法评估清楚说改了这一个文件,对其他的文件、接口和方法会造成什么样的影响,即使能够评估清楚,他也很难保证在测试的时候把这些所有的点都能够测试到,根本没这么大的精力。
所以就导致很多开发同学会不断的ControlC+V,就是宁可是把需要改的文件Copy一份出来,然后在Copy出来的文件上面做开发,原来的功能不动,这样就保证了新需求可以不影响老功能,但是这个状况就会导致进一步加大了PHP工程的臃肿,实际上是一个恶性循环。
再就是,如果碰到非改不可的PHP底层的文件和代码,如果评估不到位,就是导致出现各种各样的线上故障。所以,到了这个阶段,PHP代码就很难维护了,反而影响到了需求和版本的迭代速度。
这种情况下我们应该怎样办呢?我们选择业界比较通用的方案-Java服务化,把大的工程拆分成一个个小的应用,通过服务化框架提供RPC的调用。这个阶段,我们从PHP转向JAVA,从单一工程转向了分布式服务架构。
经过拆分后,整个架构就变成了现在的这个样子。这样看下来整个架构分了很多层,也有很多的细节,乍看上去是比刚才的架构图要复杂一些。但是这样的架构根据条理性,也会让架构里面很多的技术细节都曝露出来,更加便于管理。相对那刚才非常庞大和臃肿的PHP工程,内部的逻辑、方法和接口的依赖等等,是很难梳理清楚的。
下面主要讲一下我们做了JAVA服务化的技术转型后,对运维带来的挑战是什么,我觉得总结下来两个:
二、跨越篱笆,我们的运维解决方案
分两个阶段,一个是从0到1,运维做了哪些基础的工作,然后把基础工作做好以后,我们从1到,可以做哪些更有价值的事情。
整个的运维从0到1,从0开始我到底应该怎样做,我觉得一定一定要从标准化开始,并围绕标准化展开。
关于标准化,可能大家在各种社区和社群的分享里听到或看到过,不管是做运维平台也好,还是运维体系也好,或者运维系统也好,第一件事要做的一定是做标准化。所以关于为什么要做标准化我不再讲,大家多看看社区里的分享就可以了。我直接说我这边做的具体动作,后面我会在案例里面把标准化的重要性把它提炼出来。
标准化我们主要做了三方面的工作,一个是基础软件及基础设施的标准,主要是操作系统的版本必须统一,内核参数统一,基础设施上,我们用KVM虚拟化技术将我们的资源做成2C2G、8C16G这样的资源模板,确保资源配置的统一。
二是应用及配置标准化,这个后面细讲。
第三部分是技术架构标准化,技术架构这块分接入层、中间件技术、缓存、DB等,关于技术架构标准化这块,可能是在其他的分享里面可能见得不是很多,这块我后面还是通过案例把基础架构为什么做标准化,它的重要性和它的意义在案例中体现一下。
举个例子:
我们在做整个运维平台之前,或者是做整个运维体系之前,我们首先将整个系统梳理一下,然后看一下整个系统里面到底有哪些基础环节和软件,应用的话到底有哪些应用类型。
我们把这些东西一条一条地记下来,然后归纳总结,慢慢的就形成了左边的集团标准化,包括应用管理的标准化。基础服务的标准化,安全的标准化,稳定性的标准化,我们全部都制定清楚形成文档。
然后右边是应用部署标准,这是整个大纲里面的分册,我们把应用这边的部署目录,它应用到的版本,它的参数以及它起停的脚本、命令,这个东西我们统统定义下来。比如下面这个例子,这是针对JAVA应用的版本,容器的目录哪些,应用的目录、脚本的目录、代码的目录、应用日志的目录等统统固化下来。
我们把标准化的动作做完以后,如果只是纸面上的,那它的威力是没有显现出来的,如果仅仅是以写脚本的方式去管理它,实际上还是有点笨拙,所以我们再往后就做了这样一个应用配置系统,目的就是把我们做的标准化沉淀在我们的技术平台上面,可管理,可提供服务。
刚才大家看到的样例就是我针对Java的标准,它的目录,起停的脚本等,我们通过一个应用模板固化下来,比如实际应用过程中,典型的Java应用,是Nginx+Tomcat的运行方式,那在应用配置管理中,就会有应用模板、基础软件和应用配置文件管理几个模块来管理,具体样例如下:
刚才讲的这部分,是针对标准化,最后把它沉淀为标准的应用模板。那下面如果要去创建应用,应该怎么去匹配这个模板。首先讲一下关于应用,我们把一个Java这样一个庞大的应用拆分成几十、上百个应用以后,要将应用管理起来,首先要有应用名的定义,定义有相对准确地表达软件包或者是应用的含义就好了。
创建了这样一个应用后,选择下面模板类型,然后基于这个应用模板的起停的先命令、标准的目录就在这个应用生成了。
关于应用还有一个很核心的关联关系,就是应用-资源的关联关系,从资源管理的角度就是应用名-IP的关联关系,这个就是通过CMDB来管理了,所以我们的CMDB做的就相对轻量一些。
最后,这两个关键的基础设施建设完成之后,就有了如下的架构图:
做完了标准化及标准化管理以后,我们遇到的比较棘手的问题就是这么多的应用应该怎样高效发布,这就涉及到持续集成和发布的问题。
原来的PHP工程,只要在一个PHP的文件里面把代码写好,把文件推送到服务器上,然后最新的PHP文件就可以直接运行起来了,不用做中间环节的管控,但是对于Java应用来说整个环节就没有这么简单了,Java文件涉及到编译、二方包、三方包依赖,然后编译打包后,将软件包发布到制定的机器上,然后还要重启Java进程,最新的文件才能得以执行,期间还会涉及服务的注册和下线问题等等。
从整个过程来说,JAVA整个发布过程是要比PHP复杂很多的。所以我们为什么要去做持续集成,这个持续我的理解是说我们怎样能够把中间环节它的效率尽量提升,减少人为的干预,通过发布的自动化,提升开发和运维的效率。
持续集成和发布这里面涉及到工程效率的问题,也简单做个测算,这个是Twitter的工程师分享的数字,在这里也给大家分享一下。假设一个工程师一年工作小时(天),如果说他的效率是提升10%的话,每个月可以节省2天的时间,这是一个工程师。
但是如果我们是个或者是0个工程师,这个时候效率是多少,将是几百几千人天的效率提升,可以看到效率提升的价值和意义是非常大的。
进入到我们持续集成和发布,正常的一个持续集成,就是Java的发布过程来说,这个图中的流程是业界比较通用的过程。
首先开发同学开发完代码以后,我要提交到代码管理库,提交完以后我有一个打包的服务器,然后把二方包、三方包拖下来做编译,然后下面的过陈是发布到测试环境进行测试,测试完成还要发到预发和灰度的Bata环境。
灰度环境发布完没有什么问题就发到线上环境,这是整个持续集成的发布这过程。
蘑菇街也是按照这一过程去做的,所以这个地方后面我们就直接去看一个例子。
我们的发布都是以应有为维度去做的发布,这是进入发布系统我选择的应用,这里面它关联的Git库是哪一个,然后我们再来看一下配置信息,就是我们刚才提到的应用配置管理中的信息,这里简单提炼下发布的过程,朴素地讲,发布就是把软件包发布到哪个IP的主机上,然后主机上哪个指定的目录下,然后再通过哪个目录下的哪个脚本进行启停控制等的过程。
而上述的这些配置信息,已经存储在了我们前面所介绍到的CMDB和应用配置管理中,在发布系统中,我直接调用获取到响应的信息即可。
下面是发布的完整流程,通过基础的CMDB的应用-IP对应关系,以及应用配置管理的基础信息,完成全部自动化发布过程。
以上是我们从0到1做的两个关键的事情,一个是把基础打好,另外一个是解决了对效率影响最大的持续集成和发布。
从0到1阶段,我们还做了包括监控、自动化部署,包括资源的初始化和申请等等这些基础的东西,提升运维效率的事情。
这里挑了两个我们感觉做出来最有价值和意义的事情分享给大家,这是从0到1的阶段。
从0到1做完以后,效率问题基本得到解决,但是系统的稳定性这个矛盾马上就凸显出来了。我们经常遇到的问题是系统慢了,系统宕了,或者是突发流量非常大,会碰到这样那样各种诡异的问题。
三、运维技术管理分享这里分享一下稳定性建设这方面的内容,主要有这么几块,一个是全链路跟踪,还有一个是预案系统、开关系统、容量评估还有限流降级。
这里主要讲讲全链路跟踪系统。首先,我们为什么要做这个事情?
这整个的全链路的架构图,在前端的应用上面我们会做埋点日志,然后通过Kafka放到实时日志集群里面,这样我们可以快速看到实时的数据,然后对于历史的数据,放到Hadoop里存储。
这里面讲一下关键的技术点,其中最关键的就是TraceID,当一个请求到达接入层,会在接入层生成全局唯一的TraceID,由我们自研的Nginx的module实现。然后后续的后端接口或方法调用都会把这个ID带上,这样每一次调完会成都会输出一条日志,把本次请求花费多长时间,调用哪些接口记录下来,这样通过刚才实时的Storm集群就可以计算出整个的实时请求是怎样的。
这里面呼应一下前面所讲的我们为什么要做技术架构的标准化,刚提到这个TraceID是通过Nginx的module生成的,在ID透传的过程中,每一个请求都会从框架层面把这个ID自动带上,业务层面是不用考虑对这个ID单独做处理的,对于白癜风初期如何治疗北京治疗白癜风医院哪家比较好