微服务之间的协作方式
2018-12-20 本文已影响24人
名字想好没
原文地址: https://itweknow.cn/detail?id=57 , 欢迎大家访问。
前面几篇文章大概写了什么是微服务以及我们应该如何去划分微服务,那么本篇文章我们就来看下如果集成微服务,其实就是微服务之间如何沟通并且进行数据交换。
集成的几点原则
- 保证API的技术无关性
为什么要保证这一点呢,之前在《了解什么是微服务》一文中提到过微服务有一个优点我们称为技术异构性
。也就是我们可以在不同的服务中选择适合该服务具体业务的技术栈而不受其他服务的影响。那么如果我们的API和技术强关联性,也就意味着我们可能不能够随心所欲的去选择技术栈。 - 使服务易于消费者使用
这点就很好理解了,如果我们提供的服务消费者使用起来非常的困难或者复杂,那么消费者为啥不去自己单独实现一套呢而非要使用你的服务呢。 - 隐藏内部实现的细节
过多的内部实现细节暴露给消费方,将会极大的增加微服务之间的耦合度。
集成方式
-
共享数据库
首先说明一下,虽然这种方式的集成速度最快,但是非常不推荐使用共享数据库的方式来集成微服务,下面我们就一起来看下共享数据库会带来的问题。- 增加修改表结构的成本,因为几乎所有的服务都会和数据库打交道,哪怕是其中的一张表的修改也会牵扯到很多的服务。
- 数据库会限制我们的技术选型
- 数据的修改点可能会分布在各个服务,会导致数据库极难维护,也很难去定位bug。
-
同步与异步
这个主要说的是服务之间的协作方式。- 同步
客户端发起一个远程服务调用后,调用方会阻塞自己并等待整个操作的完成。通常情况下同步的方式是基于请求/响应机制的,客户端发起一个请求,然后等待服务端响应,我们最常用的两种调用方式就是RPC调用和REST调用。 - 异步
调用方不用等待操作完成就可以返回,甚至不需要关系操作是否执行成功。异步方式是基于事件的,客户端发布一个事件,其他的协作者收到事件后就知道该去做什么事情,无需客户端说明,可能不同的协作者收到同一个个事件后的执行的业务逻辑并不是一样的。一般来讲我们使用RabbitMQ等类似的消息中间件就可以实现异步调用。
- 同步
-
编排与协同
这里我们通过一个例子来说明编排与协同,我们有一个系统,当用户注册一个账号后我们会分别通过短信和邮件的方式通知用户注册成功,系统中存在三个服务分别是账号服务、短信服务、邮件服务。下面我们分别来看一下在这个业务场景下编排和协同分别是一个什么样的表现形式。- 编排:有一个总指挥的大脑去告驱动各个服务。在这个例子中账号服务就是一个大脑,当用户注册成功之后,账号服务会取调用短信服务和邮件服务给用户发送短信和邮件通知。
- 中心服务承担了太多职责。(缺)
- 这种架构风格容易产生少量的“上帝”服务,而与其打交道的服务则通常沦为营养不良的、基于CRUD的服务。(缺)
- 协同:告知各个服务的职责,服务通过监控事件或者消息订阅来触发对应的操作。在上述例子中,账号服务完成账号的注册之后可能只需要向消息中间件发送一条注册成功的消息,当订阅了这类消息的服务(邮件服务和短信服务)就可以执行已经定义好的业务逻辑了。
- 可以显著的解耦,只需要发布一个一个的事件即可。如果其他服务关系某个事件的话,只需要简单的订阅即可。(优)
- 完整的业务流程很难从代码中看出来,最好维护一份完整的文档。(缺)
- 需要做一些额外的工作来监控流程是否正常的执行。(缺)
-
可以降低耦合度,灵活性高。(优)
通过协同处理注册
- 编排:有一个总指挥的大脑去告驱动各个服务。在这个例子中账号服务就是一个大脑,当用户注册成功之后,账号服务会取调用短信服务和邮件服务给用户发送短信和邮件通知。
服务间的DRY和代码重用
- 在微服务内部不要违反DRY
- 但是在跨服务的情况下可以适当违反DRY,服务之间的大量共享代码可能会带来大量的耦合,这比重复代码带来的问题更大。
- 如果要开发客户端库,尽量保证SDK是由服务端API开发人员之外的人来开发。理由是,如果是同一团队开发SDK和服务端API的话很容易将服务端的逻辑泄露到SDK中,也就会降低内聚性。