HttpWebRequest和I / O完成端口

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

我必须处理A LOT …其中一个重大挑战是让HttpWebRequest类表现良好。 我最初开始只使用标准的同步方法和线程整个事情。 这不好。

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

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

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

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

如果有人可以就如何处理这个管理工作线程,完成端口和httpwebrequest提供一些认真的建议,那将非常感激!

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

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

实际上是否表现不佳? 您的原因仅仅是数量较少? 您是否获得了预期的吞吐量?

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

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

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

如果其中一个正在运行的线程变为非活动状态(睡眠/阻止/等待)并且还有其他工作项需要处理,那么将创建一个额外的线程以将活动计数保持为8.如果您看到9个线程,则表示您是在完成端口线程上的方法中几乎没有阻塞,并实际上在CPU上使用它们。

如果你有8个线程主动在8个内核上进行CPU绑定工作,那么添加更multithreading只会减慢速度(线程之间的上下文切换将是浪费的时间)。

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