英国数字银行Monzo两位资深工程师Matt Heath和Suhail Patel在伦敦一场研讨会上,分享了如何管理1600个后端微服务的经验。这间设立超过5年的英国银行,金融用户超过了4百万人,去年9月开始进军美国市场,目前也正在开发企业用的数字银行服务。Monzo所有金融服务都是通过手机App提供,也因此,他们一开始就决定建立分布式架构,而不是建立一套庞大的银行核心系统。最初采用Mesos来建立容器集群,在2016年时则全面换成了K8s,来打造了一个执行各种金融微服务的平台。Monzo是少数很早就开始建立K8s的企业,也将基础架构迁移到AWS平台,来减少运维人力。
Monzo使用了容易水平扩展的NoSQL数据库Cassandra,后端系统主要开发语言则是简洁的Go,他们的理由是,这个语言保证向下相容,所以遇到语言改版时,例如有次新版增加了垃圾搜集功能,原有代码不用修改,直接用新版Go重新编译后即可执行,就能使用新功能来提高记忆体管理效率。
这是一家喜欢自己开发工具的公司,若有需要连接第三方系统或支付平台时,Monzo都尽可能自制开发整合机制,来提高效率,避免采用第三方整合工具,而带进了许多额外不需要的代码,例如他们就开发了一个互动工具,来连接AWS环境和K8s环境,让开发者通过一个pull reques指令,就可以快速进行部署或恢复旧版部署。
在微服务设计上,Monzo将每一个微服务,都跑在一个Docker容器中。容器化微服务的代码,还分为两层,一层是所有微服务都必须内置的共用核心代码库层(Shared Core Library Layer),包括了RPC、Cassandra、锁定机制、Log记录机制、监控Matrics、Queuing等六大类代码库,另一层则是业务层,也就是这支微服务要放进入的代码。
Monzo拆分微服务颗粒度的原则是,进可能地拆解到越细小的程度,他们解释,拆解得越细,可以将变动风险降到最低,例如更新单一功能,能减少对其他微服务的影响。但是,微服务颗粒度越小,代价是会产生大量的微服务。Monzo统计,第一年不过数百个微服务,但到了2019年11月初达到了1,500个微服务,甚至去年12月更暴增到1,600个已上。这些微服务间互相的不重复呼叫超过了9,300个。
因为所有服务都在线上,Monzo希望尽可能落实零信任安全制度,因此,采取白名单方式来管控每一个微服务可呼叫的其他微服务名单。起初微服务数量不多时,这份白名单使用人工维护,但是数量达到数千,甚至近万个时,维护工作非常复杂,因此,Monzo决定开发自动化维护工具。
习惯自己开发工具的Monzo先挑了安全管控最严格的一支微服务service.ledger来测试,利用K8s的网络政策资源,在配置文件中建立一个呼叫白名单。这是一支负责跨帐户移动金钱的微服务。
接着,Monzo开发了一个微服务通讯剖析rpcmap,可以自动分析每一支Go语言程式,找出对service.ledger微服务的所有呼叫来源,来建立白名单。
有了名单之后,Monzo下一步是利用K8s的NetworkPolicy资源来执行过滤,在service.ledger所属的ledger服务配置文件中建立网络政策,只有加上可允许标签的网络流量来源才可以放行,并在ledger代码目录中,放入一份授权来源的白名单文件。一旦有其他开发团队想要取得呼叫权限时,就得更新这个白名单文件,并且重新创建ledger服务(因为代码内的档案有异动)后才能生效,ledger开发团队在构建阶段就可以审查这个新增的外部呼叫。
不过,测试后发现了几个问题,多了不少人工审查呼叫的负担,也会提高微服务回复旧版本的风险,再加上开发团队习惯手动编辑配置文件,每一个人都能修改呼叫白名单,而难以管控。后来Monzo决定导入开源的K8s网络安控项目Calico,在每一个微服务上建立一个微型防火墙功能,来管理存取。另外,Monzo也大力提高微服务管理的信息透明度,如自制微服务剖析工具,方便开发团队查询每次代码checkout后,微服务所用API的清单和状态信息,并且大量采用视觉化监测工具来追踪流量和用量。
除了工具面的管理机制,Monzo也制作了一份后端工程师101指南,要求开发团队第一次撰写后端程序就要开始遵循,内容从新服务建立,RPC处理程序导入、信息查询、如和通过Firehose发布和使用信息、如何撰写单元测试,到如何部署,都有详细的说明和规定,并提供了一个Slack频道来讨论这套后端应用规范的上手问题。Monzo要求,每一个开发成员都要遵守这个规范来开发后端的微服务。
Monzo解释,微服务的颗粒度越细,尽管有助提高弹性,但是需要搭配一致的程序架构和工具,通过标准化让工程师聚焦在业务问题,持续改善工具和功能,才能快速进行一系列的迭代修改,来打破大型金融应用的复杂性,又能降低风险。