很多空闲客户会导致“服务太忙”的例外吗?

时间:2013-08-22 21:13:07

标签: c# wcf

我有一个WCF服务,其实例模式为Single,并发模式为Multiple。我有以下代码:

    public static ICmsDataServiceWcf data
    {
        get
        {
            if (HttpContext.Current != null && HttpContext.Current.Session != null && HttpContext.Current.Session["DataService"] == null)
            {
                HttpContext.Current.Session.Add("DataService", GetDataService());
            }

            if (HttpContext.Current != null && HttpContext.Current.Session != null && HttpContext.Current.Session["DataService"] != null)
            {
                return (ICmsDataServiceWcf)HttpContext.Current.Session["DataService"];
            }
            return GetDataService();
        }
    }

    private static ICmsDataServiceWcf GetDataService()
    {
        string url = ConfigurationManager.AppSettings["service_url"];
        EndpointAddress endPoint = new EndpointAddress(url);

            var binding = new WSHttpBinding(SecurityMode.None);

            CachedWebServiceChannelFactory<ICmsDataServiceWcf> cf = new CachedWebServiceChannelFactory<ICmsDataServiceWcf>(binding, endPoint);

            var channel = cf.CreateChannel();

            return channel;
    }

这个想法是每个客户端都有自己的WCF客户端,只能阻止他们的请求,我不必承受多次创建/销毁客户端的开销。

最近我得到了一些“服务太忙”的例外情况。大多数客户大多数时间都处于空闲状态。空闲客户端是否仍然消耗服务器上的资源?它的实例是否以某种方式存在于服务器端?

任何人都可以看到这可能导致问题的原因吗? (除了让许多客户坐下来直到会议被放弃的内存浪费 - 我正在寻找使用一组客户端并定期剔除不活动/错误的客户端。)

谢谢,

编辑:我忘了提到我已经实现了自己的代理 - 不确定这是否会产生任何影响:

public class CachedWebServiceProxy<T> : RealProxy
{
    private Type _typeOfProxy;
    public object _channel;
    public CachedWebServiceProxy(Type typeOfProxy, object channel)
        : base(typeOfProxy)
    {
        _typeOfProxy = typeOfProxy;
        _channel = channel;
    }
    public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
    {
        try
        {
            var methodCall = msg as IMethodCallMessage;
            var methodInfo = methodCall.MethodBase as MethodInfo;
            object result = null;
    // Caching code removed
                result = methodInfo.Invoke(_channel, methodCall.Args);
            return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
        }
        catch (Exception ex)
        {
            // Throw the actual error fro mthe webservice
            if (ex is TargetInvocationException && ex.InnerException != null)
            {
                throw ex.InnerException;
            }
            throw ex;
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您可能想尝试创建ChannelFactory(这是一项昂贵的工作),而不是为每个频道创建一个ChannelFactory,然后抛弃工厂然后继续使用该频道,然后在每次要使用它时实例化Channel

获取和持有频道不是最佳做法 - 您应该创建,使用,关闭和处置。这就像持有数据库连接 - 除非你明确地删除它,否则它不会被处理掉。

private CachedWebServiceChannelFactory<ICmsDataServiceWcf> factory;

public ICmsDataServiceWcf GetDataService()
{
    if (factory == null) // or factory needs rebuilding
    {
        string url = ConfigurationManager.AppSettings["service_url"];
        EndpointAddress endPoint = new EndpointAddress(url);
        var binding = new WSHttpBinding(SecurityMode.None);

        factory = new CachedWebServiceChannelFactory<ICmsDataServiceWcf>
            (binding, endPoint);
    }

    return factory.CreateChannel();
}

并强行关闭&amp; dispose,将此方法包装在using

using (var client = GetDataService())
{
    // do stuff
} // client will be disposed upon reaching the end of the using block

答案 1 :(得分:0)