【golang ZeroMQ】 发布订阅模型及推拉模型的结合实现一对多长连接


目录

zmq四种模型简介

server端demo

client端demo


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:
                //其他指令
            }
		}
	}()
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值