dotnet學習筆記-專題03-RabbitMQ-01

random_d發表於2024-11-22

專題03——RabbitMQ

1. RabbitMQ安裝

服務端

使用如下sh指令碼安裝:

#!/bin/sh

sudo apt-get install curl gnupg apt-transport-https -y

## Team RabbitMQ's main signing key
curl -1sLf "https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA" | sudo gpg --dearmor | sudo tee /usr/share/keyrings/com.rabbitmq.team.gpg > /dev/null
## Community mirror of Cloudsmith: modern Erlang repository
curl -1sLf https://ppa1.novemberain.com/gpg.E495BB49CC4BBE5B.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg > /dev/null
## Community mirror of Cloudsmith: RabbitMQ repository
curl -1sLf https://ppa1.novemberain.com/gpg.9F4587F226208342.key | sudo gpg --dearmor | sudo tee /usr/share/keyrings/rabbitmq.9F4587F226208342.gpg > /dev/null

## Add apt repositories maintained by Team RabbitMQ
sudo tee /etc/apt/sources.list.d/rabbitmq.list <<EOF
## Provides modern Erlang/OTP releases
##
deb [signed-by=/usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg] https://ppa1.novemberain.com/rabbitmq/rabbitmq-erlang/deb/ubuntu jammy main
deb-src [signed-by=/usr/share/keyrings/rabbitmq.E495BB49CC4BBE5B.gpg] https://ppa1.novemberain.com/rabbitmq/rabbitmq-erlang/deb/ubuntu jammy main

## Provides RabbitMQ
##
deb [signed-by=/usr/share/keyrings/rabbitmq.9F4587F226208342.gpg] https://ppa1.novemberain.com/rabbitmq/rabbitmq-server/deb/ubuntu jammy main
deb-src [signed-by=/usr/share/keyrings/rabbitmq.9F4587F226208342.gpg] https://ppa1.novemberain.com/rabbitmq/rabbitmq-server/deb/ubuntu jammy main
EOF

## Update package indices
sudo apt-get update -y

## Install Erlang packages
sudo apt-get install -y erlang-base \
                        erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \
                        erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \
                        erlang-runtime-tools erlang-snmp erlang-ssl \
                        erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl

## Install rabbitmq-server and its dependencies
sudo apt-get install rabbitmq-server -y --fix-missing

配置檔案在/etc/rabbitmq中,透過rabbitmq-env.conf配置環境,rabbitmq-env.conf如下:

export RABBITMQ_NODENAME=rabbit@localhost
export RABBITMQ_NODE_IP_ADDRESS=127.0.0.1
export ERL_EPMD_ADDRESS=127.0.0.1

客戶端

使用NuGet安裝RabbitMQ.Client

2. 接收者

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

// 工廠方法,用於配置連線
var factory = new ConnectionFactory
{
	// RabbitMQ的服務端地址
    HostName = SharedConfig.Configuration.HostName,
    // 非同步消費
    DispatchConsumersAsync = true
};

// 建立連線
using var connection = factory.CreateConnection();
// 建立通道
var channel = connection.CreateModel();

// 注:XxxDeclare的意思是:沒有就建立,有就複用(由於不知道是Sender還是Receiver先啟動,所以都要宣告)
// 宣告交換機
channel.ExchangeDeclare(exchange: SharedConfig.Configuration.ExchangeName,
    type: SharedConfig.Configuration.ExchangeType);
// 宣告佇列
channel.QueueDeclare(queue: SharedConfig.Configuration.QueueName, durable: true, exclusive: false, autoDelete: false,
    arguments: null);
// 將佇列與交換機繫結
channel.QueueBind(queue: SharedConfig.Configuration.QueueName, exchange: SharedConfig.Configuration.ExchangeName,
    routingKey: SharedConfig.Configuration.EventName);

// 從佇列中獲取訊息(拉取模式)
var asyncEventingBasicConsumer = new AsyncEventingBasicConsumer(channel);
// 訂閱Received事件
asyncEventingBasicConsumer.Received += OnMessageReceived;
// 確認佇列中正在消費的事件狀態(Ack或Reject)
channel.BasicConsume(queue: SharedConfig.Configuration.QueueName, autoAck: false, consumer: asyncEventingBasicConsumer);

Console.ReadLine();

async Task OnMessageReceived(object sender, BasicDeliverEventArgs args)
{
    try
    {
        var bytes = args.Body.ToArray();
        var message = Encoding.UTF8.GetString(bytes);
        Console.WriteLine($"{DateTime.Now}: 收到了訊息-{message}");
        channel.BasicAck(args.DeliveryTag, multiple: false);
        await Task.Delay(800);
    }
    catch (Exception e)
    {
        channel.BasicReject(args.DeliveryTag, true); // 失敗重發
        Console.WriteLine($"處理收到的訊息出錯,{e.Message}");
    }
}

3. 傳送者

using System.Globalization;
using System.Text;
using RabbitMQ.Client;

var connectionFactory = new ConnectionFactory
{
    HostName = SharedConfig.Configuration.HostName,
    DispatchConsumersAsync = true
};
// 和RabbitMQ建立TCP連線
using var connection = connectionFactory.CreateConnection();

// 每間隔3s將當前時間傳送到佇列當中去,共傳送30次
for (int i = 0; i < 30; i++)
{
    // 等待傳送的訊息
    string message = DateTime.Now.ToString(CultureInfo.InvariantCulture);
    // 將訊息重新編碼為RabbitMQ能夠接受的格式(byte[])
    var mqMessage = Encoding.UTF8.GetBytes(message);

    // 建立通道
    using (var channel = connection.CreateModel())
    {
        var properties = channel.CreateBasicProperties();
        // 訊息遞送模式:持久化模式
        properties.DeliveryMode = 2;
        // 宣告交換機
        // 注:XxxDeclare的意思是:沒有就建立,有就複用(由於不知道是Sender還是Receiver先啟動,所以都要宣告)
        channel.ExchangeDeclare(exchange: SharedConfig.Configuration.ExchangeName,
            type: SharedConfig.Configuration.ExchangeType);
        // 釋出訊息
        channel.BasicPublish(exchange: SharedConfig.Configuration.ExchangeName,
            routingKey: SharedConfig.Configuration.EventName, mandatory: true,
            basicProperties: properties, body: mqMessage);
    }

    Console.WriteLine($"釋出了訊息:{message}");
    Thread.Sleep(3000);
}

4. 共用的配置類

namespace SharedConfig;

public struct Configuration
{
    // RabbitMQ的地址,這裡用本地地址和預設埠
    public const string HostName = "localhost";
    // 交換機名稱
    public const string ExchangeName = "exchange1";
    // 交換機型別
    public const string ExchangeType = "direct";
    // 當作routingKey使用(路由的依據)
    public const string EventName = "event1";
    // 佇列名稱
    public const string QueueName = "queue1";
}

相關文章