Go的垃圾收集器正在删除正在使用的ZeroMQ套接字。

huangapple go评论127阅读模式
英文:

Go's garbage collector is deleting ZeroMQ sockets when in use

问题

我正在使用ZeroMQ和Go开发一个分布式系统。它类似于一个分布式账本,可以获取内容并进行追加。我有自动化客户端发送GET和ADD请求。程序在运行几秒钟后会崩溃,并显示错误信息"panic: socket operation on non-socket"。

我尝试使用debug.SetGCPercent(-1)关闭垃圾回收器,但我确定这个解决方案并不完全正确。
这是服务器初始化的代码:

  1. package server
  2. import (
  3. "backend/config"
  4. "backend/gset"
  5. "backend/tools"
  6. zmq "github.com/pebbe/zmq4"
  7. )
  8. type Server struct {
  9. Zctx *zmq.Context
  10. Peers map[string]*zmq.Socket
  11. Receive_socket zmq.Socket
  12. Id string
  13. Gset map[string]string
  14. Port string
  15. My_init map[string]bool
  16. My_echo map[string]bool
  17. My_vote map[string]bool
  18. Peers_echo map[string]bool
  19. Peers_vote map[string]bool
  20. }
  21. func CreateServer(node config.Node, peers []config.Node, zctx *zmq.Context) *Server {
  22. id := node.Host + node.Port
  23. port := node.Port
  24. server_sockets := make(map[string]*zmq.Socket)
  25. my_gset := gset.Create()
  26. my_init := make(map[string]bool)
  27. my_echo := make(map[string]bool)
  28. my_vote := make(map[string]bool)
  29. peers_echo := make(map[string]bool)
  30. peers_vote := make(map[string]bool)
  31. receive_socket, _ := zctx.NewSocket(zmq.ROUTER)
  32. receive_socket.Bind("tcp://*:" + node.Port)
  33. tools.Log(id, "Bound tcp://*:"+node.Port)
  34. // Connect my dealer sockets to all other servers' router
  35. for i := 0; i < len(peers); i++ {
  36. s, _ := zctx.NewSocket(zmq.DEALER)
  37. s.SetIdentity(id)
  38. s.Connect("tcp://localhost:" + peers[i].Port)
  39. // append socket to socket list
  40. server_sockets["tcp://localhost:"+peers[i].Port] = s
  41. }
  42. return &Server{
  43. Peers: server_sockets,
  44. Receive_socket: *receive_socket,
  45. Id: id,
  46. Port: port,
  47. Gset: my_gset,
  48. My_init: my_init,
  49. My_echo: my_echo,
  50. My_vote: my_vote,
  51. Peers_echo: peers_echo,
  52. Peers_vote: peers_vote,
  53. }
  54. }

这是控制服务器的函数:

  1. func Normal_listener_task(s *server.Server) {
  2. for {
  3. message, err := s.Receive_socket.RecvMessage(0)
  4. if err != nil {
  5. fmt.Println(zmq.AsErrno(err))
  6. panic(err)
  7. }
  8. messaging.HandleMessage(s, message)
  9. }
  10. }

完整的代码在我的GitHub上这里

如果有人知道为什么会出现这种情况,你将拯救我的论文。谢谢!

英文:

I am developing a distributed system uisng ZeroMQ and Go. It's like a distributed ledger so you can get the contects and append. I have automated clients making GET and ADD requests. The program runs fine for a couple of seconds but then crashes with the error "panic: socket operation on non-socket".

I tried turning off the garbage collector using debug.SetGCPercent(-1) but im sure this solution is not entirely correct.
This is the server initialization code

  1. package server
  2. import (
  3. &quot;backend/config&quot;
  4. &quot;backend/gset&quot;
  5. &quot;backend/tools&quot;
  6. zmq &quot;github.com/pebbe/zmq4&quot;
  7. )
  8. type Server struct {
  9. Zctx *zmq.Context
  10. Peers map[string]*zmq.Socket
  11. Receive_socket zmq.Socket
  12. Id string
  13. Gset map[string]string
  14. Port string
  15. My_init map[string]bool
  16. My_echo map[string]bool
  17. My_vote map[string]bool
  18. Peers_echo map[string]bool
  19. Peers_vote map[string]bool
  20. }
  21. func CreateServer(node config.Node, peers []config.Node, zctx *zmq.Context) *Server {
  22. id := node.Host + node.Port
  23. port := node.Port
  24. server_sockets := make(map[string]*zmq.Socket)
  25. my_gset := gset.Create()
  26. my_init := make(map[string]bool)
  27. my_echo := make(map[string]bool)
  28. my_vote := make(map[string]bool)
  29. peers_echo := make(map[string]bool)
  30. peers_vote := make(map[string]bool)
  31. receive_socket, _ := zctx.NewSocket(zmq.ROUTER)
  32. receive_socket.Bind(&quot;tcp://*:&quot; + node.Port)
  33. tools.Log(id, &quot;Bound tcp://*:&quot;+node.Port)
  34. // Connect my dealer sockets to all other servers&#39; router
  35. for i := 0; i &lt; len(peers); i++ {
  36. s, _ := zctx.NewSocket(zmq.DEALER)
  37. s.SetIdentity(id)
  38. s.Connect(&quot;tcp://localhost:&quot; + peers[i].Port)
  39. // append socket to socket list
  40. server_sockets[&quot;tcp://localhost:&quot;+peers[i].Port] = s
  41. }
  42. return &amp;Server{
  43. Peers: server_sockets,
  44. Receive_socket: *receive_socket,
  45. Id: id,
  46. Port: port,
  47. Gset: my_gset,
  48. My_init: my_init,
  49. My_echo: my_echo,
  50. My_vote: my_vote,
  51. Peers_echo: peers_echo,
  52. Peers_vote: peers_vote,
  53. }
  54. }

And this is the function that contols the server

  1. func Normal_listener_task(s *server.Server) {
  2. for {
  3. message, err := s.Receive_socket.RecvMessage(0)
  4. if err != nil {
  5. fmt.Println(zmq.AsErrno(err))
  6. panic(err)
  7. }
  8. messaging.HandleMessage(s, message)
  9. }
  10. }

The entire code is in my github here

If anyone knows why this is happening you will save my thesis. Thank you

答案1

得分: 2

问题是我在声明receive_socket时使用了Receive_socket zmq.Socket,而实际上应该是*Receive_socket zmq.Socket。指针只是一个副本,因此被垃圾回收器视为垃圾。

英文:

The problem was that I was declaring the receive_socket with Receive_socket zmq.Socket when it should have been *Receive_socket zmq.Socket. The pointer was just a copy, therefore being considered trash by the GC.

huangapple
  • 本文由 发表于 2023年1月27日 22:12:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75259268.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定