我应该在每次服务调用后打开和关闭我的 WCF 客户端吗?

Vig*_*h.N 4 wcf soa windows-services autofac

我开发了一个 WCF 服务,用于在组织的以太网中使用。
该服务当前托管在 Windows 服务上并使用net.tcp绑定。服务中定义了
2 个operation contracts
连接到此服务的客户端是一个长时间运行的 Windows 桌面应用程序。
员工(> 30,000)通常让这个客户端从周一早上到周五晚上连续运行一周。

在此生命周期内,可能会根据主桌面客户端上的特定用户操作对相关 wcf 服务进行多次调用。让我们假设主桌面应用程序上每 3 个操作中的 1 个将触发对我们服务的调用。

现在我们计划在每个员工的桌面上部署这个窗口服务,
我也使用 `autofac` 作为依赖解析器容器。
我的 WCF 服务实例上下文是 `PerSession`,但理想情况下,我们在同一个桌面上运行客户端和服务(目前),所以我计划使用 `autofac` 容器为每个新会话注入相同的服务实例。
现在不会更改服务实现上的“InstanceContext”属性,因为将来我可能会在不同的托管环境中部署相同的服务,我希望每个会话都有一个新的服务对象实例。

就像前面提到的,客户端是一个长时间运行的桌面应用程序,我已经读过,为每个调用“打开”和“关闭”代理是一个很好的做法,但如果我将服务保留为 PerSession,它将创建一个新的服务实例对于每个调用,鉴于服务和客户端具有 1-1 映射,这可能不需要。
另一个论点是我计划在这个环境中为每个会话注入相同的实例,所以每个服务调用的打开和关闭应该无关紧要?
那么我应该采用哪种方法,为每次调用创建服务“单例”并打开关闭,或者在桌面应用程序加载/第一次服务调用时打开客户端代理,然后仅在桌面应用程序关闭时关闭它?

Mic*_*kyD 5

我的 WCF 服务实例上下文是PerSession,但理想情况下,我们在同一个桌面上运行客户端和服务(目前),所以我计划使用autofac容器为每个新会话注入相同的服务实例

通常,您希望避免共享 WCF 客户端代理,因为如果它出现故障,则很难将新的 WCF推送(或在您的情况下重新注入)到共享代理的代码的那些部分。最好为每个演员创建一个代理。

现在不更改InstanceContext服务实现的属性,因为将来我可能会在不同的托管环境中部署相同的服务,我希望每个会话都有一个新的服务对象实例

我想这里可能有些混乱。这InstanceContext.PerSession意味着为每个 WCF 客户端代理创建一个服务器实例。这意味着new MyClientProxy()即使您与其他 10 个使用代理单例注入的对象共享它,每次也只有一个服务实例。这与您如何托管它无关。

就像前面提到的,客户端是一个长期运行的桌面应用程序,我已阅读,这是一个很好的做法,OpenClose代理为每个呼叫

不正确。对于PerSession非常昂贵的服务。建立到服务的链接有可衡量的成本,更不用说创建工厂的开销了。 PerSession出于某种原因,服务是每个会话的,这意味着服务要在调用之间维护状态。例如在我的PerSession服务中,我喜欢在构造函数中建立一个昂贵的数据库连接,然后可以在以后的服务调用中非常快速地使用它。本示例中的打开/关闭本质上意味着创建一个新的服务实例以及一个新的 DB 连接。减缓!

加上共享一个在别处注入的客户端代理无论如何都会破坏注入代理的目的。更不用说在一个线程中关闭它会导致另一个线程中的潜在故障。再次注意,我不喜欢共享代理的想法。

另一个论点是我计划在这个环境中为每个会话注入相同的实例,所以每个服务调用的打开和关闭应该无关紧要?

是的,就像我说的,如果你要注入,那么你不应该调用 open/close。再说一次,您不应该在多线程环境中共享。

那么我应该采取哪种方法

遵循这些准则

  1. Singleton? PerCall? PerSession? 这完全取决于您的服务的性质。它是否在方法调用之间共享状态?让它PerSession否则,你可以使用PerCall。不想多次创建新的服务实例,并且想要在方法调用之间有选择地共享全局变量/单例?让它成为Singleton

  2. 不是注入 WCF 客户端代理的共享具体实例,而是注入一种机制(工厂),在调用时允许每个接收者在需要时创建自己的 WCF 客户端代理。

  3. 不要在每次调用后调用 open/close,无论服务实例模式如何,这都会影响性能。即使您的服务本质上只是计算Singleton由于客户端代理的启动成本,对服务的每个方法调用重复打开/关闭仍然很慢。

  4. 不再需要时尽快处理客户端代理。 PerSession服务实例保留在服务器上,在客户端代理的整个生命周期内或直到超时(以较早发生者为准)消耗宝贵的资源。

  5. 如果您的服务是本地机器,那么您可以考虑NetNamedPipeBinding,因为它在内核模式下运行;不使用网络重定向器并且比 TCP 更快。稍后部署远程服务时,添加 TCP 绑定

我推荐这个很棒的 WCF 大部头

在此处输入图片说明