微服务架构:事件总线、消息队列CAP.RabbitMQ

参考:

CAP官方中文文档(重点)

RabbitMQ中文文档

RabbitMQ官网英文文档

事件总线--文档

事件总线

什么是事件总线

就是用来管理所有的事件的一种机制就称作为事件总线,包括事件发布,事件存储,事件订阅,事件处理的统称

作用

事件总线是一种机制,它允许不同的组件彼此通信而不彼此了解。 组件可以将事件发送到Eventbus,而无需知道是谁来接听或有多少其他人来接听。 组件也可以侦听Eventbus上的事件,而无需知道谁发送了事件。 这样,组件可以相互通信而无需相互依赖。 同样,很容易替换一个组件。 只要新组件了解正在发送和接收的事件,其他组件就永远不会知道

CAP框架

CAP 是一个EventBus,同时也是一个在微服务或者SOA系统中解决分布式事务问题的一个框架。它有助于创建可扩展,可靠并且易于更改的微服务系统。

CAP 支持以下几种运输方式:

存储方式分为内存和数据库

RabbitMQ

RabbitMQ是消息代理:它接受并转发消息。您可以将其视为邮局:将您要发布的邮件放在邮箱中时,可以确保Mailperson先生或女士最终将邮件传递给收件人。以此类推,RabbitMQ是一个邮箱,一个邮局和一个邮递员。

RabbitMQ与邮局之间的主要区别在于,它不处理纸张,而是接收,存储和转发数据消息的二进制斑点。

六种队列模式:先进先出,后进后出

 

发布订阅模式:一般是聚合服务发布消息给RabbitMQ,RabbitMQ再发消息发动订阅者服务,通过RabbitMQ解耦,两个服务不直接通信,是RabbitMQ调用服务,不再是聚合服务调用服务

  • 发布(Publish):程序把请求消息发布给RabbitMQ后直接返回,不用再等请求执行完毕再返回,对应数据库发布表:Published
  • 订阅(Subscrib):程序订阅RabbitMQ后,RabbitMQ把消息逐一推送给订阅者,也就是RabbitMQ调用订阅者服务,对应数据库订阅表:Received

 

连接参数:

  • HostName: 宿主地址
  • UserName: 用户名
  • Password: 密码
  • VirtualHost: 虚拟主机
  • Port: 端口号
  • TopicExchangeName: CAP默认Exchange名称
  • QueueMessageExpires: 队列中消息自动删除时间
  • ConnectionFactoryOptions: 本机连接工厂选项

 

消费模式

参考:

微服务中使用CAP框架的RabbitMQ方式

环境准备 

RabbitMQ的开发语言环境:Erlang下载地址
RabbitMQ下载地址

RabbitMQ启动

1、在安装目录下添加可视化插件命令

rabbitmq-plugins enable rabbitmq_management

2、在安装目录sbin文件夹下启动

rabbitmq-server

3、sbin文件夹下查看rabbitmq状态,最后两行就是端口号,默认是15672

rabbitmqctl status

4、在浏览器输入http://127.0.0.1:15672

访问rabbitmq后台系统,默认账号和密码都是:guest

队列跟踪trace

参考:https://www.cnblogs.com/li150dan/p/9529049.html

启动trace命令:rabbitmqctl trace_on

启动日志插件命令:rabbitmq-plugins enable rabbitmq_tracing

然后添加跟踪输入,需要输入账号密码

在项目中使用RabbitMQ

MicroService.Core项目安装NuGet包

  • CAP: Nuget DotNetCore.CAP
  • CAP传输器:Nuget DotNetCore.CAP.RabbitMQ
  • CAPSql持久化:DotNetCore.CAP.SqlServer
  • CAP内存持久化:DotNetCore.CAP.InMemoryStorage

在聚合服务 MicroService.AggregateService服务中startup.cs中使用CAP

            // 添加事件总线cap
            services.AddCap(x => {
                // 使用内存存储消息(消息发送失败处理)
                x.UseInMemoryStorage();
//使用EntityFramework进行存储操作,指定数据库上下文就好,不用配置 //x.UseEntityFramework<AggregateContext>(); // 使用RabbitMQ进行事件中心处理 x.UseRabbitMQ(rb => { rb.HostName = "localhost"; rb.UserName = "guest"; rb.Password = "guest"; rb.Port = 5672; rb.VirtualHost = "/"; }); });

 

 在聚合服务MicroService.AggregateService服务中AggregateController.cs中注入且使用ICapPublisher,把消息发布给RabbitMQ

using DotNetCore.CAP;
private readonly ICapPublisher capPublisher; public TeamsController(ICapPublisher capPublisher) { this.capPublisher = capPublisher; } //异步发布对象消息 capPublisher.PublishAsync<Video>("video.event.1", video);

 

 

在视频服务MicroService.VideoService服务startup.cs中使用CAP

            // 添加事件总线cap
            services.AddCap(x => {
                // 使用RabbitMQ进行事件中心处理
                x.UseRabbitMQ(rb => {
                    rb.HostName = "localhost";
                    rb.UserName = "guest";
                    rb.Password = "guest";
                    rb.Port = 5672;
                    rb.VirtualHost = "/";
                });
            });    

在视频服务MicroService.VideoService服务VideoController.cs 的PostVideo方法上添加过滤器特性[CapSubscribe] ,从RabbitMQ中订阅,且处理这些请求

using DotNetCore.CAP;

        /// <summary>
        /// 视频添加:
        /// 从消息队列获取请求
        /// </summary>
        /// <param name="Video"></param>
        /// <returns></returns>
        [NonAction]  //指示控制器方法不是动作方法,不让控制器调用
        [CapSubscribe("video.*")]  //订阅消息:RabbitMQ推送消息给订阅者
        public ActionResult<Video> PostVideo(Video Video)
        {
            Console.WriteLine($"接受到视频事件消息");
            videoService.Create(Video);
            return CreatedAtAction("GetVideo", new { id = Video.Id }, Video);
        }

 

posted @ 2020-12-13 17:16  日积月累码农  阅读(2125)  评论(7编辑  收藏  举报