系统上线后WCF服务最近经常死掉的原因分析总结_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 系统上线后WCF服务最近经常死掉的原因分析总结

系统上线后WCF服务最近经常死掉的原因分析总结

 2014/5/30 11:59:35  aehyok  博客园  我要评论(0)
  • 摘要:前言最近系统上线完修改完各种bug之后,功能上还算是比较稳定,由于最近用户数的增加,不知为何经常出现无法登录、页面出现错误等异常,后来发现是由于WCF服务时不时的就死掉了。后来就开始分析问题。得到的初步解决方案如下:1、在Web端调用WCF服务使用后,未释放未关闭导致新的链接无法访问2、增加默认的连接数,系统默认的链接数比较小3、提供同一个WCF服务的不同实例1、在Web端调用WCF服务使用后,未释放未关闭导致新的链接无法访问首先保证客户端每次建立的连接在使用完成后进行关闭
  • 标签:总结 原因 分析 WCF 服务 上线

前言  

  最近系统上线完修改完各种bug之后,功能上还算是比较稳定,由于最近用户数的增加,不知为何经常出现无法登录、页面出现错误异常,后来发现是由于WCF服务时不时的就死掉了。后来就开始分析问题。得到的初步解决方案如下:

  1、在Web端调用WCF服务使用后,未释放未关闭导致新的链接无法访问

  2、增加默认的连接数,系统默认的链接数比较小

  3、提供同一个WCF服务的不同实例

1、在Web端调用WCF服务使用后,未释放未关闭导致新的链接无法访问  

首先保证客户端每次建立的连接在使用完成后进行关闭。那么请不要使用传统的using语句中来调用WCF,这里@dudu大神也曾经有遇到过这个问题 http://www.cnblogs.com/dudu/archive/2011/01/18/1938144.html。对其分析也比较全面,在此不再赘述。

不过自己感觉更好的处理方式可能是下面这样,也就是将@dudu中的方法进行了简单的封装,但自己感觉还有优化的空间,暂时还没试出来。

    public static class WcfExtensions
    {
        public static void Using<T>(this T client, Action<T> work)
            where T : ICommunicationObject
        {
            try
            {
                work(client);
                client.Close();
            }
            catch (CommunicationException e)
            {
                client.Abort();
            }
            catch (TimeoutException e)
            {
                client.Abort();
            }
            catch (Exception e)
            {
                client.Abort();
            }
        }
    }

进行调用看起来是如下的方式,看上去还是比较简练了,但是感觉还是有些繁琐,不知道能不能直接一行return代码搞定?

        public static DocAppend GetDocAppend(string dwid, string actionId)
        {
            DocAppend docAppend = new DocAppend();
            new DocumentServiceV2.DocumentServiceV2Client().Using(channel => docAppend = channel.GetDocAppend(dwid, actionId));
            return docAppend;
        }

另外一种关闭链接的方式,这种方式其实和上面那种大同小异,也是可以封装的,系统中暂且就使用的上面的方式。

            Document document = null;
            DocumentServiceClient client = new DocumentService.DocumentServiceClient();
            try
            {
                document= client.GetDocument(id);
                if (client.State != System.ServiceModel.CommunicationState.Faulted)
                {
                    client.Close();
                }
            }
            catch (Exception ex)
            {
                client.Abort();
            }
            return document;

 

2、增加默认的连接数,系统默认的链接数比较小  

如果采用的netTcp绑定,而在windows7中,并发连接数默认是10。

这是原来的配置文件

<binding name="netTcpBindConfig" closeTimeout="00:10:00" 
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" 
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" 
hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" 
maxReceivedMessageSize="2147483647"> 

将项目移植到服务器上之后

<binding name="netTcpBindConfig" closeTimeout="00:30:00" 
openTimeout="00:30:00" receiveTimeout="00:30:00" sendTimeout="00:30:00" 
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" 
hostNameComparisonMode="StrongWildcard" listenBacklog="100" 
maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="100" 
maxReceivedMessageSize="2147483647"> 

但有些时候还是不能解决问题,就想到是不是需要配置一下行为,于是将行为的连接数量也改变了

      <serviceBehaviors>
        <behavior name="ThrottledBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
          <serviceThrottling maxConcurrentCalls="5000" maxConcurrentSessions="5000" maxConcurrentInstances="5000" />
        </behavior>
      </serviceBehaviors>

maxConcurrentCalls:在同一时刻允许处理的最大服务器操作数。如果超过次数,则需要把其他方法调用插入队列中,以等待处理。

maxConcurrentSessions:同时传输或应用程序会话的最大个数。

maxConcurrentInstances:实例的最大个数。

增加连接数量

在Http协议中,规定了同个Http请求的并发连接数最大为2. 这个数值,可谓是太小了。而目前的浏览器,已基本不再遵循这个限制,但是Dot Net平台上的 System.Net 还是默认遵循了这个标准的。从而造成了,在使用HttpWebRequset 或者 WebClient 利用多线程的方式,访问某个网站时,经常出现 连接被异常关闭 的错误,大大降低了效率。

这个限制的值,是可以自己设置或配置的。此值设置后,只对以后发起的HTTP请求有效。

  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="5000"/>
    </connectionManagement>
  </system.net>

 

3、提供同一个WCF服务的不同实例

3、首先查看一个WCF服务类

里面有N多构造函数重载版本,我们来具体看一下第二个构造函数

        public DocumentWriteServiceClient(string endpointConfigurationName) : 
                base(endpointConfigurationName) {
        }

即传入配置名生与代码类的实例,我们在web.config中的wcf配置节,做如下处理:

      <endpoint address="http://localhost:8700/Design_Time_Addresses/SinoSZJS.WebWCF/DocumentWriteService/"
 binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICommonBinding"
 contract="DocumentWriteService.IDocumentWriteService" name="1">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint address="http://localhost:8700/Design_Time_Addresses/SinoSZJS.WebWCF/DocumentWriteService/"
 binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICommonBinding"
 contract="DocumentWriteService.IDocumentWriteService" name="2">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint address="http://localhost:8700/Design_Time_Addresses/SinoSZJS.WebWCF/DocumentWriteService/"
 binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICommonBinding"
 contract="DocumentWriteService.IDocumentWriteService" name="3">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>

修改客户端的调用代码

DocumentWriteServiceClient client = new DocumentWriteServiceClient();

改为

DocumentWriteServiceClient client = new DocumentWriteServiceClient(new Random().Next(1, 4).ToString());

即客户端随机从多个wcf服务端的host中挑一个,生成代码类实例,说白了就是把一个wcf的host分身成了3个,并且客户端随机调用3者之一。

如果要考虑到大量并发的情况下,伪随机数可能确实有一些问题,不过,这个应该也不难解决,自己另外写一个类似伪随机数的算法,只要保证生成指定范围内不重复的数字(或字符)就可以了。

总结 

暂时这三种方式有效地防止了WCF服务的再次挂掉,至少最近几天服务一直在稳定的运行,没有太大的异常,很是让人欣慰。不知道针对WCF服务的处理是否还有其他方式,也让博客园的大牛们来指点一二吧。

英语小贴士

1、 Not yet. ——还没。
2、 See you. ——再见。
3、 Shut up! ——闭嘴!
4、 So long. ——再见。
5、 Why not? ——好呀! (为什么不呢?)
6、 Allow me. ——让我来。
7、 Be quiet! ——安静点!
8、 Cheer up! ——振作起来!
9、 Good job! ——做得好!
10、 Have fun! ——玩得开心!

作者:aehyok

出处:http://www.cnblogs.com/aehyok/

感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,那不妨点个推荐吧,谢谢支持:-O。

 

发表评论
用户名: 匿名