【注意】微服务模式【进程间通信篇】

这是什么?

这篇文章是根据书籍《マイクロサービスパターン【実践的システムデザインのためのコード解説】》(impress top gear)的内容,引用了作者Chris Richardson先生的网站《A pattern language for microservices》,总结了关于进程通信章节的内容。

相同时间的远程过程调用模式 de

远程过程调用模式

模式:远程过程调用(Remote Procedure Invocation,RPI)
客户端使用诸如REST等同步的远程过程调用协议来启动服务。

    • 技術例

REST
gRPC
Apache Thrift

メリット

シンプルでやりやすい
“リクエスト/リプライ”が容易

デメリット

“リクエスト/リプライ”以外の”通知”、”Publish/subscribe”などができない
サービス側が生きていることが必須なため可用性が良くない

Issue

クライアントはサービスインスタンスの場所(IPアドレス)を見つけ出す必要がある

REST和gRPC的使用方法

由于被广泛提及于许多书籍和文章中,故省略不述。

断路器模式 lù qì

模式:断路器
当连续失败次数超过指定阈值时,RPI代理将立即拒绝调用,直到一定时间过去为止。

    • 方法

リクエストの連続的な失敗をカウントし、サーキットブレーカーをONにする。一定時間が経過するまで、サービスが直ちにエラーを返すようにする。一定時間時間が過ぎたらサーキットブレーカーをOFFにして、確認リクエストを通す。エラーならば再度ONにする。

服务发现

【服务发现的背景问题】

在微服务中,分布式服务实例的数量以及其位置(IP地址)会动态变化。

服务发现有两种主要的实现方法。

    • サービスとそのクライアントが直接サービスレジストリを操作する

 

    デプロイインフラストラクチャがサービスディスカバリを処理する

应用级服务发现的模式

模式:自注册
服务实例会将自身注册到服务注册表中。

模式:客户端服务发现
服务客户端会从服务注册表中获取可用的服务实例列表,并从中选择一个用于负载均衡算法。

image.png
    • メリット

3rdへの依存がない
Server-side Discoveryよりも少ない動的な構成とネットワークで実現できる

デメリット

サービスをシャットダウン、削除する度にサービスインスタンス側がレジストリへ通知をする必要がある
クライアントがサービスレジストリと密結合になる
クライアント側に各プログラミング言語(フレームワーク)ごとのサービスディスカバリロジックを実装する必要がある

平台提供的服务发现模式。

方案:第三方注册
第三方(如K8s等)会自动将服务实例注册到服务注册表中。

方案:服务器端服务发现
客户端向路由器发送请求,路由器进行服务发现。

image.png
    • メリット

プラットフォームのレジスターはヘルスチェックをすることだけで登録・解除の処理が可能
特定のプログラミング言語に依存しないでプラットフォームによって処理される

デメリット

そのプラットフォームを使ってデプロイされたサービスのディスカバリしかサポートできない
ルーターの設定を行わないといけない(構成要素がClient Side Discoveryより多い)

使用异步消息传递模式进行通信

模式:消息传递
客户端使用异步消息传递来调用服务。

关于消息通道

    • ポイントツーポイント (point-to-point)チャネルは、チャネルを読み取るコンシューマのなかのひとつだけにメッセージを届ける。ポイントツーポイントチャネルは、1対1のインタラクションスタイルで使われる。

 

    パブリッシュ/サブスクライブ(public/subscribe)チャネルは、接続しているすべてのコンシューマにメッセージを届ける。1対多のインタラクションスタイルで使われる。例えば、イベントメッセージは通常パブリッシュ/サブスクライブチャネルを介して送られる。

消息代理

经纪人基础的消息传递概述。

消息代理是所有消息都会通过的中介者。消息发送方无需了解消息接收方的网络位置,而且消息接收方只有在准备好处理时,代理才会将消息缓存起来。这些都是消息代理的重要优点。

在选择消息中间件时有很多选项。以下是一些受欢迎的开源消息中间件:

    • ActiveMQ

 

    • RabbitMQ

 

    Apache Kafka

还有一些云端消息服务,例如AWS Kinesis和AWS SQS。选择消息代理时,需要考虑各种因素,包括以下内容。

支持的编程语言 是否支持各种编程语言
支持的消息标准 是否支持AMQP和STOMP等标准,还是使用专有的标准
消息顺序 是否保持消息的顺序
交付保证 提供何种类型的交付保证
持久化 存储消息到磁盘,并保证在代理宕机后仍能存活
持续性 当消费者重新连接到消息代理时,能否接收到在断开连接期间发送的消息
可扩展性 能够扩展到什么程度
延迟 端到端的延迟有多少
支持竞争的消费者 是否支持竞争的消费者

使用消息中间件实现消息通道。

メッセージブローカーポイントツーポイントパブリッシュ/サブスクライブJSMキュートピックApache KafkaトピックトピックRabbitMQなどのAMQPベースのブローカー交換+キューファンアウト交換とコンシューマごとのキューAWS KinesisストリームストリームAWS SQSキュー-

经纪人消息的优缺点

    • メリット

疎結合
メッセージのバッファリング
柔軟性の高い通信: 1対1 & 1対多、同期&非同期 すべてのパターンをサポートする
明示的なIPC(プロセス間通信): 開発者に物理的なネットワークがあることを意識させる(vs RPC)

デメリット

パフォーマンスのボトルネックになる可能性
単一障害点になる危険性
運用の複雑度の上昇: メッセージングシステムは、インストール、設定、運用を必要とする新たなシステムコンポーネントである

竞合的接收器和消息的顺序

在确保顺序的服务中,需要一种机制来保证消息的顺序。像Apache Kafka和AWS Kinesis这样的新型消息中间件通过使用分片(partition)的通道来解决这个问题。

在下面的图示例中,每个Order事件消息都具有orderId作为其分片键。针对同一订单的事件(如创建、取消、完成等)将被发布到同一分片,并且将被同一消费者实例读取。因此,可以确保消息按正确的顺序进行处理。

image.png

处理重复的消息

處理重複訊息有兩個方法。

    • べき等なメッセージハンドラを作る

 

    メッセージを追跡し、重複するメッセージを捨てる

消息处理程序应当的要求

通过将消息处理程序设置为幂等(idempotent),在消息重发时可以确保消息顺序的一致性,因此无论执行多少次都是安全的。

然而,如果顺序不能保持,就需要进行以下消息追踪和重复消息丢弃的处理。

消息追踪和消息销毁

提供一个专用表格供消费者注册消息系统的消息ID,当消费者处理消息时,作为事务的一部分,他们将创建和更新业务实体,并将消息ID记录在数据库表格中。如果消息重复,插入操作将失败,消费者将丢弃该消息。

事务性消息传递

在许多情况下,如果服务需要将消息作为数据库更新事务的一部分发布,那么必须同时管理数据库更新和消息系统的发布这两个操作的事务机制。

可以使用数据库表作为消息队列的方法。

模式:事务性出箱(Transactional outbox)
通过将事件或消息保存到数据库的OUTBOX表作为数据库事务的一部分,来发布消息。

OUTBOX表作为临时消息队列,即发布后即被删除。消息中继组件会读取OUTBOX表,并发布到消息代理。

image.png
    • メリット

サービスは”高位”のドメインイベントをパブリッシュする
2Phase-Commit(2PC)無し

デメリット

開発者が送信の実装忘れを起こす可能性がある

使用事务日志追踪模式的事件发布方式。

模式:事务日志尾部追踪
通过尾部追踪事务日志,将数据库中的更改发布出来。

image.png
    • メリット

2Phase-Commit(2PC)無し
正確性の保証

デメリット

一般的になっているが定義的に比較的曖昧なやり方
データベースにスペシフィックな技術を要求する
二重送信に対する対応方法がトリッキー

このパターンが実際に使われている例

Debezium データベースへの変更をApache KafkaメッセージブローカーにパブリッシュするOSSプロジェクト

LinkedIn Databus Oracleトランザクションログをマイニングして変更点をイベントとしてパブリッシュするOSSプロジェクト。LinkedInは、Databusを使って様々な派生データストアをレコードシステムに同期させている。

DynamoDB streams DynamoDB streamsは、過去24時間のDynamoDBテーブルに加えられた変更(追加、更新、削除)の時系列順のシーケンスを格納している。アプリケーションは、DynamoDB streamsからこれらの変更を読み取り、たとえばイベントとしてパブリッシュすることができる。

UML笔记服务发现客户端
@startuml
服务实例 -> 服务注册表:自身注册

客户端 -> 服务注册表:查询服务列表请求
服务注册表 –> 客户端:返回服务列表

客户端 -> 服务实例:带有负载均衡的请求
@enduml

第三方服务发现
@startuml
平台注册器 -> 服务注册表:注册服务

客户端 -> 平台路由器:通过域名调用服务

平台路由器 -> 服务注册表:进行DNS查询
服务注册表 –> 平台路由器:返回结果

平台路由器 -> 服务实例:发送请求
@enduml

请参阅

    • マイクロサービスパターン【実践的システムデザインのためのコード解説】 (impress top gear)

 

    • https://microservices.io/patterns/

 

    https://www.slideshare.net/KaushalLahankarFRM/kafka-vs-kinesis
bannerAds