为整个应用程序保留一个 wcf 客户端代理

Posted

技术标签:

【中文标题】为整个应用程序保留一个 wcf 客户端代理【英文标题】:Keeping one wcf client proxy for whole app 【发布时间】:2012-03-10 11:28:47 【问题描述】:

我有高负载的 ASP .NET MVC2 网站和该网站使用的 WCF 服务。早期我每次需要它时都创建一个代理,甚至没有关闭它。参考我的previous question(非常感谢SO用户Richard Blewett)我发现我应该关闭这个代理。以其他方式它将成功会话限制。

现在,我在应用启动时创建代理,然后只需检查它并在需要时重新创建它。所以,这里是代码:

public static bool IsProxyValid(MyServ.MyService client) 
    bool result = true;
    if ((client == null) || (client.State != System.ServiceModel.CommunicationState.Opened) // || (client.InnerChannel.State != CommunicationState.Opened)
        )            
        result = false;

    return result;


public static AServ.AServClient GetClient(HttpContext http)             
    if (!IsProxyValid((MyService)http.Application["client"]))
        http.Application["client"] = new MyService();
    return (MyService)http.Application["client"];


public static MyServ.MyService GetClient(HttpContextBase http)

    if (!IsProxyValid((MyService)http.Application["client"]))
        http.Application["client"] = new MyService();
    return (MyService)http.Application["client"];


public ActionResult SelectDepartment(string departments)
    
       try
        
            MyService svc = CommonController.GetClient(this.HttpContext);                
            Department[] depsArray = svc.GetData(departments);

            // .... I cut here ....

            return View();
        
        catch (Exception exc)
        
            // log here                
            return ActionUnavailable();
        
    

那么,你们怎么看呢?它应该正常工作吗?有时我的应用程序卡住了。我认为这是因为客户端代理状态确定不正确,并且应用程序尝试使用损坏的代理。


后编辑

在 TCP Monitor 中,我还看到了很多从站点到服务的已建立连接。为什么它会创建很多连接而不是使用一个全局连接?可能是在调用服务方法时发生了一些异常使其处于故障状态?

希望大家帮忙!

【问题讨论】:

【参考方案1】:

我认为如果在创建新通道之前出现故障,您需要中止通道,并且 如果您创建新客户端,请确保关闭/中止旧客户端,为此使用类似的东西(这个在单例中与 DI 一起使用)

public class MyServiceClientInitializer : IMyServiceClientInitializer
 
        [ThreadStatic]
        private static MyServ.MyService _client;

        public MyServ.MyService Client
        
            get
            
                if (_client == null
                    || (_client.State != CommunicationState.Opened
                            && _client.State != CommunicationState.Opening))
                    IntializeClient();

                return _client;
            
        

        private void IntializeClient()
        
            if (_client != null)
            
                if (_client.State == CommunicationState.Faulted)
                
                    _client.Abort();
                
                else
                
                    _client.Close();    
                
            

            string url = //get url;

            var binding = new WSHttpBinding();
            var address = new EndpointAddress(url);

            _client = new MyServ.MyService(binding, address);            
        

【讨论】:

好的,谢谢您的回答!我应该检查client.InnerChannel.Stateclient.State 还是只检查client.State 我尝试了您的解决方案,但是有很多连接,而不仅仅是一个。我做错了什么? MyServiceClientInitializer 应该是单例 我通过 Visual Studio 进行调试,然后查看只创建了一次的连接。但为什么它会建立如此多的物理连接呢? IntializeClient 方法是否只被调用一次?

以上是关于为整个应用程序保留一个 wcf 客户端代理的主要内容,如果未能解决你的问题,请参考以下文章

生成的 WCF 代理为列表返回 null

WCF 客户端创建问题

终于解决:升级至.NET 4.6.1后VS2015生成WCF客户端代理类的问题

Java Web 服务的 .NET 客户端 WCF 代理类中的类定义重复

从代理客户端将参数传递给 WCF 服务中心

WCF 服务代理中伪装的类型?