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

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

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

问题

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

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

package server

import (
	"backend/config"
	"backend/gset"
	"backend/tools"

	zmq "github.com/pebbe/zmq4"
)

type Server struct {
	Zctx           *zmq.Context
	Peers          map[string]*zmq.Socket
	Receive_socket zmq.Socket
	Id             string
	Gset           map[string]string
	Port           string
	My_init        map[string]bool
	My_echo        map[string]bool
	My_vote        map[string]bool
	Peers_echo     map[string]bool
	Peers_vote     map[string]bool
}

func CreateServer(node config.Node, peers []config.Node, zctx *zmq.Context) *Server {
	id := node.Host + node.Port
	port := node.Port
	server_sockets := make(map[string]*zmq.Socket)
	my_gset := gset.Create()
	my_init := make(map[string]bool)
	my_echo := make(map[string]bool)
	my_vote := make(map[string]bool)
	peers_echo := make(map[string]bool)
	peers_vote := make(map[string]bool)
	receive_socket, _ := zctx.NewSocket(zmq.ROUTER)
	receive_socket.Bind("tcp://*:" + node.Port)
	tools.Log(id, "Bound tcp://*:"+node.Port)

	// Connect my dealer sockets to all other servers' router
	for i := 0; i < len(peers); i++ {
		s, _ := zctx.NewSocket(zmq.DEALER)
		s.SetIdentity(id)
		s.Connect("tcp://localhost:" + peers[i].Port)
		// append socket to socket list
		server_sockets["tcp://localhost:"+peers[i].Port] = s
	}

	return &Server{
		Peers:          server_sockets,
		Receive_socket: *receive_socket,
		Id:             id,
		Port:           port,
		Gset:           my_gset,
		My_init:        my_init,
		My_echo:        my_echo,
		My_vote:        my_vote,
		Peers_echo:     peers_echo,
		Peers_vote:     peers_vote,
	}
}

这是控制服务器的函数:

func Normal_listener_task(s *server.Server) {
	for {
		message, err := s.Receive_socket.RecvMessage(0)
		if err != nil {
			fmt.Println(zmq.AsErrno(err))
			panic(err)
		}
		messaging.HandleMessage(s, message)
	}
}

完整的代码在我的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

package server
import (
&quot;backend/config&quot;
&quot;backend/gset&quot;
&quot;backend/tools&quot;
zmq &quot;github.com/pebbe/zmq4&quot;
)
type Server struct {
Zctx           *zmq.Context
Peers          map[string]*zmq.Socket
Receive_socket zmq.Socket
Id             string
Gset           map[string]string
Port           string
My_init    map[string]bool
My_echo    map[string]bool
My_vote    map[string]bool
Peers_echo map[string]bool
Peers_vote map[string]bool
}
func CreateServer(node config.Node, peers []config.Node, zctx *zmq.Context) *Server {
id := node.Host + node.Port
port := node.Port
server_sockets := make(map[string]*zmq.Socket)
my_gset := gset.Create()
my_init := make(map[string]bool)
my_echo := make(map[string]bool)
my_vote := make(map[string]bool)
peers_echo := make(map[string]bool)
peers_vote := make(map[string]bool)
receive_socket, _ := zctx.NewSocket(zmq.ROUTER)
receive_socket.Bind(&quot;tcp://*:&quot; + node.Port)
tools.Log(id, &quot;Bound tcp://*:&quot;+node.Port)
// Connect my dealer sockets to all other servers&#39; router
for i := 0; i &lt; len(peers); i++ {
s, _ := zctx.NewSocket(zmq.DEALER)
s.SetIdentity(id)
s.Connect(&quot;tcp://localhost:&quot; + peers[i].Port)
// append socket to socket list
server_sockets[&quot;tcp://localhost:&quot;+peers[i].Port] = s
}
return &amp;Server{
Peers:          server_sockets,
Receive_socket: *receive_socket,
Id:             id,
Port:           port,
Gset:           my_gset,
My_init:        my_init,
My_echo:        my_echo,
My_vote:        my_vote,
Peers_echo:     peers_echo,
Peers_vote:     peers_vote,
}
}

And this is the function that contols the server

func Normal_listener_task(s *server.Server) {
for {
message, err := s.Receive_socket.RecvMessage(0)
if err != nil {
fmt.Println(zmq.AsErrno(err))
panic(err)
}
messaging.HandleMessage(s, message)
}
}

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:

确定