8

我只是在学习,并且非常喜欢 Actor 模式。我现在正在使用 Scala,但我对一般的架构风格很感兴趣,因为它用于 Scala、Erlang、Groovy 等。

我正在考虑的情况是我需要同时做一些事情,例如,让我们说“运行一份工作”。

使用线程,我将创建一个线程池和一个阻塞队列,并让每个线程轮询阻塞队列,并在作业进出队列时处理它们。

对于演员,处理这个问题的最佳方法是什么?创建一个演员池并以某种方式向他们发送包含作业或作业的消息是否有意义?也许有一个“协调员”演员?

注意:我忘记提到的案例的一个方面是:如果我想限制我的应用程序将同时处理的作业数量怎么办?也许有配置设置?我在想一个游泳池可能会很容易做到这一点。

谢谢!

4

3 回答 3

5

池是您在创建和拆除资源的成本很高时使用的一种机制。在 Erlang 中情况并非如此,因此您不应该维护一个池。

您应该在需要时生成进程,并在完成后销毁它们。

于 2009-12-31T17:06:05.040 回答
4

有时,限制在大型任务列表上同时运行的工作进程的数量是有意义的,因为生成进程以完成的任务涉及资源分配。至少进程会耗尽内存,但它们也可以保留打开的文件和/或套接字,这些文件和/或套接字往往仅限于数千个,一旦用完,就会惨遭失败且不可预测。

要拥有一个拉驱动的任务池,可以生成N个请求任务的链接进程,并且一方面给它们一个可以生成监视器的函数。一旦被监控的进程结束,他们就会回来执行下一个任务。具体需求驱动细节,但这是一种方法的概要。

我让每个任务产生一个新进程的原因是进程确实有一些状态,从一个干净的状态开始是很好的。设置进程的最小堆大小是一种常见的微调,以最小化其生命周期内所需的 GC 数量。它也是一种非常有效的垃圾收集,可以为一个进程释放所有内存并为下一个任务启动一个新内存。

像这样使用两倍数量的进程是否感觉很奇怪?这是你在 Erlang 编程中需要克服的一种感觉。

于 2009-12-31T18:23:36.790 回答
2

没有适用于所有情况的最佳方法。该决定取决于工作的数量、持续时间、到达时间和所需的完成时间。

仅生成 Actor 和使用池之间最明显的区别在于,在前一种情况下,您的工作将几乎同时完成,而在后一种情况下,完成时间将及时分布。不过,平均完成时间将是相同的。

使用演员的好处是编码简单,因为它不需要额外的处理。权衡是您的参与者将竞争您的 CPU 内核。无论您使用哪种编程范式,您都无法拥有比 CPU 内核(或 HT 等)更多的并行作业。

例如,假设您需要执行 100,000 个作业,每个作业需要一分钟,结果将在下个月到期。你有四个核心。你会派出 100,000 名演员,每个演员争夺资源一个月,还是只是将你的工作排队,一次执行四个?

作为一个反例,想象一个 Web 服务器在同一台机器上运行。如果您有五个请求,您是希望在 T 时间内为四个用户提供服务,在 2T 时间内为一个用户提供服务,还是在 1.2T 时间内为所有五个用户提供服务?

于 2009-12-31T18:43:11.400 回答