C# HttpWebRequest和I/O完成端口

C# HttpWebRequest和I/O完成端口,c#,multithreading,httpwebrequest,threadpool,io-completion-ports,C#,Multithreading,Httpwebrequest,Threadpool,Io Completion Ports,我正在开发一个应用程序,它需要一种类型的消息进入数据库,另一种类型的消息进入外部XMLAPI 我要处理很多。。。最大的挑战之一是让HttpWebRequest类运行良好。我最初只是使用标准的同步方法和线程池。这不好 因此,经过一点阅读,我发现推荐的方法是使用Begin/End方法将工作委托给IO完成端口,从而释放线程池并获得更好的性能。事实似乎并非如此。。。性能稍微好一点,但与threadpool相比,我肯定看不到IO完成端口的使用率有多高 我有一个线程,它旋转并向我发送线程池中可用的工作线程+

我正在开发一个应用程序,它需要一种类型的消息进入数据库,另一种类型的消息进入外部XMLAPI

我要处理很多。。。最大的挑战之一是让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堆栈的httpconnections吗?有人建议使用WinHttp(或其他C++库),然后从.NET中调用它,但这不是我特别想做的事情!p> 据我所知,异步请求未完成时,您不会一直占用I/O完成端口—只有在返回数据并在相应线程上处理数据时,它才会“忙”。希望您在回调中没有太多的工作要做,这就是为什么您在任何时候都没有很多正在使用的端口

你的表现真的很差吗?你担心的仅仅是数量少吗?您是否获得了预期的吞吐量


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

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

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

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

如果有8个线程在8个内核上积极地执行CPU限制的工作,那么添加更多线程只会降低速度(线程之间的上下文切换将是浪费时间)


您应该了解的是,为什么还有120个其他线程,以及它们在做什么。

回调几乎什么都不做,甚至流读写都是异步执行的(虽然这可能是我的问题的一部分?我看到的所有示例都使用同步流读取、写入和请求流操作。性能差:是-我使用秒表并在完成时发送消息。秒表的范围从<1秒到超过60秒。我已将ServicePointManager.DefaultConnevtionLimit增加到2048,我使用的是KeepAlive,netstat确实显示了2048个已建立的连接。@peteisace:听起来你做的一切都是对的。你有多确定服务器真的响应很快?你有没有尝试过抓取Wireshark转储?如果我删除了一个与我通信的外部api,另一个会更好s、 所以这肯定是我的客户端调用。我的理论是,我使用了太多的线程池线程,这会导致太多线程跳转,这意味着无法足够快地处理内容,这就是为什么我真的希望强制完成端口比现在忙得多。PS没有使用所有可用带宽!加上http内容对我的db线程产生了负面影响,这就是为什么我认为池中的线程太多。@peteisace:有没有可能您实际使用的线程太多,导致上下文切换导致效率降低?查看性能监视器,您的CPU忙吗?有可能,这是我的理论(120个工作线程的使用率似乎很高,有时甚至更高)。CPU不是很忙,但它不是一个CPU密集型的应用程序。我猜是~4-8%。谢谢。你的外部API处理负载是否合适?我有一个外部服务,如果