zeromq簡介

zeroMQ不是TCP,不是socket,也不是消息隊列,而是這些的綜合體。

ZeroMQ以嵌入式網絡編程庫的形式實現了一個並行開發框架(concurrency framework),
能夠提供進程內(inproc)、進程間(IPC)、網絡(TCP)和廣播方式的消息信道,
並支持扇出(fan-out)、發佈-訂閱(pub-sub)、任務分發(task distribution)、請求/響應(request-reply)等通信模式。

ZeroMQ的異步I/O模型能夠爲多核消息系統提供足夠的擴展性。

ZeroMQ支持30多種語言的API,可以用於絕大多數操作系統。

與socket對比

ZeroMQ提供了類似於Socket的一系列接口,他跟Socket的區別是:普通的socket是端到端的(1:1的關係),而ZMQ卻是可以N:M 的關係,人們對BSD套接字的瞭解較多的是點對點的連接,點對點連接需要顯式地建立連接、銷燬連接、選擇協議(TCP/UDP)和處理錯誤等,而ZMQ屏蔽了這些細節,讓你的網絡編程更爲簡單。ZMQ用於node與node間的通信,node可以是主機或者是進程。

ZeroMQ特點

ZeroMQ是一個傳輸層API庫,
更關注消息的傳輸。與消息隊列相比,ZeroMQ有以下一些特點:

1 點對點無中間節點.

傳統的消息隊列都需要一個消息服務器來存儲轉發消息。而ZeroMQ則放棄了這個模式,把側重點放在了點對點的消息傳輸上。

ZeroMQ能緩存消息,但是是在發送端緩存。ZeroMQ裏有水位設置的相關接口來控制緩存量。當然,ZeroMQ也支持傳統的消息隊列(通過zmq_device來實現)。

2 強調消息收發模式

在點對點的消息傳輸上ZeroMQ將通信的模式做了歸納,比如常見的訂閱模式(一個消息發多個客戶),分發模式(N個消息平均分給X個客戶)等等。下面是目前支持的消息模式配對,任何一方都可以做爲服務端。

  • PUB and SUB
  • REQ and REP
  • REQ and ROUTER (take care, REQ inserts an extra null frame)
  • DEALER and REP (take care, REP assumes a null frame)
  • DEALER and ROUTER
  • DEALER and DEALER
  • ROUTER and ROUTER
  • PUSH and PULL
  • PAIR and PAIR
    XPUB and XSUB是PUB and SUB的弱版本。

4種基本消息模式

ZeroMQ將消息通信分成4種模型,分別是一對一結對模型(Exclusive-Pair )、請求迴應模型(Request-Reply)、發佈訂閱模型(Publish-Subscribe)、推拉模型(Push-Pull)

Request-Reply請求迴應模型

由請求端發起請求,然後等待迴應端應答。一個請求必須對應一個迴應,從請求端的角度來看是發-收配對,從迴應端的角度是收-發對。跟一對一結對模型的區別在於請求端可以是1~N個。

應用場景:該模型主要用於遠程調用及任務分配等。Echo服務就是這種經典模型的應用。
image

Publish-Subscribe發佈訂閱模型

發佈端單向分發數據,且不關心是否把全部信息發送給訂閱端。如果發佈端開始發佈信息時,訂閱端尚未連接上來,則這些信息會被直接丟棄。訂閱端未連接導致信息丟失的問題,可以通過與請求迴應模型組合來解決。訂閱端只負責接收,而不能反饋,且在訂閱端消費速度慢於發佈端的情況下,會在訂閱端堆積數據。

應用場景:該模型主要用於數據分發。天氣預報、微博明星粉絲可以應用這種經典模型。
image

注意事項:在此種模式在,SUB端在建立連接後,需要先訂閱,才能接收消息,否則接收不到消息。示例如下:

ZMQ.Context context = ZMQ.context(1);
Socket subscriber = context.socket(ZMQ.SUB);
subscriber.connect("tcp://localhost:5557");
subscriber.subscribe("".getBytes());
int total = 0;
while (true) {
    byte[] bytes = subscriber.recv(0);
}

Subscribe按不同的topic主題過濾

//Publish端發送不同的topic主題
publisher.sendMore("access_point");
publisher.send(ipAddress.toByteArray(), ZMQ.NOBLOCK);
       
//topic filter過濾:根據topic過濾,不同的Subscribe訂閱不同的數據    
subscriber.subscribe("access_point".getBytes());
while (true) {
    //接收topic
    byte[] bytesTopic  = subscriber.recv(0);
    // 接收數據
    byte[] bytesData = subscriber.recv(0);
}

Parallel Pipeline PUSH-PULL推拉模型 分而治之

Server端作爲Push端,而Client端作爲Pull端,如果有多個Client端同時連接到Server端,則Server端會在內部做一個負載均衡,採用平均分配的算法,將所有消息均衡發佈到Client端上。與發佈訂閱模型相比,推拉模型在沒有消費者的情況下,發佈的消息不會被消耗掉;在消費者能力不夠的情況下,能夠提供多消費者並行消費解決方案。

應用場景:該模型主要用於多任務並行。
image

pair :The Relay Race

信號模式一定是一對一的,這種模式可以代替信號量和互斥鎖,用於協調線程。

image

安裝

使用時,注意將防火牆端口關閉。

在CentOS下使用ZeroMQ

centos 安裝 zeromq jzmq

#install zeromq
tar -xzf zeromq-2.1.7.tar.gz
cd zeromq-2.1.7
#./configure --prefix=/usr/local/zeromq  #按照此種方式,會報錯,搞不定。
./configure
yum -y install libuuid-devel ##如果報錯uuid-dev,安裝此程序
make & make install

#install jzmq
(yum -y install libtool)
git clone https://github.com/nathanmarz/jzmq.git
cd jzmq
./autogen.sh
./configure 
make & make install

測試

/ddhome/usr/jzmq/perf
sh local_lat.sh tcp://127.0.0.1:5000 1 100
    如果報以下錯誤:
    Exception in thread "main" java.lang.UnsatisfiedLinkError: no jzmq in java.library.path
            at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)
            at java.lang.Runtime.loadLibrary0(Runtime.java:823)
            at java.lang.System.loadLibrary(System.java:1028)
            at org.zeromq.ZMQ.<clinit>(ZMQ.java:34)
            at local_lat.main(local_lat.java:36)
    解決方案:(不是必選項)
    vi ~/.bashrc 
    export LD_LIBRARY_PATH=/usr/local/lib

報錯:錯誤: 找不到或無法加載主類 remote_lat。這是因爲未執行./configure

sh remote_lat.sh tcp://127.0.0.1:5000 1 100

#出現下面信息,則測試成功
message size: 1 [B]            #####說明測試成功
roundtrip count: 100
mean latency: 140.0 [us]

在Windows10下使用ZeroMQ

本人只使用zeromq client接收數據,故未做編譯安裝,參考 ZeroMQ(Java)使用個人小心得,這裏Mark一下(適用於windows64bit及32bit),下載已編譯好的文件。

已經編譯好的文件,一般是三個:jzmq.dll,libzmq.dll,zmq.jar文件(這個maven中有)

兩個dll文件放在jdk放置目錄:%JAVA_HOME%/bin/.dll

<dependency>
    <groupId>org.zeromq</groupId>
    <artifactId>jzmq</artifactId>
    <version>2.2.0</version>
</dependency>

即可在idea中運行java代碼編寫的zeromq.


ZeroMQ進階

iothread設置

When you create a new context, it starts with one I/O thread. The general rule of thumb is to allow one I/O thread per gigabyte of data in or out per second.

ZMQ.Context context = ZMQ.context(1); //1是iothread

Number of threads to use, usually 1 is sufficient for most use cases.
public static Context context(int ioThreads) {
        return new Context(ioThreads);
}

安全認證

zmq_plain(7)

clear-text authentication明文認證 Authentication Using SASL

The PLAIN mechanism defines a simple username/password mechanism that lets a server authenticate a client. PLAIN makes no attempt at security or confidentiality. It is intended for use on internal networks where security requirements are low. The PLAIN mechanism is defined by this document: http://rfc.zeromq.org/spec:24.內網使用,安全性低。

zmq_curve(7)

secure authentication and confidentiality安全的認證方式和保密方式

The CURVE mechanism defines a mechanism for secure authentication and confidentiality for communications between a client and a server. CURVE is intended for use on public networks. The CURVE mechanism is defined by this document: http://rfc.zeromq.org/spec:25.公網使用。

Pub-Sub Network with a Proxy 請求-應答代理

兩種方式來連接多個客戶端和多個服務端。

  • 第一種是讓客戶端通過負載均衡與多個服務端進行連接。
    image
  • 第二種是請求-應答代理會將兩個套接字分別綁定到前端和後端,供客戶端和服務端套接字連接。代理裝置必須要是非阻塞式的。這種方式靈活性更好。
    image

The Request-Reply Mechanisms 高級請求-應答模式

聯邦模式和同伴模式

image

The Naming Ceremony

 

 

The State Flow狀態流

image

參考文獻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章