You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Router绑定inproc地址时,如何向ZeroMQ Workers发送请求?

问题

现有基于ZeroMQ的程序架构如下:

  • Clients (REQ) → Router → Proxy → Dealer → Workers (REP)
  • Router绑定到inproc://router地址
  • Dealer绑定到TCP地址0.0.0.0:5555
  • Workers部署在远程

需要在自己的程序中向Workers发送请求并接收回复,但无法连接到绑定inproc地址的Router,且无法修改现有程序,是否有可行方案?

现有程序的C++实现代码:

#include <chrono>
#include <functional>
#include <thread>
#include <vector>

#include <spdlog/spdlog.h>

#include <zmq.hpp>

void Proxy(zmq::context_t& context)
{
    zmq::socket_t clients { context, zmq::socket_type::router };
    zmq::socket_t workers { context, zmq::socket_type::dealer };

    clients.bind("inproc://router");
    workers.bind("tcp://0.0.0.0:5555");

    zmq::proxy(clients, workers);
}

void Client(zmq::context_t& context)
{
    using namespace std::chrono_literals;

    zmq::socket_t socket { context, zmq::socket_type::req };

    socket.connect("inproc://router");

    for (;;)
    {
        socket.send(zmq::str_buffer("some request"));

        zmq::message_t reply;

        socket.recv(reply);

        spdlog::trace("reply: {}", reply.to_string());

        std::this_thread::sleep_for(1s);
    }
}

void Worker(zmq::context_t& context) // actually located remotely
{
    zmq::socket_t socket { context, zmq::socket_type::rep };

    socket.connect("tcp://localhost:5555");

    for (;;)
    {
        zmq::message_t request;

        socket.recv(request);

        spdlog::trace("request: {}", request.to_string());

        socket.send(zmq::str_buffer("some reply"));
    }
}

int main()
{
    zmq::context_t context { 1 };

    std::jthread proxy { Proxy, std::ref(context) };

    std::vector<std::jthread> workers;

    for (int i = 0; i < 4; ++i)
    {
        workers.emplace_back(Worker, std::ref(context));
    }

    std::vector<std::jthread> clients;

    for (int i = 0; i < 4; ++i)
    {
        clients.emplace_back(Client, std::ref(context));
    }

    return 0;
}

已尝试的方法:自行搭建Router-Proxy-Dealer结构,将Dealer连接到现有Dealer的0.0.0.0:5555地址,向自身Router发送请求。Wireshark确认请求已发送到现有Dealer,但Dealer未转发给Workers,未成功。

求无需从零实现套接字通信的解决方法。


解决方案

现有程序的Proxy逻辑是:Router接收同进程内REQ客户端的单帧请求,自动添加客户端身份帧后转发给Dealer,Dealer再将多帧消息转发给已连接的REP Worker;Worker回复单帧消息,经Dealer、Router原路返回给客户端。

直接连接Dealer失败的原因是:普通REQ套接字发送的单帧消息不符合Dealer期望的多帧格式(身份帧+数据帧),因此不会被转发给Worker。无需修改现有程序的可行方案如下:

核心思路:用DEALER套接字模拟Router的请求格式

创建DEALER类型套接字连接到现有Dealer,按照身份帧+数据帧的格式发送请求,即可被Proxy正常转发到Worker,并接收回复。

示例代码(C++)

#include <zmq.hpp>
#include <spdlog/spdlog.h>
#include <string>

int main() {
    zmq::context_t context{1};
    // 使用DEALER套接字,支持多帧消息发送
    zmq::socket_t custom_client{context, zmq::socket_type::dealer};

    // 替换为现有程序所在主机的IP地址
    std::string dealer_addr = "tcp://127.0.0.1:5555";
    custom_client.connect(dealer_addr);

    // 发送请求:先发送空身份帧(Router会自动为REQ客户端生成身份帧,这里用空帧模拟即可)
    custom_client.send(zmq::message_t(), zmq::send_flags::sndmore);
    // 发送实际请求数据
    custom_client.send(zmq::str_buffer("your custom request content"));

    // 接收Worker的回复
    zmq::message_t reply;
    custom_client.recv(reply);
    spdlog::info("Received worker reply: {}", std::string(static_cast<char*>(reply.data()), reply.size()));

    return 0;
}

原理说明

  • DEALER套接字支持多帧消息发送,符合Proxy中Router转发给Dealer的消息格式(身份帧+数据帧)
  • 现有Dealer收到该多帧消息后,会自动转发给已连接的REP Worker,Worker仅会接收并处理最后一帧的请求数据
  • Worker回复的单帧消息会经Dealer原路返回给你的DEALER套接字,直接接收即可

此方案无需修改现有程序,也无需从零实现完整的套接字代理逻辑,仅需模拟Router的请求格式即可完成通信。


内容的提问来源于stack exchange,提问作者user21152820

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:14:52