【问题标题】:Processing Messages with Threads, efficiently?高效地使用线程处理消息?
【发布时间】:2009-07-04 10:24:12
【问题描述】:

我需要帮助设计一个消息分发系统。到目前为止,我有 2 个进程,一个监听远程客户端的传递消息,然后 写入数据库表。

然后我有第二个进程每隔 [n] 秒从同一个表中读取一次,一次读取最多可获取 100 条消息,如果有任何新记录,则将每条记录排队以在其自己的 ThreadPool 发出的 backgorund 线程上发送.

如果可用的消息多于线程,线程池会将所有超出其最大线程数的消息排队。如果没有消息,则返回睡眠状态并等待下一个 Timer 事件将其唤醒以再次检查 db 表。

问题是我可能在一个时间间隔内有很多消息到达:最好将它们留在 Db 中直到需要,而不是留在内存中,在 ThreadPool 中排队等待。

换句话说,我正在寻找一种优雅的方式来知道何时可以添加更多排队的线程,而不是简单地等到下一个计时器间隔......

我的一个想法是计算我排队的 Worker 线程数(例如:500,等于我首先设置的最大线程数),并在它们完成时计算它们。如果它们低于 1/2(例如:250),则重新进行 Db 检查。如果找到记录,很好,一次获取 100 个,直到完全读取 db 表,或者再次达到 500 个最大值。

换句话说,使出队的主要焦点是线程本身,自我启动自身的连续性,而不是计时器(计时器间隔只是因为在管道干涸的情况下重新启动进程的机制)。

有人对这样的系统有建议/cmets/经验吗?方法可靠吗?还是有严重缺陷?

【问题讨论】:

  • 您正在讨论“生产者/消费者”场景,其中包含一个生产者和多个消费者。这是一种常见的设计模式,周围有很多类似devpinoy.org/blogs/jakelite/archive/2009/01/12/… 的引用。稍后我会尝试收集更多链接,并发布更好的回复,但我想我暂时将一些条款留给谷歌。 :-) HTH。
  • 好奇:我们在谈论什么数据库?它是否像 SQL Server、Oracle 和 DB2 那样提供开箱即用的消息传递功能?

标签: c# multithreading


【解决方案1】:

我发现线程涉及的开销(例如上下文切换)会很快使使用线程对性能产生不利影响。此外,除非您的线程花费大量时间等待 IO 等,否则拥有比 CPU(或内核)更多的线程没有任何意义。

所以假设您确实需要线程来处理您的数据,也许您可​​以创建一些线程。每个线程查询数据库以获取一大块数据(一次可能限制为 100 行)并对其进行处理。当它完成处理时,它会尝试获取另一块数据。您将需要同步数据访问(即同步检索到的最后一行 ID),并且仍然需要一个计时器,以防线程处理所有可用数据并休眠。这种方法假定数据处理时间比数据库访问时间长得多。

最重要的是,你确定你真的需要线程吗?我会说你最好的选择是让它在没有线程的情况下工作,然后在必要时进行优化。这是我从线程中学到的最重要的一课(艰难的方式)。

【讨论】:

  • 您好 Andrew:使用的交付服务是异步 Web 服务,所以是的,完成它们的时间比数据库访问慢得多。因此(我认为)很适合创建比 CPU 更多的线程。使用 ThreadPool,上下文切换相对来说比较轻松。但更重要的是,seach 每个 Send 请求都可能因超时而失败,最好给每个分配一个线程?一个线程中的多次超时可能会导致真正的消息堆积...
  • @Ciel:您说“使用 ThreadPool,上下文切换相对轻松”。我不认为这是一个真实的说法。每个 CPU 内核一个线程是理想的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
  • 2012-04-28
  • 2018-12-05
  • 1970-01-01
相关资源
最近更新 更多