当前系统

Debian GNU/Linux 12

安装命令

  1、sudo apt update    //更新系统
  2、sudo apt-get install rabbitmq-server    //安装rabbitMq 服务
  3、sudo service rabbitmq-server start     //启动 rabbitMq
  4、sudo systemctl enable rabbitmq-server //设置开机启动
  5、sudo rabbitmq-plugins enable rabbitmq_management    //启动管理平台 15672
  sudo service rabbitmq-server status   //查看服务状态

 

  netstat -lnpt | grep 15672  //查看端口是否运行

 

  

访问管理平台

http://服务器ip:15672/

默认帐号及密码:guest

异常:User can only log in via localhost

sudo rabbitmqctl add_user admin 123456    //创建 admin 管理员,密码 123456   

sudo rabbitmqctl set_user_tags admin administrator    //将新用户设置为管理员

sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"  //为新用户分配所有权限

注意:新版的 RabbitMq 就算设置了管理员权限,登录后台后很多权限无法操作或显示 404或405,这时必需使用 localhost:15672,如果部署在远程服务器可以使用隧道隐射后在用 localhost 访问权限才显示正常

 RabbitMq 缺点及功能特色:

RabbitMq 由于是单线程处理,故性能方面一般;但在一些特殊场景使用,主要用于队列中消息可以多个客户端同时处理,不会对同一条消息进行多次处理;

1、现有 .net 客户端没有异步操作(建议使用单例服务);

2、消息被分配到客户端后,如果未 Ack 操作,可以关闭通道、断开连接、结束客户端进程才会回滚到处理队列;

3、队列消息被客户端获取后,其它客户端获取不到同一条消息;

4、初始化通道时可选是否持久化,创建消息时可以配置是否持久化;

 几种常见模式:

RabbitMq 主要是由交换机和队列组织,简单理解就是将消息发送到交换机,由交换机将消息投送到队列中;

fanout    订阅/发布模式,指定一些队列绑定到交换机,消息发送到交换机后,会自动投递到绑该交换机的队列中; 

topic      主题模式:两种特殊字符“*”与“#”,用于做模糊匹配,其中“”用于匹配一个单词,“#”用于匹配多个单词。(可以给队列添加多个 routingKey ,添加后必需要绑定交换机),消息发布相对比较慢

direct     简单方式,队列模式就是这种方式,在发布的时候需要指定 队列名,交换机名可以为空;

headers      根据发送的消息内容中的 headers 属性进行匹配,一般用的很少;

 

C# RabbitMq 常用单例服务代码

using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
<br>/// <summary>
/// 表示amqp客户端
/// </summary>
public class RabbitClient : IDisposable
{
    private readonly IOptionsMonitor<RabbitOptions> options;
 
    private readonly ConnectionFactory factory;
 
    private readonly object syncRoot = new object();
 
    private IConnection? _connection;
 
    //持久化消息,需要跟持久化队列共同使用
    private IBasicProperties? properties = null;
 
    private IModel? _channel;
 
    /// <summary>
    /// 获取Channel
    /// </summary>
    private IModel Channel
    {
        get
        {
            lock (this.syncRoot)
            {
                if (this._connection == null)
                {
                    this._connection = this.factory.CreateConnection();
                }
                if (this._channel == null)
                {
                    this._channel = this._connection.CreateModel();
 
                    if (properties == null)
                    {
                        properties = this._channel.CreateBasicProperties();
                        properties.Persistent = this.options.CurrentValue.IsDurable;   //持久化消息
                    }
 
                    //创建默认队列
                    this._channel.QueueDeclare(this.options.CurrentValue.Queue, // 队列名称
                                durable: this.options.CurrentValue.IsDurable, //持久化队列
                                exclusive: false, //是否私有化,false表示所有消费者都可以访问,true表示只有第一次拥有它的消费者才能访问
                                autoDelete: false//是否自动删除,true表示不再使用队列时自动删除队列
                                arguments: null);   //其他额外参数
 
                    //创建配置交换机及队列
                    this._channel.ExchangeDeclare(
                            this.options.CurrentValue.ExchangeOptions.Name, //交换机名称
                            ExchangeType.Fanout,            //交换机类型  Fanout:广播模式,
                            this.options.CurrentValue.IsDurable
                        );
 
                    //创建主题交换机
                    this._channel.ExchangeDeclare(
                            this.options.CurrentValue.TopicName, //交换机名称
                            ExchangeType.Topic,                 //交换机类型  Fanout:主题模式,
                            this.options.CurrentValue.IsDurable
                        );
 
                    //交换机机下创建队列
                    foreach (var item in this.options.CurrentValue.ExchangeOptions.Queues)
                    {
                        //创建队列
                        this._channel.QueueDeclare(item, // 队列名称
                                durable: this.options.CurrentValue.IsDurable, //持久化队列
                                exclusive: false, //是否私有化,false表示所有消费者都可以访问,true表示只有第一次拥有它的消费者才能访问
                                autoDelete: false//是否自动删除,true表示不再使用队列时自动删除队列
                                arguments: null);   //其他额外参数
 
                        //绑定队列到交换机
                        this._channel.QueueBind(
                            item,           //队列名称
                            this.options.CurrentValue.ExchangeOptions.Name,     //交换机名称
                            ""
                            );
 
                        //给队列添加routingKey,并绑定 topic交换机
                        this._channel.QueueBind(
                                item,           //队列名称
                                this.options.CurrentValue.TopicName,     //交换机名称
                                $"#.{item}.#"      //路由关键字,发布订阅模式写""即可
                            );
                    }
                }
                return this._channel;
            }
        }
    }
 
    /// <summary>
    /// amqp客户端
    /// </summary>
    /// <param name="optionsMonitor"></param>
    public RabbitClient(IOptionsMonitor<RabbitOptions> optionsMonitor)
    {
        this.options = optionsMonitor;
        this.factory = new ConnectionFactory
        {
            UserName = options.CurrentValue.UserName,
            Password = options.CurrentValue.Password,
            HostName = options.CurrentValue.HostName,
            Port = options.CurrentValue.Port,
            AutomaticRecoveryEnabled = true
        };
    }
 
    /// <summary>
    /// 简单模式发布消息
    /// </summary>
    /// <param name="msg">消息内容</param>
    public void SimplePublish(string msg)
    {
        var message = Encoding.UTF8.GetBytes(msg);
        this.Channel.BasicPublish(
                "", //交换机名,""表示默认交换机direct
                this.options.CurrentValue.Queue,    //路由键,简单模式就是队列名
                properties, //其他额外参数
                message     //要传递的消息字节数组
            );
    }
 
    /// <summary>
    /// 交换机模式发布消息
    /// </summary>
    /// <param name="msg">消息内容</param>
    public void ExchangePublish(string msg)
    {
        var message = Encoding.UTF8.GetBytes(msg);
        //持久化消息,需要跟持久化队列共同使用
        this.Channel.BasicPublish(
                options.CurrentValue.ExchangeOptions.Name, //交换机名,""表示默认交换机direct
                "",    //路由键,简单模式就是队列名
                properties, //其他额外参数
                message     //要传递的消息字节数组
            );
    }
 
    /// <summary>
    /// 主题模式发布消息
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="topic"></param>
    public void TopicPublish(string msg, string? topic = null)
    {
        var message = Encoding.UTF8.GetBytes(msg);
        var routingKey = string.IsNullOrEmpty(topic) ? "anonymous.info" : topic;
        this.Channel.BasicPublish(
                this.options.CurrentValue.TopicName, //交换机名,""表示默认交换机direct
                routingKey,                          //路由键
                properties, //其他额外参数
                message     //要传递的消息字节数组
            );
    }
 
    /// <summary>
    /// 提取交换机消息
    /// </summary>
    /// <param name="queue">交换机中的队列名称</param>
    /// <param name="autoAck"></param>
    /// <returns></returns>
    public RabbitMessage? GetExchange(string queue, bool autoAck = false)
    {
        var result = this.Channel.BasicGet(queue, autoAck);
        return result == null ? null : new RabbitMessage(result.DeliveryTag, result.Body);
    }
 
    /// <summary>
    /// 提取消息
    /// </summary>
    /// <param name="autoAck">是否同时从服务器中删除消息</param>
    /// <returns></returns>
    public RabbitMessage? Get(bool autoAck = false)
    {
        var result = this.Channel.BasicGet(this.options.CurrentValue.Queue, autoAck);
        return result == null ? null : new RabbitMessage(result.DeliveryTag, result.Body);
    }
 
    /// <summary>
    /// 监听简单队列
    /// </summary>
    /// <param name="callback"></param>
    /// <param name="autoAck"></param>
    public void SimpleConsume(string queue, Action<RabbitMessage> callback, bool autoAck = false)
    {
        var consumer = new EventingBasicConsumer(this.Channel);
        this.Channel.BasicConsume(queue, autoAck, consumer);
        consumer.Received += (model, ea) =>
        {
            var msg = new RabbitMessage(ea.DeliveryTag, ea.Body);
            callback(msg);
        };
    }
 
    /// <summary>
    /// 确认并删除消息
    /// </summary>
    /// <param name="tag">消息标记</param>
    public void Ack(ulong tag)
    {
        this.Channel.BasicAck(tag, false);
    }
 
    /// <summary>
    /// 释放资源
    /// </summary>
    public void Dispose()
    {
        if (this._channel != null)
        {
            this._channel.Dispose();
        }
        if (this._connection != null)
        {
            this._connection.Dispose();
        }
    }

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/// <summary>
/// 表示amqp消息
/// </summary>
public class RabbitMessage
{
    /// <summary>
    /// 标记
    /// </summary>
    public ulong Tag { get; }
 
    /// <summary>
    /// 内容
    /// </summary>
    public byte[] Body { get; }
 
    /// <summary>
    /// amqp消息
    /// </summary>
    /// <param name="tag"></param>
    /// <param name="body"></param>
    public RabbitMessage(ulong tag, ReadOnlyMemory<byte> body)
    {
        this.Tag = tag;
        this.Body = body.ToArray();
    }
 
    /// <summary>
    /// 转换为字符串
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return System.Text.Encoding.UTF8.GetString(this.Body);
    }
}

  

  

 

posted @ 2024-09-20 11:45 皓月青峰 阅读(9) 评论(0) 推荐(0) 编辑
摘要: .net core 及 pgsql 在 Docker 中部署运行 当前运行linux 系统为 : CentOS Stream release 8 .net sdk 7.0、pgsql 12.0 、nginx 1.14.1、docker 24.0.1 在安装前,建议更新系统中依赖包: sudo yum 阅读全文
posted @ 2023-06-02 11:24 皓月青峰 阅读(340) 评论(0) 推荐(0) 编辑
摘要: .net core 自颁发ssl证书,及客户端证书验证 openshell 颁发证书: 先下载 openshell,下载地址:https://slproweb.com/products/Win32OpenSSL.html openssl genrsa -out server.key 2048 ope 阅读全文
posted @ 2023-05-17 17:29 皓月青峰 阅读(140) 评论(0) 推荐(0) 编辑
摘要: React 环境搭建 前提需要先下载 nodejs :https://nodejs.org/en/download 暂时使用的是 nodejs 14.15.5 1、yarn 安装 npm install -g yarn yarn -v 查看版本 1.22.19 设置yarn 源:yarn confi 阅读全文
posted @ 2023-05-12 15:42 皓月青峰 阅读(288) 评论(0) 推荐(0) 编辑
摘要: element-ui DatePicker 的使用可参考:https://element.eleme.cn/#/zh-CN/component/date-picker 具体节假日需要每年12月份,跟据国家发部的通知自己行做调整 2023年节假日通知参考:http://www.gov.cn/zheng 阅读全文
posted @ 2023-05-09 11:05 皓月青峰 阅读(866) 评论(0) 推荐(0) 编辑
摘要: 容器学习: 所有的WPF布局容器都派生自System.Windows.Controls.Panel。Panel继承自FrameworkElement。 在Panel中有一个比较重要的属性是UIElementCollection 类型的Children属性,UIElementCollection是一个 阅读全文
posted @ 2022-08-15 13:31 皓月青峰 阅读(73) 评论(0) 推荐(0) 编辑
摘要: 1、Cookies 授权验证方式 Startup.cs 文件 // 注册Cookie认证服务 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(o => { o.Expire 阅读全文
posted @ 2022-08-03 15:57 皓月青峰 阅读(229) 评论(0) 推荐(0) 编辑
摘要: 做为一个初学者,花了近一周时间去学习vue 的开发,经常采坑就是因为工具的版本导致。 只要基础环境搭建好了,其实开发起来还是比较快捷方便; 后面在慢慢分享个人实战项目中的一些学习经验。 第一步:当然是基础环境的安装备 这里主要包括使用的 vs code 软件和 nodejs 的安装 vscode 下 阅读全文
posted @ 2022-07-22 14:56 皓月青峰 阅读(1486) 评论(0) 推荐(1) 编辑
摘要: 在 Windows 上进行 web 开发,比较普遍的方案是使用 phpstudy 或者别的一些集成环境软件进行环境搭建,写好代码后将代码上传至版本管理工具 git/svn,再将代码同步到 Linux 服务器,这个过程当中开发者的开发环境(Windows)与代码最终执行的环境(Linux)不一致经常会 阅读全文
posted @ 2020-01-02 15:00 皓月青峰 阅读(506) 评论(0) 推荐(0) 编辑
摘要: 本文为 CLI 方式执行数据结构同步及迁移,请确定当前电脑是否安装 .net core 运行环境 4.1. 打开 cmd ,执行:dotnet tool install --global dotnet-ef 如版本过低请输入:dotnet tool update -g dotnet-ef 4.2. 阅读全文
posted @ 2019-12-24 15:45 皓月青峰 阅读(1225) 评论(0) 推荐(2) 编辑
点击右上角即可分享
微信分享提示