[英]Timeout and Iterating Over Unbuffered Channel in Go
在我的代码中,我有一个连接的节点图(所有节点都直接或间接地相互连接)。 初始化后,每个节点都有一个随机 64 位 integer 的Value
。
type Node struct {
ID *uuid.UUID
Value int64
ListenChannel chan Message
Connections map[uuid.UUID]*Node
}
type Message struct {
Value int64
}
这个想法是他们将相互沟通并就最大的Value
达成共识。 (通信发生在每个节点拥有的ListenChannel
上,节点也被建模为 goroutines)
func (node *Node) FormConsensus(wg *sync.WaitGroup, retChannel chan int64) {
defer wg.Done()
defer func() {
// this will be a non-blocking operation since the channel is buffered
retChannel <- node.Value
}()
listenWg := sync.WaitGroup{}
listenWg.Add(1)
// Add logic to pass messages to and fro and find the maximum value from the network
go func() {
for timedOut := false; !timedOut; {
select {
case receivedMessage := <-node.ListenChannel:
if receivedMessage.Value > node.Value {
fmt.Println("Received value")
node.Value = receivedMessage.Value
fmt.Println("Received large value")
node.BroadcastValue()
}
case <-time.After(5 * time.Second):
fmt.Println("Timeout")
listenWg.Done()
close(node.ListenChannel)
timedOut = true
}
}
}()
node.BroadcastValue()
listenWg.Wait()
}
func (node *Node) BroadcastValue() {
fmt.Println("broadcasting", node.Value)
for _, connection := range node.Connections {
connection.ListenChannel <- Message{node.Value}
}
}
为实现这一点,每个节点首先将其值广播到其连接,并且还有一个 goroutine,该 goroutine 在其自己的 listenChannel 上持续监听其他节点发送的值。 如果接收到的值大于自己的值,则它会更新自己的值,并广播更新后的值。
使用 switch case 中的超时逻辑,我试图设置 5 秒的超时,即,如果 5 秒内通道上没有收到任何消息,则假设已达成共识并退出。
然而,在执行 FormConsensus function 时,它永远不会退出。 我不确定哪里出错了,因为我是 Go 的新手,我可能会做一些完全不合常理的事情。 除了了解出了什么问题,了解是否有更好的方法来实现我在 Go 中尝试的目标也很有帮助。
我很确定错误就在这里。
func (node *Node) BroadcastValue() {
fmt.Println("broadcasting", node.Value)
for _, connection := range node.Connections {
select {
case connection.ListenChannel <- Message{node.Value}:
fmt.Println("--test message written")
default:
fmt.Println("--test message dropped")
}
}
}
看起来通道写入操作正在阻塞,因为缓冲区已满。 您将不得不调查为什么它发送的消息比您预期的多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.