ZMQ无法接收来自多个发布者的消息

时间:2018-12-29 20:10:44

标签: go zeromq

我正在实现ZMQ的Espresso模式。

我想连接许多订阅者<>代理<>许多发布者

但是,代理中的侦听器仅接收来自一个发布者的消息。因此,订阅者仅从该特定发布者接收。 我无法弄清楚我的代码出了什么问题。

package playground

import (
    zmq "github.com/pebbe/zmq4"

    "fmt"
    "math/rand"
    "time"
    "testing"
)

func subscriber_thread(id int) {
    subscriber, _ := zmq.NewSocket(zmq.SUB)
    subscriber.Connect("tcp://localhost:6001")
    subscriber.SetSubscribe("")
    defer subscriber.Close()

    for {
        msg, err := subscriber.RecvMessage(0)
        if err != nil {
            panic(err)
        }
        fmt.Println("subscriber id:", id,"received:", msg)
    }
}

func publisher_thread(n int) {
    publisher, _ := zmq.NewSocket(zmq.PUB)
    publisher.Bind("tcp://*:6000")

    for {
        s := fmt.Sprintf("%c-%05d", n +'A', rand.Intn(100000))
        _, err := publisher.SendMessage(s)
        if err != nil {
            panic(err)
        }
        fmt.Println("publisher sent:", s)
        time.Sleep(100 * time.Millisecond) //  Wait for 1/10th second
    }
}

//  The listener receives all messages flowing through the proxy, on its
//  pipe. In CZMQ, the pipe is a pair of ZMQ_PAIR sockets that connects
//  attached child threads. In other languages your mileage may vary:

func listener_thread() {
    pipe, _ := zmq.NewSocket(zmq.PAIR)
    pipe.Bind("inproc://pipe")

    //  Print everything that arrives on pipe
    for {
        msg, err := pipe.RecvMessage(0)
        if err != nil {
            break //  Interrupted
        }
        fmt.Printf("%q\n", msg)
    }
}

func TestZmqEspresso(t *testing.T) {
    go publisher_thread(0)
    go publisher_thread(1)
    go publisher_thread(2)

    go subscriber_thread(1)
    go subscriber_thread(2)

    go listener_thread()

    time.Sleep(100 * time.Millisecond)

    subscriber, _ := zmq.NewSocket(zmq.XSUB)
    subscriber.Connect("tcp://localhost:6000")

    publisher, _ := zmq.NewSocket(zmq.XPUB)
    publisher.Bind("tcp://*:6001")

    listener, _ := zmq.NewSocket(zmq.PAIR)
    listener.Connect("inproc://pipe")

    zmq.Proxy(subscriber, publisher, listener)

    fmt.Println("interrupted")

}

1 个答案:

答案 0 :(得分:0)

我已经找到了解决方案。 XPUB / XSUB应该绑定到套接字 PUB和SUB工作人员应连接到套接字

下面的工作代码

package playground

import (
    zmq "github.com/pebbe/zmq4"

    "fmt"
    "log"
    "math/rand"
    "testing"
    "time"
)

func subscriber_thread(id int) {
    subscriber, err := zmq.NewSocket(zmq.SUB)
    if err != nil {
        panic(err)
    }
    err = subscriber.Connect("tcp://localhost:6001")
    if err != nil {
        panic(err)
    }
    err = subscriber.SetSubscribe("")
    if err != nil {
        panic(err)
    }
    defer subscriber.Close()

    for {
        msg, err := subscriber.RecvMessage(0)
        if err != nil {
            panic(err)
        }
        fmt.Println("subscriber id:", id, "received:", msg)
    }
}

func publisher_thread(n int) {
    publisher, err := zmq.NewSocket(zmq.PUB)
    if err != nil {
        panic(err)
    }
    //err = publisher.Bind("tcp://*:6000")
    err = publisher.Connect("tcp://localhost:6000")
    if err != nil {
        panic(err)
    }

    for {
        s := fmt.Sprintf("%c-%05d", n+'A', rand.Intn(100000))
        _, err := publisher.SendMessage(s)
        if err != nil {
            panic(err)
        }
        fmt.Println("publisher sent:", s)
        time.Sleep(100 * time.Millisecond) //  Wait for 1/10th second
    }
}

//  The listener receives all messages flowing through the proxy, on its
//  pipe. In CZMQ, the pipe is a pair of ZMQ_PAIR sockets that connects
//  attached child threads. In other languages your mileage may vary:

func listener_thread() {
    pipe, _ := zmq.NewSocket(zmq.PAIR)
    pipe.Bind("inproc://pipe")

    //  Print everything that arrives on pipe
    for {
        msg, err := pipe.RecvMessage(0)
        if err != nil {
            break //  Interrupted
        }
        fmt.Printf("%q\n", msg)
    }
}

func TestZmqEspresso(t *testing.T) {
    log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.Lshortfile)

    go publisher_thread(0)
    go publisher_thread(1)
    go publisher_thread(2)

    go subscriber_thread(1)
    go subscriber_thread(2)

    go listener_thread()

    time.Sleep(100 * time.Millisecond)

    subscriber, err := zmq.NewSocket(zmq.XSUB)
    if err != nil {
        panic(err)
    }
    //err = subscriber.Connect("tcp://localhost:6000")
    err = subscriber.Bind("tcp://*:6000")
    if err != nil {
        panic(err)
    }

    publisher, err := zmq.NewSocket(zmq.XPUB)
    if err != nil {
        panic(err)
    }
    err = publisher.Bind("tcp://*:6001")
    if err != nil {
        panic(err)
    }

    listener, _ := zmq.NewSocket(zmq.PAIR)
    listener.Connect("inproc://pipe")

    err = zmq.Proxy(subscriber, publisher, listener)
    if err != nil {
        panic(err)
    }

    fmt.Println("interrupted")

}