BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

正确设计微服务架构:Michael Bryzek在纽约QCon上的演讲

| 作者 Daniel Bryant 关注 700 他的粉丝 ,译者 无明 关注 1 他的粉丝 发布于 2018年7月1日. 估计阅读时间: 9 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

在2018年纽约QCon大会上,Michael Bryzek讨论了如何“以正确的方式”设计微服务架构。关键要点包括:应该先为所有API和事件设计模式,这样就可以自动生成样板代码代码;优先使用事件流订阅,而不是直接调用API;应该在自动化方面进行投入,例如自动化部署和依赖管理;工程团队必须专注于编写简单有效的测试,因为这样可以提高质量、简化维护任务并实现持续交付。

Flow.io的联合创始人、董事长兼首席技术官Bryzek(之前是Gilt的联合创始人)在演讲开始时分享了自己经历过的一个故事。当时他们要将一个系统内的URL从“foo.com/latest/bar.js”改为“foo.com/1.5.3/bar.js”,却收到反馈说“需要几周的时间”,而且团队中已经没有足够的资源可以完成这项任务。为什么如此简单的一个URL格式变更需要这么大的工作量?带着这个疑惑,他发现,URL是在一个库中实现的,这个变更涉及了几百个依赖服务,其中有一些已经几年没有更新过,为了重新构建和部署这些服务,需要其他的依赖项也做出更新。

这个故事很明显可以作为“不那么伟大的架构”的一个例子,为了眼前的开发速度,却换来了未来的瘫痪。相比之下,一个伟大的架构应该有助于扩展开发团队,带来更高的质量和更高的性能,并降低成本,同时能够很自然地为未来的特性提供支持。微服务架构是一种非常流行的现代系统实现方式,但它需要正确的设计方式;工程师应该努力不要把它设计成“意大利面”系统,而是寻求“分层”的方法。

接下来,Bryzek提出了一系列对微服务的常见误解。第一个误解是“微服务能够让团队选择符合他们任务的编程语言和框架”。而实际情况是,这可能需要付出很高的代价,为了在技术栈中支持额外的开发语言,团队规模和投入成了关键的输入。

如果我们将Google视为一家优秀的工程公司,他们拥有大约20,000-30,000名工程师,使用了至少8种编程语言。那么可以说,每4000名工程师采用了一种编程语言。

第二个误解是“代码生成是邪恶的”。而现实情况是,“定义100%受信任的模式”对于资源和事件来说非常重要,因为这个时候生成代码对于扩展开发和维护工作来说非常有用。第三个误解,“事件日志一定是事实来源”,而现实情况是,事件是接口的关键部分,但“将服务作为资源的记录系统是没有问题的”。最后一个误解是“每个开发人员维护的服务不应该超过三个”,在实际当中,这个数字可能是错误的。Bryzek表示,这是“自动化发挥作用”的地方,Flow.io的开发人员每人维护大约五个服务,每周用于维护的时间不到5%。

接下来,Bryzek介绍了Flow.io的架构。他们的架构使用了基于JSON的面向资源的API模式,可以对实体和相应属性进行定义,并带有适当的元数据。模式定义文件保存在Git DVCS中,并启用了持续集成。他们通过一系列测试保证整套API的一致性,并将这些测试作为高级的linter。这些测试的目标是让工程师相信“整套API是由一个人写出来的”。

工程团队使用了开源的apibuilder.io工具,并结合他们的测试来防止出现错误,并在API设计阶段验证可能发生的重大变更。apibuilder的CLI工具可用于生成和更新与资源API和路由相关的代码。API客户端的代码也可以自动生成,其中包括用于高保真和快速测试的模拟客户端。Bryzek表示,在Flow.io的架构中,记录系统是API规范,代码生成可以确保团队“遵循规范”。

接下来讨论了数据库架构。有人建议每个微服务应该要有自己的数据库,并且不允许其他服务直接连接到此数据库,其他服务应该使用服务接口来访问不属于自己的数据库,服务接口由API和事件流组成。Flow.io工程团队花了很大精力创建CLI “dev” 工具,用来管理所有的基础设施和常见的开发任务。创建数据库只需要一个命令就可以完成。所有的存储需求通过JSON模式来定义,虽然JSON模式与相关的API模式是相互独立的,但使用的是相同的工具链。数据库DDL操作和配置(例如创建表)是自动生成的,相关的应用程序服务客户端数据访问对象(DAO)代码也是如此。这样不仅标准化了对数据库的访问,而且确保了从一开始就有适当的索引。

后续的演示侧重于代码部署。创建相关的Git标签就会触发部署,而master分支上发生变更(例如拉取请求的合并)时就会自动创建这些标签,并且是“100%自动化,100%可靠”的。Bryzek演示了Flow.io的持续交付管理系统“delta”(代码可在GitHub上获得),并强调了这种做法的重要性。

持续交付是微服务架构的先决条件。

微服务基础设施的定义要尽量保持简单,并使用单个YAML文件来定义元数据,其中包含计算实例类型、端口和操作系统的版本。系统中所有服务都会开放标准的“健康检测”端点,让所有部署、可观察性和警报工具都能够检测它们的健康状况。

在接下来的演讲中,Bryzek讨论了事件和事件流的重要性。对于人们提出的要访问Flow.io API的请求,他回应说,“我们提供了一组出色的API,但还是尽量订阅我们的事件流吧”。事件接口的关键原则包括:为所有事件定义模式;生产者可以保证至少一次交付;消费者需要实现幂等性。在Flow.io的架构中,端到端的单个事件延迟约为500毫秒,基于PostgreSQL实现,每个服务每天最大规模约为10亿个事件。

生产者将所有的操作日志记录到相应的数据表中,记录插入、更新、删除等操作。在创建事件时,相应的日志记录被放入队列,等待发布。这是实时发生的,而且是异步的,每个日志记录对应一个事件。要在服务中重播事件,只需要把日志记录重新放入队列。消费者将新事件存储在本地数据库中,为了加快删除事件,数据库被分区。在事件到达时,记录进入队列,等待处理。事件通过微批次的方式进行处理,每次消费之间的间隔默认为250毫秒。出现任何故障都会在本地进行记录。有关这个方案的更多信息和代码示例,请参阅Gilt Technology的db-journalling代码库。有兴趣的读者也可以看看变更数据捕获(CDC)的概念,Debezium是这方面的一个非常好的例子。

演讲的最后一部分侧重于依赖管理和“如何保持最新状态”。保持最新状态的目标就是要定期并自动更新所有服务,以便使用最新版本的依赖项;这对于核心库能够及时用上安全补丁和错误修复程序来说至关重要。Bryzek回顾了开场时所讲的那个故事,他说,“这应该只要几个小时,而不是数周或数月”,并且内部开发的库应该与外部开源库一样使用相同的流程。Flow.io的工程团队每周都会将所有服务的依赖项升级到最新版本,他们使用“flowcommerce/dependency”工具(已开源)来跟踪依赖项。这个工具基于服务代码库开启自动升级,并创建相关的拉取请求。一旦构建通过,就会部署每个服务。

Bryzek总结说,工程师应该首先为所有API和事件设计模式,并且应该优先使用事件而不是直接调用API。工程师应该在适当且有效的自动化上做一些投入,重点关注部署、代码生成和依赖管理等任务。还应该鼓励团队编写“简单却有效”的测试,因为这样可以提高质量、简化维护工作并实现持续交付。

Michael Bryzek的演讲幻灯片可以在SlideShare上找到,演示视频以及QCon纽约的所有演讲将在未来几个月内在InfoQ.com上发布。

查看英文原文Designing Microservice Architectures the Right Way: Michael Bryzek's Lessons Learned at QCon NY

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT