6

我正在开发一个应用程序,该应用程序需要一种类型的消息访问数据库,而另一种类型的消息需要访问一些外部 xml api。

我必须处理很多......最大的挑战之一是让 HttpWebRequest 类表现良好。我最初只使用标准同步方法和线程池化整个事情。这不好。

因此,经过一番阅读,我看到推荐的方法是使用 Begin/End 方法将工作委托给 IO 完成端口,从而释放线程池并产生更好的性能。情况似乎并非如此……性能稍微好一些,但与线程池相比,我当然看不到 IO 完成端口的使用量那么多。

我有一个旋转的线程并向我发送线程池中可用的工作线程+完成端口。完成端口总是非常低(我见过最多使用 9 个),而且我总是使用大约 120 个工作线程(有时更多)。我对所有方法都使用了开始/结束模式httpwebrequest

Begin/EndGetRequestStream
Begin/EndWrite (Stream)
Begin/EndGetResponse
Begin/EndRead (Stream)

我做对了吗?我错过了什么吗?我可以(有时)同时使用多达 2048 个 http 连接(来自 netstat 输出) - 为什么完成端口号会这么低?

如果有人可以就如何管理工作线程、完成端口提供一些认真的建议,httpwebrequest我们将不胜感激!

编辑:.NET 是一个合理的工具吗?我可以获得大量使用 .NET 和 System.Net 堆栈的 httpconnections 吗?有人建议使用 WinHttp(或其他一些 C++ 库)之类的东西,并从 .NET 中 pInvoke 它,但这不是我特别想做的事情!

4

3 回答 3

6

按照我的理解,您不会一直占用异步请求未完成的 I/O 完成端口-只有当数据已返回并正在相应线程上处理时,它才会“忙碌”。希望您在回调中没有太多工作要做,这就是为什么您在任何时候都没有很多正在使用的端口。

真的表现不佳吗?您担心的原因仅仅是数字低吗?您是否获得了预期的吞吐量?

可能遇到的一个问题是任何一台主机的 HTTP 连接池都相对较小。如果您对同一台机器有数百个请求,那么默认情况下一次实际上只会发出 2 个请求,以避免 DoS 攻击相关主机(并获得保持活动的好处)。您可以通过编程方式或使用 app.config 来增加它。当然,在您的情况下,这可能不是问题,因为您已经解决了问题,或者因为您的所有请求都是针对不同主机的。(如果 netstat 显示 2048 个连接,那听起来还不错。)

于 2011-01-24T07:28:35.953 回答
0

只有 9 个完成端口线程实际上意味着您可能正在正确有效地使用它们。我将假设您正在运行的机器具有 8 个内核或 4 个超线程内核,这意味着操作系统将尝试随时保持多达 8 个活动(不是休眠/阻塞/等待)完成端口线程。

如果其中一个正在运行的线程变得不活动(睡眠/阻塞/等待)并且有额外的工作项要处理,那么将创建一个额外的线程以将活动计数保持在 8。如果您看到 9 个线程,这意味着您正在在完成端口线程上的方法中几乎没有引入阻塞,并实际使用它们进行 CPU 工作。

如果您有 8 个线程在 8 个内核上主动执行 CPU 密集型工作,那么添加更多线程只会减慢速度(线程之间的上下文切换将浪费时间)。

您应该研究的是为什么您有 120 个其他线程以及它们在做什么。

于 2011-02-16T14:08:30.507 回答
0

也许您的 EndRead 方法应该只将结果写入线程安全队列,然后从您控制的少数工作线程中读取该队列。和/或使用 HttpWebRequest 在完成时会发出一个可等待对象的信号这一事实,并编写您自己的逻辑来等待来自单个(或少量)线程的所有未完成的请求。

于 2011-01-26T14:01:20.037 回答