之前本座有讲过现代企业架构的三大趋势是API化、微服务化和容器化,在实践过程中,就被客户问到说修改一个API地址的工作量有多大,我回答他说,额,大概半年吧~
以一个中型体量的公司来讲,API调用有显性的(在跨服务调用的代码里),也有隐型的(写在公共库中被调用),前者的URL地址还好查,后者的变更就会涉及几百个依赖服务,其中一些已经几年没有更新过,为了重新构建和部署这些服务,需要其他的依赖项也做出更新。
为了眼前的开发速度,牺牲了未来变更的灵活性,上述故事显然不是一个好的微服务架构。相比之下,一个伟大的架构应该有助于扩展开发团队,带来更高的质量和更高的性能,并降低成本,同时能够很自然地为未来的特性提供支持。微服务架构是一种非常流行的现代系统实现方式,但它需要正确的设计方式;工程师应该努力不要把它设计成“意大利面”系统,而是寻求“分层”的方法。
对于微服务,小伙伴会有一些常见的误解,首先就是认为“微服务能够让开发团队选择更适合的编程语言和框架”,在开发团队里的各种语言团队百花齐放。但实际情况是,任何一家公司引入一个新的编程语言是非常昂贵的。我们来看谷歌,谷歌全球有二到三万的程序员,但总共只覆盖了8种编程语言,平均每个技术栈4000个程序员,这在国内可能光4000人的软件公司就有不止8种编程语言了。技术栈不在多而在专精。
第二个误解就是“代码生成工具不靠谱”。跟机器学习一样,特征算法和模型是数据科学团队定义的,如果一些业务规则,因果逻辑连从业人员都没想明白,那只是接收这些输入的工具有什么责任呢?要让工具理解程序员就需要定义一个100%值得信赖的生成规则,稍后本座会演示一个代码生成的可靠案例。
第三个误解是“事件日志一定是业务的真相”。不得不说本座之前也有这样的理解,认为要从根源上解决数据治理的问题就应该直接从应用日志中提取。但其实这样做是模糊了过程数据和结果数据的边界,例如应用中创建了一个新用户,这个用户的记录一定会在数据库中添加,没必要在日志中设计把所有字段都展示出来。
第四个误解是“每个开发人员所维护的服务不能超过三个”,这个认知可能来源于早期的Netflix,当时自动化和流程工具还没有像现在那么发达。现在像在阿里巴巴这样的企业,平均每个程序员维护的服务大概在5个左右,每周存量服务的维护时间大概在5%左右,其他时间他们都在开发新功能。
下图是国内某知名互联网快递公司的应用架构:底层是Lambda批流分治的数据平台,会向上层企业级事件总线提供业务洞察的数据模型,同时总线又向Lambda平台提供实时数据。各服务间技术上的松耦合也是通过异步的事件生成与消费来完成的。
在这家公司里面,所有对象都被定义为企业资源,例如一个用户的所有属性都以API键值对的形式记录下来,方便日后扩充修改。今年网安法颁布的时候,国家要求用户的姓名、邮件地址等信息属于个人信息,严厉禁止跨境传输。对此该公司只需在原来的姓名键值对和邮件地址键值对添加是否是个人数据的标记即可(下图紫色高亮部分),这远比修改数据库的表结构要简单多了。
然后我们需要定义对象的调用方式,对于用户来说或者通用的API调用来说,无非是获取(GET)和更新(POST),因此在这边更重要的是定义企业级的返回码(包括正常处理和报错)。
API的迭代可以是一个CI/CD的过程,在集成开发环境中,各功能分支的开发团队与Git中的对应分支做交互、集成、迭代,具体可参考本座之前写的持续集成与持续交付(一)。
站在用户角度,他们并不关注一个应用是企业哪个团队开发的,因此不同功能的开发团队应尽可能保持代码风格的统一,除了定期的代码评审会,代码工具也是很好的选择。一些重复的操作如在不同环境中创建对象完全可以用代码工具来自动生成。
上述Play Json的代码工具展示了自动生成测试环境和临时环境代码的过程,这应该只要几个小时,而不是数周或数月,并且内部开发的库应该与外部开源库一样使用相同的流程以保障用户体验的一致性。
开发团队应该首先为所有 API 和事件设计模式,并且应该优先使用事件而不是直接调用 API。开发团队应该在适当且有效的自动化上做一些投入,重点关注部署、代码生成和依赖管理等任务。还应该鼓励团队编写“简单却有效”的测试,因为这样可以提高质量、简化维护工作并实现持续交付。