我在IIS中托管了一个WCF服务,该服务根据请求使用异步套接字请求向另一个服务器发出请求。请求必须快速(5秒)或超时。当很多用户同时发送请求时(我估计大约10个),那么在5秒内不会处理对另一台服务器的套接字请求。另一台服务器上的日志表示该请求几乎立即被接收和处理,并且响应被发回,但异步事件在5-10秒之前未被触发,导致wcf服务超时(注意这不是超时) wcf本身,但调用另一台服务器时内部超时)。我们认为该线程池要么太慢而不能产生新线程,要么有一些理由不这样做,这导致当没有线程可用于获取套接字的异步接收时的情况。据我所知,WCF和异步套接字处理程序都使用ThreadPool,所以他们真的争取相同的资源。有人遇到类似情况吗?处理它的最佳方法是什么?
我看到了两个简单的方法:
1)将wcf服务的最大并发请求数限制为5或其他可能导致速度较慢的因为某些请求必须在队列中等待。
2)增加ThreadPool中的MinSize数量 对于此事的任何建议我都很高兴。
P.S。处理器有8个内核,这意味着线程池的默认minsize是8,所以当超过8个并发请求发生时我开始看到问题。
答案 0 :(得分:2)
如果在等待异步IO时阻塞,则表明您正在创建一种可以保证创建ThreadPool线程饥饿的情况。
八个请求进入并使用ThreadPool中的所有线程。他们发出异步IO请求,一切都很好。 IO请求得到应答,异步回调排队到ThreadPool,但现在TheadPool中的所有线程都在等待我们刚刚排队到阻塞队列的操作。现在过了一会儿,ThreadPool注意到队列没有收缩,并在问题上抛出一个线程。慢慢地,系统中的备用线程可以缓解死锁,如果队列没有足够快地清除,ThreadPool可能会旋转另一个线程。重要的是,它没有任何急于处理这种增加的工作量,并乐观地使用尽可能少的线程,以清除积压。不好。负载延迟。
您需要重写服务合同才能返回Task<T>
而非plain'old T
。您的客户甚至都不会注意到,但是通过采用async
/ await
,您将能够毫不费力地运行数千个而不是8个并发客户端(假设实际工作量很小)。
如果这不是一个选项,请考虑使用同步方法执行IO,因为当前,您正在运行的线程以及您为了继续而依赖的线程都在相同的受约束的ThreadPool中运行。使用同步IO,您将删除大部分问题,尽管由于不编写异步服务方法,它仍会(IMO)严重受阻。
修改
在旧版本的.Net上看到你,你可能无法使用async / await。还有一些其他选项可用于编写异步服务,记录为here。 IIRC,虽然您更改了实施这些方法的合同,但是端点是w.r.t.只要您在文档中列出follow the conventions,客户就会保持不变。