CORBA 的 ASP.Net WebAPI 替代品?
Posted
技术标签:
【中文标题】CORBA 的 ASP.Net WebAPI 替代品?【英文标题】:ASP.Net WebAPI replacement for CORBA? 【发布时间】:2020-03-17 18:43:03 【问题描述】:我需要一些关于我正在从事的项目的指导。我们正在寻找 CORBA 服务器设置的替代品。简而言之,我们当前运行一个 CORBA 守护程序服务,该服务托管 10 个 C++ exe 实例,这是我们计算过程的入口点。 C++ 代码通过 COM 连接到一堆不同的 .net 和 C++ dll 和 OCX。我们还有另一个版本的可执行文件,它编译为 .dll,我们可以以类似的方式调用它,但它只是一个单实例系统,所以一切都很好。
我们现在正在寻找用 WebAPI 替换 CORBA 组件,因此我将一个基本的 ASP.net webAPI 项目放在一起,该项目能够将请求处理到这个 C++ dll 中。同样,当它一次只需要处理 1 个请求时,这很有效。当我开始测试并发请求时,事情开始横向发展。请求很好地进入我的处理程序,我可以看到 5 个请求(我到处都记录了正在发生的事情),每个线程都创建了一个 dll 的实例,但它们是同步运行的。
我发现,即使 ASP.net 处理程序中有多个线程,该 dll 也是 STAThreaded(这在代码中得到确认),因此调用排队并且一次只处理 1 个。我的猜测是因为线程都在同一个进程中,所以 dll 将所有线程视为同一个单元(STAThread)并导致队列。
我尝试了不同的 async/await 和 task.run 代码,我可以看到不同的线程,但它仍然归结为使 dll 同步运行的同一进程。我确实尝试通过将 CoInitializeEx(NULL,0x2) 更改为 CoInitializeEx(NULL,0x0) 来将 dll 更改为 MTA,但这似乎并没有改变任何东西。
我现在已经没有想法了,我认为更改为使用 .exe 版本并产生多个进程不会起作用,因为有 CORBA 的东西可以创建返回对象并将其传回给调用代码。我需要能够获取在 exe 中创建的对象以在请求中发回。
抱歉,这篇文章太长了,希望有人花时间阅读这堵文字墙,并对我可以尝试的方法有所了解。
谢谢!
【问题讨论】:
这里有很多混乱。 .DLL 不是“线程化的”。给定线程是 STA 或 MTA。这个选择是由创建线程(使用 CoInitializeXX)的开发人员做出的,而不是由其他任何人做出的。对象被标记为 Single、Apartment、Both、Free 等,这只是明确了它们在给定单元 (~thread) 中的行为方式。在 Web 服务器中,由于通常您拥有线程(它们在池中等),一切都变得复杂了。嗯...您的所有设置和架构听起来很复杂(C#、C++、CORBA、COM、.NET、线程、Web)并且很难帮助/解决 SO...中的问题... 我们的系统中发生了很多事情,核心组件已经存在了 20 年。至于没有被STATHreaded的dll,这是构造函数: CComInit() CoInitializeEx(NULL,0x2);这不会强制 dll 被 STAThreaded 处理吗?我知道在我编写的其他使用此 dll 的 .Net 应用程序中,我需要在 Main() 上使用 [STAThread] 装饰器以保持正常工作。 阅读您的问题,我毫不怀疑发生了很多事情 - 我在 COM 附近工作了 25 年 :-),这就是我的意思,因为它可能太多了关于SO的问题。无论如何,在 DLL 中调用 CoInitialize 是 Windows、COM 和线程如何工作的典型错误标志(我并不是说它不会工作,正如你所说的那样,你今天已经可以工作了)。 STAThread 只是意味着启动您的程序的线程将自己调用 CoInitialize。 【参考方案1】:我建议 WebAPI 架构无法很好地解决您的问题。通常,您不希望从 ASP.NET 生成长时间运行或阻塞的进程,因为很容易耗尽线程池并阻止服务器处理新请求。
如果您确实想继续使用 WebAPI 端点,我会先接收请求并将它们放入队列中,然后让客户端轮询或订阅完成的结果。
您可能有兴趣了解他们在 dotnetcore 3.0 中使用 gRPC 所做的事情 - 如果您想保留这种架构,但要更新平台。
【讨论】:
我一直在研究 gRPC,但我们是建立在 C/C++ 计算引擎上的遗留系统,不会很快被重写。我正在等待 .Net 核心实现当前缺少的 COM 互选内容,然后它可能会成为我们的解决方案。听起来它确实是 .Net Core 3 的一个相对较快的更新【参考方案2】:您可以创建多个应用程序域。应用程序域是“它可以被认为是一个既是容器又是边界的轻量级进程”ref。将您的 DLL 加载到不同的域中。这样,您创建的每个应用程序域都将单独加载您的 COM DLL。使用 MarshalByRefObject
创建代理,就像使用 here 一样。编写一个协调器,将请求分发到应用程序域并从应用程序域获取结果并发送响应。跟踪哪个域忙哪个不忙,或为请求创建新域。
还有这个link中提到的不同方法
【讨论】:
我也不知道多个应用程序域是正确的方法,但我一直在研究多个工作进程,即 IIS 中的 Web Garden,但是现在有多个进程在运行它似乎仍然只使用其中的 1 个。我在运行时将进程 ID 写入日志,它们都只有 5 个正在运行的进程 ID 中的 1 个。以上是关于CORBA 的 ASP.Net WebAPI 替代品?的主要内容,如果未能解决你的问题,请参考以下文章