ZeroMQ
ZMQ是一个传输层,socket lib,底层的网络通信库,在socket api上进行了封装,将网络通讯、进程通讯和线程通讯抽象成统一的API接口
ZMQ和Socket区别
- Socket是端到端(1:1),ZMQ是N:M
- ZMQ用于node和node通信
三种模式
-
应答模式(类似半双工)
使用REQ-REP套接字发送和接受消息是需要遵循一定规律的。客户端首先使用zmq_send()发送消息,再用zmq_recv()接收,如此循环。如果打乱了这个顺序(如连续发送两次)则会报错。类似地,服务端必须先进行接收,后进行发送。
import (
"github.com/pebbe/zmq4"
)
func ZeroMQReq(flag int, msg string) (string, error) {
context, err := zmq4.NewContext()
if err != nil {
return "", err
}
socket, err := context.NewSocket(zmq4.REQ)
if err != nil {
return "", err
}
defer socket.Close()
socket.Connect("tcp://localhost:5555")
socket.Send(msg, zmq4.Flag(flag))
reply, err := socket.Recv(zmq4.Flag(flag))
if err != nil {
return "", err
}
return reply, nil
}
import "github.com/pebbe/zmq4"
func ZeroMQRep(flag int) (string, error) {
context, _ := zmq4.NewContext()
socket, _ := context.NewSocket(zmq4.REP)
defer socket.Close()
socket.Bind("tcp://*:5555")
msg, err := socket.Recv(zmq4.Flag(flag))
if err != nil {
return "", err
}
_, err = socket.Send("OK", zmq4.Flag(flag))
if err != nil {
return msg, err
}
return msg, nil
}
- Pub-Sub模式(发布订阅)
PUB-SUB套接字组合是异步的。客户端在一个循环体中使用recv ()接收消息,如果向SUB套接字发送消息则会报错;类似地,服务端可以不断地使用send ()发送消息,但不能再PUB套接字上使用recv ()。
关于PUB-SUB套接字,还有一点需要注意:你无法得知SUB是何时开始接收消息的。就算你先打开了SUB套接字,后打开PUB发送消息,这时SUB还是会丢失一些消息的,因为建立连接是需要一些时间的。很少,但并不是零。解决此问题需要在PUB端加入sleep。
import "github.com/pebbe/zmq4"
func ZeroMQPub(flag int, msg string) error {
context, _ := zmq4.NewContext()
socket, _ := context.NewSocket(zmq4.PUB)
defer socket.Close()
socket.Bind("tcp://*:5555")
_, err := socket.Send(msg, zmq4.Flag(flag))
return err
}
import "github.com/pebbe/zmq4"
type Processor func(msg string)
func ZeroMQSubOne(flag int, processor Processor) error {
context, _ := zmq4.NewContext()
socket, _ := context.NewSocket(zmq4.SUB)
defer socket.Close()
filter := "sub 1"
err := socket.Connect("tcp://localhost:5555")
if err != nil {
return err
}
err = socket.SetSubscribe(filter)
if err != nil {
return err
}
go func() {
for true {
msg, err := socket.Recv(zmq4.Flag(flag))
if err != nil {
break
}
processor(msg)
}
}()
return nil
}
- 分布式处理(管道模式)
由三部分组成,push进行数据推送,work进行数据缓存,pull进行数据竞争获取处理。区别于Publish-Subscribe存在一个数据缓存和处理负载。
当连接被断开,数据不会丢失,重连后数据继续发送到对端