Stuff Goes Bad:Erlang In Anger

Queue Buffers


Queue buffers are a good alternative when you want more control over the messages you get rid of than with random drops, particularly when you expect overload to be coming in bursts rather than a constant stream in need of thinning.
Even though the regular mailbox for a process has the form of a queue, you’ll generally want to pull all the messages out of it as soon as possible. A queue buffer will need two processes to be safe:
• The regular process you’d work with (likely a gen_server);
• A new process that will do nothing but buffer the messages. Messages from the outside should go to this process.

 • 常规的工作进程(就像gen_server)。
 • 一个只做缓冲消息工作的新进程,外界的消息应当先路由到这个进程中。

To make things work, the buffer process only has to remove all the messages it can from its mail box and put them in a queue data structure 16 it manages on its own.
Whenever the server is ready to do more work, it can ask the buffer process to send it a given number of messages that it can work on. The buffer process picks them from its queue, forwards them to the server, and goes back to accumulating data.


Whenever the queue grows beyond a certain size 17 and you receive a new message, you can then pop the oldest one and push the new one in there, dropping the oldest elements as you go. 18
This should keep the entire number of messages received to a rather stable size and provide a good amount of resistance to overload, somewhat similar to the functional version of a ring buffer.
The PO Box 19 library implements such a queue buffer.

 当队列增长超过一定规模时17,这时你又收到了一个新消息,你可以弹出最老的消息,并把这个新来的消息放在那,甚至可以把最老的消息给丢弃掉18,这完全 取决于你的设计。
 这就能要保证能处理稳定的消息流,并提供一个强抗过载能力,有点类似于循环缓冲(ring buffer)的功能版。
 PO Box19就提供了这样一个缓冲队列。
[16] The queue module in Erlang provides a purely functional queue data structure that can work fine for such a buffer.
[17] To calculate the length of a queue, it is preferable to use a counter that gets incremented and decremented on each message sent or received, rather than iterating over the queue every time. It takes slightly more memory, but will tend to distribute the load of counting more evenly, helping predictability and avoiding more sudden build-ups in the buffer’s mailbox.
[18] You can alternatively make a queue that pops the newest message and queues up the oldest ones if you feel previous data is more important to keep.
[19] Available at:, the library has been used in production for a long time in large scale products at Heroku and is considered mature

[注19]: 这个库很久之前大规模用于Heroku,是很成熟的库。