前言
对于项目的迭代,如何降低复杂性的要求高于性能以及技术细节的
一个易用的项目,才能迭代到比拼性能,最后拼刺刀的阶段
传统单体项目,都是传统三层,直接请求响应的模式,这类称为Rpc模式,易用性上非常好
基于rpc模式,对前一章的代码做调整
代码结构设计
每一个请求之后,同步返回执行结果给上游,最后完成链式调用
实例编写
PayOrderRequest->PayOrderEvent->PayOrderResponse
PayOrderResponse就是外层需要的执行结果PayOrderRequest和PayOrderEvent通过Masstransit通讯,皆是Rpc的模式,等待执行结果,返回给上游调用的API
基于Handler实现Rpc执行链
cfg.ReceiveEndpoint("Transaction", config => { config.Handler<PayOrderRequest>(context => { var value = context.Message; var bus = serviceProvider.GetRequiredService<IBusControl>(); var rpcClient = context.Request<PayOrderEvent, PayOrderResponse>(bus, new PayOrderEvent { SourceId = value.SourceId, TargetId = value.TargetId, Money = value.Money } ); var response = rpcClient.Result; return context.RespondAsync(response.Message); }); }
这样就完成了简单的链式rpc调用,返回结果给上游
基于订阅端的Rpc调用
Handler和订阅端都可以完成链式rpc调用,但是出于项目分层和后续管理,不建议大量业务代码都写在Handler里
public async Task Consume(ConsumeContext<PayOrderRequest> context) { var value = context.Message; //...省略crud部分 var rpcClient = context.Request<PayOrderEvent, PayOrderResponse>(bus, new PayOrderEvent { SourceId = value.SourceId, TargetId = value.TargetId, Money = value.Money } ); var response = rpcClient.Result; await context.RespondAsync(response.Message); } public async Task Consume(ConsumeContext<PayOrderEvent> context) { //... 省略crud部分 await context.RespondAsync(new PayOrderResponse { Success = true }); }
应用层调用
var response = await busControl.Request<PayOrderRequest, PayOrderResponse>(new PayOrderRequest { SourceId = 1, TargetId = 2, Money = 2000 }); await context.Response.WriteAsync($"Hello World! Success:{response.Message.Success}");
这就是很典型的Rpc调用了
后话
基于Masstransit就可以很轻松的完成请求同步等待的过程了,整体都是基于EventBus通讯,所以从单体到分布式,可以很轻松的转变,整体本身就是分布式设计
实例本来想用TransactionContext的,仔细看了一下,这个实现是基于 CommittableTransaction,类似于TransactionScope都是基于MSDTC实现的分布式事务,就不写了~这块不能跨平台的话,就不写在实例中了
打个小广告
如果有技术交流可以加NCC的群 24791014、436035237,我在群里,有任何关于asp.net core/Masstransit的问题或者建议都可以与我交流,非常欢迎
示例代码: