2020-08-26
之间讲过使用微服务架构是为了降低系统的复杂性。其实不然,微服务不是降低复杂性,而是将复杂性转移了,系统将绝大部分复杂性都转移到微服务之间的通信。
微服务架构实现的好坏,其通信起着至关重要的作用。接下来我们将重点关注在微服务架构中进行通信的三种方式,每一种都有其自己的利弊和权衡。
选择服务如何相互通信时,最直接的方式往往是 HTTP
。事实上,我们可以提出一个案例,即所有通信渠道都来自这个渠道。但是除此之外,服务之间的 HTTP
调用是服务到服务通信的可行选择。例如,架构中有两个服务 ServiceA
和 ServiceB
,ServiceA
可以调用 ServiceB
来获取数据,反之亦然。
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import requests
# 调用 A 服务
def request_service_a(token):
url = 'http://0.0.0.0:5000/user/'
params = {'user_id': 1}
headers = {
'Content-Type': 'application/json',
'Authorization': 'token=%s' % token
}
response = requests.get(url=url, params=params, headers=headers)
data = response.json()
print(data)
if response.status_code == 200:
return True
else:
return False
request_service_a('5e8bca1c9aa34aed6d069be331')
两个服务之间进行同步的 HTTP
调用。这是一种可行的通信模式,但它确实在两种服务之间建立了耦合。
这种变化是微妙的。现在, ServiceB
不返回 saved
属性,而是返回一个 statusUrl
。这意味着此服务现在正在接收来自第一个服务的请求,并且立即返回一个 URL
。此 URL
可用来检查请求的进度。
将两种服务之间的通信从同步转换为异步,第一个服务不再停留等待第二个服务完成,然后再返回其工作。通过这种方法可以使服务彼此隔离,并且耦合松散。缺点是需要在第二个服务上创建额外的 HTTP
请求,它从外部进行轮询,直到请求完成。这也引入了客户端的复杂性,因为必须检查请求的进度。但是,异步通信允许服务直接保持松散耦合。
-
API
调用:微服务之间互相调用,最简单的通信方式。 -
RPC
:远程过程调用,由于我们架构是遵从REST
,不考虑RPC
调用。 -
Socket
:通过建立socket
实现HTTP
通信。 -
缓存表:通过
Redis
或者其他缓存服务,将数据缓存到内存中。 -
冗余表:将
ServiceA
的数据冗余到ServiceB
中,ServiceB
可以直接使用。 -
宽表:将所有用到的服务、表、字段等相关信息保存在一张大而全的数据表中,宽表并不遵循数据库的三范式。
另一种通信模式是基于消息的通信。
与 HTTP
通信不同,所涉及的服务不直接相互通信。相反,服务将消息推送到其他服务订阅的消息代理。这消除了许多与 HTTP
通信相关的复杂性。
它不需要服务知道该如何相互交流,它消除了直接相互调用的服务需求。相反,所有服务都知道消息代理,并且它们将消息推送到该代理。其他服务可以订阅代理中自己关心的消息。
当然,使用此模式的两个服务之间仍然存在一些耦合。例如,ServiceB
和 ServiceA
必须就消息结构的定义以及其中包含什么达成一致。
常见的消息队列方式:
-
QueueManager
:可以实现Python Queue
通过网络访问。 -
RedisQueue
:基于Reids
实现的消息队列。 -
Flask-RQ2
:基于Flask
实现的RedisQueue
。 -
RabbitMQ
:高级消息队列协议的开源消息代理系统。 -
Kafka
:高吞吐量的分布式发布订阅消息系统。
最后一种模式是事件驱动模式。这是另一种异步方法,它看起来完全消除了服务之间的耦合。
与消息传递模式不同,事件驱动方法不需要服务必须知道公共消息结构。服务之间的通信通过各个服务产生的事件进行。
此处仍然需要消息代理,因为各个服务会将其事件写入其中。但是与消息方法不同,消费服务不需要知道事件的细节,它们对事件的发生做出反应,而不是产生能会或可能不会传递的信息。
在形式上,这通常被称为**“仅事件驱动的通信”**。每个服务都同意以某种格式将事件推送到代理,这使得通信松散耦合。服务可以监听他们关心的事件,并且提供为响应它们而需要运行的逻辑。
此模式使服务的耦合松散,因为事件中不包含任何有效负载。此方法中的每个服务都会响应事件的发生并运行其业务逻辑。
这些是基于微服务的架构中所有可能的通信模式吗?当然不是。基于同步和异步模式进行通信的方式还有很多种。
但是这三个突出了支持同步与异步的优缺点。在选择时要考虑耦合因素,但也需要考虑开发和调试的具体情况与注意事项。