本文转载自【刘超的通俗云计算】公众号,作者刘超,网易杭州研究院云计算架构师

上文:

以业务为核心的云原生体系建设(上)

以业务为核心的云原生体系建设(中)

5、云原生体系演进阶段三:探索互联网模式,优化产品体验

上一节的最后,我们讲了阶段二可能面临的问题,如果公司想探索互联网模式,就会遇到这些问题。

其实互联网模式并不是每家企业都需要经过的阶段,但是是很多传统企业头部公司乐意探索的方向,例如工业企业有工业互联网,零售行业有新零售,金融行业有互联网金融等。

互联网模式的特点

有一种误区认为互联网模式就是做一个网站,或者做一个APP,其实不是的。吴恩达在AI Conference的讲座中,提到了他对什么是互联网公司商场 + 网站 ≠ 互联网公司,也即如果你是一个传统的商场,仅仅是做了一个网站,那不叫互联网化。

             

真正标识一个互联网公司的,有以下几点:

A/B测试,让数据说话:当你有一个页面需要改进,你的网站设计成什么样,你的APP设计成什么样,是你们一层层的回报,然后让老大决策的么?大老板往往很危险,因为他不一定了解客户的偏好,而主观认为的偏好,在实际测试的时候,往往结果大相径庭,所以不要让老板拍板,而是让数据说话,通过在线测试两种方案的结果,得出最后的结论,虽然做不到迅猛提升,但是可以保证每一次的修改,都是正向的。

更短的周期:你的应用的迭代速度必须足够的快,而且迭代是基于数据的,根据数据的反馈,不断的小步快跑,这需要组织和流程有很强的适应能力。和传统公司几个月升一次级不同,互联网公司几乎每天都升级,当你打开各种APP的时候,你会发现界面动不动就改了。

工程师和PM做决策:如何才能快速上线呢?如果每次上线都要一百多人开大会,让老大做决定,那肯定快不了,应该让工程师和PM做决策,他们才是真正听得到炮火的人,你需要让他们独立负责一块内容,独立决策,独立上线,独立负责,所有的PM并行工作,才使得更新速度飞快。

所以互联网模式可不仅仅是一个网站和APP的事情,我们还是从企业架构的五个方面来依次阐述。

5.1、业务架构:架构微服务化,侧重服务治理能力

阶段二的服务化是按照业务领域进程拆分的,而互联网模式下,我们会遇到性能问题,因而需要进一步的拆分。

假设第一个阶段我们拆分出来了订单服务,订单服务是大促的时候,最容易出现性能瓶颈的,我们就以他为例子。

性能问题的常用解决方案有,数据库读写分离,数据库分库分表,使用缓存。就像下面图展示的一样,从单一的数据库,到数据库读写分离,缓存使用Memcached,到数据库使用分布式数据库,缓存使用Redis。每次基础设施改变,影响所有业务方,耦合严重,修改复杂。

 

             

 

             

 

             

 

为了解决这个问题,常用的方式是纵向分层拆分。

原子层generic:将数据库缓存操作封装在这一层,提供原子化接口

组合层compose:组合多次调用,实现复杂的业务逻辑,封装公共业务逻辑

controller层:实现特定场景的业务逻辑。

 

             

有的时候,当并发量再高的时候,还会进一步拆分。

例如上面的Order-compose服务中,有两部分逻辑,他们的高并发场景完全不同,一部分逻辑是订单生命周期的管理,也即核心交易逻辑,这部分主要是写入,而且是和交易相关的,是需要事务能力的。另一部分是订单关联状态查询,这部分主要是读取,关联的表比较多,但是不需要事务的能力。这两部分处理高并发的策略不同,应该拆分出来。其中Order-Center主要处理订单生命周期的管理,里面涉及状态机,分布式事务,分布式数据库分库分表等。而Order-Searcher主要用于关联查询,如果用分布式数据库,很难找到合适的分库ID,因而使用ElasticSearch,可以各种关联查询,但是不需要事务,只读性能高。

             

当服务拆分的粒度比较细了之后,就需要服务治理的能力。

第一:服务依赖的管理,就是一个服务到底调用了哪些,被哪些服务调用,如果依赖管理比较混乱,就会比较痛苦,比如说你要发布一个应用,你可能不知道这个应用被谁依赖了,有没有有一个特别关键的应用在依赖于我这个应用,会不会我升级了以后是否会引发关键业务的不稳定,是应该白天发布,还是凌晨发布,这个时候我们就特别需要希望有一个系统能够看到任何一个服务都被哪些服务依赖以及依赖于哪些服务。

第二:调用统计问题,对于调用记录有一个统计和告警,例如有没有接口突然调用失败率增高,有没有接口突然时延增长,都应该及早发现,而不能因为因为一次发布引入一个bug,导致时延变长但无人知晓,等到流量一来,直接就可能压挂了。再就是有没有接口再也没有人调用,这个接口是否可以下线,这在接口升级的时候,常常采取先添加接口,再下线接口的方式,就需要这样一个统计系统。

第三:服务之间要设定熔断,限流,降级策略,一旦调用阻塞应该快速失败,而不应该卡在那里,处于亚健康状态的服务要被及时熔断,不产生连锁反应。非核心业务要进行降级,不再调用,将资源留给核心业务。要在压测到的容量范围内对调用限流,宁可慢慢处理,也不用一下子都放进来,把整个系统冲垮。

第四:第九,调用链分析问题,一旦出现慢的时候,相对比较难以发现慢的点,尤其是当服务数目多,调用链长了之后。

5.2、技术架构:基础设施容器化,统一微服务框架和工具链

为了解决服务治理的问题,需要配备相应的工具链,也即技术架构的部分。

             

在这个阶段,要实现微服务框架与开源技术栈的统一。一开始微服务做的比较混乱,有用Spring Cloud,有用Dubbo的,需要一个统一的开源技术栈。另外,还要构建一个持续集成的平台,通过Agent和虚拟镜像部署软件包。

统一微服务框架之前,我们情况是这样的,一开始用服务注册服务发现,还是比较简单的。后来发现,我们还需要分流、需要降级、配置中心、认证鉴权、监控统计等,在业务代码之外加的越来越多,大家的代码写得到处都是,而且依赖于不同人的水平不一样,有的人写得好,有的人写得差,这就是一个当时遇到的问题。

       

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1

后来我们就把它抽象成为了一个Agent,这个Agent在程序启动的过程中,通过jar直接带起来,使得统一的服务框架组件在Agent里面实现,并且提供统一的界面进行配置,这样业务方可以只写业务代码,基本上就搞定了这件事。

             

拆分成的服务太多了,没办法一个个配置,需要统一的一个配置中心,将配置下发;

拆分成的服务太多了,没办法一个个看日志,需要统一的日志中心,将日志汇总;

拆分成的服务太多了,很难定位性能瓶颈,需要通过APM全链路应用监控,发现性能瓶颈,及时修改;

拆分成的服务太多了,不压测一下,谁也不知道到底能够抗住多大的量,因而需要全链路的压测系统。

服务数目的增多,对运维又造成了很大的压力,原来是基于虚拟机镜像来构建应用运行环境的,因为部署的应用越来越多,我们发现虚拟镜像的模板越来越多,会出现上千个无法复用的模板,好像每个小组织都有自己的一个东西,毕竟它还不是一个标准,所以接下来我们就拥抱了容器的标准。并且Auto Scaling原来是基于虚拟镜像的,现在使用Kubernetes来做。Kubernetes作为统一的对接资源的编排平台,无论是Vmware上,还是KVM机器上,还是物理机上,公有云上,上面都可以有Kubernetes统一平台。这个时候只需要对Kubernetes下发一个编排,就可以实现跨多个地方进行部署。

在基于虚拟机的运行环境和PaaS中间件之外,基于Kubernetes也可以有自己的容器镜像和运行环境,以及基于容器镜像PaaS中间件。

5.3、数据架构:个性化推荐与精准营销,业务融合数据,数据驱动创新

上一个阶段的数据架构,还是将企业的运营情况通过BI报表实时的反馈给领导层,但是仍然需要领导层根据报表,下决策来调整业务。没有和业务真正的结合。到阶段三,数据和业务要真正的融合,实现数据驱动业务创新了。

一种方式就是前面提到的A/B测试,通过他来优化产品体验。前面咱们讲过了埋点数据的收集,基于埋点数据,我们可以做用户的行为分析,如下图所示。可以做用户的事件分析,漏斗分析,留存分析,粘性分析。

 

             

对于每一个不确定的Release版本,可以通过A/B测试来决定用户到底喜欢哪个样式,例如下图的D版本在各个位置的点击率和非D版本的点击率的比较。                          

第二种方式就是建立标签体系,给用户打各种标签,从而根据标签进行推荐与精准营销。

通过标签建立用户画像,并根据用户画像进行推荐。

       第三种方式是提供接口给业务方调用,例如供应商系统需要对供应商进行评级,供应商评级需要供应商的商品销售数据、评论数据、退货数据、质量数据,供应商采购的交期数据等等。数据中台可以提供接口给供应商系统。

5.4、研发流程:DevOps流程,一切即代码,不可改变基础设施

微服务化之后,对于部署上线的流程也有很大的挑战,服务的数目就会非常的多,每个服务都会独立发布,独立上线,因而版本也非常多。

原来基于虚拟机镜像的部署也遇到了问题,是因为虚拟机镜像实在是太大了,动不动几百个G,如果一共一百个服务,每个服务每天一个版本,一天就是10000G,这个存储容量,谁也受不了。

这个时候,容器就有作用了。镜像是容器的根本性发明,是封装和运行的标准,其他什么namespace,cgroup,早就有了。

原来开发交付给运维的,是一个war包,一系列配置文件,一个部署文档,但是由于部署文档更新不及时,常常出现运维部署出来出错的情况。有了容器镜像,开发交付给运维的,是一个容器镜像,容器内部的运行环境,应该体现在Dockerfile文件中,这个文件是应该开发写的。

这个时候,从流程角度,将环境配置这件事情,往前推了,推到了开发这里,要求开发完毕之后,就需要考虑环境部署的问题,而不能当甩手掌柜。由于容器镜像是标准的,就不存在脚本无法标准化的问题,一旦单个容器运行不起来,肯定是Dockerfile的问题。

而运维组只要维护容器平台就可以,单个容器内的环境,交给开发来维护。这样做的好处就是,虽然进程多,配置变化多,更新频繁,但是对于某个模块的开发团队来讲,这个量是很小的,因为5-10个人专门维护这个模块的配置和更新,不容易出错。自己改的东西自己知道。

如果这些工作量全交给少数的运维团队,不但信息传递会使得环境配置不一致,部署量会大非常多。

容器作用之一就是环境交付提前,让每个开发仅仅多做5%的工作,就能够节约运维200%的工作,并且不容易出错。

容器的另外一个作用,就是不可改变基础设施。

容器镜像有个特点,就是ssh到里面做的任何修改,重启都不见了,恢复到镜像原来的样子,也就杜绝了原来我们部署环境,这改改,那修修最后部署成功的坏毛病。

因为如果机器数目比较少,还可以登录到每台机器上改改东西,一旦出了错误,比较好排查,但是微服务状态下,环境如此复杂,规模如此大,一旦有个节点,因为人为修改配置导致错误,非常难排查,所以应该贯彻不可改变基础设施,一旦部署了,就不要手动调整了,想调整从头走发布流程。

这里面还有一个概念叫做一切即代码,单个容器的运行环境Dockerfile是代码,容器之间的关系编排文件是代码,配置文件是代码,所有的都是代码,代码的好处就是谁改了什么,Git里面一清二楚,都可以track,有的配置错了,可以统一发现谁改的。

             

持续交付流水线,是以Master和线上对应的,自己分支开发的模式。按需自动化构建及部署,线上环境还是需要人工触发的,但基本上是通过流水线代码处理的方式来做的。

容器化带来的另外一个问题,服务规模越来越大,增加速度越来越快,需求指数性增加,大家都需要一个环境。比如一个集群一千个容器,如果三个小组各开发一个项目,想并行开发,每个人都需要一个环境,一下子需要三千个容器。这时候就需要中间件的灰度发布和流量染色的能力。

在最外层的网关上,可以做两个环境之间流量的分发,以及在微服务的Agent里面也可以做一个分发。最终,我们会有一个基准环境,就是Master对应的环境。

             

两个小组,一组开发了五个服务,另外一组开发了六个服务,他们部署的时候不需要一千个全部布一遍,只需要布五个,布六个。在请求调用的时候,从这五个里面互相调,不在这五个里面,在基准环境调,另外六个也是。这样就把三千个变成一千零十几个,环境大幅度减少。

这个时候环境的合并怎么办?环境合并和代码合并逻辑一致,统一在发布平台管理,谁后合并谁负责Merge。这是我们的一个效果,我们节省了非常多的机器。

有了流量染色以后,还可以得到单元化和多机房的染色。如果我们做高可用,至少需要两个机房,那么就存在一个问题,当一个机房完全挂了怎么办?微服务框架可以把它引流到另外一个机房。服务请求之后,还应该回来,因为应该本机房优先,毕竟本机房的容量大得多。所以我们建议整个部署模式,总分总的部署模式。

首先第一个总,要有统一的发布平台,无论发布到哪个Kubernetes,都应该通过一个平台。其次,你应该有一个多Kubernetes统一的管理,有多个机房,就有多个Kubernetes,我们并不建议跨机房。然后,我们建议应用层要有统一的视图,即使Kubernetes出现了问题,应用层可以把流量切到另外一个环境。就是这样一个总分总的模式。

另外Kubernetes也面临升级的问题,它更新比较快,经常升级。虽然业界有各种平滑的最佳实践,但是很难保证它升级的时候不出事。一旦Kubernetes出现状况,你也不想停里面的应用,可以采用分流的方式。

             

5.5、组织架构:研发和运维融合,应用交付提前到开发,应用治理下沉到运维

到了微服务阶段,实施容器化之后,你会发现,然而本来原来运维该做的事情开发做了,开发的老大愿意么?开发的老大会投诉运维的老大么?

这就不是技术问题了,其实这就是DevOps,DevOps不是不区分开发和运维,而是公司从组织到流程,能够打通,看如何合作,边界如何划分,对系统的稳定性更有好处。

其实开发和运维变成了一个融合的过程,开发会帮运维做一些事情,例如环境交付的提前,Dockerfile的书写。

运维也可以帮助研发做一些事情,例如微服务之间的注册发现,治理,配置等,不可能公司的每一个业务都单独的一套框架,可以下沉到运维组来变成统一的基础设施,提供统一的管理。

             

至此,整个云原生体系建设,才算基本完整了。

----------  END  ----------

 

作者简介:刘超,网易杭州研究院云计算技术部首席架构师,出版《Lucene应用开发解密》,极客时间专栏《趣谈网络协议》《趣谈Linux操作系统》,毕业于上海交通大学,曾经就职于EMC,CCTV证券资讯频道,HP,华为等,目前在网易从事容器,Kubernetes和微服务的架构工作。长期致力于云计算开源技术的分享,布道和落地,将网易内部最佳实践服务客户与行业。个人公众号《刘超的通俗云计算》发表OpenStack, Kubernetes, 微服务类技术文章107篇,其中《终于有人把云计算,大数据,人工智能讲明白了》累积10万+。
 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐