如何确定go通道的哪一侧正在另一侧等待?
我想知道这一点,所以我可以弄清楚我的处理受到限制的地方,并通过分配更多资源做出回应。
我想到的两种方法都需要做一些记录值的移动平均值,因此测量值不会太嘈杂,但这不是big problem。
在单个消费者的情况下,我可以在从频道消费之前启动计时器,在我获得记录后停止计时器。我可以跟踪等待的时间百分比,并在每个获取周期内做出相应的响应。
如果频道定期为0,则意味着我们比发送消费更快。同样,如果缓冲区已满,我们发送的速度比我们收到的速度快。我们可以检查我们频道的长度,以确定运行缓慢的内容。
出于性能原因或其他原因,是否有充分的理由选择其中一个到另一个?这个问题有更简单的解决方案吗?
我的服务正在执行N
个HTTP请求,同时抓取最多W
个goroutines中的内容,并将频道上的所有内容发送到processor
个单个goroutine,然后将数据反馈给客户。
每个工作人员任务都会导致在频道上发送大量消息。每个worker
的任务可能需要几分钟才能完成。
下图总结了3个并发工作者(W=3
)的数据流。
[worker: task 1] -
\
[worker: task 2] - | --- [ channel ] --- [ processor ] -> [ client ]
/
[worker: task 3] -
我想知道在请求期间是否应该运行更多工作人员(增加W
)或更少工人(减少W
)。由于客户端在速度非常不同的连接上工作,因此每个请求的变化很大。
答案 0 :(得分:3)
实现目标的一种方法是使用“有界发送”和“有界接收”操作 - 如果您能够提出合理的轮询超时。
当你的任何一个工人试图通过频道发送一个完整的结果时,不要让它“永远”阻塞(直到频道的缓冲区中有空格);相反,只允许它阻止一些最长的时间。如果在通道缓冲区中有空间之前发生超时,则可以对该条件做出反应:计算它发生的次数,调整未来的最后期限,限制或减少工人数量,等等。
同样,对于接收工作人员结果的“处理器”,您可以限制其阻止的时间。如果在有可用值之前发生超时,则处理器将处于饥饿状态。创建更多的工人来更快地提供它(假设工人将受益于这种并行性)。
这种方法的缺点是每个creating timers或send的receive operation开销。
草绘,每个工人都可以访问这些声明:
const minWorkers = 3
var workers uint32
在每个工人goroutine中:
atomic.AddUint32(&workers, 1)
for {
result, ok := produce()
if !ok {
break
}
// Detect when channel "p"'s buffer is full.
select {
case p <- result:
case <-time.After(500 * time.Millisecond):
// Hand over the pending result, no matter how long it takes.
p <- result
// Reduce worker count if above minimum.
if current := atomic.LoadUint32(&workers); current > minWorkers &&
atomic.CompareAndSwapUint32(&workers, current, current-1) {
return
}
// Consider whether to try decrementing the working count again
// if we're still above the minimum. It's possible another one
// of the workers also exited voluntarily, changing the count.
}
}
atomic.AddUint32(&workers, -1)
请注意,如上所述,您可以通过计算发送到通道p
完成所需的时间以及花费太长时间对其做出反应来实现相同的效果,而不是执行一次有限发送然后是潜在的阻止发送。但是,我用这种方式草拟了它,因为我怀疑这样的代码会在超时到期时成熟,包括日志记录和检测计数器颠簸。
同样,在处理器goroutine中,您可以限制阻止从工作人员接收值的时间:
for {
select {
case result <- p:
consume(result)
case <-time.After(500 * time.Millisecond):
maybeStartAnotherWorker()
}
}
显然,你可以在这个装置上加上许多旋钮。最终将生产者的调度与消费者和生产者本身联系起来。引入一个不透明的“倾听者”,生产者和消费者“抱怨”延迟可以让你打破这种循环关系,更容易改变控制你如何应对拥堵的政策。