Внедрение службы без отслеживания состояния в службу с отслеживанием состояния в структуре службы

У меня есть служба с отслеживанием состояния, которая обрабатывает данные в надежной очереди (внутри цикла while). Обработка данных фактически вызывает службу без сохранения состояния.

Поскольку служба без сохранения состояния может перемещаться с одного узла на другой, безопасно ли внедрять эту зависимость (службу без сохранения состояния) в конструктор службы с отслеживанием состояния? Просто хочу убедиться, что зависимость, инициализированная/введенная в конструктор, не привязана к одному узлу.


person alltej    schedule 09.01.2017    source источник


Ответы (2)


Если вы используете удаленное взаимодействие для связи со службой без отслеживания состояния можно внедрить IServiceProxyFactory в конструкторе. Таким образом вы также можете внедрить Mock для целей тестирования.

После этого ответа вопрос изменился. Дополнительная информация: служба удаленного взаимодействия обрабатывает разрешение адресов службы, подключение, повторные попытки и обработку ошибок

пример:

    public class MyStatefulService : StatefulService
    {
        private readonly Uri CalledServiceName = new Uri("fabric:/MyApp/MyStatefulService");
        private readonly IServiceProxyFactory ServiceProxyFactory;  

        public MyStatefulService(StatefulServiceContext serviceContext, IReliableStateManagerReplica reliableStateManagerReplica, IServiceProxyFactory serviceProxyFactory = null)
           : base(serviceContext, reliableStateManagerReplica)        
        {       
            ServiceProxyFactory = serviceProxyFactory ?? new ServiceProxyFactory();
        }

        public Task InsertAsync(object value)
        {
            var serviceProxy = ServiceProxyFactory.CreateServiceProxy<IMyStatefulService>(CalledServiceName);        
            return serviceProxy.InsertAsync(value);
        }
    }
person LoekD    schedule 09.01.2017
comment
Да. Я инициализирую/вызываю его как: ServiceProxy.Create<IMyStatelessService>(serviceUri) - person alltej; 09.01.2017
comment
Да, это действительно то, откуда я пришел - внедрить зависимость для тестируемости. В любом случае, поскольку я вызываю службу без сохранения состояния внутри цикла, мне нужно инициализировать/обнаруживать эту службу в каждой итерации надежной очереди? Или безопасно использовать один и тот же экземпляр serviceProxy? Это означает, что SF будет обрабатывать обнаружение, если служба больше не доступна в узле. - person alltej; 09.01.2017
comment
Вы можете безопасно повторно использовать один и тот же сервисный прокси. Он автоматически повторяет попытки и повторно обнаруживает новые конечные точки, когда что-то идет не так. - person LoekD; 09.01.2017

TL;DR Да, вы можете, клиент службы удаленного взаимодействия обрабатывает этот сценарий за вас в большинстве случаев.

Объяснение: когда вы создаете прокси-сервер для связи со службой с помощью удаленного взаимодействия службы, вы получаете клиент, способный повторить попытку связи с фактической службой. В документации есть некоторое описание этого (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-connect-and-связь-с-службами ), особенно раздел, описывающий обнаружение и разрешение службы:

Разрешение и подключение к службам включает в себя следующие шаги, выполняемые в цикле:

  • Решить: получить конечную точку, опубликованную службой, из службы именования.
  • Подключение: подключение к службе по любому протоколу, который она использует на этой конечной точке.
  • Повторить попытку. Попытка подключения может завершиться неудачей по ряду причин, например, если служба была перемещена с момента последнего разрешения адреса конечной точки. В этом случае необходимо повторить предыдущие шаги разрешения и подключения, и этот цикл повторяется до тех пор, пока подключение не будет установлено.

Последняя часть очень актуальна для вашего вопроса: если служба была перемещена с момента последнего раза, она фактически повторяет попытку разрешить, а затем подключиться. Таким образом, это означает, что если вы используете транспорт фабрики для удаленного доступа к своим службам, на самом деле существует встроенный механизм для обработки только этого сценария.

Когда вы вызываете реализацию по умолчанию IServiceProxyFactory (Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory), вы получаете ServiceProxy, который взаимодействует с использованием IServiceRemotingClient. В части Retry этого IServiceRemotingClient IExceptionHandler, связанный с этим, повторяет как временные, так и невременные ошибки, если они связаны с известными ошибками структуры. Один из них заключается в том, что адрес службы каким-то образом изменился.

Существует простой в использовании статический класс ServiceProxy (используемый через ServiceProxy.Create<...>), этот действительно использует только Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory под капотом. Как отметил @LoekD в своем ответе, подход, при котором вы вводите экземпляр IServiceProxyFactory в конструктор, помогает вам в тестировании. В живом коде вы вводите экземпляр Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory, а при тестировании вы предоставляете свой собственный макет. В своем коде вы используете его аналогично статическому ServiceProxy, например. _serviceProxyFactory.Create<IMyService>(...).

Обратите внимание: если вы, с другой стороны, реализуете свой собственный IServiceRemotingClient, вам необходимо рассмотреть возможность повторного использования различных исключений структуры (например, FabricNotReadableException и FabricTransientException). Проверьте https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-errors-and-exceptions для получения дополнительной информации о распространенных исключениях в FabricClients.

person yoape    schedule 09.01.2017