2016-08-20 64 views
0

是否可以指示ServicePartitionClient與服務結構中的特定節點對話?

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的時間它連接到一個特定的節點,有沒有辦法做到這一點?

這種情況是,它的網關應用程序轉發請求到其他服務,我希望它的行爲像粘滯的會議。

回答

0

在服務方面比節點思考更合理。因此,不是連接到特定的節點,而是實際連接到特定的服務實例。

當你連接到一個服務時,如果它是無狀態的,它應該無關緊要連接到哪個實例,根據定義它是無狀態的。如果您發現用戶與特定服務實例綁定,該服務是有狀態的(它跟蹤某個用戶狀態),而這正是有狀態服務要處理的情形類型。

+0

有拐角的情況。 Signalr需要在握手過程中做3次必須碰到同一個實例的請求(是的,它不是無狀態的)。存在兩種解決方案,或者在負載平衡器上進行粘性會話,或者(對於我的情況,在編寫反向代理時,我可以使用cookie自己實現粘貼會話)。但從技術上講,是的,你是正確的:) –

0

我找到了一個解決方案,我在下面的ExecuteServiceCallAsync調用中從請求中讀取一個cookie,其中包含關於它連接到哪個節點的信息(如果它是一個粘性會話),並且如果沒有cookie存在,我使用請求。如果節點不再存在,則cookie更新爲新節點。

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