none
用iis7 发布wcf服务,偶尔socket出错 RRS feed

  • 问题

  • 开发时用 wcftestClient已测试通过,测试时用iis7发布wcf服务(net.tcp绑定) ,可是,在测试过程中,经常(1/5的概率)会socket异常中断(iis日志信息),奇怪的是,你继续操作,又可以继续下去(比如:你有一次点击了保存,提示失败,在一次点保存又是可以的)。

    请各位大侠,帮忙分析下原因,谢谢

    2010年8月6日 5:46

答案

  • 你有没有并发调用 private DrugServiceClient m_clsWSDrug; 的可能?

    出错后,你的详细错误信息是什么?

     

    一般来说,private static DrugServiceClient m_clsWSDrug; 来在全局维护一个唯一的 DrugServiceClient 实例,

    DrugServiceClient 的 Open 和 Close 都要用 lock 保护起来,而且要使用 double check 技术。

    可以从服务器和客户端中Tcp的绑定配置中增加空闲超时时间,另外,当 DrugServiceClient 的实例出错后,排除Security的错,CommunicationException 需要重新 Open 通道。

    • 已标记为答案 凤舞 2010年8月7日 7:48
    2010年8月6日 8:44

全部回复

  • 开发时用 wcftestClient已测试通过,测试时用iis7发布wcf服务(net.tcp绑定) ,可是,在测试过程中,经常(1/5的概率)会socket异常中断(iis日志信息),奇怪的是,你继续操作,又可以继续下去(比如:你有一次点击了保存,提示失败,在一次点保存又是可以的)。

    请各位大侠,帮忙分析下原因,谢谢


    原因很简单,你的 tcp 连接空闲超时候关闭了,所以第一次点失败,再点一次它重新建立连接,就又成功了.
    2010年8月6日 6:31
  • 也不光是第一次点击,比如,我切换下拉框(根据下拉框内容,重新加载列表数据),会时不时出现加载失败,但失败后,做同样操作或者其他操作,wcf服务又可以连接。
    这也有可能是tcp空闲超时吗?
    以前用的是webService,因为性能需要,改成wcf的tcp绑定,结果出现这类问题,头疼ing
    2010年8月6日 7:19
  • 也不光是第一次点击,比如,我切换下拉框(根据下拉框内容,重新加载列表数据),会时不时出现加载失败,但失败后,做同样操作或者其他操作,wcf服务又可以连接。
    这也有可能是tcp空闲超时吗?
    以前用的是webService,因为性能需要,改成wcf的tcp绑定,结果出现这类问题,头疼ing


    你的客户端的代理类怎么写的?

    是每次调用都重复 打开连接〉〉执行〉〉关闭连接吗?

    2010年8月6日 7:30
  • 是的,关闭连接也会有问题吗?刚才我还在怀疑是不是abort的原因

    下面是我的写法

    private DrugServiceClient m_clsWSDrug;

    public int SearchDrugStock(IHDDrugStockQry clsDrugStockQry, ref IHDDrugStockInfoList clsListDrugStockInfo)
            {
                int nResult = CIHDConst.DATA_NOT_EXIST;
                try
                {
                     //初始化
                    Init();
                    //开始计时
                    StartSW();
                    for (int i = 0; i < base.clsSettings.nConnectCount; i++)
                    {
                        try
                        {
                            nResult = m_clsWSDrug.SearchDrugStock(clsDrugStockQry, ref clsListDrugStockInfo);
                            break;
                        }
                        catch (Exception ex)
                        {
                            base.AgainConnect(ex, i);
                        }
                    }
                    //结束计时,并写日志
                    StopSW("IHDClinic.CIHDDrug.SearchDrugStock");
                    //将记录放入List
                    //clsListDrugStockInfo.AddRange(clsDrugStockInfo);
                }
                catch (Exception e)
                {
                    //写错误日志
                    AddErrorLog(e);
                    //抛出异常到上层
                    throw new CIHDWSException(e.Message);
                }
                finally
                {
                    CloseClient(m_clsWSDrug);
                }
                return nResult;
            }

            /// <summary>
            /// 初始化
            /// </summary>
            private void Init()
            {
                //传递Soap头

                m_clsWSDrug = new DrugServiceClient();
                OperationContext.Current = new OperationContext((IContextChannel)m_clsWSDrug.InnerChannel);
                base.InitSoapHeader();
            }

     /// <summary>
            /// 服务完成后关闭
            /// </summary>
            /// <param name="clsClientBase"></param>
            public void CloseClient(ICommunicationObject clsClientBase)
            {
                try
                {
                    if (clsClientBase.State != CommunicationState.Faulted)
                    {
                        clsClientBase.Close();
                    }
                    else
                    {
                        clsClientBase.Abort();
                    }
                }
                catch
                {
                    clsClientBase.Abort();
                }
            }

    2010年8月6日 7:37
  • 你有没有并发调用 private DrugServiceClient m_clsWSDrug; 的可能?

    出错后,你的详细错误信息是什么?

     

    一般来说,private static DrugServiceClient m_clsWSDrug; 来在全局维护一个唯一的 DrugServiceClient 实例,

    DrugServiceClient 的 Open 和 Close 都要用 lock 保护起来,而且要使用 double check 技术。

    可以从服务器和客户端中Tcp的绑定配置中增加空闲超时时间,另外,当 DrugServiceClient 的实例出错后,排除Security的错,CommunicationException 需要重新 Open 通道。

    • 已标记为答案 凤舞 2010年8月7日 7:48
    2010年8月6日 8:44
  • 有。那除了lock之外,我在方法体内用临时变量的形式,实例化DrugServiceClient ,这样是不是也可以解决并发的问题。
    2010年8月6日 10:17
  • 有。那除了lock之外,我在方法体内用临时变量的形式,实例化DrugServiceClient ,这样是不是也可以解决并发的问题。


    可以,但是你会遇到性能问题,而且随着并发数的增加,性能问题会越来越严重.

    建议的做法,仍然是为应用程序域中的所有操作维持一个实例.

    2010年8月9日 2:46