AI智能
改变未来

Go 实现高并发下同步请求的思路

Go 实现同步请求的思路

  • 1、背景
  • 2、思路

1、背景

在实际生产中,我们或多或少的需要对接第三方的同步接口,那我们如何实现高并发下go的同步请求方法呢,下面我就讲一下我最近在生产中运用的一种方法。

我们最近遇到的需求是对接第三方的接口,需要实时的获取到对方的相应数据,超过三秒没有拿到则判断请求失败,返回对应的错误信息。

2、思路

我的做法是,首先定义一个全局的channel

var ReqChannel = make(chan *Packet, 20)

然后在请求的业务里,定义一个请求唯一的id并往这个channel里塞值,同时起一个协程循环的读取这个channel

for {req := <-model.ReqChannelpacket := &Packet{Sign:      SignPubwin,CompanyId: CompanyId,Type:      req.Type,Id:        req.Id,Data:      req.Data,}Logger.Debugf(\"send packet to pubwin, id:%d, type:%#x, body:%s\", req.Id, req.Type, string(req.Data))err := ptr.SendPacket2Pubwin(packet)if err != nil {Logger.Errorf(\"send packet to pubwin failed, id:%d, type:%#x, body:%s, err:%v\", err, req.Id, req.Type, string(req.Data))}}

读取完以后,再定义一个全局的map,key是刚读取的请求的唯一ID,value定义成需要返回类型的channel

// 我的请求是返回一个byte数组var ResMapChannel map[uint32]chan []byte

请求返回后,将请求的ID和返回的值塞到定义的map里,同是在请求的地方循环的读取key为请求ID的channel,
并设置对应的超时时间,记得处理结束移除对应map里的key,防止循环处理

// 初始化channelvar respChannel []byte// 设置超时时间ticker := time.NewTicker(3 * time.Second)// 阻塞读取channelfor {select {case respChannel = <-model.ResMapChannel[id]:if respChannel != nil {// 处理返回的channel []byteerr := json.Unmarshal(respChannel, &checkoutInfo)if err != nil {Logger.Errorf(\"response change failed! id %d, response channel %+v, err %s \\n\", id, respChannel, err.Error())return nil, err}// 处理结束移除mapdelete(model.ResMapChannel, id)return checkoutInfo, nil}case <-ticker.C:Logger.Errorf(\"response timeout, id %d\", id)// 处理结束移除mapdelete(model.ResMapChannel, id)return nil, nil}}

这样就可以保证高并发下的请求的返回的唯一正确性,以上仅仅是个人思路,仅供参考,对于有更好方法的小伙伴,或者是我的方法有不正确的地方,欢迎大家在评论区留言。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Go 实现高并发下同步请求的思路