Вопросы надежности WCF - PullRequest
       20

Вопросы надежности WCF

2 голосов
/ 01 апреля 2011

Попытка проверить надежность моих услуг wcf.Я вызываю службу wcf в цикле со стороны клиента.Служба отдыха wcf (webhttpbinding) выполняет некоторую обработку данных и вставляет записи в базу данных.Вся операция выполняется в рамках транзакции.

Я обнаружил, что из примерно 60 сообщений (в 60 раз больше, чем служба вызывается из цикла) только 40 проходят через базу данных, если я установил свой InstanceContextMode в PerCall.Там нет ошибок, нет исключений.Сообщения просто удаляются.

Если я установлю InstanceContextMode в Single, то я увижу, что все сообщения попадают в БД.Является ли InstanceContextMode.Percall потерями ожидаемого поведения?Кроме того, у меня нет набора параллелизма.Любые разъяснения будут очень полезны.Добавил код.Использование MySQL в качестве базы данных ...

РЕДАКТИРОВАТЬ Моя ошибка - я только что заметил, что получаю исключение на стороне сервера - {"Обнаружен тупик при попытке получить блокировку; попробуйте перезапустить транзакцию"}

Это связано с тем, что во время выполнения транзакции для тех же записей была вызвана другая транзакция.Исправить это, перезапустив транзакцию, если она провалилась один раз.

Служба

    [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;
        }

    }

Клиентсторона просто вызывает услугу в цикле

1 Ответ

0 голосов
/ 06 апреля 2011

Я настоятельно рекомендую добавить глобальную обработку исключений для любого WCF.Это помогло мне сэкономить много часов отладки и поймать любые необработанные исключения.Это немного больше, чем global.ascx в ASP.NET

Шаг 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 - Добавить элемент в Интернет.config

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