向消费者通知新事件的常用方式 消息传递系统(messaging system):Pro发送包含事件的消息,然后将消息推给Con。
像Pro和Con之间的 Unix 管道或 TCP 连接这样的直接信道,是实现消息传递系统的简单方法。但大多消息传递系统都在这一基本模型扩展。Unix管道和TCP将恰好一个发送者与恰好一个接收者连接,而一个消息传递系统允许多个Pro节点将消息发到同一主题,并允许多个Con节点接收主题的消息。在这发布 / 订阅模式中,不同系统采取各种方法,并没有针对所有目的的通用答案,区分前提:
- 若生产者发送消息的速度>消费者能够处理的速度,一般有三种选择:系统丢掉消息,将消息放入缓冲队列,或使用背压(backpressure,也称流量控制flow control:阻塞生产者,以免其发送更多的消息)。Unix 管道和 TCP 使用背压:它们有一个固定大小的小缓冲区,如填满,发送者会被阻塞,直到接收者从缓冲区中取出数据。 如消息被缓存在队列,当队列装不进内存时系统会崩溃吗?还是将消息写盘?如这样,磁盘访问又会如何影响消息传递系统的性能?
- 如节点崩溃或暂时脱机,是否会有消息丢失?与数据库一样,持久性可能需写入磁盘和 / 或复制的某种组合,这有代价。如果你能接受有时消息会丢失,则可能在同一硬件上获得更高吞吐量、更低延迟。
是否接受消息丢失取决应用。如对周期传输的传感器读数和指标,偶尔丢失的数据点可能并不重要,因为更新的值会在短时间内发出。但若大量消息被丢弃,可能无法立刻意识到指标已经不正确。若你正在对事件计数,则它们能可靠送达更重要,因为每个丢失的消息都意味着使计数器错误扩大。
批处理系统的一个好特性是,它们提供强大可靠性保证:失败任务会自动重试,失败任务的部分输出会自动丢弃。这意味着输出与没发生故障一样,简化了编程模型。