微服务间通信常见的两种方式

由于微服务架构慢慢被更多人使用后,迎面而来的问题是如何做好微服务间通信的方案。我们先分析下目前最常用的两种服务间通信方案。

gRPC(rpc远程调用)

gRPC-微服务间通信实践

  • 场景:A服务主动发起请求到B服务,同步方式

  • 范围:只在微服务间通信应用

EventBus(基于消息队列的集成事件)

  • 技术:NotNetCore.Cap + Rabbitmq + Database

  • 场景:A服务要在B服务做某件事情后响应,异步方式

  • 实现:B服务在完成某件事情后发布消息,A服务订阅此消息

  • 范围:只在微服务间通信应用

通过对比,两种方式完全不一样。rpc是类似于http请求的及时响应机制,但是比http更轻量、快捷,它更像以前的微软的WCF,可以自动生成客户端代码,充分体现了面向实体对象的远程调用的思想;Eventbus是异步的消息机制,基于cap的思想,不关心下游订阅方服务是否消费成功,保障了主服务业务的流畅性,同时也是一款分布式事务的实现方案,可以保障分布式架构中的数据的最终一致性。

我们今天主要介绍CAP在微服务中的实践案例。

搭建框架介绍

新建项目

  1. 新建解决方案 DotNetCore.Cap.Demo

  2. 新建项目 DotNetCore.Cap.Demo.Publisher 消息发布端

  3. 新建项目 DotNetCore.Cap.Demo.Subscriber 消息订阅端

主要sdk

  • 项目框架 netcoreapp 3.1

  • 消息队列选用RabbitMQ

  • 数据库存储选用PostgreSql

根据实际情况选择合适的消息队列和数据库存储

CAP 支持 Kafka、RabbitMQ、AzureServiceBus 消息队列:

PM> Install-Package DotNetCore.CAP.Kafka
PM> Install-Package DotNetCore.CAP.RabbitMQ
PM> Install-Package DotNetCore.CAP.AzureServiceBus

CAP 提供了 Sql Server, MySql, PostgreSQL,MongoDB 作为数据库存储:

PM> Install-Package DotNetCore.CAP.SqlServer
PM> Install-Package DotNetCore.CAP.MySql
PM> Install-Package DotNetCore.CAP.PostgreSql
PM> Install-Package DotNetCore.CAP.MongoDB

本次demo使用的nuget包如下所示

$ dotnet list package
项目“DotNetCore.Cap.Demo.Publisher”具有以下包引用[netcoreapp3.1]: 顶级包                                                          已请求      已解决   > DotNetCore.CAP                                             3.1.1    3.1.1> DotNetCore.CAP.PostgreSql                                  3.1.1    3.1.1> DotNetCore.CAP.RabbitMQ                                    3.1.1    3.1.1> Microsoft.VisualStudio.Azure.Containers.Tools.Targets      1.10.9   1.10.9> Npgsql.EntityFrameworkCore.PostgreSQL                      3.1.4    3.1.4> Npgsql.EntityFrameworkCore.PostgreSQL.Design               1.1.0    1.1.0项目“DotNetCore.Cap.Demo.Subscriber”具有以下包引用[netcoreapp3.1]:顶级包                                                          已请求      已解决> DotNetCore.CAP                                             3.1.1    3.1.1> DotNetCore.CAP.PostgreSql                                  3.1.1    3.1.1> DotNetCore.CAP.RabbitMQ                                    3.1.1    3.1.1> Microsoft.VisualStudio.Azure.Containers.Tools.Targets      1.10.9   1.10.9> Npgsql.EntityFrameworkCore.PostgreSQL                      3.1.4    3.1.4> Npgsql.EntityFrameworkCore.PostgreSQL.Design               1.1.0    1.1.0

DotNetCore.Cap.Demo.Publisher 消息发布端

修改Startup文件

注入dotnetcore.cap组件及数据库上下文

    services.AddDbContext<PgDbContext>(p => p.UseNpgsql("数据库连接字符串"));services.AddCap(x =>{//rabbitmq在docker运行时,需要映射两个端口:5672和15672//5672供程序集访问//15672供web访问//默认用户名和密码为:guest/guestx.UseRabbitMQ(p =>{p.HostName = "localhost";p.Port = 5672;p.UserName = "guest";p.Password = "guest";});x.UseEntityFramework<PgDbContext>();//x.FailedRetryCount = 1;//x.UseDashboard();});

新建Controller作为Publisher

  • 构造函数注入DotNetCore.CAP.ICapPublisher

提供了同步和异步的消息发布方法

  • 发布字符串消息

await _capPublisher.PublishAsync("消息名称", "消息内容");

        [HttpGet("string")]public async Task<IActionResult> PublishString(){await _capPublisher.PublishAsync("sample.rabbitmq.demo.string", "this is text!");return Ok();}
  • 发布对象

await _capPublisher.PublishAsync("消息名称", "消息对象");

        [HttpGet("dynamic")]public async Task<IActionResult> PublishDynamic(){await _capPublisher.PublishAsync("sample.rabbitmq.demo.dynamic", new{Name = "xiao gou",Age = 18});return Ok();}
  • 分布式事务场景

当需要在数据库操作后,发布消息出去,DotNetCore.Cap也提供了分布式事务的解决方案。它扩展的transcation能保证只有在数据库操作和消息发送都完成后,才提交Commit

        [HttpGet("transcation")]public async Task<IActionResult> PublishWithTranscation(){using (var trans = _pgDbContext.Database.BeginTransaction(_capPublisher)){var apiConfig = new ApiConfig{ApiName = "111122",ApiDesc = "223",ReturnType = "1",ReturnExpect = "1",IsAsync = true,OperCode = "999",OperTime = DateTime.Now};await _pgDbContext.ApiConfig.AddAsync(apiConfig);await _pgDbContext.SaveChangesAsync();_capPublisher.Publish("sample.rabbitmq.demo.transcation", apiConfig);trans.Commit();return Ok();}}

DotNetCore.Cap.Demo.Subscriber 消息订阅端

修改Startup文件

注入dotnetcore.cap组件及数据库上下文

    services.AddDbContext<PgDbContext>(p => p.UseNpgsql("数据库连接字符串"));services.AddCap(x =>{//rabbitmq在docker运行时,需要映射两个端口:5672和15672//5672供程序集访问//15672供web访问//默认用户名和密码为:guest/guestx.UseRabbitMQ(p =>{p.HostName = "localhost";p.Port = 5672;p.UserName = "guest";p.Password = "guest";});x.UseEntityFramework<PgDbContext>();//x.FailedRetryCount = 1;//x.UseDashboard();});

新建Controller作为Subscriber

  • 订阅字符串消息

[NonAction] 标签:Indicates that a controller method is not an action method.

[CapSubscribe] 标签:标志此方法为订阅方法,并以消息名称匹配发布端的消息事件

        [NonAction][CapSubscribe("sample.rabbitmq.demo.string")]public void SubscriberString(string text){Console.WriteLine($"【SubscriberString】Subscriber invoked, Info: {text}");}
  • 订阅对象消息

方法入参person即为消息体

        [NonAction][CapSubscribe("sample.rabbitmq.demo.dynamic")]public void SubscriberDynamic(dynamic person){Console.WriteLine($"【SubscriberDynamic】Subscriber invoked, Info: {person.Name} {person.Age}");}

新建Service作为Subscriber

  • 除了Controller可以作为消息订阅端外,也可以用继承自DotNetCore.CAP.ICapSubscribe接口的Service作为订阅端

  • Controller作为订阅者时,不用继承ICapSubscribe;Service作为订阅者时,必须继承ICapSubscribe

  • Controller和Service同时订阅了一个消息时,只触发了Service的消费;若要多个消费,需要在不同的Group下

using DotNetCore.CAP;
using System;namespace DotNetCore.Cap.Demo.Subscriber.Services
{/// <summary>/// 消费订阅服务/// </summary>public class SubscriberService : ICapSubscribe{[CapSubscribe("sample.rabbitmq.demo.string")]public void SubscriberString(string text){Console.WriteLine($"【SubscriberString】Subscriber invoked, Info: {text}");}[CapSubscribe("sample.rabbitmq.demo.dynamic")]public void SubscriberDynamic(dynamic person){Console.WriteLine($"【SubscriberDynamic】Subscriber invoked, Info: {person.Name} {person.Age}");}[CapSubscribe("sample.rabbitmq.demo.object")]public void SubscriberObject(Person person){Console.WriteLine($"【SubscriberObject】Subscriber invoked, Info: {person.Name} {person.Age}");}[CapSubscribe("sample.rabbitmq.demo.trans")]public void SubscriberTrans(ApiConfig apiConfig){Console.WriteLine($"【SubscriberTrans】Subscriber invoked, Info: {apiConfig.Id}");}}
}

总结

  • DotNetCore.Cap 是一种异步消息的通信,可以作为微服务间通信的一种方式

  • DotNetCore.Cap 为微服务架构提供了分布式事务的解决方案,保障了数据的最终一致性

  • 开发中,应根据实际业务需求和场景,选择合适可靠的微服务间通信方案

参考

https://github.com/dotnetcore/CAP/blob/master/README.md
https://book.douban.com/subject/33425123/

Demo 代码

https://github.com/cailin0630/DotNetCore.Cap.Demo

原文地址:https://www.cnblogs.com/jiangyihz/p/13864245.html

CAP-微服务间通信实践相关推荐

  1. gRPC-微服务间通信实践

    微服务间通信常见的两种方式 由于微服务架构慢慢被更多人使用后,迎面而来的问题是如何做好微服务间通信的方案.我们先分析下目前最常用的两种服务间通信方案. gRPC(rpc远程调用) 场景:A服务主动发起 ...

  2. Istio:一个用于微服务间通信的服务网格开源项目

    http://www.infoq.com/cn/news/2017/05/istio Istio:一个用于微服务间通信的服务网格开源项目 Google.IBM和Lyft开源了微服务管理.保护和监控框架 ...

  3. 实践《如何使用Seata保证Dubbo微服务间的一致性》

    原文在这里:如何使用Seata保证Dubbo微服务间的一致性. 从这里下载sample代码,master分支,最新的代码提交日期是2019.9.16,修订号cd10c5a.本文代码在模块dubbo里. ...

  4. .NET Core 微服务学习与实践系列文章目录索引(2019版)

    Photo :.NET Core 文 | Edison Zhou 2018年,我开始学习和实践.NET Core,并开始了微服务的学习,以及通过各种开源组件搭建服务治理技术方案,并在学习过程中总结了一 ...

  5. 微服务理论与实践[1]-什么是微服务

    微服务理论与实践[1]-什么是微服务 什么是微服务 微服务 (Microservices) 是一种软件架构风格,将应用程序构造为围绕业务的小型自治服务的集合 微服务以专注于单一责任与功能的小型功能区块 ...

  6. 【微服务】什么是微服务?微服务与分布式的区别?微服务怎么具体实践微服务?服务端发现和客户端发现...

    目录 什么是微服务 微服务与分布式的区别 HOW - 怎么具体实践微服务 So What - 思考 服务发现 微服务之客户端发现,服务端发现 参考资料和推荐阅读 什么是微服务 https://zhua ...

  7. 【微服务】什么是微服务?微服务与分布式的区别?微服务怎么具体实践微服务?服务端发现和客户端发现

    目录 什么是微服务 微服务与分布式的区别 HOW - 怎么具体实践微服务 So What - 思考 服务发现 微服务之客户端发现,服务端发现 参考资料和推荐阅读 什么是微服务 https://zhua ...

  8. 现代化Web的微服务架构最佳实践全景

    原文地址:点击打开链接 作者丨Vinay Sahni 编辑丨Cindy "基于搭建微服务架构的实践,作者总结出一套适用于现代化Web和云技术的实战经验,并从微服务领域的先行者(如Netfli ...

  9. Spring Cloud Alibaba 之 服务通信 REST消息通信:如何使用 OpenFeign 简化服务间通信

    上一讲我们学习了 Ribbon 与 RestTemplate 两个组件.Ribbon 提供了客户端负载均衡,而 RestTemplate 则封装了 HTTP 的通讯,简化了发送请求的过程.两者相辅相成 ...

最新文章

  1. bootstrap官网
  2. Git分支命令学习使用
  3. leetcode404. 左叶子之和
  4. 饿了吗商品列表_仅仅一字之差,饿了么起诉饿了吗
  5. asp.net学习之扩展GridView
  6. 西南交大量子计算机,上海交大“致远学者”本科生突破光量子计算机探测瓶颈问题...
  7. 自然语言处理——语言模型(三)
  8. 查 oracle 的sid,oracle 查询sid 运行的sql语句
  9. MTK平台 Android8.1 SD卡驱动能力修改
  10. Hulk容器服务的镜像CI解决方案
  11. SpringSecurity授权管理介绍
  12. 国外问卷调查好做吗?
  13. UART数据发送和接收(Verilog)
  14. 内存取证-volatility工具的使用 (史上更全教程,更全命令)
  15. 学大伟业 Day 2 培训总结
  16. HTML表格练习---个人简历
  17. 海康摄像头二次开发详解,包含海康摄像头登录、海康云台控制、视频下载等功能
  18. HTML,css和JavaScript的基础学习—html篇
  19. 【扬汤止沸,不如釜底抽薪】夜来风雨声,Lucene知多少?
  20. 【OpenCV 例程300篇】206. Photoshop 色阶调整算法

热门文章

  1. 【开发工具之Spring Tool Suite】6、用Spring Tool Suite简化你的开发
  2. title与h1标签的区别和联系
  3. 携程编程大赛 (预赛第二场)第一题【剪刀石头布】
  4. 《那些年啊,那些事——一个程序员的奋斗史》——35
  5. android 游戏 重力
  6. ACPI知识学习笔记
  7. 目标跟踪 facebook_如何关闭Facebook Messenger的位置跟踪(如果已启用)
  8. 自定义异常最佳实践_播放,自定义和组织媒体的最佳文章
  9. 公用ip地址查询_是什么使您无法更改公用IP地址并在Internet上造成严重破坏?
  10. Ubuntu安装Samba文件共享服务器(NAS)