First, the official website: http://www.rabbitmq.com/
Then. NET Client link: http://www.rabbitmq.com/dotnet.html
GitHub warehouse: https://github.com/rabbitmq/rabbitmq-dotnet-client
Next, I will go directly to the text. There are two themes: how to write for consumers? How to write for producers?
Consumer
In dotnet core mvc, consumers must not start through API or other things, and should start with the program
So...
In dotnet core 2.0 and above, we directly use IHostedService interface
- Implementation of background timing task based on IHostedService in. NET Core
- Implementing background tasks in .NET Core 2.x webapps or microservices with IHostedService and the BackgroundService class
Code directly
// RabbitListener.cs is the base class, which only implements the Process of registering RabbitMQ and listening to messages, and then each consumer rewrites the RouteKey/QueueName / message processing function using System; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using RabbitMQ.Client; using RabbitMQ.Client.Events; namespace Test.Listener { public class RabbitListener : IHostedService { private readonly IConnection connection; private readonly IModel channel; public RabbitListener(IOptions<AppConfiguration> options) { try { var factory = new ConnectionFactory() { // This is my configuration. Just change it to my own use HostName = options.Value.RabbitHost, UserName = options.Value.RabbitUserName, Password = options.Value.RabbitPassword, Port = options.Value.RabbitPort, }; this.connection = factory.CreateConnection(); this.channel = connection.CreateModel(); } catch (Exception ex) { Console.WriteLine($"RabbitListener init error,ex:{ex.Message}"); } } public Task StartAsync(CancellationToken cancellationToken) { Register(); return Task.CompletedTask; } protected string RouteKey; protected string QueueName; // How to process messages public virtual bool Process(string message) { throw new NotImplementedException(); } // Registered consumer monitoring here public void Register() { Console.WriteLine($"RabbitListener register,routeKey:{RouteKey}"); channel.ExchangeDeclare(exchange: "message", type: "topic"); channel.QueueDeclare(queue:QueueName, exclusive: false); channel.QueueBind(queue: QueueName, exchange: "message", routingKey: RouteKey); var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body); var result = Process(message); if (result) { channel.BasicAck(ea.DeliveryTag, false); } }; channel.BasicConsume(queue: QueueName, consumer: consumer); } public void DeRegister() { this.connection.Close(); } public Task StopAsync(CancellationToken cancellationToken) { this.connection.Close(); return Task.CompletedTask; } } } // Post a subclass casually using System; using System.Text; using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; using RabbitMQ.Client; using RabbitMQ.Client.Events; using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace Test.Listener { public class ChapterLister : RabbitListener { private readonly ILogger<RabbitListener> _logger; // Because the Process function is a delegate callback, if you inject other services directly, they are not in the same scope, // To call other Service instances here, you can only get instance objects after IServiceProvider CreateScope private readonly IServiceProvider _services; public ChapterLister(IServiceProvider services, IOptions<AppConfiguration> options, ILogger<RabbitListener> logger) : base(options) { base.RouteKey = "done.task"; base.QueueName = "lemonnovelapi.chapter"; _logger = logger; _services = services; } public override bool Process(string message) { var taskMessage = JToken.Parse(message); if (taskMessage == null) { // When false is returned, the message is rejected directly, indicating that it cannot be processed return false; } try { using (var scope = _services.CreateScope()) { var xxxService = scope.ServiceProvider.GetRequiredService<XXXXService>(); return true; } } catch (Exception ex) { _logger.LogInformation($"Process fail,error:{ex.Message},stackTrace:{ex.StackTrace},message:{message}"); _logger.LogError(-1, ex, "Process fail"); return false; } } } }
Then, remember
When injecting to Startup.cs, use AddHostedService
services.AddHostedService<ChapterLister>();
This is how consumers play
How do producers play?
This is actually simpler
using System; using System.Net; using Newtonsoft.Json.Linq; using RestSharp; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using RabbitMQ.Client; using Newtonsoft.Json; using System.Text; namespace Test.SDK { public class RabbitMQClient { private readonly IModel _channel; private readonly ILogger _logger; public RabbitMQClient(IOptions<AppConfiguration> options, ILogger<RabbitMQClient> logger) { try { var factory = new ConnectionFactory() { HostName = options.Value.RabbitHost, UserName = options.Value.RabbitUserName, Password = options.Value.RabbitPassword, Port = options.Value.RabbitPort, }; var connection = factory.CreateConnection(); _channel = connection.CreateModel(); } catch (Exception ex) { logger.LogError(-1, ex, "RabbitMQClient init fail"); } _logger = logger; } public virtual void PushMessage(string routingKey, object message) { _logger.LogInformation($"PushMessage,routingKey:{routingKey}"); _channel.QueueDeclare(queue: "message", durable: false, exclusive: false, autoDelete: false, arguments: null); string msgJson = JsonConvert.SerializeObject(message); var body = Encoding.UTF8.GetBytes(msgJson); _channel.BasicPublish(exchange: "message", routingKey: routingKey, basicProperties: null, body: body); } } }
Remember to use the singleton mode when injecting instances
services.AddSingleton<RabbitMQClient, RabbitMQClient>();
The full text is finished.