ZeroMQ介绍

来源:互联网 发布:mac pro测评 编辑:程序博客网 时间:2024/06/05 10:52

ZeroMQ介绍

一.介绍

MQ有很多种,比如MSMQ,ActiveMQ,RabbitMQ等等

今天主要介绍的MQ是ZeroMQ,其具有一个独特的非中间件的模式,不需要安装和运行一个消息服务器,或中间件。你只需要简单的引用ZeroMQ程序库,然后你就可以愉快的在应用程序之间发送消息了,因此部署是非常简单的。就性能上来说比其他几个MQ要强的非常多。

ZeroMQ,新一层的网络堆栈,轻量级,socket风格的接口,支持多种消息传送模式,如:P2P,订阅发布模式以及请求-响应模式等等,支持多种底层协议,支持多种平台和CPU架构。

 

二.模型

服务端:

public classServer {

         publicstatic voidmain(String[] args)throws Exception{

                  // Prepare our context andsockets

                  final ZMQ.Context context=ZMQ.context(1);

                  ZMQ.Socket socket= context.socket(ZMQ.REP);

                  socket.bind("tcp://*:5555"); 

                  while (true){

                           byte[]request= socket.recv(0);

                           System.out.println(newString(request));

                           while (socket.hasReceiveMore()){

                                    request =socket.recv(0);

                                    System.out.println(newString(request));

                           }

                           String s= new String(request);

                           long r= Long.parseLong(s)+ 100;

                       // reply = request+100

                           socket.send(String.valueOf(r).getBytes(),0);

                  }

        }

}

客户端:

public classClient {

         publicstatic voidmain(String[] args){

                  // Prepare our context andsocket

                  final ZMQ.Context context=ZMQ.context(1);

                  ZMQ.Socket socket= context.socket(ZMQ.REQ); 

                  System.out.println("Connecting tohello world server...");

                  socket.connect("tcp://localhost:5555"); 

                  while (true){

                           long l= System.nanoTime();

                           String s= String.valueOf(l);

                           socket.send(s.getBytes(),0);

                           byte[] r= socket.recv(0);

                           System.out.println(l+ " + 100 = "+newString(r));

               }

       }

}

三.设计模式

ZeroMQ 把通讯的需求看成四类。其中一类是一对一结对通讯,用来支持传统的 TCP socket模型,但并不推荐使用。常用的通讯模式只有三类

1.    请求回应模型。由请求端发起请求,并等待回应端回应请求。从请求端来看,一定是一对收发配对的;反之,在回应端一定是发收对。请求端和回应端都可以是 1:N的模型。通常把 1 认为是 server N 认为是 ClientZeroMQ 可以很好的支持路由功能(实现路由功能的组件叫作 Device),把 1:N扩展为 N:M (只需要加入若干路由节点)。从这个模型看,更底层的端点地址是对上层隐藏的。每个请求都隐含有回应地址,而应用则不关心它。

2.    发布订阅模型。这个模型里,发布端是单向只发送数据的,且不关心是否把全部的信息都发送给订阅端。如果发布端开始发布信息的时候,订阅端尚未连接上来,这些信息直接丢弃。不过一旦订阅端连接上来,中间会保证没有信息丢失。同样,订阅端则只负责接收,而不能反馈。如果发布端和订阅端需要交互(比如要确认订阅者是否已经连接上),则使用额外的 socket 采用请求回应模型满足这个需求。

3.    管道模型。这个模型里,管道是单向的,从 PUSH端单向的向 PULL 端单向的推送数据流。如果有多个client端同时连接到这个server,则服务器会在内部做一个负载均衡,采用平均分配的算法,将所有的消息均衡发布到client端上

2,3两种模式中,无论是server端还是client端在启动时 都是不知道client实际数量的,这就意味着,一个使用zeromq搭建的服务,可以进行”热更新”.

 

1)request-reply
就是一般的C/S架构中,client与server之间一问一答的通信模式,比如最经典的echo服务.需要注意的是,client发送一个request,server必须有一个回应.
这个pattern并不是什么亮点,下面亮点来了.

2)publish-subscribe
server端作为publish端,而任何连接到服务端的client都会成为subscribe端.也就是说,server端会把当前的所有需要publish出去的消息全部发送到当前连接上去的client上.

3)push-pull
server端作为push端,而client端作为pull端.如果有多个client端同时连接到这个server,则服务器会在内部做一个负载均衡,采用平均分配的算法,将所有的消息均衡发布到client端上.

看上去,很稀松平常?接下来亮点真的来了.
2),3)两种模式中,无论是server端还是client端在启动时 都是不知道client实际数量的,这就意味着,一个使用zeromq搭建的服务,可以进行”热更新”.
考虑如下一种场景.一个server端做为一组服务器集群最上层的一个proxy,起到负载均衡的作用,将请求按照它下面对应服务器集群依次派发到不同的 client端进行处理.某个时刻可能处理的机器只有2台,而随着负载越来越大,可能需要3台机器了,这个时候如果使用zeromq的push-pull 搭建的proxy端,则可以不用对之前搭建的server,client端进行停机,只需要新启动一个client连接上去,proxy层就会自动根据当 前的机器分配平均派发任务了.cool.

实际上,这些模式并不是什么新东西,只不过zeromq为使用者做了一个封装,而不是像libevent,ACE等还局限在网络层部分的封装,它关注的是通信层,通信模式等.



四.搭建安装

Linux安装

下载地址:http://download.zeromq.org/zeromq-2.1.7.tar.gz

解压后下载文件

cd zeromq-2.1.7

./configure --prefix=/usr/local/zeromq

make

make install

 

Window安装:

下载地址:http://download.zeromq.org/zeromq-2.1.7.zip

需要C编译环境,VC2008或者MinGW,RubyInstall中的DevKit

下载MinGW

地址: http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/mingw-get-inst/mingw-get-inst-20110530/mingw-get-inst-20110530.exe/download

点击打开,根据需要选择下载的功能,开始安装下载(需要网络)

安装完毕后,在window环境变量中设置PATH路径

下载DevKit

地址:http://rubyinstaller.org/downloads

下载exe文件安装即可,在Window环境变量中设置PATH路径

 

五.支持的客户端

 

C,C++,JAVA,PHP,Python,Ruby,C#,Erlang,Perl等等

 

六.运行(Linux系统,Java为例)

 

前提:需要定义环境变量JAVA_HOME

  需要先安装zeromq

下载jzero:https://github.com/zeromq/jzmq

解压下载文件

cd zeromq-jzmq-59616d9

$ ./autogen.sh

$ ./configure --prefix=/opt/jzmq --with-zeromq=/usr/local/zeromq

回车运行后,如果缺少什么会有提示,根据提示解决就可以

比如 zmq.h 缺少,那就是证明 --with-zeromq配置不正确

Java找不到,说JAVA_HOME没有设置正确

$ make

$ make install

 

编译完成,编写测试java文件

package com.jzmq;

import org.zeromq.ZMQ;

import org.zeromq.ZMQQueue;

public class MqQueue {  

    public static void main(String[] args) {

        ZMQ.Context context =ZMQ.context(1);

        ZMQ.Socket clients =context.socket(ZMQ.XREP);

        clients.bind("inproc://gate_clients");

        ZMQ.Socket workers =context.socket(ZMQ.XREQ);

        workers.bind("inproc://gate_workers");

        ZMQ.Socket client =context.socket(ZMQ.REQ);

        client.connect("inproc://gate_clients");

        ZMQ.Socket worker =context.socket(ZMQ.REP);

        worker.connect("inproc://gate_workers");

        Thread t = new Thread(new ZMQQueue(context, clients,workers));

            t.start();

            for (int i = 0; i < 100; i++) {

                byte[] req = ("request" + i).getBytes();

                byte[] rsp = ("response" + i).getBytes();

                client.send(req, 0);

                // worker receives request

                byte[] reqTmp = worker.recv(0);

                System.out.println(new String(reqTmp));

                // worker sends response

                worker.send(rsp, 0);

                // client receives response

                byte[] rspTmp = client.recv(0);

                System.out.println(new String(rspTmp));

            }      

        t.interrupt();
        }

}

编译前准备

设置exportJAVA_HOME=/usr/java/jdk1.6.0.22

设置exportCLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:/usr/local/zeromq/share/java/zmq.jar:.

设置exportLD_LIBRARY_PATH=/opt/jzmq/lib/:/usr/local/zeromq/lib/

 

javac com/jzmq/MqQueue.java

java com.jzmq.MqQueue

response0

request1

response1

request2

response2

request3

response3

..............

0 0