Как правильно разрешить ссылку на службу состояния без обслуживания? - PullRequest
0 голосов
/ 27 октября 2018

Я занимаюсь разработкой системы, в которой интенсивно используются службы фабрики обслуживания без сохранения состояния. Я думал, что хорошо представляю, как все работает, однако сейчас я делаю что-то немного другое, и, очевидно, мое понимание ограничено.

У меня есть кластер из 5 узлов, и все мои службы в настоящее время имеют счетчик -1 для простоты. Со всем на каждом узле это означает, что я могу наблюдать за одним узлом на предмет правильности базового поведения.

Я только что добавил новую службу, которой нужно количество экземпляров 1. Однако, похоже, я не могу правильно разрешить эту службу. Вместо этого SF пытается разрешить службу на каждой машине, которая дает сбой для всех машин, кроме той, на которой существует одна служба.

Я предполагал, что SF автоматически разрешит ссылку на службу в любом месте кластера. Если эта ссылка потерпит неудачу, она автоматически разрешит новую ссылку и так далее. Похоже, что это неправильно, по крайней мере, из-за того, как я сейчас поступаю.

Я могу найти экземпляр, используя код, похожий на this , однако, что произойдет, если этот экземпляр потерпит неудачу. Как получить другую ссылку?

Я могу разрешить каждый вызов, такой как этот , однако это кажется ужасной идеей, когда я действительно хочу разрешить только IXyzService и передать его.

Так я разрешаю сервисы, так как использую пользовательскую сериализацию V2.

            var _proxyFactory = new ServiceProxyFactory(c =>
            {
                return new FabricTransportServiceRemotingClientFactory(                                        
                    serializationProvider: new CustomRemotingSerializationProvider(Logger)
                );
            });

            var location = new Uri("fabric:/xyz/abcService");
            var proxy = _proxyFactory.CreateServiceProxy<TService>(location); 

На самом деле это работает, но, похоже, разрешает службу только на той же машине. Поэтому ServiceA разрешит ссылку на ServiceB на том же компьютере. Однако, если ServiceB не существует на машине по уважительной причине, разрешение не будет выполнено.

Резюме:

Как правильно использовать ServiceA для использования пользовательской сериализации V2 ServiceProxyFactory для разрешения ссылки на интерфейс ServiceB, где бы ни находились ServiceA и ServiceB в кластере?

Обновление:

Доказательством того, что это не работает, является призыв к разрешению зависаний навсегда. Согласно этой ссылке это правильное поведение, потому что сервис в конечном итоге будет запущен. Однако только один узел когда-либо разрешал его правильно, и это тот узел, где активен один экземпляр. Я пробовал несколько вещей, даже подождав 30 секунд, чтобы убедиться, что это не проблема инициализации.

var proxy = _proxyFactory.CreateServiceProxy<TService>(location);

// Never gets here except on the one node.
SomethingElse(proxy);

Код слушателя

По сути, это почти точно соответствует учебному пособию V2 .

    var listeners = new[]
    {
        new ServiceInstanceListener((c) =>
        {
            return new FabricTransportServiceRemotingListener(c, this, null,
                new CustomRemotingSerializationProvider(Logger));
        })
    };

public class HyperspaceRemotingSerializationProvider : IServiceRemotingMessageSerializationProvider
    {
        #region Private Variables

        private readonly ILogger _logger;
        private readonly Action<RequestInfo> _requestAction;
        private readonly Action<RequestInfo> _responseAction;

        #endregion Private Variables

        public CustomRemotingSerializationProvider(ILogger logger, Action<RequestInfo> requestAction = null, Action<RequestInfo> responseAction = null)
        {
            _logger = logger;
            _requestAction = requestAction;
            _responseAction = responseAction;
        }

        public IServiceRemotingRequestMessageBodySerializer CreateRequestMessageSerializer(Type serviceInterfaceType, IEnumerable<Type> requestWrappedTypes,
            IEnumerable<Type> requestBodyTypes = null)
        {
            return new RequestMessageBodySerializer(_requestAction);
        }

        public IServiceRemotingResponseMessageBodySerializer CreateResponseMessageSerializer(Type serviceInterfaceType, IEnumerable<Type> responseWrappedTypes,
            IEnumerable<Type> responseBodyTypes = null)
        {
            return new ResponseMessageBodySerializer(_responseAction);
        }

        public IServiceRemotingMessageBodyFactory CreateMessageBodyFactory()
        {
            return new MessageBodyFactory();
        }
    }

Код подключения

            _proxyFactory = new ServiceProxyFactory(c =>
            {
                return new FabricTransportServiceRemotingClientFactory(                                        
                    serializationProvider: new CustomRemotingSerializationProvider(Logger)
                );
            });

// Hangs here - tried different partition keys or not specifying one.
var proxy = _proxyFactory.CreateServiceProxy<TService>(location, ServicePartitionKey.Singleton); 
...