我开发了一个WCF服务,供组织的以太网使用
该服务目前托管在Windows服务上,并使用net.tcp
绑定
服务中定义了2个operation contracts
连接到此服务的客户端是一个运行时间很长的Windows桌面应用程序
员工(> 30,000)通常会在周一早上到周五晚上的整个星期内运行此客户。
在此生命周期内,根据主桌面客户端上的某个用户操作,可能会对wcf服务进行多次调用。 让我们在主桌面应用程序的每3个操作中说1 触发对我们服务的调用。
现在我们计划在每个员工的桌面上部署这个窗口服务
我也使用`autofac`作为依赖解析器容器
我的WCF服务实例上下文是`PerSession`,但理想情况下我们在同一个桌面上运行客户端和服务(现在),所以我打算使用`autofac`容器为每个新会话注入相同的服务实例。
现在我没有改变服务实现的`InstanceContext`属性
因为将来我可能会在不同的托管环境中部署相同的服务,我希望每个会话都有一个新的服务对象实例。
如前所述,客户端是一个长期运行的桌面应用程序,我已经读过,对每个调用“打开”和“关闭”代理是一个好习惯,但是如果我将服务保留为PerSession,它将创建一个新的服务实例对于每个调用,这可能不是必需的,因为服务和客户端具有1-1映射。
另一个论点是我计划在此环境中为每个会话注入相同的实例,因此Open&关闭每个服务电话应该无关紧要?
那么我应该采取哪种方法,为每次通话或者提供服务`Singleton`和Open Close
桌面应用程序加载/第一次服务调用时打开客户端代理,然后仅在桌面应用程序关闭时关闭它?
答案 0 :(得分:4)
我的WCF服务实例上下文是
PerSession
,但理想情况下我们在同一个桌面上运行客户端和服务(现在),所以我打算使用{为每个新会话注入相同的服务实例{1}}容器
通常,您希望避免共享WCF客户端代理,因为如果它出现故障,则很难将新的WCF推送(或者在您的情况下重新投影)到共享代理的代码的那些部分。最好为每个actor创建一个代理。
现在我没有更改服务实现的
autofac
属性,因为将来我可能会在不同的托管环境中部署相同的服务,我希望每个会话都有一个新的服务对象实例
我认为这里可能存在一些混淆。 InstanceContext
表示为每个WCF客户端代理创建服务器实例。这意味着每次InstanceContext.PerSession
时都会有一个服务实例,即使您与其他10个使用代理单例注入的对象共享它也是如此。这与您如何托管它无关。
如前所述,客户端是一个长期运行的桌面应用程序,我已经读过
new MyClientProxy()
和Open
每次调用的代理是一个好习惯
不正确的。对于非常昂贵的Close
服务。建立与服务的链接存在可衡量的成本,更不用说创建工厂的开销。 PerSession
服务是按会话出于某种原因,它意味着服务是在调用之间维持状态。例如,在我的PerSession
服务中,我喜欢在构造函数中建立一个昂贵的数据库连接,然后可以在以后的服务调用中非常快速地使用它。此示例中的打开/关闭实质上意味着与新的DB连接一起创建新的服务实例。慢!
另外,共享一个注入其他地方的客户端代理会破坏注入代理的目的。更不用说在一个线程中关闭它将导致另一个线程中的潜在错误。再次注意,我不喜欢共享代理的想法。
另一个论点是我计划在这个环境中为每个会话注入相同的实例,所以Open&关闭每个服务电话应该不重要吗?
是的,就像我说如果你要注射那么你不应该打开/关闭。那么你不应该分享多线程环境。
我应该选择哪种方法
请遵循以下指南
PerSession
? Singleton
? PerCall
?这完全取决于您服务的性质。它是否在方法调用之间共享状态?设为PerSession
,否则可以使用PerSession
。不想多次创建新的服务实例,并且您希望在方法调用之间选择性地共享全局/单例?将其设为PerCall
而不是注入WCF客户端代理的共享具体实例,而是注入一个机制(工厂),当被调用时允许每个收件人在需要时创建自己的WCF客户端代理。
每次通话后都不要打开/关闭,这会影响性能,无论服务实例模式如何。即使您的服务基本上是仅计算,由于客户端代理的启动成本,Singleton
服务上的每个方法调用的重复打开/关闭仍然很慢
不再需要时,请尽快处理客户端代理。 Singleton
服务实例保留在服务器上,在客户端代理的整个生命周期中占用宝贵的资源,或者直到超时(以较早者为准)。
如果您的服务是localmachine,那么您认为它NetNamedPipeBinding 在内核模式下运行;不使用网络重定向器,并且比TCP更快。稍后部署远程服务时,请添加TCP绑定