ZeroMQ中的PUB / SUB模式无法正常工作

时间:2017-12-14 15:45:22

标签: go zeromq distributed-system

我正在尝试使用ZeroMQ实现一个非常基本的 PUB/SUB 模式。我想为所有客户端提供一个服务器(始终处于活动状态)广播消息(发布者),而不关心连接的客户端。 如果客户端以订户身份连接到此服务器,则应收到该消息。

但是,我无法使用# publisher (server.py) import zmq ctx = zmq.Context() publisher = ctx.socket(zmq.PUB) publisher.bind('tcp://127.0.0.1:9091') while True: publisher.send_string("test") 发送消息。

在Python中它将是:

# subscriber (client.py)
import zmq

ctx = zmq.Context()
subscriber = ctx.socket(zmq.SUB)
subscriber.connect('tcp://127.0.0.1:9091')

while True:
    msg = subscriber.recv_string()
    print msg

package main

import (
    "github.com/pebbe/zmq4"
    "log"
    "time"
)

func Listen(subscriber *zmq4.Socket) {
    for {
        s, err := subscriber.Recv(0)
        if err != nil {
            log.Println(err)
            continue
        }
        log.Println("rec", s)
    }
}

func main() {
    publisher, _ := zmq4.NewSocket(zmq4.PUB)
    defer publisher.Close()
    publisher.Bind("tcp://*:9090")

    subscriber, _ := zmq4.NewSocket(zmq4.SUB)
    defer subscriber.Close()
    subscriber.Connect("tcp://127.0.0.1:9090")

    go Listen(subscriber)
    for _ = range time.Tick(time.Second) {
        publisher.Send("test", 0)
        log.Println("send", "test")

    }
}

或者在golang:

ADD dump.sql /docker-entrypoint-initdb.d

我是否误解了这种模式,或者在连接时是否需要从客户端向服务器发送特定信号。我对golang版本感兴趣,只使用python版本进行测试。

1 个答案:

答案 0 :(得分:2)

我是否误解了这种模式?是的,幸运的是你做到了。

定义ZeroMQ原型以表示某种行为。如上所述,PUSH - 原型AccessPoint推送每条消息"通过"所有到目前为止设置的通信信道,PULL - 或者AccessPoint将已经到达线路的所有内容拉到"它的手",PUB - lisher AccessPoint发布,SUB - scriber AccessPoint订阅,以便只接收与其主题过滤器匹配的消息,但不接受任何其他消息。

似乎很清楚,这样的Archetype"规范"有助于构建ZeroMQ智能消息/信令基础架构,以便在架构中轻松使用。

# subscriber (client.py)
import zmq

ctx        = zmq.Context()
subscriber = ctx.socket( zmq.SUB )
subscriber.connect( 'tcp://127.0.0.1:9091' )
subscriber.setsockopt( zmq.LINGER,    0 )         # ALWAYS:
subscriber.setsockopt( zmq.SUBSCRIBE, "" )        # OTHERWISE NOTHING DELIVERED

while True:
    msg = subscriber.recv_string()                # MAY USE .poll() + zmq.NOBLOCK
    print msg
subscriber, _ := zmq4.NewSocket( zmq4.SUB )
subscriber.Connect(             "tcp://127.0.0.1:9090" )
subscriber.SetSubscribe(         filter )                 // SET: <topic-filter>

subscriber.SetLinger(            0 )    //  SAFETY FIRST: PREVENT DEADLOCK
defer subscriber.Close()                //  NOW MAY SAFELY SET:

...
msg, _ := subscriber.Recv( 0 )

根据定义,任何正确实例化的 SUB -side AccessPoint对象实际上都没有机会知道什么是正确的消息选择,所以他们应该被交付&#34;什么消息不是。

如果没有这一初步知识,ZeroMQ设计师有一个主要选择要么 Archetype-policy一致,让PUB - 侧AccessNode分配所有.send() - 仅通过SUB - 机制明确要求接收任何此类权限的zmq.SUBSCRIBE方AccessNode获取的消息,以传递从PUB发送的所有内容{1}}到目前为止还没有决定SUB - s。

前者是ZeroMQ作者的一贯而专业的设计步骤 后者实际上意味着违反ZeroMQ自己的RFC规范。

后者的选择就像是如果一个人刚搬到一个新的公寓,人们几乎没想到会发现所有的报纸和杂志从第二天早上出现在一个新的邮箱中,是吗?但是,如果有人订阅波士顿环球报,那么第二天早上新的发布将在门口,因为它仍将存在,直到一个取消订阅或报纸破产或缺乏纸卷阻止印刷厂交付在适当的时间和时尚或Big Dig隧道的交通堵塞可能会导致所有人或仅在某一天的当地交付时遇到麻烦。

这一切都很自然,并且与Archetype政策兼容。

Intermezzo: Golang已经绑定到许多不同的API版本
技术纯粹主义者会在此反对,早期的API版本(直到某些v3.2 +)实际上在技术上将所有消息有效负载从PUB传输到所有SUB - s,因为它简化了{{1} } - 工作负载包络,但增加了传输类数据流和PUB - 侧资源/延迟主题 - 过滤处理。然而,所有这一切都隐藏在用户代码中,正是API抽象的视界。因此,除了需要适当地扩展资源之外,这对用户来说是透明的。更新的API版本恢复了主题过滤器处理器的作用,现在让它发生在SUB侧。然而,在这两种情况下,ZeroMQ RFC规范策略都是以这种方式实现的,PUB - 方将永远不会(通过SUB - 接口)传递一条与有效信息不匹配的消息。 ,明确的.recv() - 边订阅

在所有情况下,SUB - 方尚未明确设置任何SUB - 指示的主题过滤器,它不能并且不会提供任何内容(这两者都是自然的并且与为zmq.SUBSCRIBE类型的AccessPoint定义的ZeroMQ RFC Archetype-policy完全一致。

最佳下一步:

至少,请务必阅读ZeroMQ API文档,其中所有细节都经过专业指定 - 至少,人们可以第一眼看到智能消息/信令框架的气息。

这无助于任何人开始绿色领域并完全构建自己复杂的心理概念,并深入理解所有内容如何在内部工作,这显然不是任何API文档和#39的野心,是吗?然而,一旦掌握了ZeroMQ内部架构,这将有助于任何人刷新或提醒所有可配置的细节,详见下文中提到的源代码。

另外,对于确实对本身感兴趣的任何人来说,值得花时间和精力来永远阅读Pieter HINTJENS&#39;书&#34;代码连接,第1卷&#34; (以PDF格式免费提供)以及他之后关于他在软件工程方面丰富经验的任何其他书籍,因为他对现代计算的许多见解可能并且将激发(和很多)。

编辑:

GO中的MWE

SUB