现有的一些问题讨论了如何使用ZeroMQ来解决丢弃消息的可能性,而且大多数都非常有启发性。
尽管如此,有一件事让我一直不禁对ZMQ_DEALER套接字感到不安。我一直在测试一个非常简单的情况:1个服务器和2个客户端,每个都使用一个ZMQ_DEALER套接字。服务器发送消息,客户端接收消息。
如果服务器使用socket.bind()和客户端socket.connect(),我们可以观察到正确的循环平衡并杀死其中一个客户端,导致服务器将其所有消息重定向到剩余的客户端。没有延迟,没有丢包,工作得非常好。
现在,如果我有客户端执行socket.bind()和服务器socket.connect()(仍使用一个插槽但连接到两个客户端),则服务器行为会受到影响。杀死其中一个客户端后,不会将其流量重定向到剩余的客户端,而是继续对两者进行负载均衡,直到队列中的消息数达到死客户端的高水位。
在已经绑定的套接字上使用连接的可能性导致我认为它或多或少是对称的用法,但我很想知道这种行为的原因,以及是否有办法复制绑定套接字故障转移到连接套接字。
编辑:为了使问题更具启发性,下面是一些测试此行为的代码。
这是经销商:
// dealer.cc
// compile using something like this: g++ dealer.cc -o dealer -lzmq
#include <zmq.hpp>
#include <unistd.h>
#include <stdint.h>
int main() {
// prepare zmq
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_DEALER);
socket.bind ("tcp://127.0.0.1:5555");
//socket.connect("tcp://127.0.0.1:5555");
//socket.connect("tcp://127.0.0.1:5556");
zmq::message_t msg;
int64_t more;
int counter = 0;
size_t more_size = sizeof more;
bool gotClients = false;
while (true) {
// send incrementing numbers
zmq::message_t world(sizeof(int));
memcpy(world.data(), &counter, sizeof(int));
socket.send(world);
counter++;
usleep(100000);
}
return 0;
}
这是客户:
// client.cc
// compile using something like this: g++ client.cc -o client -lzmq
#include <zmq.hpp>
#include <iostream>
int main(int argc, char ** argv) {
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_DEALER);
socket.connect("tcp://127.0.0.1:5555");
//socket.bind(argv[1]);
zmq::message_t msg;
while (true) {
socket.recv(&msg, 0);
std::cout << "Received a message: " << *(int *)msg.data() << std::endl;
}
return 0;
}
创建2个客户,然后启动经销商,然后杀死其中一个客户,然后杀死经销商。 如果检查输出,则可以看到没有单个消息被丢弃或卡在zmq队列中。只要两个客户端都处于活动状态,负载就会平衡,并在发生“故障”时完全重定向到剩余的负载。
现在让我们将connect()/ bind()交换为它们的反转(使用注释代码)。 我们必须让客户知道要绑定到哪个地址,因此应该使用URL启动它们,如下所示:
./client tcp://127.0.0.1:5555
./client tcp://127.0.0.1:5556
然后,就像以前一样,启动经销商并杀死其中一个客户。 您可以看到,即使在第一个客户端被杀之后,剩下的客户端也只收到了经销商消息的一半。 我的理解是,只要基础ZMQ队列未满,经销商将继续为断开连接的对等体排队消息(在此示例中,并且给定默认参数,将花费相当长的时间)< / p>
答案 0 :(得分:1)
首先,除非您是服务器,否则通常不会绑定,即侦听套接字。所以我不知道你为什么要让客户端绑定。绑定告诉操作系统,当数据包到达特定端口号和特定地址时,您希望在应用中听到它们。这是一个较低的水平,并且比ZeroMQ更普遍,我不相信ZeroMQ改变了这一点。
当你谈论绑定和连接时,你不是在讨论ZeroMQ,而是讨论ZeroMQ消息传输的低级传输。
Connecting to multiple servers from a single client socket C是关于bind的另一个答案。