当我使用ZeroMQ

时间:2015-04-22 12:31:13

标签: fork zeromq

我有一个监听ZeroMQ套接字的简单应用程序。当客户端连接并请求工作节点时,我 fork() 我的流程,分叉的子进程会创建一个新的 context 和一个新的ZeroMQ socket 即可。客户端和工作节点对REQ执行 REP - socket 正式行为。

我的问题是我如何能够优雅地处理我的工作节点的关闭。

客户端向我的工作节点发送EXIT消息,该节点需要关闭其socket及其context(?)

从我所看到的,子进程退出但是,新客户现在无法与我原来的父进程通信。

Psuedo Code

while (looping) {
    zmq::message_t request;
    try {
        socket.recv(&request);  // Wait
        string reqStr = string(static_cast<char *>(request.data()), request.size());
        if (reqStr.compare("exit") == 0) {
            LOG(INFO) << "exiting.." << endl;
            looping = false;
        }

        LOG(INFO) << "******************************************************************" << endl;
        LOG(INFO) << "Received request for an endpoint " << reqStr << endl;
        int port = doFork(reqStr);
        if (port > 0) {
            LOG(INFO) << "Returning endPoint: " << reqStr << " on port: " << port << endl;
            string result = NumberToString(port);
            zmq::message_t reply(result.length());
            memcpy((void *) reply.data(), result.c_str(), result.length());
            socket.send(reply);
        }
        else {
            // Child Process exiting OR error in Fork"
            looping = false;
            child = true;
        }

    }
    catch (zmq::error_t &e) {
        LOG(INFO) << "W: Caught Exception OR Interrupt: " << e.what() << " : and pid is " << getpid() << endl;
    }
}
if (!child) {
    socket.close();
    context.close();
    LOG(INFO) << "Closed socket and context for pid " << getpid() << endl;
}}

int Forker::doFork(string reqStr) {
pid_t pid;
int port = ++startingPort;

switch (pid = fork()) {
    case -1:
        LOG(INFO) << "Error in fork";
        return -1;

    case 0:
        LOG(INFO) << "Created child process with pid: " << getpid() << endl;
        {
            ServicePtr servicePtr(new Service(NumberToString(port)));
            LOG(INFO) << "Spawning on port: " << port << endl;
            servicePtr->spawn();
        }
        LOG(INFO) << "Child Process exiting on port: " << port << endl;
        return 0;

    default:
        LOG(INFO) << "Parent process. My process id is " << getpid() << endl;
}
return port;

}

1 个答案:

答案 0 :(得分:0)

你的伪代码不足以在任何地方获得很多 - 特别是你没有在那里定义你的套接字,所以我甚至不知道哪一边是REQ而哪一边是{{1} (或者,实际上,您实际上正在使用这些套接字类型),或者哪个边绑定以及哪个边连接。

但是,我的第一个猜测是你的发送/接收配对不均匀,发生以下情况:

  1. 客户端绑定REP套接字,工作连接REQ套接字
  2. 客户端发送请求(客户端希望REP下一步)
  3. 工作人员发送响应(客户端希望recv下一步)
  4. 客户端发送跟进消息(客户端希望send下一步)
  5. 工人关闭
  6. 新工人旋转
  7. 客户端发送请求(ERROR - recv套接字严格发送/接收订购)
  8. IF 这是导致您出现问题的原因,您可以确保回复以重置客户端套接字,也可以使用REQ套接字而不是DEALER