是否可以指示ServicePartitionClient与服务结构中的特定节点通信?

时间:2016-08-20 12:04:16

标签: azure-service-fabric

我有

public class HttpCommunicationClient : HttpClient, ICommunicationClient
{
    public HttpCommunicationClient()
        : base(new HttpClientHandler() { AllowAutoRedirect = false, UseCookies = false })
    {
    }

    public HttpCommunicationClient(HttpMessageHandler handler)
        : base(handler)
    {
    }

    public HttpCommunicationClient(HttpMessageHandler handler, bool disposeHandler)
        : base(handler, disposeHandler)
    {
    }

    #region ICommunicationClient

    string ICommunicationClient.ListenerName { get; set; }

    ResolvedServiceEndpoint ICommunicationClient.Endpoint { get; set; }

    ResolvedServicePartition ICommunicationClient.ResolvedServicePartition { get; set; }

    #endregion ICommunicationClient
}

public class HttpCommunicationClientFactory : CommunicationClientFactoryBase<HttpCommunicationClient>
{
    private readonly Func<HttpCommunicationClient> _innerDispatcherProvider;

    public HttpCommunicationClientFactory(IServicePartitionResolver servicePartitionResolver = null, IEnumerable<IExceptionHandler> exceptionHandlers = null, string traceId = null)
        : this(() => new HttpCommunicationClient(), servicePartitionResolver, exceptionHandlers, traceId)
    {
    }

    public HttpCommunicationClientFactory(Func<HttpCommunicationClient> innerDispatcherProvider, IServicePartitionResolver servicePartitionResolver = null, IEnumerable<IExceptionHandler> exceptionHandlers = null, string traceId = null)
        : base(servicePartitionResolver, exceptionHandlers, traceId)
    {
        if (innerDispatcherProvider == null)
        {
            throw new ArgumentNullException(nameof(innerDispatcherProvider));
        }

        _innerDispatcherProvider = innerDispatcherProvider;
    }

    protected override void AbortClient(HttpCommunicationClient dispatcher)
    {
        if (dispatcher != null)
        {
            dispatcher.Dispose();
        }
    }

    protected override Task<HttpCommunicationClient> CreateClientAsync(string endpoint, CancellationToken cancellationToken)
    {
        var dispatcher = _innerDispatcherProvider.Invoke();
        dispatcher.BaseAddress = new Uri(endpoint, UriKind.Absolute);

        return Task.FromResult(dispatcher);
    }

    protected override bool ValidateClient(HttpCommunicationClient dispatcher)
    {
        return dispatcher != null && dispatcher.BaseAddress != null;
    }

    protected override bool ValidateClient(string endpoint, HttpCommunicationClient dispatcher)
    {
        return dispatcher != null && dispatcher.BaseAddress == new Uri(endpoint, UriKind.Absolute);
    }
} 

正在使用它,如下所示

var servicePartitionClient = new ServicePartitionClient<HttpCommunicationClient>(_httpClientFactory,
                                                                                           _options.ServiceUri,
                                                                                           _options.GetServicePartitionKey?.Invoke(context),
                                                                                           _options.TargetReplicaSelector,
                                                                                           _options.ListenerName,
                                                                                           _options.OperationRetrySettings);

using (var responseMessage = await servicePartitionClient.InvokeWithRetryAsync(httpClient => ExecuteServiceCallAsync(httpClient, context)))
{
    await responseMessage.CopyToCurrentContext(context);
}

问题是,如果我在使用ServicePartitionClient时知道我希望它连接到特定节点,有没有办法这样做?

案例是它的网关应用程序将请求转发给其他服务,我希望它的行为与粘性会话一样。

2 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,我在下面ExecuteServiceCallAsync调用中从请求中读取一个cookie,其中包含有关连接到哪个节点的信息,如果它是一个粘性会话,如果没有cookie,我设置一个来自请求的信息。如果该节点不再存在,则cookie将更新为新节点。

using (var responseMessage = await servicePartitionClient.InvokeWithRetryAsync(httpClient => ExecuteServiceCallAsync(httpClient, context)))
{
    await responseMessage.CopyToCurrentContext(context);
}

答案 1 :(得分:0)

从服务角度考虑比节点更有意义。因此,您不是连接到特定节点,而是实际连接到特定的服务实例。

当您连接到某个服务时,如果它是无状态的,那么根据它的无状态定义,连接到哪个实例并不重要。如果您发现某个用户与某个服务的特定实例绑定,则该服务是有状态的(它会跟踪某些用户状态),而这正是有状态的方案类型服务旨在处理。

相关问题