同一 Windows 服务主机上的两个 WCF 服务库之间的通信

Posted

技术标签:

【中文标题】同一 Windows 服务主机上的两个 WCF 服务库之间的通信【英文标题】:Communication between two WCF service libraries on the same Windows Service host 【发布时间】:2013-04-30 16:23:42 【问题描述】:

我目前正在处理的项目包括一个服务器,它从客户端接收 C# 脚本(部分代码),将其包装以创建一个完整的类,对其进行编译,然后将其加载到单独的 AppDomain 中执行。

任务(当前正在运行的脚本)可以在其执行的任何时候向用户发送反馈,正如用户在脚本中定义的那样。并且可能该任务可能会等待用户的响应(目前假设它只是在发送反馈之后)。并且用户可能在任何时候决定终止一个任务。

服务器实现为托管 WCF 服务库的 Windows 服务。

由于我不想让客户端过于复杂化以使其直接与动态创建的 AppDomain 通信,因此我在进行一些研究后考虑的(​​部分)解决方案是托管具有命名管道绑定的第二个 WCF 服务以生成动态 AppDomain将其用作它们与面向客户端的 WCF 服务之间的中继。

我的问题是,现在我想不出一种让两个 WCF 服务交互的干净方法。

我的想法是:

    让它们保持对彼此的直接引用: 正常情况下,这两个服务都是单例的,应该不难做到。 但是,如果其中一个失败并且需要重新启动,那将是一个痛苦的维护。 (我还是 WCF 的新手,所以我不知道这有多普遍,但这仍然是一个需要考虑的问题。我认为。) 引入了某种“消息队列”(或两个,每个方向一个),其属性可以设置和订阅。因此,当一个服务设置一个属性时,将在第二个服务中触发一个事件。但这对我来说有点生硬,尽管我真的想不出任何明确的问题。

对于我想要完成的工作,我真的可以使用一些专家意见,无论是对我的想法或新想法的意见。即使这涉及重新思考架构。这个项目仍处于足够早的阶段,可以承受一些返工,当然,只要有足够的理由这样做。

由于我已经付出了很多努力(阅读:2 分钟的绘画时间)来准备系统的快速(阅读:无用)架构,因此我将在此处链接它,因为我没有发布图像的声誉: Link to schema


编辑:

因为我现在有声望,多亏了赞成票:

在重读我的问题之后,我觉得也许我一直从过于狭隘的角度看待这个问题,将服务视为比普通课程更特别的东西。我越想越觉得观察者模式可能是最好的方法。

【问题讨论】:

【参考方案1】:

仅作记录,为了避免让我的(愚蠢的)问题得不到解答,我意识到我试图找到一个特定于 WCF 服务的解决方案来过于狭隘地看待这个问题。 最后我最终使用了观察者模式的变体(基于IObservable<T>Interface)。

【讨论】:

其实你的问题一点也不傻。我正在运行的项目之一是大致相同的架构,使用 2.0 远程处理来跨越内部应用程序域边界。我正在用 wcf 服务替换它。 此外,在其自己的应用程序域边界内运行“脚本”非常有意义 - 这是一种隔音,使您能够按需废弃整个域 f.ex【参考方案2】:

我遇到了同样的问题。我处理两台服务器之间双工通信的方式如下:

为每个进程(AppDomain Seperated Task)创建一对 WCF 服务。两种服务都将其 Instancing 设置为 PerSession(不需要单例,从长远来看可能会导致问题,如断开连接)。这意味着客户端将为每个进程(AppDomain 分离任务)与两个不同的服务实例或服务对(即 Service1 和 Service2)进行通信。 我们希望这两个服务之间进行双工通信,这意味着两者都可以相互通信并传递数据(以 DataContract 类对象的形式)。

为此: 1-声明两个服务(即在单独的类库中)并托管它们(自托管或其他)。 2- 创建您的 DataContract 类并根据需要添加任何属性、集合、枚举等。两个服务都必须有这个类的 get-set 属性。 3- 在同一个类库(Service1 和 2 类所在的位置)中,创建另一个类。此类将充当服务对实例的存储库。它有一个静态列表,用于注册服务对实例(您可以使用 GUID 识别每个服务)。 4- 我们使用 svcUtil.exe(或通过代码)设置客户端代理。当客户端发出服务请求时,WCF 将创建一个服务(即 service1)。在 service1 处,以 client2 的身份创建或启动进程(应用程序域分离任务),并在其构造函数中通过代码创建 Service2 代理。 5- 初始化 Service2 实例(即通过调用 service2)并在存储库的静态列表中注册服务对实例(以便以后可以检索它以进行双工通信)。现在我们有两个服务实例,并且它们都作为一对注册到静态列表中。 6- 通过从 Client1 代理调用来启动两个服务之间的通信。 7- 在 Service1 调用方法中,从静态列表中检索服务对。使用 (2) 中提到的 get-set 属性将 Datacontract 类对象从 Service1 深度复制 (DeepClone) 到 Service2。 (请注意,您可以使用 Nuget 的众多 Deep Clone 库之一,例如 DeepCloner)。 8- 从 Service2 回电。 Client2 现在具有与 Client1 相同的 DataContract 类属性值 9- 对 Client2 代理重复步骤 6-8 以进行 Service2-Service1 通信。

【讨论】:

以上是关于同一 Windows 服务主机上的两个 WCF 服务库之间的通信的主要内容,如果未能解决你的问题,请参考以下文章

从同一服务器上的 MVC 调用 WCF 服务时出现 SocketException

来自同一主机上的 Invoke-WebRequest 的 WCF 客户端证书身份验证

同一端点(svc 文件)上的两个休息式 WCF 合同

从主机 WinForms 程序访问自托管 WCF 服务

无法在 Windows 7 上的 Windows 服务中使用 netNamedPipeBinding 托管和启动 WCF 服务

工作组上的 WCF