前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《微服务设计》第 4 章 集成

《微服务设计》第 4 章 集成

作者头像
yeedomliu
发布2019-09-28 12:59:26
5410
发布2019-09-28 12:59:26
举报
文章被收录于专栏:yeedomliuyeedomliu

  • 集成是微服务相关技术中最重要的一个。做得好的话,你的微服务可以保持自治性,你也可以独立地修改和发布它们;但做得不好的话会带来灾难

4.1 寻找理想的集成技术

4.1.1 避免破坏性修改

  • 如果一个微服务在一个响应中添加了一个字段,那么已有的消费方不应该受到影响

4.1.2 保证API的技术无关性

  • 保证微服务之间通信方式的技术无关性是非常重要的

4.1.3 使你的服务易于消费方使用

  • 消费方应该可以使用任何技术来实现,从另一方面来说,提供一个客户端库也可以简化消费方的使用
  • 让我们考虑一下,如何让消费方简便地使用美妙的新服务

4.1.4 隐藏内部实现细节

  • 所有倾向于暴露内部实现细节的技术都不应该被采用

4.2 为用户创建接口

  • 创建客户这个业务,乍一看似乎就是简单的 CRUD 操作,但对于大多数系统来说并不止这些。添加新客户可能会触发一个新的流程,比如进行付账设置、发送欢迎邮件等

4.3 共享数据库

  • 目前为止,我和同事在业界所见到的最常见的集成形式就是数据库集成。使用这种方式时,如果其他服务想要从一个服务获取信息,可以直接访问数据库

4.4 同步与异步

  • 这两种不同的通信模式有着各自的协作风格,即请求 / 响应或者基于事件
  • 哪些因素会影响对这两种风格的选择呢?一个重要的因素是这种风格能否很好地解决复杂问题,比如如何处理跨服务边界的流程,而且这种流程有可能会运行很长时间

4.5 编排与协同

  • 编排方式的缺点是,客户服务作为中心控制点承担了太多职责,它会成为网状结构的中心枢纽及很多逻辑的起点。我见过这个方法会导致少量的“上帝”服务,而与其打交道的那些服务通常都会沦为贫血的、基于 CRUD 的服务
  • 如果使用协同,可以仅仅从客户服务中使用异步的方式触发一个事件,该事件名可以叫作“客户创建”。电子邮件服务、邮政服务及积分账户可以简单地订阅这些事件并且做相应处理
  • 构建与业务流程相匹配的监控系统。实际的监控活动是针对每个服务的,但最终需要把监控的结果映射到业务流程中
  • 使用异步方式有利于协同方案的实施,从而大大减少服务间的耦合,这恰恰就是我们为了能独立发布服务而追求的特性
  • 针对请求 / 响应方式,可以考虑两种技术:RPC(Remote Procedure Call,远程过程调用)和 REST(REpresentational State Transfer,表述性状态转移)

4.6 远程过程调用

  • 远程过程调用允许你进行一个本地调用,但事实上结果是由某个远程服务器产生的。RPC 的种类繁多,其中一些依赖于接口定义(SOAP、Thrift、protocol buffers 等)

4.6.1 技术的耦合

  • 有一些 RPC 机制,如 Java RMI,与特定的平台紧密绑定,这对于服务端和客户端的技术选型造成了一定限制

4.6.2 本地调用和远程调用并不相同

  • RPC 的核心想法是隐藏远程调用的复杂性。但是很多 RPC 的实现隐藏得有些过头了,进而会造成一些问题

4.6.3 脆弱性

4.6.4 RPC很糟糕吗


4.7 REST

  • REST 是受 Web 启发而产生的一种架构风格。REST 风格包含了很多原则和限制,但是这里我们仅仅专注于,如何在微服务的世界里使用 REST 更好地解决集成问题。REST 是 RPC 的一种替代方案
  • 其中最重要的一点是资源的概念

4.7.1 REST和HTTP

  • HTTP 本身提供了很多功能,这些功能对于实现 REST 风格非常有用。比如说 HTTP 的动词(如 GET、POST 和 PUT)就能够很好地和资源一起使用

4.7.2 超媒体作为程序状态的引擎

  • REST 引入的用来避免客户端和服务端之间产生耦合的另一个原则是“HATEOAS”(Hypermedia As The Engine Of Application State,超媒体作为程序状态的引擎。天哪,它真的需要一个缩写吗?)。这个概念很长也很有趣,所以让我们详细看一下
  • 超媒体的概念是:有一块内容,该内容包含了指向其他内容的链接,而这些内容的格式可以不同(如文本、图像、声音等)。这个概念你应该很熟悉,因为你可以在任何一个网页上看到超媒体控制形式的链接,当你点击链接时可以看到相关的内容。HATEOAS 背后的想法是,客户端应该与服务端通过那些指向其他资源的链接进行交互,而这些交互有可能造成状态转移。它不需要知道 Customer 在服务端的 URI,相反客户端根据链接导航到它想要的东西

4.7.3 JSON、XML还是其他

  • 到目前为止我们看到的例子都是 XML 的,但事实上目前 JSON 更加流行

4.7.4 留心过多的约定

4.7.5 基于HTTP的REST的缺点

  • 有些 Web 框架无法很好地支持所有的 HTTP 动词。性能上也可能会遇到问题

4.8 实现基于事件的异步协作方式

4.8.1 技术选择

  • 微服务发布事件机制和消费者接收事件机制
  • 这种系统通常具有较好的可伸缩性和弹性,但这么做也是有代价的。它会增加开发流程的复杂度,因为你需要一个额外的系统(即消息代理)才能开发及测试服务。你也需要额外的机器和专业知识来保持这些基础设施的正常运行。但一旦做好了,它会是实现松耦合、事件驱动架构的一种非常有效的方法。通常来说我很喜欢这种方式
  • 尽量让中间件保持简单,而把业务逻辑放在自己的服务中

4.8.2 异步架构的复杂性

  • 灾难性故障转移(catastrophic failover)的一个典型例子(http://martinfowler.com/bliki/CatastrophicFailover.html)
  • 代码中的 bug 外,我们还忘了设置一个作业最大重试次数。我们也意识到需要有一种方式来查看甚至是重发这些有问题的消息。所以最后实现了一个消息医院(或者叫死信队列),所有失败的消息都会被发送到这里

4.9 服务即状态机


4.10 响应式扩展

  • 响应式扩展(Reactive extensions,Rx)提供了一种机制,在此之上,你可以把多个调用的结果组装起来并在此基础上执行操作。调用本身可以是阻塞或者非阻塞的

4.11 微服务世界中的DRY和代码重用的危险

  • 我的经验是:在微服务内部不要违反 DRY,但在跨服务的情况下可以适当违反 DRY。服务之间引入大量的耦合会比重复代码带来更糟糕的问题

4.12 按引用访问


4.13 版本管理

4.13.1 尽可能推迟

  • 减小破坏性修改影响的最好办法就是尽量不要做这样的修改
  • 另一个延迟破坏性修改的关键是鼓励客户端的正确行为,避免过早地将客户端和服务端紧密绑定起来
  • 客户端尽可能灵活地消费服务响应这一点符合 Postel 法则(也叫作鲁棒性原则,https://tools.ietf.org/html/rfc761)。该法则认为,系统中的每个模块都应该“宽进严出”,即对自己发送的东西要严格,对接收的东西则要宽容

4.13.2 及早发现破坏性修改

  • 强烈建议使用消费者驱动的契约来及早定位这些问题,第 7 章会对该技术做详细的讲解

4.13.3 使用语义化的版本管理

  • 语义化版本管理(http://semver.org/)就是一种能够支持这种方式的规格说明。语义化版本管理的每一个版本号都遵循这样的格式:MAJOR.MINOR.PATCH。其中 MAJOR 的改变意味着其中包含向后不兼容的修改;MINOR 的改变意味着有新功能的增加,但应该是向后兼容的;最后,PATCH 的改变代表对已有功能的缺陷修复

4.13.4 不同的接口共存

  • 我用过的一种比较成功的方法是,在同一个服务上使新接口和老接口同时存在
  • 这其实就是一个扩展 / 收缩模式的实例,它允许我们对破坏性修改进行平滑的过度。首先扩张服务的能力,对新老两种方式都进行支持。然后等到老的消费者都采用了新的方式,再通过收缩 API 去掉旧的功能

4.13.5 同时使用多个版本的服务

  • 另一种经常被提起的版本管理的方法是,同时运行不同版本的服务,然后把老用户路由到老版本的服务,而新用户可以看到新版本的服务,
  • 我个人不太喜欢这个想法,也理解为什么用 Netflix 的很少
  • 短期内同时使用两个版本的服务是合理的,尤其是当你做蓝绿部署或者金丝雀发布时

4.14 用户界面

4.14.1 走向数字化

4.14.2 约束

  • 尽管我们的核心服务可能是一样的,但仍需要应对不同应用场景的约束

4.14.3 API组合

  • 与服务之间过多的交互对移动设备来说会有些吃力,而且对使用流量套餐的用户来说也很不利!使用 API 入口(gateway)可以很好地缓解这一问题,在这种模式下多个底层的调用会被聚合成为一个调用,当然它也有一定的局限性,后面会做讨论

4.14.4 UI片段的组合

  • 相比 UI 主动访问所有的 API,然后再将状态同步到 UI 控件,另一种选择是让服务直接暴露出一部分 UI,然后只需要简单地把这些片段组合在一起就可以创建出整体 UI

4.14.5 为前端服务的后端

  • 对与后端交互比较频繁的界面及需要给不同设备提供不同内容的界面来说,一个常见的解决方案是,使用服务端的聚合接口或 API 入口。该入口可以对多个后端调用进行编排,并为不同的设备提供定制化的内容,
  • 我个人比较喜欢的模式是,保证一个这样的后端只为一个应用或者用户界面服务
  • 这种模式有时也叫作 BFF(Backends For Frontends,为前端服务的后端)

4.14.6 一种混合方式

  • 一个组织会选择基于片段组装的方式来构建网站,但对于移动应用来说,BFF 可能是更好的方式。关键是要保持底层服务能力的内聚性

4.15 与第三方软件集成

  • 不管怎样,即使你所在的组织拥有很强的定制化软件开发的能力,你还是需要外部组织提供的商业或者开源软件产品。为什么会这样呢?
    • 你的组织对软件的需求几乎不可能完全由内部满足
    • 也是最重要的一点是,这样做非常低效!
  • 我的客户经常纠结这样的问题:“应该自己做,还是买?”一般来讲,我和同事的建议是,对于一般规模的组织来说,如果某个软件非常特殊,并且它是你的战略性资产的话,那就自己构建;如果不是这么特别的话,那就购买

4.16 小结

  • 最大程度地保证微服务之间 的低耦合:
    • 无论如何避免数据库集成
    • 理解 REST 和 RPC 之间的取舍,但总是使用 REST 作为请求 / 响应模式的起点
    • 相比编排,优先选择协同
    • 避免破坏性修改、理解 Postel 法则、使用容错性读取器
    • 将用户界面视为一个组合层

  • 《REST 实战》
  • 《企业集成模式》
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 yeedomliu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 4.1 寻找理想的集成技术
    • 4.1.1 避免破坏性修改
      • 4.1.2 保证API的技术无关性
        • 4.1.3 使你的服务易于消费方使用
          • 4.1.4 隐藏内部实现细节
          • 4.2 为用户创建接口
          • 4.3 共享数据库
          • 4.4 同步与异步
          • 4.5 编排与协同
          • 4.6 远程过程调用
            • 4.6.1 技术的耦合
              • 4.6.2 本地调用和远程调用并不相同
                • 4.6.3 脆弱性
                  • 4.6.4 RPC很糟糕吗
                  • 4.7 REST
                    • 4.7.1 REST和HTTP
                      • 4.7.2 超媒体作为程序状态的引擎
                        • 4.7.3 JSON、XML还是其他
                          • 4.7.4 留心过多的约定
                            • 4.7.5 基于HTTP的REST的缺点
                            • 4.8 实现基于事件的异步协作方式
                              • 4.8.1 技术选择
                                • 4.8.2 异步架构的复杂性
                                • 4.9 服务即状态机
                                • 4.10 响应式扩展
                                • 4.11 微服务世界中的DRY和代码重用的危险
                                • 4.12 按引用访问
                                • 4.13 版本管理
                                  • 4.13.1 尽可能推迟
                                    • 4.13.2 及早发现破坏性修改
                                      • 4.13.3 使用语义化的版本管理
                                        • 4.13.4 不同的接口共存
                                          • 4.13.5 同时使用多个版本的服务
                                          • 4.14 用户界面
                                            • 4.14.1 走向数字化
                                              • 4.14.2 约束
                                                • 4.14.3 API组合
                                                  • 4.14.4 UI片段的组合
                                                    • 4.14.5 为前端服务的后端
                                                      • 4.14.6 一种混合方式
                                                      • 4.15 与第三方软件集成
                                                      • 4.16 小结
                                                      相关产品与服务
                                                      测试服务
                                                      测试服务 WeTest 包括标准兼容测试、专家兼容测试、手游安全测试、远程调试等多款产品,服务于海量腾讯精品游戏,涵盖兼容测试、压力测试、性能测试、安全测试、远程调试等多个方向,立体化安全防护体系,保卫您的信息安全。
                                                      领券
                                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档