Windows C# RabbitMQ 安装--配置--信息收发

前言

        近期要实现一个图片异步上传的需求,需要用到RabbitMQ,辅助客户端完成对高并发请求的处理。

一、安装Erlang

  1. 由于RabbitMQ服务器是用Erlang语言编写,所以我们需要先安装Erlang环境,本文使用的版本是erl-24.1

  2. 下载地址: https://github.com/erlang/otp/releases/download/OTP-24.1/otp_win64_24.1.exe
    在这里插入图片描述

  3. 下载完成后,双击exe完成安装。记录安装目录,默认路径:C:\Program Files\erl-24.1

  4. 配置环境变量
    路径:计算机–右键–属性–高级系统设置–环境变量–系统变量
    step 1 新建:
            变量名:ERLANG_HOME
            变量值:C:\Program Files\erl-24.1
    在这里插入图片描述
    step 2 在系统变量栏找到Path
            新建值%ERLANG_HOME%\bin
    在这里插入图片描述

  5. 检测安装状态
            Win+R输入cmd,打开命令提示符,输入erl,如下,Erlang安装结束。
    在这里插入图片描述

二、安装RabbitMQ

  1. 本文使用的版本为rabbitmq-server-windows-3.9.8
    下载地址:https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.8/rabbitmq-server-windows-3.9.8.zip
  2. 解压到任意目录下,本文解压地址是 C:\Program Files
  3. 配置环境变量
    方式同上,在系统变量栏
    step 1 新建:
            变量名:RABBITMQ_SERVER
            变量值:C:\Program Files\rabbitmq_server-3.9.8
    step 2 在系统变量栏找到Path
            新建值%RABBITMQ_SERVER%\sbin
    在这里插入图片描述
  4. 安装页面管理工具
    4.1 CMD命令进入sbin目录, 或直接在该目录内Shift+右键–>在此处打开命令窗口
    在这里插入图片描述
    4.2 输入 rabbitmq-plugins.bat enable rabbitmq_management
    在这里插入图片描述
  5. 启动服务
            命令窗输入rabbitmq-server.bat,或直接双节打开rabbitmq-server.bat
    在这里插入图片描述
  6. 测试
    浏览器输入 http://localhost:15672/ ,username和password都输入 guest,登录。
    在这里插入图片描述
    在这里插入图片描述

三、配置账户

默认情况下,如果只有guest账户,RabbitMQ是不允许用户通过远程ip访问管理页面的。因此需要配置自定义账户,才能通过远程方式(即IP+端口号)访问RabbitMQ。

  1. 在Admin栏右侧,点击Virtual Host新增virtual host(虚拟消息服务器)。每个VirtualHost相当于一个相对独立的RabbitMQ服务器;每个VirtualHost之间相互隔离,互不干扰。
    在这里插入图片描述
  2. 在Admin栏右侧,点击User新增用户,(新创建的用户默认是没有任何权限的)
    在这里插入图片描述
  3. 为新增账号添加权限,点击新增的用户名即可编辑权限
    在这里插入图片描述
    此处权限设置,表明该用户具有访问列表中virtual host的权限
    在这里插入图片描述
  4. 分配权限后,guest账户就不再需要了,删除即可,点击guest用户名
    在这里插入图片描述
    在这里插入图片描述
  5. 删除guest后,RabbitMQ会检测到当前guest账户登录失效,有弹窗提示输入账号密码,填入新创建的账号信息即可,然后退出guest账号
    在这里插入图片描述
  6. 远程访问,并用新账号登录在这里插入图片描述
  7. 如果登录失败可以尝试以下方案
    方案一:将新增账户类型设置为Administrator,CMD命令,在sbin目录下输入
            rabbitmqctl set_user_tags admin administrator
    设置后重试登录。(admin为刚才新增的账户名)
    方案二:为新增账户添加默认virtual host的权限
            rabbitmqctl set_permissions -p / admin ‘.’ '.’ ‘.*’
    设置后重试登录。(/ 为默认virtual host, admin为新增账号)
    方案三:新建账号,并为其分配权限
            rabbitmqctl add_user guest1 123456         (账号guest1 密码123456)
            rabbitmqctl set_user_tags guest1 administrator        (设置账号类型为administrator)
            rabbitmqctl set_permissions -p / guest1 ‘.’ '.’ ‘.*’        (为guest1添加权限)
    设置后使用guest1重试登录。

四、配置队列

  1. 创建队列
    Virtual host :当前队列输入那个消息服务器
    Type:队列类型默认选择Classic(经典款)
    Name:队列名
    Durability:Durable(默认,持久化),另一个是Transient,瞬态。持久化消息存储在磁盘,瞬态消息存储在内存中,大部分情况都选择持久化消息方式存储
    Auto delete:No,关闭队列自动删除。否则当至少有一个消费者连接到队列时,该队列将删除自身,并将所有消费者的连接断开。(有点像滴滴司机抢单)
    Arguments:参考网上其他博主的讲解,不在过多阐述
    在这里插入图片描述

--------------------------------------------------------------------以下操作非必要---------------------------------------------------------------
感兴趣可以先了解一下RabbitMQ中 exchange、route、queue的关系

  1. 创建Exchanges,这里Type选择direct,要求routing key必须完全一致才能访问队列,其他都能网上查到,不再赘述在这里插入图片描述4. 配置自定义的Exchange,配置好后可以通过点击队列名,查看Binds情况在这里插入图片描述在这里插入图片描述

五、编写测试脚本

  1. 创建两个C#控制台项目(本文使用vs2019),分别作为消息发布者消息订阅者。.Net Framework框架版本选择为4.6.1
    在这里插入图片描述
  2. 两个工程创建后,都需要添加RabbitMQ包。(安装过程有弹窗,确定即可)
    在这里插入图片描述
    在这里插入图片描述
  3. 消息发布者代码(publisher.cs):每隔150ms,向队列TestQueue1发送一条消息
using System;
using System.Text;
using System.Threading;
using RabbitMQ.Client;

namespace publisher
{
    class Program
    {
        static void Main(string[] args)
        {
        	//基本登录信息
            var factory = new ConnectionFactory()
            {
                HostName = "192.168.123.29",
                VirtualHost = "visual_knitting_machine",
                UserName = "admin",
                Password = "123456",
                Port = 5672
            };
			
			//创建连接
            using (var connection = factory.CreateConnection())
            {
            	//分配channel
                using (var channel = connection.CreateModel())
                {
                    for (int i = 1; i < 1000; i++)
                    {
                    	//描述队列
                        channel.QueueDeclare(
                            queue: "TestQueue1",
                            durable: true,
                            exclusive: false,
                            autoDelete: false,
                            arguments: null
                            );
						
						//要发送的消息
                        string message = "Hello World! -- " + i.ToString();
                        var body = Encoding.UTF8.GetBytes(message);
						
						//发布消息
                        channel.BasicPublish(
                            exchange: "myTestExchange",
                            routingKey: "queue1_routingKey",
                            basicProperties: null,
                            body: body
                            );

                        Console.WriteLine(" {0} Sent \'{1}\'", i.ToString(), message);
                        Thread.Sleep(150);
                    }
                }
            }
        }
    }
}

在这里插入图片描述
4. 消息订阅者代码(consumer.cs):每隔200ms,从队列消费一条消息。消费者可以有多个。

using System;
using System.Text;
using System.Threading;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace consumer
{
    class Program
    {
        static EventingBasicConsumer consumer;
        static IConnection connection;
        static IModel channel;

        static void Main(string[] args)
        {
            // 禁用控制台快速编辑模式,防止窗口假死。
            // 假死后会阻塞程序,导致无法接受消息
            // 可通过按回车解除假死状态
            ConsoleUtil.DisbleQuickEditMode();

            try
            {
                var factory = new ConnectionFactory()
                {
                    HostName = "192.168.123.29",
                    VirtualHost = "visual_knitting_machine",
                    UserName = "admin",
                    Password = "123456",
                    Port = 5672
                };
                connection = factory.CreateConnection();

                channel = connection.CreateModel();

                //队列声明
                channel.QueueDeclare("TestQueue1", true, false, false, null);

                //公平分发,一次只为某个消费者发送一条消息,
                //否则会出现其他消费者拿不到消息的情况
                //也可设置一次接受多条消息,将1设置n即可。
                channel.BasicQos(0, 1, false);

                //构建消费者实例
                consumer = new EventingBasicConsumer(channel);

                //消息接收后的事件委托,异步,非阻塞。
                consumer.Received += OnReceiveMessage;

                //启动消费者
                //关闭自动确认,避免一次性将消息全部消费
                channel.BasicConsume("TestQueue1", false, consumer);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            //此循环无特殊意义,用来防止控制台自动关闭。
            while (true) { }
        }

        static void OnReceiveMessage(object sender, BasicDeliverEventArgs e)
        {
            //手动确认消息被消费,只有确认消费后,RabbitMQ才会重新为该消费者发送新消息
            channel.BasicAck(e.DeliveryTag, false);

            var body = e.Body.ToArray();
            var message = Encoding.UTF8.GetString(body);

            if (!string.IsNullOrEmpty(message))
            {
                Console.WriteLine(" Received '{0}'", message);
            }
            Thread.Sleep(200);
        }
    }
}

在这里插入图片描述

  1. 控制台工具类,可以不用该类,没有太大影响。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

public class ConsoleUtil
{
    #region 设置控制台标题 禁用关闭按钮

    [DllImport("user32.dll", EntryPoint = "FindWindow")]
    extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll", EntryPoint = "GetSystemMenu")]
    extern static IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert);
    [DllImport("user32.dll", EntryPoint = "RemoveMenu")]
    extern static IntPtr RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);


    static void DisbleClosebtn()
    {
        IntPtr windowHandle = FindWindow(null, "控制台标题");
        IntPtr closeMenu = GetSystemMenu(windowHandle, IntPtr.Zero);
        uint SC_CLOSE = 0xF060;
        RemoveMenu(closeMenu, SC_CLOSE, 0x0);
    }
    protected static void CloseConsole(object sender, ConsoleCancelEventArgs e)
    {
        Environment.Exit(0);
    }

    #endregion


    #region 关闭控制台 快速编辑模式、插入模式
    const int STD_INPUT_HANDLE = -10;
    const uint ENABLE_QUICK_EDIT_MODE = 0x0040;
    const uint ENABLE_INSERT_MODE = 0x0020;
    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr GetStdHandle(int hConsoleHandle);
    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint mode);
    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint mode);


    public static void DisbleQuickEditMode()
    {
        IntPtr hStdin = GetStdHandle(STD_INPUT_HANDLE);
        uint mode;
        GetConsoleMode(hStdin, out mode);
        mode &= ~ENABLE_QUICK_EDIT_MODE;//移除快速编辑模式
        mode &= ~ENABLE_INSERT_MODE;      //移除插入模式
        SetConsoleMode(hStdin, mode);
    }

    #endregion


    #region 设置控制台颜色
    static void WriteColorLine(string str, ConsoleColor colorF, ConsoleColor colorB)
    {
        ConsoleColor currentForegroundColor = Console.ForegroundColor;
        ConsoleColor currentBackgroundColor = Console.BackgroundColor;
        Console.ForegroundColor = colorF;
        Console.BackgroundColor = colorB;
        //Console.WriteLine(str);
        Console.ForegroundColor = currentForegroundColor;
        Console.BackgroundColor = currentBackgroundColor;
    }
    #endregion
}

看完记得点赞、评论、收藏哦~~

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jack_dos

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值