3

我有一个托管在 IIS 中的 WCF 服务,它调用线程不安全的非托管库。

我需要以某种方式设置 IIS,以便它保留一个进程池并为每个进程分配一个请求。

我该怎么做?

线程不安全性质的解释:非托管库包含进程范围的共享静态数组,该数组在操作开始时归零,然后在操作期间缓慢(30s-3m)填充结果,然后将最终结果返回给我。调用不是 CPU 密集型的,数据是从外部来源收集的。进行顺序调用是安全的,但任何并行调用都会导致数组中的数据损坏,并且两个调用都返回错误的结果。我无法控制这个库。

我需要能够并行处理 30-100 个请求。

4

2 回答 2

2

由于您有一个单个进程资源,因此您需要手动启动进程,因为我不知道有任何方法可以自动执行此操作。您仍然可以使用 WCF 执行进程间通信,并为所有进程提供一个面向公众的入口点。

您需要一个主管服务来接受请求,启动工作进程,向其发送数据并等待其完成,然后接收数据并将其转发给原始请求者。每个工作进程都可以使用ServiceHost该类托管一个 WCF 服务器(使用起来非常简单)。您可以让工作进程在返回结果时终止,也可以执行自己的池化。如果你想合并,只需在工人合同上有两种方法:DoWorkShutdown. 串行调用每个工作人员的 DoWork,或者您可以通过将以下属性应用于工作人员服务类来让 WCF 本身阻止并发请求:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                 ConcurrencyMode = ConcurrencyMode.Single)]

这将确保在单个工作进程上运行两个并行操作的任何尝试都会阻塞并将请求排队,因此您可以简单地以循环方式调用所有工作线程来处理和排队超过您的峰值负载处理能力。

您的主管将有一个简单的面向客户的合同,该合同只是将工作分配给工作进程。如果您正在汇集工作人员,您可以在负载减少并且不再需要它们时关闭其中的一些(如果需要的话)。主管可以使用 WCF 的异步模式几乎不使用任何资源(因为它实际上并没有做任何工作),而不是每个请求都阻塞并占用一个线程。对于 WCF 异步,我建议使用 .NET 4.5,因为Task<T>与在 .NET 4.0 及更低版本中跳过 WCF 所需的异步箍相比,这更容易实现(只需返回 a )。

底线是,由于你奇怪的限制,你必须做一些腿部工作才能实现你想要的目标。尽管如此,大部分管道仍然可以由 WCF 处理。

于 2012-12-31T09:12:38.977 回答
0

您可以使用ServiceThrotttlingBehavior来配置进程池,并使用Concurrency Mode来指定服务类是支持单线程还是多线程操作模式。

实例上下文模式指定可用于处理传入消息中包含的调用的服务实例数。

对于您的情况,
1.ConcurrencyMode应该是ConcurrencyMode.Singleor ConcurrencyMode.Reentrant
2.InstanceContextMode应该是PerCallPerSession

会话、实例化和并发

WCF 并发(单、多和可重入)和限制

于 2012-12-31T03:09:48.610 回答