基于 RabbitMQ 实现高性能可靠的 RPC 远程调用(.NET 完整实战 + 最佳实践)

在分布式系统开发中,RPC(远程过程调用) 是实现服务间通信的核心方式之一,而 RabbitMQ 作为一款成熟的消息队列中间件,不仅能实现异步消息投递,也能完美实现标准的 RPC 调用模式。

与传统的 HTTP RPC、gRPC 相比,基于 RabbitMQ 实现的 RPC 具备解耦、高可用、天然重试、负载均衡、异步非阻塞等核心优势,非常适合在分布式服务、跨进程通信、物联网设备指令调用等场景中落地。

本文将从原理到实战,完整讲解 RabbitMQ 实现 RPC 的核心机制,同时提供一套 符合 C# 编码规范、基于.NET 异步编程模型、可直接上生产环境 的完整 RabbitMQ RPC 封装代码,包含客户端 + 服务端全量实现,以及最佳实践和避坑指南。

一、RabbitMQ 实现 RPC 的核心原理

RabbitMQ 本身是异步的消息队列,但通过三大核心机制的组合,就能完美实现「客户端发起请求、同步等待响应、服务端处理并返回结果」的 RPC 核心诉求,这也是 RabbitMQ 官方文档中推荐的标准 RPC 实现方案。

✅ 核心实现三要素

1. CorrelationId(唯一请求标识,核心中的核心)

客户端发起每次 RPC 请求时,生成一个全局唯一的CorrelationId(通常用 Guid)并随消息一起发送;服务端处理完成后,原样带回该 ID 到响应消息中。客户端通过这个 ID 可以精准匹配「当前响应对应哪一次请求」,彻底解决响应错乱的问题,是实现 RPC 的基石。

2. ReplyTo(指定响应回调地址)

客户端发送请求时,通过消息属性ReplyTo指定「服务端处理完成后,将响应消息发送到哪个队列 / 路由键」;服务端从请求消息中读取该地址,处理完业务逻辑后,将响应结果发送到这个地址即可。

3. TaskCompletionSource(异步转同步等待)

这是.NET 中实现「异步等待结果」的核心类,客户端发送请求后,创建TaskCompletionSource对象并缓存,随后进入异步等待状态;当监听到对应CorrelationId的响应消息时,通过该对象唤醒等待并返回结果,全程无同步线程阻塞,高并发友好。

✅ RabbitMQ RPC 完整调用流程

  1. 客户端生成唯一CorrelationId,创建TaskCompletionSource并缓存,封装请求消息(参数 + CorrelationId+ReplyTo)发送到请求队列;
  2. 服务端监听请求队列,收到消息后执行业务处理逻辑,得到返回结果;
  3. 服务端从请求消息中读取ReplyToCorrelationId,封装响应消息发送到指定的响应队列;
  4. 客户端监听响应队列,匹配到对应CorrelationId的响应消息后,唤醒等待的请求并返回结果;
  5. 客户端清理本次请求的缓存对象,完成一次 RPC 调用。

二、核心特性说明(本次封装的 RPC 组件)

本次封装的RabbitMqRpcService是一套生产级的 RabbitMQ RPC 完整实现,基于.NET6 + 异步编程模型开发,完全遵循 C# 编码规范和 RabbitMQ 最佳实践,具备以下核心特性,开箱即用:✅ 客户端 + 服务端一体化封装,一套代码支持 RPC 调用与服务提供;✅ 基于业务编码businessCode实现多业务隔离,不同业务独立队列,互不干扰;✅ 完全异步编程模型,无同步阻塞,支持超高并发调用;✅ 完善的超时控制、异常捕获、日志记录,生产环境可追溯;✅ 通道 / 消费者复用机制,避免重复创建 RabbitMQ 资源,提升性能;✅ 严格实现 IDisposable 接口,资源自动释放,杜绝内存泄漏;✅ 支持 RabbitMQ 连接自动恢复、网络重连,高可用保障;✅ 手动 ACK 确认机制,消息零丢失,可靠性拉满;✅ 无侵入式设计,调用简单,耦合度极低。

三、完整封装代码(生产级可直接复制)

3.1 代码结构说明

  • 命名空间:SPC.AbpComponets.RPC.RabbitMQ
  • 核心类:RabbitMqRpcService 密封类,实现IRabbitMqRpcService接口,包含客户端 + 服务端全部逻辑;
  • 配置基类:RabbitMqRpcConfigBase 抽离 RabbitMQ 连接工厂配置,解耦配置逻辑;
  • 接口约束:IRabbitMqRpcService 规范对外暴露的 RPC 调用和服务启动方法。

3.2 全量完整代码

cs 复制代码
using System;
using System.Collections.Concurrent;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using RabbitMQ.Client.Exceptions;

namespace SPC.AbpComponets.RPC.RabbitMQ
{
    /// <summary>
    /// RabbitMQ 实现的RPC远程调用服务(客户端+服务端一体化)
    /// 遵循RabbitMQ官方RPC规范:CorrelationId+ReplyTo 实现请求响应绑定
    /// 完全异步编程模型,支持业务隔离、自动重连、资源自动释放、超时控制、消息可靠投递
    /// </summary>
    public sealed class RabbitMqRpcService : RabbitMqRpcConfigBase, IRabbitMqRpcService, IDisposable
    {
        #region 常量定义 - 杜绝魔法字符串/魔法值,规范核心
        private const string ExchangeRpcName = "rpc";
        private const string RequestQueuePrefix = "rpc_request_queue_";
        private const string ResponseQueuePrefix = "rpc_response_queue_";
        private const string RequestRoutingKeyPrefix = "rpc_request_key_";
        private const string ResponseRoutingKeyPrefix = "rpc_response_key_";
        private const string DefaultBusinessCode = "DEFAULT";
        private const int MinTimeoutSeconds = 1;
        private const int MaxTimeoutSeconds = 300;
        private const int ResponseMessageExpirationSeconds = 600;
        private const int ResourceReleaseTimeoutMs = 1000;
        #endregion

        #region 私有字段 - 只读化+命名规范+按需私有化
        private readonly IConnection _rabbitConnection;
        private readonly ILogger<RabbitMqRpcService> _logger;
        private readonly ConcurrentDictionary<string, IChannel> _channelCache = new ConcurrentDictionary<string, IChannel>();
        private readonly ConcurrentDictionary<string, AsyncEventingBasicConsumer> _responseConsumerCache = new ConcurrentDictionary<string, AsyncEventingBasicConsumer>();
        private readonly ConcurrentDictionary<string, AsyncEventingBasicConsumer> _serverConsumerCache = new ConcurrentDictionary<string, AsyncEventingBasicConsumer>();
        private static readonly ConcurrentDictionary<string, TaskCompletionSource<string>> _pendingRequests = new ConcurrentDictionary<string, TaskCompletionSource<string>>();

        private bool _isDisposed;
        #endregion

        /// <summary>
        /// 构造函数 - 依赖注入初始化,禁止手动实例化
        /// </summary>
        /// <param name="configuration">配置文件</param>
        /// <param name="logger">日志对象</param>
        public RabbitMqRpcService(IConfiguration configuration, ILogger<RabbitMqRpcService> logger = null)
        {
            _logger = logger;
            var connectionFactory = CreateConnectionFactory(configuration);
            _rabbitConnection = CreateRabbitConnection(connectionFactory);
            
            // 注册连接生命周期事件,主动释放资源
            _rabbitConnection.ConnectionShutdown += (sender, args) => ReleaseAllResources();
            _rabbitConnection.CallbackException += (sender, args) => _logger?.LogError(args.Exception, "RabbitMQ连接回调异常");
            _rabbitConnection.ConnectionBlocked += (sender, args) => _logger?.LogWarning("RabbitMQ连接被阻塞:{0}", args.Reason);
        }

        #region 核心规范:严格实现IDisposable接口 - 资源释放标准写法
        /// <inheritdoc />
        public void Dispose()
        {
            if (_isDisposed) return;

            ReleaseAllResources();
            _isDisposed = true;
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放所有RabbitMQ相关资源(连接、通道、消费者、等待任务)
        /// 线程安全,幂等调用,可重复执行,无副作用
        /// </summary>
        private void ReleaseAllResources()
        {
            try
            {
                // 1. 释放所有缓存的通道
                if (_channelCache.Count > 0)
                {
                    foreach (var (cacheKey, channel) in _channelCache)
                    {
                        if (channel is not null && channel.IsOpen)
                        {
                            _ = channel.CloseAsync().WaitAsync(TimeSpan.FromMilliseconds(ResourceReleaseTimeoutMs));
                            _ = channel.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromMilliseconds(ResourceReleaseTimeoutMs));
                        }
                    }
                    _channelCache.Clear();
                }

                // 2. 取消所有待处理的RPC请求,避免内存泄漏
                if (_pendingRequests.Count > 0)
                {
                    foreach (var tcs in _pendingRequests.Values)
                    {
                        _ = tcs.TrySetCanceled();
                    }
                    _pendingRequests.Clear();
                }

                // 3. 释放RabbitMQ主连接
                if (_rabbitConnection is not null && _rabbitConnection.IsOpen)
                {
                    _ = _rabbitConnection.CloseAsync().WaitAsync(TimeSpan.FromMilliseconds(ResourceReleaseTimeoutMs));
                    _rabbitConnection.Dispose();
                }

                _logger?.LogInformation("RabbitMQ RPC所有资源释放完成");
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "RabbitMQ RPC资源释放过程中发生异常");
            }
        }
        #endregion

        #region 私有核心方法:获取RabbitMQ通道 - 复用+创建+队列交换机声明
        /// <summary>
        /// 获取指定业务编码的RabbitMQ通道,通道复用机制,不存在则创建并声明交换机/队列/绑定关系
        /// </summary>
        /// <param name="connection">RabbitMQ连接</param>
        /// <param name="businessCode">业务隔离编码</param>
        /// <returns>可用的RabbitMQ通道</returns>
        private async Task<IChannel> GetChannelAsync(IConnection connection, string businessCode = "")
        {
            if (connection is null || !connection.IsOpen)
            {
                _logger?.LogError("RabbitMQ连接已关闭或为空,无法获取通道");
                return null;
            }

            var cacheKey = string.IsNullOrWhiteSpace(businessCode) ? DefaultBusinessCode : businessCode;

            // 通道复用:存在且可用则直接返回,提升性能
            if (_channelCache.TryGetValue(cacheKey, out var existChannel) && existChannel.IsOpen)
            {
                return existChannel;
            }

            try
            {
                var channel = await connection.CreateChannelAsync();

                // 声明持久化交换机:direct类型,RPC专用
                await channel.ExchangeDeclareAsync(
                    exchange: ExchangeRpcName,
                    type: ExchangeType.Direct,
                    durable: true,
                    autoDelete: false);

                // 声明请求队列+绑定路由键
                var requestQueueName = $"{RequestQueuePrefix}{cacheKey}";
                var requestRoutingKey = $"{RequestRoutingKeyPrefix}{cacheKey}";
                await channel.QueueDeclareAsync(
                    queue: requestQueueName,
                    durable: true,
                    exclusive: false,
                    autoDelete: false,
                    arguments: null);
                await channel.QueueBindAsync(requestQueueName, ExchangeRpcName, requestRoutingKey);

                // 声明响应队列+绑定路由键
                var responseQueueName = $"{ResponseQueuePrefix}{cacheKey}";
                var responseRoutingKey = $"{ResponseRoutingKeyPrefix}{cacheKey}";
                await channel.QueueDeclareAsync(
                    queue: responseQueueName,
                    durable: true,
                    exclusive: false,
                    autoDelete: false,
                    arguments: null);
                await channel.QueueBindAsync(responseQueueName, ExchangeRpcName, responseRoutingKey);

                // 缓存通道
                _channelCache[cacheKey] = channel;
                _logger?.LogDebug("RabbitMQ通道创建并缓存成功,业务编码:{0}", businessCode);

                return channel;
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "RabbitMQ通道创建失败,业务编码:{0}", businessCode);
                return null;
            }
        }
        #endregion

        #region 私有核心方法:创建响应消息消费者 - 监听响应队列,匹配并唤醒RPC请求
        /// <summary>
        /// 创建并初始化响应消息消费者,持续监听指定队列的响应消息
        /// </summary>
        private async Task<AsyncEventingBasicConsumer> CreateResponseConsumerAsync(IChannel channel, string queueName)
        {
            if (channel is null || !channel.IsOpen || string.IsNullOrWhiteSpace(queueName))
            {
                _logger?.LogWarning("创建响应消费者失败:通道不可用或队列为空");
                return null;
            }

            var consumer = new AsyncEventingBasicConsumer(channel);
            consumer.ReceivedAsync += async (sender, eventArgs) => await HandleResponseMessageAsync(channel, eventArgs);

            // 启动消费:手动确认模式,确保消息可靠消费
            await channel.BasicConsumeAsync(queue: queueName, autoAck: false, consumer: consumer);
            return consumer;
        }

        /// <summary>
        /// 处理响应队列的消息,匹配CorrelationId并唤醒对应的RPC请求
        /// </summary>
        private async Task HandleResponseMessageAsync(IChannel channel, BasicDeliverEventArgs eventArgs)
        {
            try
            {
                var messageBody = Encoding.UTF8.GetString(eventArgs.Body.ToArray());
                var messageProps = eventArgs.BasicProperties;
                var correlationId = messageProps.CorrelationId;

                // 匹配并唤醒对应的RPC请求
                if (!string.IsNullOrWhiteSpace(correlationId) && _pendingRequests.TryRemove(correlationId, out var tcs))
                {
                    _ = tcs.TrySetResult(messageBody);
                    await channel.BasicAckAsync(eventArgs.DeliveryTag, multiple: false);
                    _logger?.LogDebug("RPC响应消息处理成功,CorrelationId:{0},响应内容:{1}", correlationId, messageBody);
                }
                else
                {
                    // 无法匹配的消息,重新放回队列
                    await channel.BasicNackAsync(eventArgs.DeliveryTag, multiple: false, requeue: true);
                    _logger?.LogWarning("收到无法匹配的RPC响应消息,CorrelationId:{0}", correlationId);
                }
            }
            catch (Exception ex)
            {
                // 消费异常,消息重新入队,避免丢失
                await channel.BasicNackAsync(eventArgs.DeliveryTag, multiple: false, requeue: true);
                _logger?.LogError(ex, "处理RPC响应消息时发生异常");
            }
        }
        #endregion

        #region 对外实现:RPC客户端调用 - 发送请求并异步等待响应(核心业务)
        /// <inheritdoc />
        public async Task<string> RpcClientAsync(string requestMessage, string businessCode = "", int timeoutSeconds = 60)
        {
            // 1. 入参合法性校验
            if (string.IsNullOrWhiteSpace(requestMessage))
            {
                const string errorMsg = "RPC请求消息不能为空";
                _logger?.LogWarning(errorMsg);
                return $"error:{errorMsg}";
            }

            // 2. 超时参数兜底,防止非法值
            timeoutSeconds = Math.Clamp(timeoutSeconds, MinTimeoutSeconds, MaxTimeoutSeconds);
            var messageExpirationMs = timeoutSeconds * 1000;
            var correlationId = Guid.NewGuid().ToString("N");
            var cacheKey = string.IsNullOrWhiteSpace(businessCode) ? DefaultBusinessCode : businessCode;
            var responseResult = string.Empty;

            try
            {
                // 3. 获取可用通道
                var channel = await GetChannelAsync(_rabbitConnection, businessCode);
                if (channel is null || !channel.IsOpen)
                {
                    const string errorMsg = "获取RabbitMQ通道失败,无法发送RPC请求";
                    _logger?.LogError(errorMsg);
                    return $"error:{errorMsg}";
                }

                // 4. 初始化响应消费者(单例,只创建一次)
                if (!_responseConsumerCache.TryGetValue(cacheKey, out var consumer) || consumer.Model is null || !consumer.Model.IsOpen)
                {
                    var responseQueueName = $"{ResponseQueuePrefix}{cacheKey}";
                    consumer = await CreateResponseConsumerAsync(channel, responseQueueName);
                    _responseConsumerCache[cacheKey] = consumer;
                }

                // 5. 构建请求消息属性
                var requestProps = channel.CreateBasicProperties();
                requestProps.Persistent = true;
                requestProps.CorrelationId = correlationId;
                requestProps.ReplyTo = $"{ResponseRoutingKeyPrefix}{cacheKey}";
                requestProps.Expiration = messageExpirationMs.ToString();

                // 6. 创建异步等待任务并缓存
                var tcs = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
                if (!_pendingRequests.TryAdd(correlationId, tcs))
                {
                    var errorMsg = $"RPC请求ID重复,创建等待任务失败,CorrelationId:{correlationId}";
                    _logger?.LogError(errorMsg);
                    return $"error:{errorMsg}";
                }

                // 7. 发送RPC请求消息
                var requestRoutingKey = $"{RequestRoutingKeyPrefix}{cacheKey}";
                var requestBody = Encoding.UTF8.GetBytes(requestMessage);
                await channel.BasicPublishAsync(ExchangeRpcName, requestRoutingKey, mandatory: false, requestProps, requestBody);

                _logger?.LogDebug("RPC请求发送成功,业务编码:{0},超时时间:{1}秒,CorrelationId:{2}", businessCode, timeoutSeconds, correlationId);

                // 8. 异步等待响应,带超时控制
                using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));
                var responseTask = tcs.Task;
                await responseTask.WaitAsync(cancellationTokenSource.Token);
                responseResult = responseTask.Result;
            }
            catch (OperationCanceledException)
            {
                var errorMsg = $"RPC请求超时,{timeoutSeconds}秒内未收到响应";
                _logger?.LogWarning("{0},业务编码:{1},CorrelationId:{2}", errorMsg, businessCode, correlationId);
                responseResult = $"timeout:{errorMsg}";
            }
            catch (BrokerUnreachableException ex)
            {
                var errorMsg = $"RabbitMQ服务不可达:{ex.Message}";
                _logger?.LogError(ex, errorMsg);
                responseResult = $"error:{errorMsg}";
            }
            catch (AlreadyClosedException ex)
            {
                var errorMsg = $"RabbitMQ通道已关闭:{ex.Message}";
                _logger?.LogError(ex, errorMsg);
                responseResult = $"error:{errorMsg}";
            }
            catch (Exception ex)
            {
                var errorMsg = $"RPC请求处理异常:{ex.Message}";
                _logger?.LogError(ex, "{0},业务编码:{1}", errorMsg, businessCode);
                responseResult = $"exception:{errorMsg}";
            }
            finally
            {
                // 无论成败,必须移除等待任务,杜绝内存泄漏
                if (_pendingRequests.TryRemove(correlationId, out _))
                {
                    _logger?.LogDebug("RPC请求任务已释放,CorrelationId:{0}", correlationId);
                }
            }

            return responseResult;
        }
        #endregion

        #region 对外实现:RPC服务端启动 - 监听请求队列并处理业务逻辑(核心业务)
        /// <inheritdoc />
        public async Task RpcServerAsync(Func<string, string> businessHandler, string businessCode = "")
        {
            // 入参校验:业务处理委托不能为空
            if (businessHandler is null)
            {
                const string errorMsg = "RPC服务端业务处理委托不能为空";
                _logger?.LogError(errorMsg);
                throw new ArgumentNullException(nameof(businessHandler), errorMsg);
            }

            var cacheKey = string.IsNullOrWhiteSpace(businessCode) ? DefaultBusinessCode : businessCode;

            // 服务端消费者复用:已存在则直接返回,避免重复创建
            if (_serverConsumerCache.TryGetValue(cacheKey, out var existConsumer) 
                && existConsumer.Model is not null 
                && existConsumer.Model.IsOpen)
            {
                _logger?.LogDebug("RPC服务端消费者已存在,无需重复创建,业务编码:{0}", businessCode);
                return;
            }

            // 获取可用通道
            var channel = await GetChannelAsync(_rabbitConnection, businessCode);
            if (channel is null || !channel.IsOpen)
            {
                _logger?.LogError("RPC服务端启动失败:获取RabbitMQ通道失败,业务编码:{0}", businessCode);
                return;
            }

            var requestQueueName = $"{RequestQueuePrefix}{cacheKey}";
            var consumer = new AsyncEventingBasicConsumer(channel);

            // 注册请求消息处理事件
            consumer.ReceivedAsync += async (sender, eventArgs) => 
                await HandleRequestMessageAsync(channel, eventArgs, businessHandler);

            // 启动消费:手动确认模式,确保消息可靠消费
            await channel.BasicConsumeAsync(queue: requestQueueName, autoAck: false, consumer: consumer);
            _serverConsumerCache[cacheKey] = consumer;

            _logger?.LogInformation("RPC服务端启动成功,业务编码:{0},监听队列:{1}", businessCode, requestQueueName);
        }

        /// <summary>
        /// 处理请求队列的消息,执行业务逻辑并返回响应结果
        /// </summary>
        private async Task HandleRequestMessageAsync(IChannel channel, BasicDeliverEventArgs eventArgs, Func<string, string> businessHandler)
        {
            try
            {
                var requestMessage = Encoding.UTF8.GetString(eventArgs.Body.ToArray());
                var requestProps = eventArgs.BasicProperties;
                var replyToRoutingKey = requestProps.ReplyTo;
                var correlationId = requestProps.CorrelationId;

                // 无回调地址,直接确认消息并丢弃
                if (string.IsNullOrWhiteSpace(replyToRoutingKey))
                {
                    await channel.BasicAckAsync(eventArgs.DeliveryTag, multiple: false);
                    _logger?.LogWarning("RPC请求无回调地址,已丢弃,CorrelationId:{0}", correlationId);
                    return;
                }

                // 执行业务逻辑
                var responseMessage = businessHandler.Invoke(requestMessage);
                _logger?.LogDebug("RPC请求处理完成,CorrelationId:{0},请求内容:{1},响应内容:{2}", correlationId, requestMessage, responseMessage);

                // 构建响应消息属性
                var responseProps = channel.CreateBasicProperties();
                responseProps.Persistent = true;
                responseProps.CorrelationId = correlationId;
                responseProps.Expiration = ResponseMessageExpirationSeconds.ToString();

                // 发送响应消息
                var responseBody = Encoding.UTF8.GetBytes(responseMessage);
                await channel.BasicPublishAsync(ExchangeRpcName, replyToRoutingKey, mandatory: false, responseProps, responseBody);

                // 手动确认消息消费完成
                await channel.BasicAckAsync(eventArgs.DeliveryTag, multiple: false);
            }
            catch (Exception ex)
            {
                // 业务处理异常,消息重新入队重试
                await channel.BasicNackAsync(eventArgs.DeliveryTag, multiple: false, requeue: true);
                _logger?.LogError(ex, "处理RPC请求消息时发生异常");
            }
        }
        #endregion

        #region 私有辅助方法:创建RabbitMQ连接 - 同步安全创建
        /// <summary>
        /// 安全创建RabbitMQ连接,异步转同步无死锁
        /// </summary>
        private IConnection CreateRabbitConnection(IConnectionFactory factory)
        {
            try
            {
                return Task.Run(async () => await factory.CreateConnectionAsync()).GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "RabbitMQ连接创建失败");
                throw new InvalidOperationException("RabbitMQ连接初始化失败,请检查配置", ex);
            }
        }
        #endregion
    }

    /// <summary>
    /// RabbitMQ连接配置基类
    /// </summary>
    public abstract class RabbitMqRpcConfigBase
    {
        /// <summary>
        /// 创建RabbitMQ连接工厂,配置自动重连、心跳等核心参数
        /// </summary>
        protected IConnectionFactory CreateConnectionFactory(IConfiguration configuration)
        {
            return new ConnectionFactory
            {
                HostName = configuration["RabbitMQ:HostName"] ?? "localhost",
                Port = int.Parse(configuration["RabbitMQ:Port"] ?? "5672"),
                UserName = configuration["RabbitMQ:UserName"] ?? "guest",
                Password = configuration["RabbitMQ:Password"] ?? "guest",
                VirtualHost = configuration["RabbitMQ:VirtualHost"] ?? "/",
                DispatchConsumersAsync = true, // 必须开启:支持异步消费者
                AutomaticRecoveryEnabled = true, // 自动恢复连接,高可用核心
                NetworkRecoveryInterval = TimeSpan.FromSeconds(5), // 网络恢复间隔
                RequestedHeartbeat = TimeSpan.FromSeconds(60) // 心跳检测,防止连接断开
            };
        }
    }

    /// <summary>
    /// RabbitMQ RPC服务接口规范
    /// </summary>
    public interface IRabbitMqRpcService
    {
        /// <summary>
        /// RPC客户端调用,发送请求并异步等待响应
        /// </summary>
        /// <param name="requestMessage">请求消息内容</param>
        /// <param name="businessCode">业务隔离编码</param>
        /// <param name="timeoutSeconds">超时时间(秒)</param>
        /// <returns>响应消息内容</returns>
        Task<string> RpcClientAsync(string requestMessage, string businessCode = "", int timeoutSeconds = 60);

        /// <summary>
        /// RPC服务端启动,监听指定业务的请求队列
        /// </summary>
        /// <param name="businessHandler">业务处理委托</param>
        /// <param name="businessCode">业务隔离编码</param>
        Task RpcServerAsync(Func<string, string> businessHandler, string businessCode = "");
    }
}
相关推荐
脏脏a9 小时前
手撕 vector:从 0 到 1 模拟实现 STL 容器
开发语言·c++·vector
爱说实话9 小时前
C# 20260109
开发语言·c#
superman超哥9 小时前
Rust VecDeque 的环形缓冲区设计:高效双端队列的奥秘
开发语言·后端·rust·rust vecdeque·环形缓冲区设计·高效双端队列
星辰烈龙9 小时前
黑马程序员JavaSE基础加强d6
java·开发语言
电商API&Tina9 小时前
电商数据采集 API:驱动选品、定价、运营的数据分析核心引擎
大数据·开发语言·人工智能·python·数据分析·json
半路程序员9 小时前
Go内存泄漏排查pprof和trace使用
开发语言·后端·golang
沐知全栈开发9 小时前
PHP MySQL 插入数据
开发语言
WongLeer9 小时前
Go + GORM 多级分类实现方案对比:内存建树、循环查询与 Preload
开发语言·后端·mysql·golang·gorm
小罗和阿泽10 小时前
Java项目 简易图书管理系统
java·开发语言