集成是微服务相关技术中最重要的一个。做的好,可以保持微服务的自治性,做的不好会带来灾难。

1.理想的集成技术

1.1避免破坏性修改

如果在一个微服务的响应中添加一个字段,服务的消费方不应该受到影响。

1.2保证API的技术无关性

微服务之间的通信应该是与技术无关的。

1.3使服务的消费方易于使用

如果消费方使用该服务比登天还难,那么无论该微服务多漂亮都没用任何意义。但同时,易于使用的服务可能内部封装了很多细节,这会增加耦合。

1.4隐藏内部实现细节

消费方与服务方的内部细节应该是分开的,如果与细节绑定,则意味着改变服务内部的一些变化,消费方也要跟着修改,这会增加修改的成本。

2.数据库共享?

共享数据库是最快的集成方式,但这种方式应该避免。

如果共享了数据库,那么外部的服务则能查看内部的实现细节,并与其绑定在一起,存储在数据库中的数据结构对所有人来说都是平等的,数据库是一个很大的共享API,那么为了不影响其他服务,必须非常小心地避免修改与其他服务相关的表结构。这样的情况下,需要做大量的回归测试来保证功能的正确性。

其次,消费方与服务方的特定技术绑定在了一起,如果消费方要从关系型数据库换成非关系型数据库,那么这样是不容易实现的。这不符合低耦合的原则。

最后,那么原本由服务方提供的修改,现在可以由各个消费方直接操作数据库来完成,而且每个消费方可能都会有一套自己的修改方法。这不符合高内聚的原则。

3.同步与异步

如果使用同步方式进行通信,发起方发起一个远程调用后,发起方会阻塞自己并等待整个操作的完成。

异步通信对于运行时间较长的任务来说比较有用,异步的通信模型有两种。

一种是请求/响应方式,这与同步的不同,它是在发起一个请求时,同时注册一个回调,当服务端操作结束之后,会调用该回调。

一种是基于事件的方式,服务提供方不发起请求,而是发布一个事件,然后期待调用方接收消息,并知道该怎么做,服务提供方不需要知道该或者什么会对此做出响应,这也意味着,你可以在不影响服务提供方的情况下对该事件添加新的订阅。

4.编排与协同

假如你现在一家网站上注册账户,在注册账户系统做了下面三件事:

(1)在客户的积分账户上创建一条记录

(2)通过EMS系统发送一个欢迎礼包

(3)向客户发送欢迎电子邮件

当考虑实现时,编排是一种架构风格,它由一个中心大脑来指导并驱动整个流程。它可由客户管理这个服务来承担,在创建客户时会跟积分账户服务、电子邮件服务及EMS服务通过请求/响应的方式进行通信。客户管理服务可以对当前进行到了哪一步进行跟踪,它会检查积分账户是否创建成功、电子邮件是否发送出去、EMS包裹是否寄出。这种方式的缺点是:客户管理服务承担了太多职责,它会成为网关结构的中心和很多逻辑的起点。这样会导致少量的“上帝”服务,而与其打资产的那些服务通常会沦为贫血的CRUD服务。

另一种实现的风格则是协同,它仅仅告知各个系统各自的职责,具体的实现留给他们自己。就上例而言,客户管理服务创建一个事件,邮件服务、积分服务、EMS服务会订阅这些事件并做相应的处理,如果其他的服务也关心客户创建这件事情,它们只需要简单的订阅该事件即可。这种方式能显著地消除耦合,但这需要额外做一些监控工作,以保证其正确进行。我们可以建一个跟业务流程相匹配的监控服务,分别监控每个服务。

5.远程过程调用

rpc带来的问题,用dubbo举例:

  • 耦合问题

刚开始使用Dubbo大家都会很容易的接受Provider和Consumer的jar包方式进行服务的管理工作。而慢慢的逐渐深入使用会逐渐的体会到Dubbo的API JAR包变成了一种约束。这样就非常间接,不明显的将Provider和Consumer绑定在一起。如果其中一方出现问题,就会造成另外一方的一些问题。

  • 语言锁定

微服务的一个准则就是每个服务可以独立的演进,独立发展。可以通过不同的编程语言对服务进行编写。而Dubbo和类似的RPC实现方式使用Jar包的方式发布接口,那么就只能使用JVM上语言进行Jar的解析与加载工作。导致必须使用相同的语言进行rpc接口的调用。

  • 上下文传递

Http是一种无状态服务,那并不代表RPC必须是一种无状态服务。在Http协议通过不断的发展在协议中传递了一些有状态的上下文信息,这样可以为服务提供一些有状态的信息以便在业务处理过程中使用。而RPC是一种更加纯粹的无状态服务,它没有标准化的规范导致不可能形成完善的解决方案。在Dubbo中可以借助多种方式进行上下文的传递工作,不过实现起来比较复杂。其中包括:Dubbo 上下文信息,事件通知,协议扩展

  • 版本兼容问题

向下兼容问题对于每个软件来说都是一个非常棘手的问题。一方面我们需要让我们的软件持续的发展,另一方面需要兼容之前的代码。现在Dubbo上如果需要对接口进行新加或者变更的时候就会发现需要重新发布Dubbo API的Jar包。这样对于Provider和Consumer都是工作负担。使用版本号控制Dubbo API版本号时就得进行多服务实例启动。这个问题在Dubbo中没有很好的解决。兼容性
负载均衡就剩下一种方案:客户端负载均衡。
对于负载均衡来说Dubbo直接使用了客户端负载均衡的策略完成,直接摒弃了服务端负载均衡的可能行。这种情况下对于负载均衡的动态控制与动态管理工作就会形成问题。

  • 发布过程支撑问题

线上发布一般基于新旧并存平滑过度的方式进行灰度发布,而对于长链接的Dubbo。不能很好的支撑蓝绿发布,灰度发布方式。

  • 运维能力
  1. 故障隔离能力:

就现阶段技术而言,没有中很好的方式进行可以进行接口(http和rpc)的故障降级与隔离方式。导致服务中一个接口(http和rpc)发生故障后可能传播到整个服务甚至整个系统中。
2. 服务隔离能力:

对于整个系统来说部分业务在docker外,部分服务在docker内时就很难进行处理。一套体系最好在一个注册中心中进行服务组册与发现工作。做服务隔离就非常困难。多注册中心

  1. 指标监控能力:

指标监控对于线上业务服务来说是不可或缺的内容。但是对于Dubbo来说支持的比较弱。只有几个点完成这个,所以有些鸡肋的感觉。
4. 服务检测能力:

每个线上服务都需要不断的检测服务的状态,接口响应情况等。对于使用dubbo或heissian方法的检测几乎不太可能。

6.版本管理

6.1尽可能推迟

6.2及早发现破坏性修改

尽量对修改的影响进行全面的回归。

6.3使用语义话的版本管理

6.4不同的接口并存

当不得不这么做时,我们的生产环境可以同时存在接口的新老版本。

假如一个接口存在着V1、V2、V3三种版本,我们可以在所有对V1的请求转换给V2,然后V2转换给V3,这样是一种平滑的过度,首先扩张服务的能力,对新老两种都支持,然后等老的消费者都采用了新的方式,再通过收缩API去掉旧的功能。

我们也可以在URI中存放版本信息,但同时我们需要一套方法来对不同的请求进行路由。

6.5.同时使用多个版本的服务

短期内同时使用两个版本的服务是合理的,尤其是当你做蓝绿部署或者金丝雀发布时,在这些情况下,不同版本的服务可能只会存在几分钟或者几个小时,而且一般只会有两个版本。升级

7.用户界面

8.与第三方软件的集成