理解go通道处理/缓冲区溢出



我继承了一些我仍在努力理解的代码。它的核心是:

for msg := range this.out {
for i, handler := range this.handlers {
select {
case handler <- msg:
default:
this.logger.Printf("Buffer overflow occurred for handler %s", this.names[i])
}
}
}

out是chan byte处理程序是[]chan []byte

看起来就像是从数组中读取和写入处理程序,默认情况下是抱怨缓冲区溢出。我想。

但我需要细节。我是新来的,这是我第一次和陈打交道。所以第一个问题,这就是这里发生的事情吗?如果是的话。。。如何防止缓冲区溢出?

在Go中,可以通过两种方式创建通道:

c := make(chan []byte)

其创建将同步发送器和接收器的信道。这意味着接收方将不得不等待,直到发送方发送数据,而发送方将不得不等待直到接收方获得该数据。但是,通过向通道添加缓冲区:

c := make(chan []byte, 100)

您实际上是在取消发送方和接收方的同步。在这种情况下,当缓冲区满时,发送方将阻塞,当缓冲区时,接收方将阻塞。

现在,我不知道handler的容量是多少,但这是您应该期待的一般工作流程:

  1. Go将检查handler中是否有空间,如果有,msg将写入通道
  2. 如果没有空间,则会记录错误消息

实际处理缓冲区溢出的方法有点棘手。

首先,作为权宜之计,您可以增加handler的容量,以便它可以容纳更多的消息。如果问题是间歇性的(即流量的大峰值(,这可能代表实际的解决方案。否则,你所做的只是暂时搁置这个问题。

其次,您可以水平扩展handler另一端的处理程序,以处理更多的消息,从而确保通道不会溢出。然而,这样做的问题是,你必须担心在不同的容量级别管理处理程序,这样你就可以进行自动扩展之类的事情。

第三,您可以查看处理来自handler的消息的代码,看看是否可以对其进行重新设计,以更有效地处理消息。当代码的原始设计假设不再成立时,这种重新设计非常常见。

最后,您可以完全不再使用通道作为基础设施,而是使用包含内存的基于云的pub/sub来替换该组件。这里的优点是,这将允许您根据需要扩展应用程序,而不必担心溢出,但这会产生额外的成本并需要更改基础结构。

最新更新