本文图片来源网络,侵权联系删除
一、ZeroMQ简介:
是一个处理数据传输的库,重点在传输上,看起来它像是在socket上面封装了一层,让我们可以很容易的利用它来做N对M的数据传输,在分布式系统中很方便,在接收端它有round-robin负载均衡。
号称最快的消息队列系统,专门为高吞吐量/低延迟的场景开发,在金融界的应用中经常使用,偏重于实时数据通信场景。
优点:
缺点:
三、灵活的组网架构:
常用的三种基本模型:
扩展模型
四、三种基本模型:
请求应答模型(Request-Reply):
该模型和我们经常见到的CS有点像,双方可以相互发送数据;
代码示例:
#ifdef WIN32
void
#else
void*
#endif
thread_client(void* args)
{
void* context = zmq_ctx_new(); //zmq_init(2);
//zmq_ctx_set();
void* request = zmq_socket(context, ZMQ_REQ);
int ret = zmq_connect(request, "tcp://127.0.0.1:9527");
printf("%d zmq_connect:%d\n", GETTID(), ret);
for (int i = 0; i < 10; i++) {
char buffer[1024] = "client request!\n";
ret = zmq_send(request, buffer, strlen(buffer), 0);
printf("%d zmq_send:%d %s", GETTID(), ret, buffer);
ret = zmq_recv(request, buffer, sizeof(buffer), 0);
printf("%d zmq_recv:%d %s\n", GETTID(), ret, buffer);
SLEEP(100);
}
ret = zmq_send(request, "exit", 4, ZMQ_DONTWAIT);
printf("%d zmq_send:%d exit\n", GETTID(), ret);
ret = zmq_close(request);
printf("%d zmq_close:%d exit\n", GETTID(), ret);
ret = zmq_ctx_destroy(context);
//zmq_term()
//zmq_ctx_term(context);
printf("%d zmq_ctx_destroy:%d exit\n", GETTID(), ret);
printf("%d exit\n", GETTID());
THREADEND();
}
#ifdef WIN32
void
#else
void*
#endif
thread_server(void* args)
{
void* context = zmq_ctx_new();
void* reply = zmq_socket(context, ZMQ_REP);
int ret = zmq_bind(reply, "tcp://*:9527");
printf("zmq_bind:%d\n", ret);
int i = 1;
while (true) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
zmq_recv(reply, buffer, sizeof(buffer), 0);
printf("data from client:%s\n", buffer);
if (strcmp(buffer, "exit") == 0) {
//zmq_recv(reply, buffer, sizeof(buffer), 0);
break;
}
char ack[64] = "";
snprintf(ack, sizeof(ack), "server reply:ok! %d\n", i++);
zmq_send(reply, ack, strlen(ack), 0);
}
SLEEP(500);
printf("server close!\n");
zmq_close(reply);
zmq_ctx_destroy(context);
printf("%d server exit\n", GETTID());
THREADEND();
}
订阅发布模型:也叫广播订阅模式
发布订阅模型的数据流向是单向的,发布者负责发布topic消息,也就是说发布者只能给订阅者发送消息,而不能接收订阅者的消息;
订阅者只能订阅消息,只能接收订阅了发布者有的topic,不能向发布者发布消息.
#ifdef WIN32
void
#else
void*
#endif
thread_publish(void* args)
{
void* context = zmq_init(4);
void* publish = zmq_socket(context, ZMQ_PUB);
zmq_bind(publish, "tcp://*:9527");
SLEEP(100);
char message[64] = "";
for (int i = 0; i < 10; i++) {
snprintf(message, sizeof(message), "The %d Message!", i + 1);
zmq_send(publish, message, strlen(message), 0);
SLEEP(100);
}
zmq_send(publish, "exit", 4, 0);
SLEEP(100);
zmq_close(publish);
zmq_ctx_destroy(context);
THREADEND();
}
#ifdef WIN32
void
#else
void*
#endif
thread_subscribe(void* args)
{
void* context = zmq_init(4);
void* subscriber = zmq_socket(context, ZMQ_SUB);
zmq_connect(subscriber, "tcp://localhost:9527");
zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
while (true) {
char buf[64] = "";
zmq_recv(subscriber, buf, sizeof(buf), 0);
printf("%d recv:%s\n", GETTID(), buf);
if (strcmp(buf, "exit") == 0) {
break;
}
}
zmq_close(subscriber);
zmq_ctx_destroy(context);
THREADEND();
}
流水线模型:也可以理解为分治
流水线模型: 可以是一个大任务划分为多个子任务worker,子任务之间的互相关联的,最后这些worker将结果push到slink进行组装,使得整个大任务的完成,如果添加了多个不同的任务,这些任务是可以并发执行的。
也可以是同一个任务,比如造车,可能需要用不同的原料、不同的颜色等,也是可以直接push给worker的。
这三个worker可以是做不同的事情:比如做自行车:
1.造轮子 2.造屁股坐 3.造支架,最后进行sink组装。
当然也可以做相同的事情,这样看起来只是单纯的并发。
举个例子:将本地的文件通过网络发送给其他用户,任务切割如下:
优点:提高CPU的并行处理,充分利用CPU资源。
代码示例:
#ifdef WIN32
void
#else
void*
#endif
thread_push(void* args)
{
void* context = zmq_ctx_new();
void* push = zmq_socket(context, ZMQ_PUSH);
zmq_bind(push, "tcp://*:9527");
for (int i = 0; i < 10; i++) {
zmq_msg_t msg;
zmq_msg_init_size(&msg, 6);
memcpy(zmq_msg_data(&msg), "hello!", 6);
zmq_msg_send(&msg, push, 0);
SLEEP(100);
zmq_msg_close(&msg);
}
zmq_msg_t msg;
zmq_msg_init_size(&msg, 4);
memcpy(zmq_msg_data(&msg), "exit", 4);
zmq_msg_send(&msg, push, 0);
zmq_msg_close(&msg);
zmq_close(push);
zmq_ctx_destroy(context);
THREADEND();
}
#ifdef WIN32
void
#else
void*
#endif
thread_pull(void* args) {
void* context = zmq_ctx_new();
void* pull = zmq_socket(context, ZMQ_PULL);
zmq_connect(pull, "tcp://localhost:9527");
while (true) {
zmq_msg_t msg;
zmq_msg_init(&msg);
zmq_msg_recv(&msg, pull, 0);
char pData[128] = "";
memcpy(pData, zmq_msg_data(&msg), zmq_msg_size(&msg));
zmq_msg_close(&msg);
printf("%s\n", pData);
if (strcmp(pData, "exit") == 0) {
break;
}
}
zmq_close(pull);
zmq_ctx_destroy(context);
THREADEND();
}
补充: Zeromq可以同时添加很多的任务,并发数线程数可以在设置上下文的时候指定。
函数接口说明
官网
想了解消息中间件的可以点这里,网上一篇不错的文章
下一篇文章聊聊zeromq的几个扩展模型。