读书笔记-微服务架构中的进程间通信-02

2020-07-23  本文已影响0人  愤怒的老照

1 进程间通信

和单体应用不同的是,单体应用部署在同一台机器,属于同一个进程,各个模块之间通过函数互相调用;但是微服务架构中的服务实例通常是部署在多个机器上的,所以必须使用进程间通信。
有很多进程间通信技术可供参考。服务可以使用基于同步/异步的通信机制,同时服务通信的消息格式也是不相同的,服务可以使用具有可读性的格式(JSON/XML),也可以使用更高效的二进制格式。

1.1 交互方式

有多种客户端和服务的交互方式,可以分两个维度。
1、一对一和一对多

一对一:

一对多:
发布/订阅:客户端发出消息,发送给多个订阅者
发布/异步响应:客户端发布消息,并等待订阅者的响应。

1.2 API演化

API作为客户端和服务端的通信桥梁,不可避免的会随着功能的增加而发生变化。在单体应用中,变更API是相对简单并且不容易出错的事,因为更改之后编译器会对不兼容的调用提示编译错误;但是基于微服务的API更改起来就比较麻烦了,你并不能保证客户端和你的api保持一致,一般有两种处理方法

1.3 消息格式

如果使用了HTTP歇息,那么需要选择具体的消息格式(JSON/XML);有些进程间的通信机制已经指定了消息格式(gRPC/Thrift)。我们不应该使用类似Java序列化这类跟变成虚言强相关的消息格式,因为今后可能会扩展到其他的语言。

2 使用断路器保护系统

分布式系统中,当服务试图向另一个服务发送请求,随时都会面临着局部故障的风险,因为二者是独立的进程,如下图所示:


image.png

此时服务B和服务A将会无限期的阻塞,所以要通过合理的设计服务来防止整个应用程序的故障传导

3 服务发现机制

服务发现和服务注册是属于服务治理的概念(治理肯定是有问题了才需要的),你的客户端调用服务端,必须知道服务实例具体的ip地址和端口号,在单体应用中,这些都是固定的,但是在微服务中,因为一个服务可能通过X轴或者Z轴扩展为多个实例,并且服务实例的ip地址会变服务实例集群会动态更改因此微服务必须使用服务发现。

3.1 服务发现概念

其关键组件是服务注册表,它是包含服务实例网络位置信息的一个数据库。当服务实例启动或者停止时,服务发现机制会更新服务注册表。(采用服务发现需要给服务起一个为一个名字,以便于调用方可以调用)

3.2 应用层服务发现模式

3.2.1 概念

客户端会通过服务注册表,获取可用的服务列表,然后通过路由策略选择要调用的实例发送请求。这个过程包括两部分:

3.2.2 优点

可以处理多平台部署的问题

3.2.3 缺点

必须为每种编程语言提供API,并且必须由开发人员对服务发现进行开发。

3.3 平台层服务发现模式(服务治理平台)

3.3.1 概念

部署平台包括一个服务注册表,用于跟踪可用服务的IP地址,当由请求时,平台会根据指定的路由策略(同机房优先,同城市优先)在实例之间进行负载均衡,包括两部分:

3.3.2 优点

客户端和服务端不需要包含服务发现相关的代码

3.3.3 缺点

对平台有限制

4 基于异步消息模式的通信

4.1 两种类型的消息通道

4.2 无代理消息和有代理消息

image.png

如上图所示,无代理的架构中服务直接通信,有代理的架构中服务通过代理通信

4.2.1 无代理消息

服务可以直接通信,典型的是ZMQ,虽然操作起来很简单,但是客户端和服务端还是强耦合的方式,双方需要了解彼此的位置(也就是要使用服务发现机制),导致服务双方必须同时存在。

4.2.2 基于代理的消息

发送方将消息写入消息代理,消息代理将消息发送给接受方(发送方并不需要知道接收方的位置,并且可以使用消息队列进行削峰,例如Kafka,kafka使用topic和消费组的概念实现消息机制),可以理解发送方和接受方是松耦合,因为二者不需要知道彼此的位置,并且可以使用消息队列进行削峰;但是因为引入了消息代理,所以会引来消费队列造成的瓶颈问题。

4.2.3 kafka

4.2.3.1 名词解释
4.2.3.2 消费逻辑

当启动一个消费组去消费一个topic的时候,无论有多少个consumer,这个consumer group一定回去把这个topic下所有的partition都消费了。当consumer group里面的consumer数量小于这个topic下的partition数量的时候,如下图groupA,groupB,就会出现一个conusmer thread消费多个partition的情况,总之是这个topic下的partition都会被消费。如果consumer group里面的consumer数量等于这个topic下的partition数量的时候,如下图groupC,此时效率是最高的,每个partition都有一个consumer thread去消费。当consumer group里面的consumer数量大于这个topic下的partition数量的时候,如下图GroupD,就会有一个consumer thread空闲。因此,我们在设定consumer group的时候,只需要指明里面有几个consumer数量即可,无需指定对应的消费partition序号,consumer会自动进行rebalance。


image.png
4.2.3.3 消息有序

有序从两方面保证:kafka节点不仅要保存数据的时候有序,并且消费者消费也要有序。kafka是怎么保证单个分片有序的?

参考:https://www.zhihu.com/question/266390197/answer/772404605

上一篇下一篇

猜你喜欢

热点阅读