8

我正在为 Linux 设计一个专用的系统日志处理守护进程,它需要强大且可扩展,并且我正在讨论多线程与多进程。

多线程的明显反对意见是复杂性和讨厌的错误。由于 IPC 通信和上下文切换,多进程可能会影响性能。

“Unix 编程的艺术”在这里讨论了这一点。

您会推荐基于进程的系统(如 Apache)还是多线程方法?

4

8 回答 8

23

它们都可以以自己的方式变得复杂和复杂。

你可以做任何一个。从宏观上看,你选择哪一个可能并不重要。重要的是你做得如何。所以:

做你最有经验的事情。或者,如果你领导一个团队,那就做团队最有经验的事情。

---穿线!---

我做过很多线程编程,我喜欢其中的一部分,也有一部分我不喜欢。我学到了很多东西,现在通常可以编写一个多线程应用程序而不会太痛苦,但它确实必须以非常具体的方式编写。即:

1) 它必须用非常明确定义的数据边界来编写,这些边界是 100% 线程安全的。否则,任何可能发生的情况都会发生,而且当你有一个调试器时,它可能不会发生。另外,调试线程代码就像窥视薛定谔的盒子……通过查看那里,其他线程可能有也可能没有有时间处理更多。

2) 它必须用对机器施加压力的测试代码编写。许多多线程系统仅在机器承受很大压力时才显示它们的错误。

3)必须有一些非常聪明的人拥有数据交换代码。如果有任何方法可以创建快捷方式,一些开发人员可能会创建它,并且您将遇到错误的错误。

4) 必须有包罗万象的情况,以最少的麻烦重置应用程序。这是针对由于某些线程问题而中断的生产代码。简而言之:演出必须继续。

- -跨进程! - -

我对基于进程的线程的经验较少,但最近一直在 Windows 中做一些跨进程的东西(其中 IPC 是 Web 服务调用...... WOO!),它相对干净和简单,但我遵循一些规则这里也是。总的来说,进程间通信将不会出错,因为程序可以很好地接收来自外部世界的输入……而且这些传输机制通常是异步的。反正...

1) 定义清晰的流程边界和沟通机制。通过 TCP 或 Web 服务或管道或任何其他方式的消息/事件,只要边界清晰,并且在这些边界处有大量验证和错误检查代码。

2) 为瓶颈做好准备。代码宽恕非常重要。我的意思是,有时您将无法写入该管道。您必须能够重新排队并重试这些消息,而应用程序不会锁定/抛出异常。

3) 通常会有更多的代码,因为跨进程边界传输数据意味着您必须以某种方式对其进行序列化。这可能是问题的根源,尤其是当您开始维护和更改该代码时。

希望这可以帮助。

于 2009-03-24T22:28:28.813 回答
3

你遗漏了太多细节。实际上,就您已经说过的内容而言,选择是无关紧要的,多线程本质上没有什么比多处理更容易出错的了;你错过了为什么这些技术有这样的声誉。如果您不共享数据,那么不会有太大问题(当然,可能还有一些其他问题,但我们需要详细信息来决定这些问题)。此外,在什么平台上,在像 UNIX 这样的操作系统上,进程是非常轻量级的也很重要。

但是,还有其他问题需要考虑吗?您将在什么样的系统上运行?您绝对不想在单处理器系统上生成多个进程,因为您不会获得太多好处,这取决于您可以指定的其他一些细节。如果您描述了您要解决的问题的性质,我们可以提供进一步的帮助。

于 2009-03-22T22:31:53.470 回答
2

取决于您要使用的编程语言(以及哪些库)。我个人会选择多线程,因为我知道与线程相关的问题(以及如何解决它们)。

如果您想在多台机器上运行守护程序并在它们之间分配负载,多处理可能会对您有所帮助,但我认为这不是一个主要问题。

于 2009-03-22T21:07:59.850 回答
2

如果您想要稳健性,请使用多处理。

这些进程将在它们之间共享日志记录负载。迟早,日志记录请求会遇到错误并使记录器崩溃。使用多处理,您只会丢失一个进程,因此只会丢失一个日志记录请求(由于错误,您无论如何都无法处理)。

多线程很容易崩溃,因为一个致命的错误会破坏您的单个进程。

多处理在某些方面在技术上更具挑战性,因为您必须在进程之间平衡工作负载,这可能需要使用共享内存。

于 2009-03-24T22:06:05.717 回答
1

您是否需要在更新频繁且 IPC 过于昂贵的实例之间共享更新数据?在这种情况下,多线程可能会更好。否则,您必须权衡单独进程的健壮性或线程创建/通信的简易性对您来说是否更重要。

于 2009-03-22T21:11:00.373 回答
0

感谢大家的反馈。

我决定采用类似于 Apache Web 服务器的多进程架构。这些过程将在多处理器/核心系统上很好地扩展。将使用管道或套接字进行通信。

进程将准备好在进程池中使用,因此没有进程生成成本。

与我将获得的稳健性相比,性能损失可以忽略不计。

于 2009-03-28T18:19:08.117 回答
0

一个问题是是否有必要这样做。我不知道您的要求的详细信息,但是使用单线程应用程序select(2)可能适合您的需求,并且没有进程或线程的缺点。这要求您能够将所有 I/O 集中到一个中心位置,最有可能通过回调分派到其他模块,但这并不难,除非您有很多库想要自己做 I /O 并且不能以这种方式重组。

于 2009-03-24T22:17:24.410 回答
0

好吧,我们最终将它实现为一个多进程系统,其中包含用于 IPC 的管道和一个根据需要生成进程的簿记员。类似于 Apache httpd。它完美地工作。

于 2009-10-02T12:47:06.837 回答