Golang ZeroMQ:REQ / REP无意义无阻塞

时间:2016-11-04 12:22:50

标签: asynchronous go zeromq

在Python上,ZeroMQ .recv()/.send() 操作正在阻止,这对于 REQ/REP 非常适合。
在Golang,我必须将 zmq.DONTWAIT 传递给.recv().send()操作才能使其正常运行。

但问题是,流程需要锁定步骤,​​所以:

  1. server.recv()
  2. client.send()
  3. client.recv()
  4. server.send()
  5. 在3到4之间,怪异开始了,因为它们是异步的。

    当客户端发送消息且服务器尚未收到消息但客户端尝试接收响应时,锁定步骤不再是锁定步骤。

    zmq.DOBLOCK 相比,是否存在某种 zmq.DONTWAIT

    或者我在这里弄错了什么?

    EDIT:

    我在C中使用此绑定绑定zeromq:https://godoc.org/github.com/pebbe/zmq4#Type

    正如您在此处所看到的, .recv() 需要输入flag,这是第二个参考中的两者之一:

    Recv:https://godoc.org/github.com/pebbe/zmq4#Socket.Recv

    要传递的标志:https://github.com/pebbe/zmq4/blob/master/zmq4.go#L403

    这是我制作解决方法的当前代码,感觉有点难看:

    package connection
    
    import (
      "zmq4"
      "fmt"
      "time"
    )
    
    
    const ERRTMPUNAV="resource temporarily unavailable"
    
    
    func checkError(e error){
      if e != nil {
        panic(e)
      }
    }
    
    
    func CreateRepNode(address string,onMessage chan<- string,send <-chan string,closeConn <-chan bool){
      stop:=false
      socket,err:=zmq4.NewSocket(zmq4.REP)
      checkError(err)
      err=socket.Bind(address)
      checkError(err)
      go func(socket *zmq4.Socket){
        for {
          msg,err:=socket.Recv(zmq4.DONTWAIT)
          fmt.Println("server message"+msg)
          if stop==true {
            return
          }
          if err != nil {
            rateLimit := time.Tick(100 * time.Millisecond)
        <-rateLimit
        continue
          }
          checkError(err)
          onMessage<-msg
          rep:=<-send
          _,err=socket.Send(rep,zmq4.DONTWAIT)
        }
      }(socket)
      <-closeConn
      stop=true
    }
    
    
    func CreateReqNode(address string,onMessage chan<- string,send <-chan string,closeConn <-chan bool){
      stop:=false
      socket,err:=zmq4.NewSocket(zmq4.REQ)
      checkError(err)
      err=socket.Connect(address)
      checkError(err)
      go func(){
        for {
          msg:=<-send
          if stop==true {
            return
          }
          _,err:=socket.Send(msg,zmq4.DONTWAIT)
          for {
            msg,err=socket.Recv(zmq4.DONTWAIT)
            fmt.Println("client got message "+msg)
            if err!=nil {
              if err.Error()==ERRTMPUNAV {
                w:=time.Tick(100*time.Millisecond)
                <-w
                continue
              }
            }
            break
          }
          onMessage<-msg
        }
      }()
    
      <-closeConn
      stop=true
    }
    

1 个答案:

答案 0 :(得分:2)

ZeroMQ琐碎的基本原型比任何需要的生产级解决方案更像是一组构建块

Go-lang是一种非常强大的现代语言,带有协同程序和其他智能工具,可以控制并发,所以请原谅我提出以下建议列表:

  • 避免阻止设计无论何时都可以(非阻塞设计让一个人完全控制所有事物,因为它们来了...... 没有“悬挂”在任何地方无限/无法控制等待循环,已经发展的僵局中更糟糕的情况)

  • 避免依赖SLOC示例使用单一的基本类型的形式通信模式,我们应该为所有人开发强大的生存性处理策略可能出现问题的情况(传输网络中的信号丢失,消息丢失,DDoS级别的资源超载,......)

重新设计提示 - 根本不要使用 REQ/REP 。是的,永远不会......

ZeroMQ可扩展正式通信模式REQ/REP适用于学习ZeroMQ,但在实际生产等级部署中是致命的。 For details, read here

接下来考虑一下内部无条件模式,类似 PAIR (虽然标记为 experimental ,但对于某些用例来说效果很好), {{ 1}} XREQ/XREP 或某些复合信令/传输多插槽自定义设计的自有模式。

最好的下一步?

What I can do for your further questions right now is to direct you to see a bigger picture on this subject包含更多参数,一个简单的信号平面/消息平面插图以及与Pieter HINTJENS必读书籍的直接链接。

这本书值得一时间和努力。如果一个人对分布式系统设计非常认真,那么你会非常喜欢Pieter对Zero-sharing,Zero-blocking,(几乎)Zero-copy等人的热情。