demo如下,一个订单处理的小例子:

首先看看结果很简单:

核心代码如下:

  1. using MassTransit;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using Microsoft.Extensions.Logging;
  4. using OrderProcessor.Event;
  5. using ServiceModel;
  6. using ServiceModel.Command;
  7. using ServiceModel.DTO;
  8. using ServiceModel.Event;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14.  
  15. namespace OrderProcessor.Service
  16. {
  17. public class OrderProcessorStateMachine:MassTransitStateMachine<ProcessingOrderState>
  18. {
  19. private readonly ILogger<OrderProcessorStateMachine> logger;
  20.  
  21. public OrderProcessorStateMachine()
  22. {
  23. this.logger = GlobalServiceProvider.Instance.CreateScope().ServiceProvider.GetService<ILogger<OrderProcessorStateMachine>>();
  24. this.InstanceState(x => x.State);
  25. this.State(() => this.Processing);
  26. this.ConfigureCorrelationIds();
  27. this.Initially(this.SetOrderSummitedHandler());
  28. this.During(Processing, this.SetStockReservedHandler(), SetPaymentProcessedHandler(), SetOrderShippedHandler());
  29. SetCompletedWhenFinalized();
  30. }
  31.  
  32. private void ConfigureCorrelationIds()
  33. {
  34. this.Event(() => this.OrderSubmitted, x => x.CorrelateById(c => c.Message.CorrelationId).SelectId(c => c.Message.CorrelationId));
  35. this.Event(() => this.StockReserved, x => x.CorrelateById(c => c.Message.CorrelationId));
  36. this.Event(() => this.PaymentProcessed, x => x.CorrelateById(c => c.Message.CorrelationId));
  37. this.Event(() => this.OrderShipped, x => x.CorrelateById(c => c.Message.CorrelationId));
  38. }
  39.  
  40. private EventActivityBinder<ProcessingOrderState, IOrderSubmitted> SetOrderSummitedHandler() =>
  41. When(OrderSubmitted).Then(c => this.UpdateSagaState(c.Instance, c.Data.Order))
  42. .Then(c => this.logger.LogInformation($"Order submitted to {c.Data.CorrelationId} received"))
  43. .ThenAsync(c => this.SendCommand<IReserveStock>("rabbitWarehouseQueue", c))
  44. .TransitionTo(Processing);
  45.  
  46. private EventActivityBinder<ProcessingOrderState, IStockReserved> SetStockReservedHandler() =>
  47. When(StockReserved).Then(c => this.UpdateSagaState(c.Instance, c.Data.Order))
  48. .Then(c => this.logger.LogInformation($"Stock reserved to {c.Data.CorrelationId} received"))
  49. .ThenAsync(c => this.SendCommand<IProcessPayment>("rabbitCashierQueue", c));
  50.  
  51. private EventActivityBinder<ProcessingOrderState, IPaymentProcessed> SetPaymentProcessedHandler() =>
  52. When(PaymentProcessed).Then(c => this.UpdateSagaState(c.Instance, c.Data.Order))
  53. .Then(c => this.logger.LogInformation($"Payment processed to {c.Data.CorrelationId} received"))
  54. .ThenAsync(c => this.SendCommand<IShipOrder>("rabbitDispatcherQueue", c));
  55.  
  56. private EventActivityBinder<ProcessingOrderState, IOrderShipped> SetOrderShippedHandler() =>
  57. When(OrderShipped).Then(c =>
  58. {
  59. this.UpdateSagaState(c.Instance, c.Data.Order);
  60. c.Instance.Order.Status = Status.Processed;
  61. })
  62. .Publish(c => new OrderProcessed(c.Data.CorrelationId, c.Data.Order))
  63. .Finalize();
  64.  
  65. private void UpdateSagaState(ProcessingOrderState state, Order order)
  66. {
  67. var currentDate = DateTime.Now;
  68. state.Created = currentDate;
  69. state.Updated = currentDate;
  70. state.Order = order;
  71. }
  72.  
  73. private async Task SendCommand<TCommand>(string endpointKey, BehaviorContext<ProcessingOrderState, IMessage> context)
  74. where TCommand : class, IMessage
  75. {
  76. var sendEndpoint = await context.GetSendEndpoint(new Uri(""));
  77. await sendEndpoint.Send<TCommand>(new
  78. {
  79. CorrelationId = context.Data.CorrelationId,
  80. Order = context.Data.Order
  81. });
  82. }
  83. public State Processing { get; private set; }
  84. public Event<IOrderSubmitted> OrderSubmitted { get; private set; }
  85. public Event<IOrderShipped> OrderShipped { get; set; }
  86. public Event<IPaymentProcessed> PaymentProcessed { get; private set; }
  87. public Event<IStockReserved> StockReserved { get; private set; }
  88.  
  89. }
  90. }
  1. using MassTransit;
  2. using MassTransit.MongoDbIntegration.Saga;
  3. using OrderProcessor;
  4. using OrderProcessor.Service;
  5.  
  6. var builder = WebApplication.CreateBuilder(args);
  7.  
  8. // Add services to the container.
  9.  
  10. builder.Services.AddControllers();
  11.  
  12. builder.Services.AddMassTransit(x =>
  13. {
  14. x.UsingRabbitMq((context, cfg) =>
  15. {
  16. var connection = "amqp://lx:admin@ip:5672/my_vhost";//不加主机会报错
  17. cfg.Host(connection);
  18. cfg.UseDelayedRedelivery(r => r.Intervals(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(30)));
  19. cfg.UseMessageRetry(r => r.Immediate(5));
  20.  
  21. cfg.ConfigureEndpoints(context);
  22. cfg.ReceiveEndpoint("", ep =>
  23. {
  24. ep.StateMachineSaga(new OrderProcessorStateMachine(), MongoDbSagaRepository<ProcessingOrderState>.Create("connecturl","db"));
  25. });
  26.  
  27. });
  28. });
  29.  
  30. var app = builder.Build();
  31.  
  32. app.Run();

这是整个订单的几个步骤。

想把代码都贴出来,过程梳理给大家参考,但是时间有限这个点没那么多了,而且我理应要把这个程序跑起来的。明天照常上班,暂不过多研究。

整个demo代码:

exercise/MassTransitDemo/MassTransitSagasDemo at master · liuzhixin405/exercise (github.com)

有兴趣可以还有一个demo:

exercise/MassTransitDemo/SagaTest-master at master · liuzhixin405/exercise (github.com)

masstransit官网:

MassTransit (masstransit-project.com)

不得不说这个东西真的很不错,不过暂时没找到翻译,大概的过了下文档,还有好多不清楚的,英文水平有限。demo都是来自外国大佬贡献的,很遗憾国内有这方面的文章,但是深入一点的都是国外友人的贡献,而且现成的微服务demo写的很好很多,视情况项目可借鉴。

NetCore微服务实现事务一致性masstransit之saga使用的更多相关文章

  1. NetCore微服务实战体系:日志管理

    一. 起始 进入NetCore时代,日志的使用有了很大的变化,因为跨平台以及虚拟化技术的使用,日志不能够再像Framework的方式直接记录在文本,文本其实也可以,但是日志的管理以及查看都不太方便.L ...

  2. SpringCloud微服务实现生产者消费者+ribbon负载均衡

    一.生产者springcloud_eureka_provider (1)目录展示 (2)导入依赖 <dependency> <groupId>org.springframewo ...

  3. SpringCloud微服务实现生产者消费者以及ribbon负载均衡

    一.SpringCloud_eureka_server 1.导入依赖 <dependencies> <dependency> <groupId>junit</ ...

  4. Spring Cloud 微服务实战笔记

    Spring Cloud 微服务实战笔记 微服务知识 传统开发所有业务逻辑都在一个应用中, 开发,测试,部署随着需求增加会不断为单个项目增加不同业务模块:前端展现也不局限于html视图模板的形式,后端 ...

  5. .Net微服务实战之必须得面对的分布式问题

    系列文章 .Net微服务实战之技术选型篇 .Net微服务实战之技术架构分层篇 .Net微服务实战之DevOps篇 .Net微服务实战之负载均衡(上) .Net微服务实战之CI/CD .Net微服务实战 ...

  6. go-zero微服务实战系列(十一、大结局)

    本篇是整个系列的最后一篇了,本来打算在系列的最后一两篇写一下关于k8s部署相关的内容,在构思的过程中觉得自己对k8s知识的掌握还很不足,在自己没有理解掌握的前提下我觉得也很难写出自己满意的文章,大家看 ...

  7. Spring Cloud微服务实战阅读笔记(一) 基础知识

    本文系<Spring Cloud微服务实战>作者:翟永超,一书的阅读笔记. 一:基础知识   1:什么是微服务架构     是一种架构设计风格,主旨是将一个原本独立的系统拆分成多个小型服务 ...

  8. 微服务实战(四):服务发现的可行方案以及实践案例 - DockOne.io

    原文:微服务实战(四):服务发现的可行方案以及实践案例 - DockOne.io 这是关于使用微服务架构创建应用系列的第四篇文章.第一篇介绍了微服务架构的模式,讨论了使用微服务架构的优缺点.第二和第三 ...

  9. 微服务实战(一):微服务架构的优势与不足 - DockOne.io

    原文:微服务实战(一):微服务架构的优势与不足 - DockOne.io [编者的话]本文来自Nginx官方博客,是微服务系列文章的第一篇,主要探讨了传统的单体式应用的不足,以及微服务架构的优势与挑战 ...

随机推荐

  1. C# 开始支持动态化编程

    在.NET 4.0的运行时进行动态编程时,我们引入了一个新功能:动态语言运行时.可以这样理解,CLR的目的是为静态类型的编程语言提供一个统一的框架或编程模型,而DLR便是在.NET平台上为动态语言提供 ...

  2. docker-docke安装和镜像仓库安装和管理

    1.安装docker # yum install -y yum-utils device-mapper-persistent-data lvm2 # yum-config-manager \ --ad ...

  3. MySQL第四讲

    昨日内容回顾 表与表之间建关系(外键) """ 表与表之间最多只有四种关系 一对多 多对多 一对一 没有关系 在确定表与表之间的关系的时候记住一句话 换位思考 " ...

  4. Python 细聊可以媲美 PS 的 PIL 图片处理库

    1 . 前言 PIL 是 Python Image Library 的简称. PIL 库中提供了诸多用来处理图片的模块,可以对图片做类似于 PS(Photoshop) 的编辑.比如:改变图像大小.旋转 ...

  5. Vue3中setup语法糖学习

    目录 1,前言 2,基本语法 2,响应式 3,组件使用 3.1,动态组件 3.2,递归组件 4,自定义指令 5,props 5.1,TypeScript支持 6,emit 6.1,TypeScript ...

  6. 微信小程序结合 tp实现秒杀

    一:建表 1:用户表 2:订单表 3:收货地址 4:秒杀的商品表: 二: 微信后台方法 1 /** 2 * 秒杀接口 3 */ 4 public function seckill(Request $r ...

  7. jq全选、全不选、反选、单删、批量删除

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  8. tp 七牛云文件上传

    1.先创建好七牛云账号和存储空间 申请七牛云账号: 创建七牛云存储空间: 在账号的秘钥管理里面创建秘钥 获取AccessKey / SecretKey: 2.集成PHP-SDK 七牛云开发文档:htt ...

  9. 微信退款通知,退款回调数据解密.SHA256签名AEAD_AES_256_GCM解密

    $xmlResult = file_get_contents("php://input");//获取微信的数据$result = $this->xmlToArray($xml ...

  10. 如何实现ARC中weak功能?

    原文链接 我们都知道ARC中weak与assign或者说unsafe_unretained最大的不同就是设置weak属性后,系统会在对象被释放后自动将指向对象的指针置为nil,而assign则会产生一 ...