WCF 可靠性问题

Posted

技术标签:

【中文标题】WCF 可靠性问题【英文标题】:WCF reliability issues 【发布时间】:2011-07-27 22:19:33 【问题描述】:

试图测试我的 wcf 服务的可靠性。我正在从客户端循环调用 wcf 服务。 wcf 休息服务(webhttpbinding)做一些数据处理和插入 记录到数据库中。整个操作在一个事务中完成。

如果我将 InstanceContextMode 设置为 PerCall,我发现在大约 60 条消息(从循环内调用服务的 60 倍)中只有 40 条消息通过数据库。没有错误没有例外。消息刚刚被丢弃。

如果我将 InstanceContextMode 设置为 Single,那么我会看到所有消息都到达了 db。 InstanceContextMode.Percall 是有损的预期行为吗?另外,我没有设置并发。任何澄清都会非常有帮助。添加了代码。使用 mysql 作为数据库...

编辑我的错 - 我刚刚注意到服务器端出现异常 - "Deadlock found when trying to get lock; try restarting transaction"

这是因为在进行事务时,对同一记录调用了另一个事务。如果它失败一次,则通过重新启动事务来修复它。

服务

    [WebInvoke(UriTemplate = "employee", Method = "POST")]
    public long AddNewEmployee(EmployeeEntity newEmployee)
    
        EmployeeRepository eRep = new EmployeeRepository();
        return eRep.AddNewEmployee(newEventEntity);                     
    

存储库类构造函数初始化对象上下文

    public EmployeeRepository()
    
        bd = new EmployeeEntity();
    

代码 - 服务调用

    //bd is the object context 
    //there are two tables 
    internal long AddNewEmployee(EmployeeEntity newEmployee)
    
        bool tSuccess = false;
        using (TransactionScope transaction = new TransactionScope())
        
            try
            
                //get existing employees
                var existingEmployees = from employee
                                        in bd.employees select employee;


                List<employee> returnedEmployees = new List<employee>();                    

                //Do some processing 
                returnedEmployees = DoSomeprocessing(existingEmployees);

                //Insert returned employees as updates
                foreach (employee e in returnedEmployees)
                
                    bd.employees.AddObject(e);
                

                bd.SaveChanges();
                returnedEmployees.Clear();

                //add to second table 
                bd.otherdetails.AddObject(newEmployee);
                bd.SaveChanges();


                //Transaction Complete                        
                transaction.Complete();
                tSuccess = true;

            
            catch (Exception e)
            
                //return something meaningful 
                return -1;                    
            
        

        if (tSuccess)
        
            //End Transaction
            bd.AcceptAllChanges();
            return 200;
                    
        else
        
           return -1;
        

    

客户端只是循环调用服务

【问题讨论】:

当你说“没有错误没有例外”时,你的意思是什么?客户端没有看到任何错误? WCF 异常处理程序没有触发?服务方法本身没有异常? 客户端没有看到任何错误。服务器方法也不会抛出异常。对服务的一些调用刚刚被丢弃。当我使用 instancecontext 单一模式时,一切正常.. 【参考方案1】:

我强烈建议为任何 WCF 添加全局异常处理。它帮助我节省了许多小时的调试时间,并且可以捕获任何未处理的异常。它比 ASP.NET 中的 global.ascx 涉及更多一点

第 1 步 - 实施 IerroHander 和 IServiceBehavior

注意 HandleError 内部我正在使用 Enterprise Library 来处理异常。您也可以在此处使用您的自定义实现。

 public class ErrorHandler : IErrorHandler, IServiceBehavior
                
            public bool HandleError(Exception error)
            
                // Returning true indicates you performed your behavior.
                return true;
            


            public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
                        
                // Log Exception

                ExceptionPolicy.HandleException(error, "ExceptionPolicy");

                // Shield the unknown exception
                FaultException faultException = new FaultException(
                    "Server error encountered. All details have been logged.");
                MessageFault messageFault = faultException.CreateMessageFault();

                fault = Message.CreateMessage(version, messageFault, faultException.Action);
            

            private IErrorHandler errorHandler = null;

            public ErrorHandler()
            

            

            public ErrorHandler(IErrorHandler errorHandler)
            
                this.errorHandler = errorHandler;
            

            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            
                foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
                
                    ChannelDispatcher cd = cdb as ChannelDispatcher;

                    if (cd != null)
                    
                        cd.ErrorHandlers.Add(new ErrorHandler());
                    
                
            

            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
            
                foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
                
                    ChannelDispatcher cd = cdb as ChannelDispatcher;

                    if (cd != null)
                    
                        cd.ErrorHandlers.Add(new ErrorHandler());
                    
                
            

            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            

            
        

    

第 2 步 - 创建错误元素

public class ErrorHandlerElement : BehaviorExtensionElement
    
        protected override object CreateBehavior()
        
            return new ErrorHandler();
        

        public override Type BehaviorType
        
            get
            
                return typeof(ErrorHandler);
            
        
    

第 3 步 - 将元素添加到 web.config

<serviceBehaviors>
        <behavior>                              
          <ErrorHandler />
        </behavior>
      </serviceBehaviors>

【讨论】:

使用ExceptionPolicy.HandleException记录日志?

以上是关于WCF 可靠性问题的主要内容,如果未能解决你的问题,请参考以下文章

WCF 可靠性问题

WCF 可靠会话的目的是啥?

启用可靠会话时 WCF ContractFilter 不匹配

在同一 Service Fabric 可靠服务中同时使用 WCF 服务和 Web Api

从 WCF 客户端传播到 WCF 服务的事务的隔离是啥意思?

WCF概念