目录
zmq四种模型简介
zmq可以简单的理解为给原生socket的API做了一层封装封装
1、REQ/REP模型
请求响应模型必须满足send、recv成对出现,收发顺序需满足:客户端先send之后等待接收recv;服务端先recv之后再send。recv为阻塞接收,可设置阻塞时间
2、PULL/PUSH模型
推拉模型的收发数据是单向的
3、SUB/PUB模型
发布订阅模型,sub端能够从服务端recv数据内容,pub端向所有监听同一端口号的sub端发布消息
4、Router/Dealer模型
可简单的理解为非阻塞的请求响应模型
为了实现一对多的长连接,主机从机都需要收发,并且需要一定程度的并发(主机send的时候可与从机并发进行,recv同),总体思路:主机用一个端口作PUB,一个端口用作PULL,从机对应的两个端口分别绑定SUB和PUSH。
server端demo
package main
import (
"fmt"
zmq "github.com/pebbe/zmq4"
)
//SetMasterZmq 建立zmq_socket
func SetMasterZmq() (*zmq.Socket, *zmq.Socket) {
context, _ := zmq.NewContext()
publisher, _ := context.NewSocket(zmq.PUB)
publisher.SetSndhwm(1100000)
publisher.Bind("tcp://*:6000")
context1, _ := zmq.NewContext()
receiver, _ := context1.NewSocket(zmq.PULL)
receiver.Bind("tcp://*:7000")
return publisher, receiver
}
// HeartBeatMaster Master心跳程序
func HeartBeatMaster(publisher *zmq.Socket, receiver *zmq.Socket){
fmt.Println("开启心跳程序......")
//开启keepalive属性
receiver.SetTcpKeepalive(1)
//如果20s内没有数据往来,检测连接
receiver.SetTcpKeepaliveIdle(20000)
//检测时发包间隔为2秒
receiver.SetTcpKeepaliveIntvl(2)
receiver.SetTcpKeepaliveCnt(3) //检测3次未响应标记为不可用
for{
<-Channel_Heartbeat
if len(gotHB) != 0 {
rpl := fmt.Sprintf("1got your heartbeats-%v", key)
publisher.Send(rpl, 0)
}
}
}
func main(){
publisher,receiver := SetMasterZmq()
go HeartBeatMaster(publihser,receiver)
go func(receiver *zmq.Socket) {
for {
gotmsg, err := receiver.Recv(0)
if err != nil {
fmt.Println(err)
}
switch gotmsg[:1]{
case "1":
Channel_Heartbeat <- gotmsg
default:
//其他指令
}
}
}()
}
client端demo
package main
import (
"fmt"
zmq "github.com/pebbe/zmq4"
)
//SetSlaveZmq 建立zmq_socket
func SetSlaveZmq() (*zmq.Socket, *zmq.Socket) {
context, _ := zmq.NewContext()
subscriber, _ := context.NewSocket(zmq.SUB)
subscriber.SetRcvhwm(100000)
subscriber.SetSubscribe("")
subscriber.Connect("tcp://_:6000")
context1, _ := zmq.NewContext()
sender, _ := context1.NewSocket(zmq.PUSH)
sender.Connect("tcp://_:7000")
return subscriber, sender
}
// HeartBeatMaster Master心跳程序
func HeartBeatSlave(subscriber *zmq.Socket, sender *zmq.Socket){
fmt.Println("开启心跳程序......")
//开启keepalive属性
receiver.SetTcpKeepalive(1)
//如果20s内没有数据往来,检测连接
receiver.SetTcpKeepaliveIdle(20000)
//检测时发包间隔为2秒
receiver.SetTcpKeepaliveIntvl(2)
receiver.SetTcpKeepaliveCnt(3) //检测3次未响应标记为不可用
for {
HB := fmt.Sprintf("1heartbeat from device:%v"scujson.Key)
sender.Send(HB, 0)
select {
case <-ChannelSlaveHeartbeat:
for len(ChannelSlaveHeartbeat) > 0 {
<-ChannelSlaveHeartbeat
}
fmt.Println("收到fcu回复")
break
case <-time.After(2 * time.Second):
fmt.Println("2s未收到回复")
HB := fmt.Sprintf("1heartbeat from device:%v"scujson.Key)
sender.Send(HB, 0)
//超时处理
break
}
RecvTime = time.Now().Local()
time.Sleep(time.Second)
}
}
func main(){
subscriber,sender:= SetMasterZmq()
go HeartBeatSlave(subscriber,sender)
go func(subscriber *zmq.Socket) {
for {
gotmsg, err := subscriber.Recv(0)
if err != nil {
fmt.Println(err)
}
switch gotmsg[:1]{
case "1":
ChannelSlaveHeartbeat <- gotmsg
default:
//其他指令
}
}
}()
}