65

.NET Core微服务之基于MassTransit实现数据最终一致性(Part 1)

 6 years ago
source link: http://www.10tiao.com/html/391/201807/2654071021/4.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一、预备知识:数据一致性

  关于数据一致性的文章,园子里已经有很多了,如果你还不了解,那么可以通过以下的几篇文章去快速地了解了解,有个感性认识即可。

  (1)左正,《保证分布式系统数据一致性的6种方案》

  (2)成金之路,《分布式系统的数据一致性解决方案》

  (3)E_Star,《分布式环境下数据一致性的设计总结》

  必须要了解的点:ACID、CAP、BASE、强一致性、弱一致性、最终一致性

  

  CAP理论由加州大学伯克利分校的计算机教授Eric Brewer在2000年提出,其核心思想是任何基于网络的数据共享系统最多只能满足数据一致性(Consistency)、可用性(Availability)和网络分区容忍(Partition Tolerance)三个特性中的两个(由此我们知道在分布式系统中,同时满足CAP三个特性是不可能的),三个特性的定义如下:

C:数据一致性(Consistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性(Strong Consistency)(又叫原子性Atomic或线性一致性Linerizable Consistency)

A:服务可用性(Availability):所有读写请求在一定时间内得到响应,可终止、不会一直等待

P:分区容错性(Partition-Tolerance):在网络分区的情况下,被分隔的节点仍能正常对外服务  

  • 强一致性:当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。=> 在传统单体式应用中,大部分都是强一致性的应用,想想我们写过多少工作单元模式的Code?

  • 弱一致性:系统并不保证续进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。

  • 最终一致性:弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。

  为保证可用性,互联网分布式架构中经常将强一致性需求转换成最终一致性的需求,并通过系统执行幂等性的保证,保证数据的最终一致性

  在微服务架构中,各个微服务之间通常会使用事件驱动通信和发布订阅系统实现最终一致性。

  

  更多背景知识,还是得看上面列出的参考文章,这里不再赘述。

二、MassTransit极简介绍

  MassTransit 是一个自由、开源、轻量级的消息总线, 用于使用. NET 框架创建分布式应用程序。MassTransit 在现有消息传输上提供了一组广泛的功能, 从而使开发人员能够友好地使用基于消息的会话模式异步连接服务。基于消息的通信是实现面向服务的体系结构的可靠和可扩展的方式。

  官网地址:http://masstransit-project.com/,GitHub地址:https://github.com/MassTransit/MassTransit (目前:1590Star,719Fork)

  类似的国外开源组件还有NServiceBus,没有用过,据说MassTransit比NServiceBus更加轻量级,并且在开发之初就选用了RabbitMQ作为消息传输组件,当然MassTransit还支持Azure Service Bus。类似的国内开源组件则有园友savorboard(杨晓东)的CAP,这个我会在MassTransit学习结束后去使用使用,CAP在GitHub上已经有了超过1000个Star,是NCC的几个千星项目之一。另外,张善友大队长在他的NanoFabric项目中推荐我们使用Rebus和Ray,如下图所示:

  

  

  由于时间和精力,以及文档资料的可见性,我在我的POC和这个系列博文的准备中,只会使用到MassTransit和CAP这两个开源项目。

三、MassTransit Quick Start

  这里以MassTransit + RabbitMQ为例子,首先请确保安装了RabbitMQ,如果没有安装,可以阅读我的《基于EasyNetQ使用RabbitMQ消息队列》去把RabbitMQ先安装到你的电脑上。另外,RabbitMQ的背景知识也有一堆,有机会也还是要了解下Exchange,Channel、Queue等内容。

3.1 最简单的发送/接收实例

  (1)准备两个控制台程序,一个为Sender(发送者),一个为Receiver(接收者),并分别通过NuGet安装MassTransit以及MassTransit.RabbitMQ

NuGet>Install-Package MassTransit

NuGet>Install-Package MassTransit.RabbitMQ  

  (2)编写Sender

 这里首先连接到我的RabbitMQ服务,然后向指定的Queue发送消息(这里是一个Client类型的实例对象)。

  (3)编写Receiver

 对于Receiver,要做的事就只有两件:一是连接到RabbitMQ,二是告诉RabbitMQ我要接收哪个消息队列的什么类型的消息。下面是TestConsumerClient和TestConsumerAgent的定义:

(4)测试一下:

  

3.2 最简单的发布/订阅实例

  除了简单的发送/接收模式外,我们用的更多的是发布/订阅这种模式。

  (1)准备下图所示的类库和控制台项目,并对除Messages类库之外的其他项目安装MassTransit以及MassTransit.RabbitMQ。

  

  (2)Messages类库:准备需要传输的Message

(3)Publisher:接收我的消息吧骚年们

 这里向RabbitMQ发布了两个不同类型的消息(TestBaseMessage和TestCustomMessage)

  (4)SubscriberA:我只接收TestBaseMessage类型的消息,其他的我不要

 这里ConsumerA的定义如下:可以看出,它实现了一个泛型接口IConsumer,然后指定了TestBaseMessage为消费的消息类型。

 (5)SubscriberA:我只接收TestCustomMessage类型的消息,其他的我不要

这里的ConsumerA的定义如下;它实现的接口是IConsumer<TestCustomMessage>

(6)测试一下:由于Publisher发送了两个不同类型的消息,两个Subscriber均只接受其中的一个类型的消息。

  

3.3 带返回状态消息的示例

  之前的例子都是发布之后,不管订阅者有没有收到以及收到后有没有处理成功(即有没有返回消息,类似于HTTP请求和响应),在MassTransit中提供了这样的一种模式,并且还可以结合GreenPipes的一些扩展方法实现重试、限流以及熔断机制。这一部分详见官方文档:http://masstransit-project.com/MassTransit/usage/request-response.html

  (1)准备下图所示的三个项目:通过NuGet安装MassTransit以及MassTransit.RabbitMQ

  

  (2)Messages:准备请求和响应的消息传输类型

(3)Sender 请求发送端

  这里不再解释,请看注释。

  (4)Receiver 接收端

 其中,RequestConsumer的定义如下:

(5)测试一下:

  

  可以看出,请求调用方收到了来自接收方返回的状态消息,我们可以借助返回值去check一些状态。这里不再演示发生异常从而启用重试、熔断等的示例,有兴趣的园友可以自行测试。

3.4 Observer模式的发布/订阅示例

   在某些场景中,我们需要针对一个消息进行类似于AoP(面向切面编程)或者监控的操作,比如在发送消息之前和结束后记日志等操作,我们可以借助MassTransit中的Observer模式来实现。(在MassTransit的消息接收中,可以通过两种模式来实现:一种是基于实现IConsumer接口,另一种就是基于实现IObserver接口)关于这一部分,详见官方文档:http://masstransit-project.com/MassTransit/usage/observers.html

  (1)准备以下图所示的项目:

  

  (2)Messages:定义要使用的Consumer和Observer

  Consumer:

Observer:

(3)ObserverPublish

可以看到,这里我们使用了两个用于发送消息的Observer:SendObserver和PublishObserver

  (3)ObserverReceive

(4)测试一下:

  

  由此看出,我们可以借助Observer这种方式来截取到消息的一个lifecycle,用以进行不同阶段的业务逻辑操作。

四、小结

  本篇极简的介绍了一下数据一致性和MassTransit这个开源的组件,通过几个例子介绍了在.NET环境下如何使用MassTransit操作RabbitMQ实现消息的接收/发送以及发布/订阅。后续我会继续使用MassTransit结合Quartz.Net和Polly在ASP.NET Core环境下实现一个简单的基于补偿机制的数据一致性的小案例,希望到时也可以和各位园友分享。

示例代码

  Click Here => 点我下载

参考资料

(1)桂素伟,《基于.NET Core的微服务》

(2)richieyangs(张阳),《如何优雅的使用RabbitMQ》,《使用Masstransit开发基于消息传递的分布式应用》

(3)青客宝团队,《MassTransit&Sagas分布式服务开发ppt分享》

(4)成天,《MassTransit实现应用程序间的交互》

(5)娃娃都会打酱油了,《MassTransit学习记录》

(6)MassTransit 官方文档,http://masstransit-project.com/MassTransit/

原文地址

https://www.cnblogs.com/edisonchou/p/dnc_microservice_masstransit_foundation_part1.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK