8

我们在 .net 项目中引用了第 3 方专有的 CLI DLL。该 DLL 只是其专有 C++ 库的接口。我们的项目是一个 asp.net (MVC4/Web API) Web 应用程序。

C++ 非托管库相当不稳定。有时它会因悬空指针而崩溃。我们没有办法解决,使用这个库是一流的客户需求。

当应用程序崩溃时,IIS 中的应用程序池不再响应。我们必须重新启动它,这样做需要几分钟(是的,那么久!)。

我们希望防止这个不稳定的 DLL 使我们的应用程序崩溃。最好的方法是什么?我们可以将 CLI DLL 保存在单独的 AppDomain 中吗?如何?

提前致谢。

4

4 回答 4

6

我认为这个问题的每一个答案都将是某种解决方法。

我的解决方法是不直接与 Web 应用程序中的 DLL 交互。

而是将您的请求从 Web 应用程序写入消息队列或 SQL 表。然后,您可以让另一个应用程序(例如 Windows 服务)读取请求、与 DLL 交互,然后将结果写回供您的 Web 应用程序读取。

我并不是说 SQL / Message Queues 是正确的方法,我更多的是考虑一般的流程。

于 2013-06-10T20:47:41.683 回答
4

我在访问受保护内存以与硬件复制保护加密狗进行交互的第三方库时遇到了这个确切的问题。它在控制台或 winforms 应用程序中运行良好,但在从 IIS 应用程序调用时却像疯了一样崩溃。

我们尝试了几种不同的方法,其中一些在本页的其他答案中有所提及。但最终,对我们来说最好的解决方案是一种非常古老的技术——.Net Remoting。我知道——这几天有点皱眉。但它非常适合这种特殊需求。

不稳定的代码被放置在 Windows 服务应用程序中。Web 应用程序对该服务进行远程调用,该服务将命令中继到第三方库。

现在我确信您可以使用 WCF、套接字等来做同样的事情。但是远程处理设置起来又快又容易,而且因为我们只与同一个服务器通信,所以它可以在不打开任何端口的情况下工作。它只是在命名管道上进行对话。

这确实意味着除了 Web 应用程序之外还要安装第二个服务,但这在我的特定用例中是可以接受的。

如果你做了类似的事情,而第三方代码实际上使服务崩溃,你可能会在你的主应用程序中编写一些代码来恢复它。

因此,当您需要处理不稳定的代码时,进程边界可能比应用程序域更有用。

于 2013-06-17T00:01:44.260 回答
2

I suggest following solution.

  1. Wrap this dll with another web application. Can be one of the following ones. Since you already use web api, it is most suitable for you.

    1. Simple ASMX Web Service
    2. WCF Service
    3. Asp.Net MVC - WEB Api Service
  2. Control your p-invoke code so that you do not have any bug? See following articles.

    1. The Black Art of P/Invoke and Marshaling in .NET
    2. P/Invoke Revisited
  3. Publish this application to IIS with different application pool.
  4. Use standard techniques suggested before like. I suggest configure recycling IIS for both memory and scheduled times.
    1. IIS process recycling rate
    2. How to limit the memory used by an application in IIS?
于 2013-06-15T20:35:18.563 回答
2

我会首先提高IIS进程回收率,可能DLL代码在调用一定次数后失败,或者在进程达到一定的内存使用量后。

您可以在此处找到有关 IIS 7.0 回收选项配置的信息:http ://technet.microsoft.com/en-us/library/cc753179(v=ws.10).aspx

在您的情况下,当您知道应用程序的负载较少时,我会在特定时间回收该过程。并且在经过一定数量的请求(低于默认值)之后,大部分时间都尝试“新鲜”处理。

从某种意义上说,回收过程是优雅的,旧的进程在替换它的进程准备好之前不会终止,因此应该没有明显的停机时间。有关回收机制的更多信息,请访问:http ://technet.microsoft.com/en-us/library/cc745955.aspx

如果上述方法不能解决问题,我会将调用包装在我自己的代码中,以管理不稳定的 DLL 执行。

该代码应该从失败中恢复,例如通过重复失败的调用直到获得结果,如果在多次尝试后仍然不可能,则失败并出现正常错误。

在内部,对不稳定 DLL 的调用可以在衍生线程中进行,甚至代码也可以在您可以使用 Process.Start 启动的新外部可执行文件中。

最后一个选项有更多开销,但它可能是您唯一的选择。有关此问题的更多信息,请参阅此 SO 问题:您如何处理挂起呼叫的线程?

于 2013-06-10T09:22:16.687 回答