美文网首页远程控制
ZeroMQ分享-part1

ZeroMQ分享-part1

作者: 分享放大价值 | 来源:发表于2016-09-28 17:17 被阅读416次

    1. ZeroMQ背景知识(version-4.2.0)

    ZMQ(以下ZeroMQ简称ZMQ)是一个简单好用的、轻量级的消息组件,像框架一样的一个socket library。它的本质是个消息处理队列库,在BSD socket基础上做了一层封装,将网络通讯、进程通讯和线程通讯抽象为统一的接口,可在多个线程、内核和主机盒之间弹性伸缩。

    2. ZMQ的几种模型

    • Client-server模型(http://rfc.zeromq.org/spec:41/CLISRV/)
      • client端可以连接一个或多个server。当连接到多个server时,发送数据采用轮询的方式;接收数据采用公平队列按序接收。
      • client端在没有可用连接时会阻塞,或者返回错误。(除非特殊配置)
      • server端可以连接0或多个client。它只能回复client的请求信息,应答数据会送到指定的client端。接收数据采用公平队列按序接受。
      • server端应答时,若client端接收队列已满,会马上返回(重试),不会阻塞。
      • 任何一对client-server都是全双工的,每端都会维护两个队列用于收发数据。
      • 无论哪端,都不会因为不能入队列丢弃消息。
      • client和server套接字是线程安全的。
    • Publish-subscribe模型(http://rfc.zeromq.org/spec:29)
      • pub端向一系列sub或xsub端广播数据,并且只发数据,会丢弃所有从sub端(一般是xsub)发送过来的数据。
      • pub端在sub端接收队列已满的情况下,会丢弃发送数据,不会堵塞。
      • pub端会将数据发送到所有订阅消息的sub端。
      • xpub拓展了pub,可以从同时收发数据。在接收数据时,会将订阅和非订阅的sub端数据提交给应用程序。
      • sub端连接了任意多个pub或xpub端,只会接收数据(除向pub端发送订阅非订阅外),采用公平队列策略。
      • xsub拓展了sub,可以同时收发数据。在pub端接收队列已满的情况下,会丢弃所发送的数据,不会阻塞。
    • Pipline模型(http://rfc.zeromq.org/spec:30)
      • push端采用轮询的方式向任意多个pull端发送数据。
      • push端在没有可用连接时,发送数据会阻塞,或者返回一个错误。
      • push端在无可用连接时不会接收应用程序的数据,因此不会丢弃数据。
      • pull端采用公平队列的方式接收一系列push端的数据。
      • push端不能接收数据,同样,pull端不能发送数据。
    • Exclusive pair模型(http://rfc.zeromq.org/spec:31)
      • peer两端互连,一个用于进程间通讯的模型
      • 当peer进入静音模式时(缓冲区满或未建立连接),任何一方的发送数据都会被阻塞,因此不会丢弃数据。
    • Native模型
      • 用于TCP连接两端进行异步请求和应答的模型。
      • 在将接收到的数据传递给应用程序之前,socket会提前准备一个包含数据发送端id的消息。
      • 在发送消息时,会移除消息的第一部分用于路由选择,再将剩余的消息发送到指定id的接收端。不能路由的消息会返回错误信息并发送失败。
    // Create a new ZMQ context
    void *context = zmq_ctx_new();
    // For client-server pattern
    void *client_receiver = zmq_socket(context, ZMQ_CLIENT)
    void *server_receiver = zmq_socket(context, ZMQ_SERVER)
    // For publish-subscribe pattern
    void *pub_receiver = zmq_socket(context, ZMQ_PUB)
    void *xpub_receiver = zmq_socket(context, ZMQ_XPUB)
    void *sub_receiver = zmq_socket(context, ZMQ_SUB)
    void *xsub_receiver = zmq_socket(context, ZMQ_XSUB)
    // For pipeline pattern
    void *push_receiver = zmq_socket(context, ZMQ_PUSH)
    void *pull_receiver = zmq_socket(context, ZMQ_PULL)
    // For exclusive pair pattern
    void *pair_receiver = zmq_socket(context, ZMQ_PAIR)
    int rc;
    rc = zmq_bind(pair_receiver, "inproc://#1")
    assert(rc == 0);
    rc = zmq_connect(pair_receiver, "inproc://#1")
    assert(rc == 0);
    
    // Native pattern
    void *stream_receiver = zmq_socket(context, ZMQ_STREAM)
    

    3. I/O模型

    • (同步)阻塞式I/O模型
      • 默认情形下,所有的socket都是阻塞的。以用户线程在内核进行IO操作为例,用户在发起read系统调用后发生阻塞,转到内核空间,内核等到数据到达后将数据拷到用户空间,完成操作,线程返回。如下图所示:


        阻塞式I/O模型
    • (同步)非阻塞式I/O模型
      • 通过将socket设置为非阻塞式的,可以在IO不能立即响应时返回一个错误,此时并没有数据返回。用户线程需不断重复发起IO请求,直到数据到达后才能得到真正的数据,剩余部分和阻塞式I/O相同。如下图所示:


        非阻塞式I/O模型
      • 非阻塞式I/O模型一般很少直接使用,往往实在其他模型中使用非阻塞这一特性。因为该模型需要反复发起IO请求,消耗了大量的CPU资源。
    • (同步)I/O复用模型
      • 建立在内核提供的select基础之上,可以避免非阻塞式I/O模型中轮询等待的问题。与阻塞式I/O不同,I/O复用模型会阻塞在select或poll调用处,直到等待的套接字中有变为可读的。如下图所示:


        I/O复用模型
    • 异步I/O模型
      • 异步I/O需要操作系统更强的支持,与I/O复用不同,异步I/O不需要用户线程自行读取数据、处理数据,而是讲这些工作讲给操作系统完成,只接收内核通知I/O事件已经完成。如下图所示:


        异步I/O模型
      • 异步I/O中,用户需要自行编写处理数据的回调程序并递交给操作系统。相比较于I/O复用,异步I/O并十分常用。很多高性能并发服务器使用I/O复用加多线程任务处理的架构基本可以满足需求。

    相关文章

      网友评论

        本文标题:ZeroMQ分享-part1

        本文链接:https://www.haomeiwen.com/subject/batkyttx.html