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

首先看看结果很简单:

核心代码如下:

using MassTransit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using OrderProcessor.Event;
using ServiceModel;
using ServiceModel.Command;
using ServiceModel.DTO;
using ServiceModel.Event;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace OrderProcessor.Service
{
public class OrderProcessorStateMachine:MassTransitStateMachine<ProcessingOrderState>
{
private readonly ILogger<OrderProcessorStateMachine> logger; public OrderProcessorStateMachine()
{
this.logger = GlobalServiceProvider.Instance.CreateScope().ServiceProvider.GetService<ILogger<OrderProcessorStateMachine>>();
this.InstanceState(x => x.State);
this.State(() => this.Processing);
this.ConfigureCorrelationIds();
this.Initially(this.SetOrderSummitedHandler());
this.During(Processing, this.SetStockReservedHandler(), SetPaymentProcessedHandler(), SetOrderShippedHandler());
SetCompletedWhenFinalized();
} private void ConfigureCorrelationIds()
{
this.Event(() => this.OrderSubmitted, x => x.CorrelateById(c => c.Message.CorrelationId).SelectId(c => c.Message.CorrelationId));
this.Event(() => this.StockReserved, x => x.CorrelateById(c => c.Message.CorrelationId));
this.Event(() => this.PaymentProcessed, x => x.CorrelateById(c => c.Message.CorrelationId));
this.Event(() => this.OrderShipped, x => x.CorrelateById(c => c.Message.CorrelationId));
} private EventActivityBinder<ProcessingOrderState, IOrderSubmitted> SetOrderSummitedHandler() =>
When(OrderSubmitted).Then(c => this.UpdateSagaState(c.Instance, c.Data.Order))
.Then(c => this.logger.LogInformation($"Order submitted to {c.Data.CorrelationId} received"))
.ThenAsync(c => this.SendCommand<IReserveStock>("rabbitWarehouseQueue", c))
.TransitionTo(Processing); private EventActivityBinder<ProcessingOrderState, IStockReserved> SetStockReservedHandler() =>
When(StockReserved).Then(c => this.UpdateSagaState(c.Instance, c.Data.Order))
.Then(c => this.logger.LogInformation($"Stock reserved to {c.Data.CorrelationId} received"))
.ThenAsync(c => this.SendCommand<IProcessPayment>("rabbitCashierQueue", c)); private EventActivityBinder<ProcessingOrderState, IPaymentProcessed> SetPaymentProcessedHandler() =>
When(PaymentProcessed).Then(c => this.UpdateSagaState(c.Instance, c.Data.Order))
.Then(c => this.logger.LogInformation($"Payment processed to {c.Data.CorrelationId} received"))
.ThenAsync(c => this.SendCommand<IShipOrder>("rabbitDispatcherQueue", c)); private EventActivityBinder<ProcessingOrderState, IOrderShipped> SetOrderShippedHandler() =>
When(OrderShipped).Then(c =>
{
this.UpdateSagaState(c.Instance, c.Data.Order);
c.Instance.Order.Status = Status.Processed;
})
.Publish(c => new OrderProcessed(c.Data.CorrelationId, c.Data.Order))
.Finalize(); private void UpdateSagaState(ProcessingOrderState state, Order order)
{
var currentDate = DateTime.Now;
state.Created = currentDate;
state.Updated = currentDate;
state.Order = order;
} private async Task SendCommand<TCommand>(string endpointKey, BehaviorContext<ProcessingOrderState, IMessage> context)
where TCommand : class, IMessage
{
var sendEndpoint = await context.GetSendEndpoint(new Uri(""));
await sendEndpoint.Send<TCommand>(new
{
CorrelationId = context.Data.CorrelationId,
Order = context.Data.Order
});
}
public State Processing { get; private set; }
public Event<IOrderSubmitted> OrderSubmitted { get; private set; }
public Event<IOrderShipped> OrderShipped { get; set; }
public Event<IPaymentProcessed> PaymentProcessed { get; private set; }
public Event<IStockReserved> StockReserved { get; private set; } }
}
using MassTransit;
using MassTransit.MongoDbIntegration.Saga;
using OrderProcessor;
using OrderProcessor.Service; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddMassTransit(x =>
{
x.UsingRabbitMq((context, cfg) =>
{
var connection = "amqp://lx:admin@ip:5672/my_vhost";//不加主机会报错
cfg.Host(connection);
cfg.UseDelayedRedelivery(r => r.Intervals(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(30)));
cfg.UseMessageRetry(r => r.Immediate(5)); cfg.ConfigureEndpoints(context);
cfg.ReceiveEndpoint("", ep =>
{
ep.StateMachineSaga(new OrderProcessorStateMachine(), MongoDbSagaRepository<ProcessingOrderState>.Create("connecturl","db"));
}); });
}); var app = builder.Build(); 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. Linux Docker虚拟机入门实战讲解

    什么是Docker? Docker是基于Go语言实现的云开源项目,诞生于2013年初,最初发起者是dotCloud公司.Docker自开源后受到广泛的关注和讨论,目 前已有多个相关项目,逐渐形成了围绕 ...

  2. 华为RH2288H服务器引导ServiceCD安装Windows Server操作系统

    安装准备 ServiceCD光盘. Windows操作系统安装光盘. 物理光驱. 使用虚拟控制台远程安装操作系统时,需要准备以下软件: ServiceCD光盘或ServiceCD ISO文件. Win ...

  3. 将Android手机无线连接到Ubuntu实现唱跳Rap

    您想要将Android设备连接到Ubuntu以传输文件.查看Android通知.以及从Ubuntu桌面发送短信 – 你会怎么做?将文件从手机传输到PC时不要打电话给自己:使用GSConnect就可以. ...

  4. 【C# 程序集】.NET core Could not load file or assembly

    NET core 添加了新的nuget包,部署出现Could not load file or assembly 这个坑,今天整了一天,我添加了Microsoft.AspNetCore.Mvc.Ver ...

  5. 远程连接DB2

    今天需要和别的公司业务系统进行对接,刚好他们使用的数据库是DB2,需求场景是这样的:我们需要往DB2里面写数据.查看数据,修改数据,统计数据.我们的源库是SQL SEVER,目标库是DB2;需求已经告 ...

  6. linux基础-jdk1.8和weblogic12.2.1.3.0安装

    转至:https://www.cnblogs.com/jiarui-zjb/p/9642416.html 1.环境探查与准备 安装jdk和weblogic前需要对进行安装的linux系统硬件和软件环境 ...

  7. idea教程--如何申请免费的ideaIDE

    开始申请前请先到 https://www.jetbrains.com/zh/student/ 阅读免费学生授权的介绍和常见问题,再依照下方流程进行申请. (1)到 https://www.jetbra ...

  8. urllib-访问网页的两种方式:GET与POST

    学习自:https://www.jianshu.com/p/4c3e228940c8 使用参数.关键字访问服务器 访问网络的两种方法: 1.GET 利用参数给服务器传递信息 参数data为dict类型 ...

  9. 六、Java方法

    Java方法 何为方法 System.out.println(),那么它是什么呢? ​ System是一个类,out是一个对象,println()是一个方法 Java方法是语句的集合,它们在一起执行的 ...

  10. MySQL中使用IN会不会走索引

    结论:IN肯定会走索引,但是当IN的取值范围较大时会导致索引失效,走全表扫描 navicat可视化工具使用explain函数查看sql执行信息 场景1:当IN中的取值只有一个主键时 我们只需要注意一个 ...