到处似乎都在讨论从频道阅读应始终是一种阻止操作。态度似乎是这就是Go的方式。这是有道理的,但我试图弄清楚如何从频道汇总事物。
例如,发送http请求。假设我有一个生成数据流的管道设置,所以我有一个生成点队列/流的通道。然后我可以使用goroutine监听此频道并发送HTTP请求以将其存储在服务中。这有效,但我为每个点创建了一个http请求。
我发送的端点也允许我批量发送多个数据点。我想做的是
这就是我使用线程安全队列和select语句在C中做的事情。基本上在可能的情况下刷新整个/队列缓冲区。这是一种有效的技术吗?
似乎go select语句确实给了我一些与C选择相似的东西,但是我仍然不确定是否存在非阻塞读取'在频道上。
编辑:我也愿意接受我打算可能不是Go Way的内容,但是不断打击非停止的http请求对我来说似乎也是错误的,特别是如果它们可以聚合的话。如果有人有一个很酷的替代架构,但我想避免像神奇地缓冲N个项目,或等待X秒直到发送。
答案 0 :(得分:3)
以下是在通道为空之前批处理的方法。变量batch
是数据点类型的一部分。变量ch
是数据点类型的通道。
var batch []someType
for {
select {
case v := <-ch:
batch = append(batch, v)
default:
if len(batch) > 0 {
sendBatch(batch)
batch := batch[:0]
}
batch = append(batch, <-ch) // receiving a value here prevents busy waiting.
}
}
您应该阻止批次无限制地增长。这是一个简单的方法:
var batch []someType
for {
select {
case v := <-ch:
batch = append(batch, v)
if len(batch) >= batchLimit {
sendBatch(batch)
batch := batch[:0]
}
default:
if len(batch) > 0 {
sendBatch(batch)
batch := batch[:0]
}
batch = append(batch, <-ch)
}
}
答案 1 :(得分:2)
Dewy Broto为您的问题提供了很好的解决方案。这是一个直接的直接解决方案,但我想更广泛地评论如何为不同问题寻找解决方案。
Go使用Communicating Sequential Process代数(CSP)作为渠道,选择和轻量级流程的基础(&#39; goroutines&#39;)。 CSP保证事件的顺序;当你做出选择时,它只会引入非决定论(a.k.a。select
)。保证订购有时被称为&#34;发生之前&#34; - 它使编码比替代(广泛流行)非阻塞风格简单得多。它还为创建组件提供了更多的空间:长寿命功能单元,通过可预测的方式通过通道与外部世界互动。
或许在频道上谈论阻止会给人们学习Go带来心理障碍。我们在I / O上阻止,但我们在渠道上 等待 。只要系统整体上有足够的并行松弛(即其他活动的goroutine)来保持CPU忙碌,在通道上等待就不要皱眉了。
可视化组件
所以,回到你的问题。让我们根据组件来考虑它,您需要探索许多要点。假设每个源都是goroutine,它然后在输出通道中形成一个组件。 Go允许共享通道末端,因此许多源可以安全地将它们的点交错到单个通道上。你不必做任何事情 - 它只是渠道的运作方式。
Dewy Broto描述的批处理功能本质上是另一个组成部分。作为一种学习练习,以这种方式表达是一件好事。批处理组件有一个点输入通道和一个批处理输出通道。
最后,HTTP i / o行为也可以是具有一个输入通道且没有输出通道的组件,仅用于接收整批点,然后通过HTTP发送它们。
仅使用一个来源的简单情况,可能会这样描述:
+--------+ point +---------+ batch +-------------+
| source +------->-------+ batcher +------->-------+ http output |
+--------+ +---------+ +-------------+
这里的目的是描述在基础层面的不同活动。它有点像数字电路图,并不是巧合。
你确实可以在Go中实现它,它会起作用。它甚至可能运行得很好,但实际上您可能希望通过组合成对组件来优化它,并根据需要重复进行。在这种情况下,很容易将batcher和http输出结合起来,最终得到Dewy Broto的解决方案。
重要的是,Go并发最容易发生
我将挑战移动频道可视化的更高级主题(Pi-Calculus)作为挑战,其中使用频道将频道结束发送到其他goroutines。