基于微服务的团队协作优化
相比于单体模式,各个服务相对比较独立,开发和运行能够自闭环,各团队间的耦合更低。同时微服务架构对基础设施的依赖会增强。主要体现在以下几个方面:
-
公共开发环境:单体架构开发时,一般会共享开发数据库、缓存、MQ等中间件,应用在本地运行。进行开发自测、联调时,只需要本地应用运行起来就可以。使用微服务架构后,本地运行所有的服务需要大量的资源,如果要协调其他服务进行更新联调,也比较复杂和繁琐。所以需要一个公共的开发环境用于自测和联调。结合公共开发环境进行开发时,以下几种模式:
- 将开发的服务更新到公共开发环境进行自测、联调。这样基础设施比较简单,但操作比较繁琐,且不方便Debug。
- 将开发环境中正在开发的服务连接,替换为本地运行的服务,需要工具支持服务替换配置。该模式无法支持多人同时替换同一个服务,适合Debug的场景。
- 支持分支灰度环境。可以将某个分支修改的所有服务部署一个新版本,请求标识中包含分支编码,所有请求都会走到该分支版本的服务上。该模式实现相对复杂,需要系统支持全链路的灰度。好处是不同的版本可以很好的进行隔离,如果有比较大的专项需要开发时,可能涉及多个团队而且周期长,使用分支灰度环境能够很好的隔离对其他分支的影响,也能很方便的进行联调。
-
服务级的“单元测试”支撑:在微服务架构下,很多时候实现的功能只能通过接口来验证,一方面使用方可能在下一个迭代才会用到,另一方面可能有多个BFF会调用服务,但每个BFF可能使用的接口场景有差异,协调多方进行完整的验证比较复杂且会带来团队强耦合。因此需要支持服务级的单元测试。在测试某个服务接口时,可能会涉及到依赖其他服务的情况,就需要对被依赖项进行打桩或模拟(类似单元测试,只是颗粒度比较大)。这时候就需要提供对应的测试工具来对服务进行Mork。同时需要提供自动执行用例及测试报告等一系列自动化测试相关的能力。
-
自助式的CI/CD:在团队解耦的背景下,团队自闭环高效运行的需求会非常突出,因此在CI/CD过程中,团队也希望能够自闭环。因此CI/CD相关的工具链需要支持绝大部分的配置需求。同时工具需要有更完善的质量基线、安全基线、变更流程管制,否则基础的质量、安全、架构底线等很容易被破坏。
举个栗子:安全要求只有运维能够接触生产环境资源密码(如数据库密码)。单体时期所有团队统一迭代,迭代发版日由运维对本次迭代的配置进行统一处理。到了微服务时期,各团队的发布节奏不一致,而且配置量大增,开发和运维沟通成本就很高,而且影响效率和节奏。这个时候要满足安全要求,同时需要保证效率,一个可行的方案是在配置中心中,将基础资源类的配置进行抽象,应用配置时使用资源变量。这样研发团队在开发阶段就可以申请好各个环境在什么时间前要什么资源,运维配置好资源后,将对应环境资源的配置到配置中心,开发团队就可以按自己的时间节奏部署不同的环境了。一方面开发不会接触到资源的密码,另一方面配置在不同环境迁移时不需要修改,可以进一步提高效率。
-
开发团队参与运维:在大规模的微服务场景中,运维再能无法像单体时代一样,通过观测服务基础信息就能发现和解决问题了。很多时候发现了基础信息的异常,运维也无法进行定位。因此需要开发团队参与进来,一起维护系统稳定。他们对自己维护的服务面临的场景,服务的性能,可能出现的异常情况最了解,但可能对基础设施的运行原理和配置不够清楚和深入。因此一方面需要开发团队有人员对基础中间件进行学习,另一方面需要提供运维工具简化配置,规避危险操作。
举个栗子:开发团队可以根据自己的业务特性,设置POD的资源范围、数量、自动伸缩的条件等。运维团队负责管理POD可设置范围的上下限,超限需要单独审批,对超出集群负载的申请进行限制。同时运维会监测服务资源利用率,对利用率不达标的服务要求开发团队进行调整。
在微服务模式下,团队对耦合会天然的抗拒,团队间的协作也变得需要更回的灵活。
- 发布周期解耦:团队保持相同的发布周期变得低效而没有必要(注意,有的实践可能还是会要求有相同的迭代周期,但在微服务时代,一个迭代很可能有多次发布)。这就需要针对微服务设计不同的分支模型和流水线,同时工具需要提供足够的自定义支持。
- 涉及多个团队的需求产品化协作:相比于单体时候更倾向于有关联的功能同时上线,在微服务时代则更倾向于独立上线。主要还是在微服务时候,团队更强的自闭环需要,另外得利于微服务自身的高质量保障要求。在前面我们提到过甲乙方的模式,甲方功能未完成时,乙方可以先上线,复杂的情况可以结合开关来处理。但在单体情况下,开发团队对于未被使用的接口的测试往往不够充分,所以在甲方上线集成时,经常还会发现新的问题。在微服务模式下,一个服务可以当成一个产品来看待,内部其他服务的需求和第三方的需求概念上是等同的,所以都需要进行完善的对外接口设计以及保持兼容,并且保证发布出去的接口质量是OK的。服务接口一经发布就能正常使用,而不太关心是谁来用(需要关注使用方的场景,以评估本服务可能的流量和性能需求等,但在功能逻辑上不会关心是谁来用)。