【问题标题】:Would lots of idle clients cause a "service too busy" exception?大量空闲客户端会导致“服务太忙”异常吗?
【发布时间】:2013-08-23 05:54:21
【问题描述】:

我有一个 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;
        }
    }
}

【问题讨论】:

    标签: c# wcf


    【解决方案1】:

    与其为每个通道创建一个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();
    }
    

    要强制关闭和处置,请将此方法包装在 using

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

    【讨论】:

    • 啊,谢谢。我明天会做一些基准测试,然后投票作为最佳答案。另外 - 你会说我在回答中引用的内容是一个糟糕的解决方案,我不应该使用它吗?谢谢,乔。
    • 我不知道我是否会说这是一个“糟糕”的解决方案,但如果您要创建大量连接,那么最好尽快关闭它们你已经完成了他们。
    • 好的,谢谢,我遇到的主要问题是我被引入了一个项目,该项目的所有内容都基于上述属性,而其他开发人员已经做了很多这样的事情:helper.data .WcfCall(123); helper.data.OtherWcfCall("foo");我想我只需要告诉他修复他的代码。
    【解决方案2】:

    【讨论】:

    • 看起来有点古怪
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    相关资源
    最近更新 更多