传统企业微服务落地大法(3)-离微服务更近一步的第二阶段

2019-07-16 11:18:21 浏览数 (1)

如果你真出现了第一阶段描述那些问题,进入第二阶段才会水到渠成。

物流行业有一定规模自主研发团队的,10%能进入这个阶段,有些对外宣称自己是微服务架构的,实际情况基本处于这个阶段,甚至还没达到

第二阶段的三大特征:

组织服务化,架构SOA化,基础设施云化

3.1. 阶段二的组织形态

怎么解决上面的问题呢?

根据康威定理,组织方面就需要有一定的调整,整个公司还是分运维组和开发组。

由于痛点是从业务层面发生的,开始调整的应该是开发组。

应该建立独立的前端组,统一前端框架,界面一致,所有人掌握统一的前端开发能力,积累前端代码,在有新的需求的时候,能够快速的进行开发。

建立中间件组,或者架构师组,这部分人不用贴近业务开发,每天的任务就是研究如何使用这些中间件,如何调优,遇到问题如何Debug,形成知识积累。如果有统一的一帮人专注中间件,就可以根据自身的情况,选择有限几个中间件集中研究,限定业务组只使用这些中间件,可保证选型的一致性,如果中间件被这个组统一维护,也可以提供可靠的SLA给业务方。

将业务开发组分出一部分来,建立中台组,将可以复用的能力和代码,交由这几个组开发出服务来,给业务组使用,这样数据模型会统一,业务开发的时候,首先先看看有哪些现成的服务可以使用,不用全部从零开发,也会提高开发效率。

3.2. 阶段二的应用架构

要建立中台,变成服务为其他业务使用,就需要使用SOA架构,将可以复用的组件服务化,注册到服务的注册中心。

对于有钱的企业,可能会采购商用的ESB总线,也有使用Dubbo自己封装称为服务注册中心。

接下来就是要考虑,哪些应该拆出来? 最后考虑的是如何拆出来?

这两个题目的答案,不同的企业不同,其实分为两个阶段,第一个阶段是尝试阶段,也即整个公司对于服务化拆分没有任何经验,当然不敢拿核心业务上手,往往选取一个边角的业务,先拆拆看,这个时候拆本身是重要的,其实是为了拆而拆,拆的比较理想化,符合领域驱动设计的最好,如何拆呢?当然是弄一个两个月,核心员工大家闭门开发,进行拆分和组合,来积累经验。很多企业目前处于这个阶段。

但是其实这个阶段的拆法也只能用来积累经验,因为咱们最初要拆分,是为了快速响应业务请求,而这个边角的模块,往往不是最痛的核心业务。本来业务就边角,拆不拆收益不大,而且也没办法很好的做能力复用。复用当然都想复用核心能力。

所以其实最重要的是第二个阶段,业务真正的服务化的阶段。当然要拿业务需求最多的核心业务逻辑下手,才能起到快速响应业务请求,复用能力的作用。

例如考拉最初也是一个使用Oracle,对外只有一个online业务的单体应用,而真正的拆分,就是围绕核心的下单业务逻辑进行的。

那核心业务逻辑中,哪些应该拆出来呢?很多企业会问我们,其实企业自己的开发最清楚。

这个时候经常犯的错误是,先将核心业务逻辑从单体应用中拆分出来。例如将下单逻辑形成下单服务,从online服务中拆分出来。

当然不应该这样,例如两军打仗,当炊事班的烟熏着战士了,是将中军大营搬出去,还是讲炊事班搬出去呢?当然是炊事班了。

另外一点是,能够形成复用的组件,往往不是核心业务逻辑。这个很好理解,两个不同的业务,当然是核心业务逻辑不同(要不就成一种业务了),核心业务逻辑往往是组合逻辑,虽然复杂,但是往往不具备复用性,就算是下单,不同的电商也是不一样的,这家推出了什么什么豆,那家推出了什么什么券,另一家有个什么什么活动,都是核心业务逻辑的不同,会经常变。能够复用的,往往是用户中心,支付中心,仓储中心,库存中心等等核心业务的周边逻辑。

所以拆分,应该将这些核心业务的周边逻辑,从核心业务里面拆出来,最终Online就剩下下单的核心路径了,就可以改成下单服务了。当业务方突然有了需求推出一个抢购活动,就可以复用刚才的周边逻辑了。抢购就成了另一个应用的核心逻辑,其实核心逻辑是传真引线的,周边逻辑是保存数据,提供原子化接口的。

那哪些周边逻辑应该先拆出来呢?问自己的开发吧,那些战战兢兢,自己修改后生怕把核心逻辑搞挂了的组,是自己有动力从核心逻辑中拆分出来的,这个不需要技术总监和架构师去督促,他们有自己的原有动力,是一个很自然的过程。

这里的原有动力,一个是开发独立,一个是上线独立,就像考拉的online系统里面,仓库组就想自己独立出去,因为他们要对接各种各样的仓储系统,全球这么多的仓库,系统都很传统,接口不一样,没新对接一个,开发的时候,都担心把下单核心逻辑搞挂了,造成线上事故,其实仓储系统可以定义自己的重试和容灾机制,没有下单那么严重。物流组也想独立出去,因为对接的物流公司太多了,也要经常上线,也不想把下单搞挂。

您也可以梳理一下贵公司的业务逻辑,也会有自行愿意拆分的业务,形成中台服务。

当周边的逻辑拆分之后,一些核心的逻辑,互相怕影响,也可以拆分出去,例如下单和支付,支付对接多个支付方的时候,也不想影响下单,也可以独立出去。

然后我们再看,如何拆分的问题?

关于拆分的前提,时机,方法,规范等,参考文章微服务化之服务拆分与服务发现

首先要做的,就是原有工程代码的标准化,我们常称为“任何人接手任何一个模块都能看到熟悉的面孔”

例如打开一个java工程,应该有以下的package:

  • API接口包:所有的接口定义都在这里,对于内部的调用,也要实现接口,这样一旦要拆分出去,对于本地的接口调用,就可以变为远程的接口调用
  • 访问外部服务包:如果这个进程要访问其他进程,对于外部访问的封装都在这里,对于单元测试来讲,对于这部分的Mock,可以使得不用依赖第三方,就能进行功能测试。对于服务拆分,调用其他的服务,也是在这里。
  • 数据库DTO:如果要访问数据库,在这里定义原子的数据结构
  • 访问数据库包:访问数据库的逻辑全部在这个包里面
  • 服务与商务逻辑:这里实现主要的商业逻辑,拆分也是从这里拆分出来。
  • 外部服务:对外提供服务的逻辑在这里,对于接口的提供方,要实现在这里。

另外是测试文件夹,每个类都应该有单元测试,要审核单元测试覆盖率,模块内部应该通过Mock的方法实现集成测试。

接下来是配置文件夹,配置profile,配置分为几类:

  • 内部配置项(启动后不变,改变需要重启)
  • 集中配置项(配置中心,可动态下发)
  • 外部配置项(外部依赖,和环境相关)

当一个工程的结构非常标准化之后,接下来在原有服务中,先独立功能模块 ,规范输入输出,形成服务内部的分离。在分离出新的进程之前,先分离出新的jar,只要能够分离出新的jar,基本也就实现了松耦合。

接下来,应该新建工程,新启动一个进程,尽早的注册到注册中心,开始提供服务,这个时候,新的工程中的代码逻辑可以先没有,只是转调用原来的进程接口。

为什么要越早独立越好呢?哪怕还没实现逻辑先独立呢?因为服务拆分的过程是渐进的,伴随着新功能的开发,新需求的引入,这个时候,对于原来的接口,也会有新的需求进行修改,如果你想把业务逻辑独立出来,独立了一半,新需求来了,改旧的,改新的都不合适,新的还没独立提供服务,旧的如果改了,会造成从旧工程迁移到新工程,边迁移边改变,合并更加困难。如果尽早独立,所有的新需求都进入新的工程,所有调用方更新的时候,都改为调用新的进程,对于老进程的调用会越来越少,最终新进程将老进程全部代理。

接下来就可以将老工程中的逻辑逐渐迁移到新工程,由于代码迁移不能保证逻辑的完全正确,因而需要持续集成,灰度发布,微服务框架能够在新老接口之间切换。

最终当新工程稳定运行,并且在调用监控中,已经没有对于老工程的调用的时候,就可以将老工程下线了。

3.3. 阶段二的运维模式

经过业务层的的服务化,也对运维组造成了压力。

应用逐渐拆分,服务数量增多。

在服务拆分的最佳实践中,有一条就是,拆分过程需要进行持续集成,保证功能一致。

而持续集成的流程,往往需要频繁的部署测试环境。

随着服务的拆分,不同的业务开发组会接到不同的需求,并行开发功能增多,发布频繁,会造成测试环境,生产环境更加频繁的部署。

而频繁的部署,就需要频繁创建和删除虚拟机。

如果还是采用上面审批的模式,运维部就会成为瓶颈,要不就是影响开发进度,要不就是被各种部署累死。

这就需要进行运维模式的改变,也即基础设施层云化。

虚拟化到云化有什么不一样呢?

首先要有良好的租户管理,从运维集中管理到租户自助使用模式的转换。

也即人工创建,人工调度,人工配置的集中管理模式已经成为瓶颈,应该变为租户自助的管理,机器自动的调度,自动的配置。

其次,要实现基于Quota和QoS的资源控制。

也即对于租户创建的资源的控制,不用精细化到运维手动管理一切,只要给这个客户分配了租户,分配了Quota,设置了Qos,租户就可以在运维限定的范围内,自由随意的创建,使用,删除虚拟机,无需通知运维,这样迭代速度就会加快。

再次,要实现基于虚拟网络,VPC,SDN的网络规划。

原来的网络使用的都是物理网络,问题在于物理网络是所有部门共享的,没办法交给一个业务部门自由的配置和使用。因而要有VPC虚拟网络的概念,每个租户可以随意配置自己的子网,路由表,和外网的连接等,不同的租户的网段可以冲突,互不影响,租户可以根据自己的需要,随意的在界面上,用软件的方式做网络规划。

除了基础设施云化之外,运维部门还应该将应用的部署自动化。

因为如果云计算不管应用,一旦出现扩容,或者自动部署的需求,云平台创建出来的虚拟机还是空的,需要运维手动上去部署,根本忙不过来。因而云平台,也一定要管理应用。

云计算如何管理应用呢?我们将应用分成两种,一种称为通用的应用,一般指一些复杂性比较高,但大家都在用的,例如数据库。几乎所有的应用都会用数据库,但数据库软件是标准的,虽然安装和维护比较复杂,但无论谁安装都是一样。这样的应用可以变成标准的PaaS层的应用放在云平台的界面上。当用户需要一个数据库时,一点就出来了,用户就可以直接用了。

所以对于运维模式的第二个改变是,通用软件PaaS化。

前面说过了,在开发部门有中间件组负责这些通用的应用,运维也自动部署这些应用,两个组的界限是什么样的呢?

一般的实践方式是,云平台的PaaS负责创建的中间件的稳定,保证SLA,当出现问题的时候,会自动修复。

而开发部门的中间件组,主要研究如何正确的使用这些PaaS,配置什么样的参数,使用的正确姿势等等,这个和业务相关。

除了通用的应用,还有个性化的应用,应该通过脚本进行部署,例如工具Puppet, Chef, Ansible, SaltStack等。

这里有一个实践是,不建议使用裸机部署,因为这样部署非常的慢,推荐基于虚拟机镜像的自动部署。在云平台上,任何虚拟机的创建都是基于镜像的,我们可以在镜像里面,将要部署的环境大部分部署好,只需要做少量的定制化,这些由部署工具完成。

下图是OpenStack基于Heat的虚拟机编排,除了调用OpenStack API基于镜像创建虚拟机之外,还要调用SaltStack的master,将定制化的指令下发给虚拟机里面的agent。

基于虚拟机镜像和脚本下发,可以构建自动化部署平台NDP

这样可以基于虚拟机镜像,做完整的应用的部署和上线,称为编排。基于编排,就可以进行很好的持续集成,例如每天晚上,自动部署一套环境,进行回归测试,从而保证修改的正确性。

进行完第二阶段之后,整个状态如上图所示。

这里运维部门的职能有了一定的改变,除了最基本的资源创建,还要提供自助的操作平台,PaaS化的中间件,基于镜像和脚本的自动部署。

开发部门的职能也有了一定的改变,拆分称为前端组,业务开发组,中台组,中间件组,其中中间件组合运维部门的联系最紧密。

3.4. 阶段二有什么问题吗?

其实大部分的企业,到了这个阶段,已经可以解决大部分的问题了。

能够做到架构SOA化,基础设施云化的公司已经是传统行业在信息化领域的佼佼者了。

中台开发组基本能够解决中台的能力复用问题,持续集成也基本跑起来了,使得业务开发组的迭代速度明显加快。

集中的中间件组或者架构组,可以集中选型,维护,研究消息队列,缓存等中间件。

在这个阶段,由于业务的稳定性要求,很多公司还是会采用Oracle商用数据库,也没有什么问题。

实现到了阶段二,在同行业内,已经有一定的竞争优势了。

3.5. 什么情况下才会觉得阶段二有问题?

我们发现,当传统行业不再满足于在本行业的领先地位,希望能够对接到互联网业务的时候,上面的模式才出现新的痛点。

对接互联网所面临的最大的问题,就是巨大的用户量所带来的请求量和数据量,会是原来的N倍,能不能撑得住,大家都心里没底。

例如有的客户推出互联网理财秒杀抢购,原来的架构无法承载近百倍的瞬间流量。

有的客户对接了互联网支付,甚至对接了国内最大的外卖平台,而原来的ESB总线,就算扩容到最大规模(13个节点),也可能撑不住。

有的客户虽然已经用了Dubbo实现了服务化,但是没有熔断,限流,降级的服务治理策略,有可能一个请求慢,高峰期波及一大片,或者请求全部接进来,最后都撑不住而挂一片。

有的客户希望实现工业互连网平台,可是接入的数据量动辄PB级别,如果扛的住是一个很大的问题。

有的客户起初使用开源的缓存和消息队列,分布式数据库,但是读写频率到了一定的程度,就会出现各种奇奇怪怪的问题,不知道应该如何调优。

有的客户发现,一旦到了互联网大促级别,Oracle数据库是肯定扛不住的,需要从Oracle迁移到DDB分布式数据库,可是怎么个迁移法,如何平滑过渡,心里没底。

有的客户服务拆分之后,原来原子化的操作分成了两个服务调用,如何仍然保持原子化,要不全部成功,要不全部失败,需要分布式事务,虽然业内有大量的分布式方案,但是能够承载高并发支付的框架还没有。

当出现这些问题的时候,才应该考虑进入第三个阶段,微服务化

0 人点赞