zoukankan      html  css  js  c++  java
  • ZeroMQ:现代而快速的网络栈 标签: zeromqzeroMQZeroMQZMQ 20130122 17:37 3483人阅读 评

    ZeroMQ:现代而快速的网络栈

    Berkeley Socket(BSD)是所有网络通信共同使用的API。建立于20世纪80年代初期,它是TCP/IP协议族的原始实现,是目前任何操作系统广泛支持的必备组件。BSD套接字中我们最熟悉的是点对点连接,它需要显式的建立,断开,选择传输协议(TCP,UDP),错误处理,等等。当解决了上述问题,你就来到了应用层协议(例如 HTTP)的世界,需要额外的组帧,缓冲,以及处理逻辑。换句话说,难怪高性能的网络程序写起来一点都不简单。

    如果我们可以将各种套接字类型,连接处理,组帧,甚至是路由等底层细节抽象出来岂不是很棒?这就是 ZeroMQ(ØMQ/ZMQ)网络库产生的初衷:“它提供横跨各种传输层运载消息的套接字:进程内通信(INPROC),进程间通信(IPC),TCP,多播(multicast);你还可以使用诸如扇出(fanout),发布订阅(pubsub),任务分发(task distribution)和请求应答(request-reply)等模式建立多对多的连接。”真是一大堆流行术语,那么就让我们来更详细的讨论一下其中的一些概念。

    面向消息 vs 流和数据报

    ZeroMQ socket 在传统 socket API 之上提供了一层抽象,能够隐藏很多我们被迫在程序中重复的复杂日常样板。首先,ZeroMQ通讯是面向消息的,而不是面向流(TCP)数据报(UDP)的。这意味着,如果一个客户端套接字发送一个150KB的消息,那么服务端套接字将在另一头收到一个完整的一致的消息,而无需实现任何显式的缓冲或组帧(framing)。当然,我们仍然可以实现流传输接口,但这样做需要一个显式的应用层协议。

    # create zeromq request / reply socket pair
    ctx = ZMQ::Context.new
    req = ctx.socket ZMQ::REQ
    rep = ctx.socket ZMQ::REP
    
    # connect sockets: notice that reply can connect first even with no server!
    rep.connect('tcp://127.0.0.1:5555')
    req.bind('tcp://127.0.0.1:5555')
    req.send ZMQ::Message.new('hello' * (1024*1024))
    
    msg = ZMQ::Message.new
    rep.recv(msg)
    msg.copy_out_string.size # => 5242880
    

    从流传输/数据报转到面向消息的模型看起来是个微小的改变,但承载了很多意义。因为ZeroMQ将为你处理所有的缓冲和组帧,客户端和服务器程序将成数量级的变得更简单,更安全,更加容易编写。

    套接字无关的传输

    ZeroMQ套接字也是与传输层无关的:有一个单独、统一的API来对所有协议发送接收消息。默认支持进程内(inproc),进程间(IPC),多播TCP,在其中切换就像更改连接串前缀那么简单。这意味着我们用最小代价就可以先用IPC快速的本地通信,然后在分布式情况下可以随时切换到TCP。一个额外的好处是,ZeroMQ在底层处理所有的连接建立,断开和重连逻辑。就是这么简单。

    路由和拓扑敏感的套接字

    ZeroMQ套接字对路由和网络拓扑敏感。既然我们不需要明确的管理点对点连接状态——全都被库抽象了,如上述——那么让一个单独的ZeroMQ套接字绑定到两个不同端口来监听入站的请求就没有任何阻碍了,或者反之,通过一个单独的API调用发送数据到两个不同套接字。ZeroMQ怎么知道监听谁,或将数据推送给谁?这取决于我们为程序挑选的套接字对的类型:请求/应答,发布/订阅,管道,和配对(alpha)。

    ctx = ZMQ::Context.new
    
    # create publisher socket, and publish to two pipes!
    pub = ctx.socket(ZMQ::PUB)
    pub.bind('tcp://127.0.0.1:5000')
    pub.bind('inproc://some.pipe')
    
    # generate random message, ex: '1 9'
    Thread.new { loop { pub.send [rand(2), rand(10)].join(' ') } }
    
    # create a consumer, and listen for messages whose key is '1'
    sub = ctx.socket(ZMQ::SUB)
    sub.connect('inproc://some.pipe')
    sub.setsockopt(ZMQ::SUBSCRIBE, '1')
    
    loop { p sub.recv } # => "1 9" ...
    

    当使用发布/订阅套接字配对的情况下(单向通信:从发布者到订阅者),发布者套接字会将消息发送给所有连接的客户(本地IPC客户端,远程TCP监听器等)。当使用请求/应答套接字配对的情况下(双向通信:服务器、客户端),消息会由套接字自动负载均衡并生成请求到其中一个连接的客户端。最后一种,推送/拉取套接字配对(管道:单向、负载均衡)将允许你模拟带有内嵌负载均衡的分段消息传递结构。

    ZeroMQ允许我们通过套接字API直接将服务拓扑编码,无需定义维护一个分离的用于协调路由、负载均衡、消息中介的层级。当然,ZeroMQ也不阻止我们任意组合使用这些工具,但是在很多情况下,ZeroMQ方式可以获取更佳性能且大大简化操作复杂性。

    ZeroMQ底层

    默认情况下,ZeroMQ的所有通信都是以异步方式完成的。要启用的话,在创建带有ZeroMQ的应用程序时,需要明确定义后台I/O线程的数量——多数情况下,一个专用的I/O线程就够用了。所有线程逻辑都由链接库的C++核心本身来处理,但这意味着,你的程序最起码将有两个调度线程。

    这种异步处理模型允许ZeroMQ能够将所有连接建立,中断,重连的逻辑抽象出来,同时也能最小化消息传递延迟:非阻塞意味着消息的分发,传递和排队(发送方或接收方)可以与应用程序的常规过程并行处理。当然,你也可以通过为每一个套接字设置允许使用的内存限制甚至是交换区大小,来控制ZeroMQ套接字的队列行为。因此,如有必要你可以模拟出阻塞API,但异步I/O是默认值。组合了零拷贝语义,优化的组帧,非阻塞数据结构,最终结果是一个带有现代API的,高性能且面向吞吐量的中间件。

    ZeroMQ在野外:Mongrel2

    Mongrel2提供了将ZeroMQ引入web-service世界的有趣案例研究:所有入站请求都由Mongrel2路由,通过一个自动将请求负载均衡到已连接处理器的“推送”套接字。这些处理器依次处理到来的请求(通过拉取套接字)并将他们发布到一个“发布者”套接字,Mongrel2服务器自己订阅和监听该套接字的进程ID(通过主题过滤器)。

    因此,处理过程不是像我们通常做法那样绑定到简单的请求-响应循环,那样的话就不得不用一个单独的后台从头到尾处理全部请求。相反,我们可以设置几个处理阶段 (通过管道模式),并且仅当所有阶段处理完毕后才发出我们的答复。

    雄心勃勃且值得探索

    毫无疑问ZeroMQ是一个雄心勃勃的项目,这个简短的介绍仅仅触及到完整功能集的表层。ZeroMQ的既定目标是“成为标准网络栈的一部分,然后是Linux内核”。他们能否成功还有待观察,但绝对是在“传统”BSD套接字之上的一个非常富有前途,可以说是迫切需要的抽象层。ZeroMQ让编写高性能网络应用变得极为简单有趣。

    开始使用ZeroMQ的最好的办法是通过一些实际操作的例子——概念不新,但用它来做创作时的轻松舒适倒是可能需要你适应一下。对于Ruby开发者,Andrew Cholakian整合了已经制作了一个大量示例集来让你起步(也可从dripdrop检出),对于其他人,访问ZeroMQ网站,获取你的语言绑定然后潜入到源码中。


    伊利亚·Grigorik是一个网络性能工程师,被谷歌的"让网络更快"团队所推崇,在那里他日以继夜的致力于让网络更快速和推动性能最佳实践的采纳。
    关注@igrigorik

  • 相关阅读:
    vs要用报表功能
    汉字与字节
    php 实现excel导入导出
    php 判断是否是手机端和电脑端访问
    php getimagesize image_type_to_extension 等函数不能用
    php 处理base64图片信息
    php 百度编辑器ueditor-dev-1.5.0编译版细节流程
    react 可拖拽改变位置和大小的弹窗
    Java 进制转换
    Java自动装箱测试
  • 原文地址:https://www.cnblogs.com/zerofire/p/7162166.html
Copyright © 2011-2022 走看看