我正在尝试理解在Erlang演讲中提到的一种设计模式。基本上,演讲者提到使用工作队列时,使用“消息作为进程”而不是使用作业作为进程。
关键思想是通过使用“消息作为进程”,您可以节省序列化/反序列化开销。
谢谢
我正在尝试理解在Erlang演讲中提到的一种设计模式。基本上,演讲者提到使用工作队列时,使用“消息作为进程”而不是使用作业作为进程。
关键思想是通过使用“消息作为进程”,您可以节省序列化/反序列化开销。
谢谢
假设我们有一个 Erlang term(),即在系统中发送的 消息,记为M
。 处理M
的一种明显方法是构建一个处理过程和队列的管道。 第一个工作进程将处理M
,然后将其发送到下一个队列。 然后由下一个工作进程接收、再次处理并放入队列。 重复这个过程直到消息完全处理完。
可能不那么明显的方法是定义一个进程P
,然后将M
交给P
。 我们将其表示为P(M)
。现在,消息本身是一个进程而不是一个数据。P
会执行与队列解决方案中的工作进程相同的工作,但它不必花费精力来把M
重新放入队列,再取出等。当处理P(M)
完成时,进程将简单地结束其生命周期。如果交给另一个消息M'
,我们将简单地生成P(M')
并让它同时处理该消息。如果我们得到一组进程,我们将执行[P(M) || M <- Set]
等操作。
如果P
需要进行同步或消息传递,它可以这样做,而无需“冒充”消息,因为它就是消息。与工作人员队列方法相比,其中工作进程必须对经过其处理的消息负责。如果P
出现错误,只有受到该错误影响的消息P(M)
会崩溃。再次与工作人员队列方法相比,管道中的崩溃可能会影响其他消息(特别是如果管道设计不良)。
因此,技巧在于:将一个消息转化为成为该消息的进程。
这个成语是“One Process per Message”,在Erlang中很常见。创建新进程的价格和开销足够低,这样就行得通了。然而如果使用这个想法,您可能需要一些类型的过载保护措施。原因是您可能希望限制并发请求的数量,以便控制系统的负载,而不是盲目地让其摧毁服务器。一个这样的实现是由Erlang Solutions创建的Jobs,请参见: https://github.com/esl/jobs Ulf Wiger在以下网址上展示了它: http://www.erlang-factory.com/conference/ErlangFactoryLiteLA/speakers/UlfWiger 正如Ulf在演讲中暗示的那样,我们通常会在P
之外进行一些预处理,以解析消息并将其内部化到Erlang系统中。但是尽快通过将消息M
包装在进程(P(M)
)中,我们就可以立即获得Erlang调度程序的好处。