NestJS中使用RabbitMQ实现无端口微服务间连接方案咨询
基于RabbitMQ实现无暴露端口微服务间通信方案
核心逻辑
你现在的场景不需要做服务之间的直接TCP连接——毕竟你已经把服务配置成不对外暴露端口了,完全可以复用你现有网关对接服务的思路:所有服务仅作为RabbitMQ客户端主动和MQ Broker建立长连接,所有跨服务调用流量全部走RabbitMQ转发,服务本身不需要监听任何端口,网络层面只需要放通服务到RabbitMQ的出口规则即可。
落地步骤
- 统一消息协议
直接复用你网关到服务已经在用的消息体结构就行,必须包含几个核心字段:全局请求ID(用于链路追踪、请求响应匹配)、目标服务标识、调用方法标识、请求参数、超时时间。不用重新设计协议,减少重复开发。 - 被调用方配置
每个服务启动后,主动在RabbitMQ上声明一个和自身服务ID绑定的专属队列,建议设置为排他、自动删除属性,服务下线时队列会自动清理,不需要人工维护。
以Spring AMQP为例的核心实现代码:
整个过程被调用方不需要绑定任何对外服务端口,只需要维持和RabbitMQ的客户端连接即可。// 服务启动时初始化专属队列,队列名可直接拼接服务唯一标识,比如service.queue.order、service.queue.user Queue serviceOwnQueue = QueueBuilder.nonDurable("service.queue." + currentServiceId) .exclusive() .autoDelete() .build(); amqpAdmin.declareQueue(serviceOwnQueue); // 监听专属队列的请求,处理完成后直接把响应发回请求指定的返回队列 @RabbitListener(queues = "#{serviceOwnQueue.name}") public Message processIncomingRequest(Message request) { // 解析请求参数、调用本地对应业务方法、封装响应 return MessageBuilder.withBody(objectMapper.writeValueAsBytes(responseData)) .setHeader("requestId", request.getMessageProperties().getHeader("requestId")) .build(); } - 调用方配置
服务需要调用其他服务时,不需要做目标服务的网络探测、直连操作,直接把请求消息发送到RabbitMQ默认交换机,路由键填目标服务的专属队列名即可,同时通过RabbitMQ自带的replyTo机制指定自身的响应接收队列,用请求ID作为关联标识匹配请求和响应:// 构造请求消息,携带自身响应队列地址、全局请求ID CorrelationData requestTrace = new CorrelationData(globalRequestId); Message requestMsg = MessageBuilder.withBody(objectMapper.writeValueAsBytes(requestParams)) .setHeader("requestId", globalRequestId) .setReplyTo(selfResponseQueueName) // 调用方自己监听的响应队列 .build(); // 发送消息到目标服务队列,等待响应 rabbitTemplate.convertAndSend("", "service.queue." + targetServiceId, requestMsg, requestTrace); // 本地维护请求ID和CompletableFuture的映射,收到对应响应后直接触发future完成,返回给业务层 - 必要配置项
- 服务主机侧除了RabbitMQ客户端的出口连接外,拒绝所有入站端口访问,符合无对外端口的安全要求
- 开启RabbitMQ生产者确认、消费者手动ACK机制,避免消息丢失
- 给所有跨服务调用设置合理的超时时间,防止调用方永久阻塞
- 多实例部署同一个服务时,给对应队列配置单活消费者,避免消息重复投递
可选优化点
- 不需要额外部署服务注册中心,直接通过RabbitMQ的队列查询接口就能拿到当前在线的服务列表(只要队列存在就代表对应服务实例在线),省掉注册中心的运维成本
- 直接复用网关层的链路追踪逻辑,跨服务调用时在消息头透传全局请求ID,就能实现全链路日志追踪
- 可以给不同优先级的请求设置不同的队列优先级,适配核心接口的调度要求
注意:这个架构下不存在服务之间的直接网络连接,所有流量都经RabbitMQ中转,和你已经实现的网关到服务链路逻辑完全一致,改造成本极低,完全适配你当前服务不对外暴露端口的部署要求。
内容的提问来源于stack exchange,提问作者Binni kumari
相关产品推荐
相关产品推荐

