我在IIS中托管了一个WCF服务,该服务调用了线程不安全的非托管库。
我需要以某种方式设置IIS,以便它保留一个进程池,并为每个进程分配一个请求。
我该怎么做?
线程不安全性的解释: 非托管库包含进程范围的共享静态数组,该数组在操作开始时归零,然后在操作期间缓慢(30s-3m)填充结果,然后将最终结果返回给我。呼叫不是CPU密集型的,数据是从外部源收集的。 进行顺序调用是安全的,但任何并行调用都会导致数组中的数据损坏,并且两个调用都会返回错误的结果。 我无法控制这个库。
我需要能够并行处理30-100个请求。
答案 0 :(得分:2)
由于您只有一个每个进程资源,因此您需要手动启动进程,因为我不知道有任何方法可以自动执行此操作。您仍然可以使用WCF执行进程间通信,并为所有进程提供单个面向公众的入口点。
您需要一个主管服务来接受请求,启动工作进程,发送数据并等待数据完成然后接收数据并将其转发给原始请求者。每个工作进程都可以使用ServiceHost
类(非常简单易用)来托管WCF服务器。您可以在返回结果时让工作进程终止,也可以执行自己的池。如果您想要合并,只需在工作合同上使用两种方法:DoWork
和Shutdown
。以串行方式调用每个worker的DoWork,或者通过将以下属性应用于worker服务类,您可以让WCF本身阻止并发请求:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Single)]
这将确保在单个工作进程上运行两个并行操作的任何尝试都会阻止请求并将请求排队,因此您可以以循环方式简单地调用所有工作线程来处理和排队峰值负载超出你的处理能力。
您的主管将有一个简单的面向客户的合同,简单地将工作分配给工人流程。如果你正在汇集工人,你可以在负载减少时将其中一些关闭,并且不再需要它们(如果这是可取的)。主管可以使用WCF的异步模式几乎不使用任何资源(因为它实际上没有做任何工作),而不是每个请求阻塞和绑定一个线程。对于WCF异步,我建议使用.NET 4.5,因为与在.NET 4.0及更低版本中跳转WCF所需的异步箍相比,它更容易实现(只返回Task<T>
)。
最重要的是,由于你的奇怪约束,你将不得不做一些腿部工作来达到你想要的目标。尽管如此,大多数管道仍然可以由WCF处理。
答案 1 :(得分:0)
您可以使用ServiceThrotttlingBehavior配置进程池,使用Concurrency Mode来指定服务类是否支持单线程或多线程操作模式。
Instance Context Mode指定可用于处理传入消息中包含的呼叫的服务实例数。
对于你的情况,
1. ConcurrencyMode
应为ConcurrencyMode.Single
或ConcurrencyMode.Reentrant
2. InstanceContextMode
应为PerCall
或PerSession
。
Sessions, Instancing, and Concurrency
WCF Concurrency (Single, Multiple, and Reentrant) and Throttling