好,现在看看真实的代码。
(defn connect
[server-url]
(let [ctx (ZMQ/context 1)
worker-url (str "inproc://" (java.util.UUID/randomUUID))
queue-thread (Thread.
(fn []
(let [client-sock (.socket ctx ZMQ/DEALER)
worker-sock (.socket ctx ZMQ/ROUTER)]
(.connect client-sock server-url)
(.bind worker-sock worker-url)
(.run (ZMQQueue. ctx client-sock worker-sock)))))]
(.start queue-thread)
{:ctx ctx
:worker-url worker-url
:queue-thread queue-thread}))
(defn disconnect
"Useful for tests etc. Pass the map returned by `connect` above."
[connection]
(.interrupt (get connection :queue-thread))
(.term (get connection :ctx)))
(defn with-req-sock
"Takes the connection and a higher order function that is passed a new REQ
socket. When this function returns, the REQ socket is destroyed."
[connection handler]
(let [socket (.socket (get connection :ctx) ZMQ/REQ)]
(.connect socket (get connection :worker-url))
(try
(handler socket)
(finally (.close socket)))))
;; Usage
(def connection (connect "tcp://127.0.0.1:1337"))
(dotimes [n 5]
(.start
(Thread.
(fn []
(with-req-sock connection
(fn [sock]
(.send sock (.getBytes (str "Hello, " n)) 0)
(let [res (.recv sock 0)]
(println (String. res))))))))) (connectserver-url)创建了一些新连接。我们为我们的进程创建了一个单独的连接,让后在我们需要进行请求的时候把请求传给它。我们对每个请求创建一个新的REQ套接字,然后使用"inproc://"发送消息给ROUTER。ROUTER然后前转消息给DEALER(像以前一样通过ZMQQueue)。DEALER通过TCP连接真正的服务器。 要注意的几个事项:
如果你运行这段代码,那么在你的终端将交叉的插入输出。这是因为请求和应答同时发生。
另外,线程间除了inproc的url外没有其他状态共享,我们真正要做的一切是在它们之间发送ZeroMQ消息。
正如上面已经提到的,我们可以直接对服务器发送REQ,不过这意味着我们需要对每个请求执行完整的TCP连接。在这样的部署里,DEALER是一个单独的TCP连接,其他的所有都是inproc。我们可以结束在同一个TCP连接上运行的并发请求。DEALER不真正关心消息类型,因此它可以发送5个请求,得到2个应答,然后发送2个或者更多请求等等。ROUTER套接字根据内部的套接字ID来关注发送消息给正确的地方。
正如代码所呈现那样,现在我们创建了多个处在独立线程里的REQ套接字,并执行了请求。通常你对每个进入的请求使用(with-req-sock)创建新的REQ。