【问题标题】:Using unmanaged thread-unsafe library in WCF service hosted in IIS在 IIS 中托管的 WCF 服务中使用非托管线程不安全库
【发布时间】:2012-12-31 02:56:17
【问题描述】:

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

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

我该怎么做?

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

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

【问题讨论】:

  • 你能解释一下为什么你的非托管库不安全吗?如果是因为内存和对象的状态,那么您不一定需要运行多个进程。您可以通过每个会话或调用拥有它自己的服务实例,从而分离非托管对象的实例。
  • @TylerOhlsen 我已经更新了问题。
  • 这个共享静态数组是per thread还是per process
  • @AllonGuralnek 每个进程

标签: .net wcf iis thread-safety unmanaged


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 我的服务托管在 IIS 中。 IIS 可以旋转进程(所谓的网络森林)。有什么方法可以利用 IIS 设施来帮助实现您所描述的目标?
  • @KonstantinSpirin:我不了解 IIS 本身,但从 WCF 方面来看,没有控制进程的方法,只有线程 (AFAIK)。 IIS 可能具有您描述的功能,但我不是 IIS 专家,抱歉。
【解决方案2】:

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

Instance Context Mode 指定可用于处理传入消息中包含的调用的服务实例数。

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

Sessions, Instancing, and Concurrency

WCF Concurrency (Single, Multiple, and Reentrant) and Throttling

【讨论】:

  • 会在不同进程中并行处理多个请求吗?
  • 每个过程都不​​一样。将 InstanceContextMode 设置为 PerCall 或 PerSession 将处理同一 Process 内多个服务对象的多个请求。
  • 不幸的是,我不允许在同一个进程中运行多个并行请求(请参阅我的问题更新以获得澄清)。
猜你喜欢
  • 1970-01-01
  • 2022-12-13
  • 2020-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多