2015-12-08 7 views

Antwort

14

aktualisieren

Mit SDK v2 können Sie jetzt (relativ) ändern leicht die Header sowohl zuverlässige Dienste und Schauspieler. Beachten Sie, dass in den folgenden Beispielen einige Wrapper-Elemente der Kürze halber weggelassen wurden.

Kunde

Wir verwenden ServiceProxyFactory Proxies statt der statischen ServiceProxy zu erstellen. Dann können wir IServiceRemotingClientFactory und IServiceRemotingClient wickeln und die Serviceaufrufe abfangen. Das Gleiche kann mit ActorProxyFactory getan werden. Beachten Sie, dass dies das Verhalten von Attributen wie WcfServiceRemotingProviderAttribute außer Kraft setzt, da wir die Client Factory explizit angeben.

_proxyFactory = new ServiceProxyFactory(c => new ServiceRemotingClientFactoryWrapper(
// we can use any factory here 
new WcfServiceRemotingClientFactory(callbackClient: c))); 

    private class ServiceRemotingClientFactoryWrapper : IServiceRemotingClientFactory 
    { 
     private readonly IServiceRemotingClientFactory _inner; 

     public ServiceRemotingClientFactoryWrapper(IServiceRemotingClientFactory inner) 
     { 
      _inner = inner; 
     } 

     public async Task<IServiceRemotingClient> GetClientAsync(Uri serviceUri, ServicePartitionKey partitionKey, TargetReplicaSelector targetReplicaSelector, 
      string listenerName, OperationRetrySettings retrySettings, CancellationToken cancellationToken) 
     { 
      var client = await _inner.GetClientAsync(serviceUri, partitionKey, targetReplicaSelector, listenerName, retrySettings, cancellationToken).ConfigureAwait(false); 
      return new ServiceRemotingClientWrapper(client); 
     } 
    } 

    private class ServiceRemotingClientWrapper : IServiceRemotingClient 
    { 
     private readonly IServiceRemotingClient _inner; 

     public ServiceRemotingClientWrapper(IServiceRemotingClient inner) 
     { 
      _inner = inner; 
     } 

     public Task<byte[]> RequestResponseAsync(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody) 
     { 
      // use messageHeaders.AddHeader() here 
      return _inner.RequestResponseAsync(messageHeaders, requestBody); 
     } 

     public void SendOneWay(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody) 
     { 
      // use messageHeaders.AddHeader() here 
      _inner.SendOneWay(messageHeaders, requestBody); 
     } 
    } 

Server

vererben ServiceRemotingDispatcher und ActorServiceRemotingDispatcher die Header zu untersuchen.

class CustomServiceRemotingDispatcher : ServiceRemotingDispatcher 
{ 
    public override async Task<byte[]> RequestResponseAsync(IServiceRemotingRequestContext requestContext, ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody) 
    { 
     // read messageHeaders here 
     // or alternatively put them in an AsyncLocal<T> scope 
     // so they can be accessed down the call chain 
     return base.RequestResponseAsync(requestContext, messageHeaders, requestBody); 
    } 
} 

diese Klasse verwenden, wieder müssen wir die ServiceRemotingProviderAttribute durch direkte Erstellung der Kommunikations Zuhörer außer Kraft zu setzen:

class MyService : StatelessService 
{ 
    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners() 
    { 
      yield return new ServiceInstanceListener(context => new WcfServiceRemotingListener(context, new CustomServiceRemotingDispatcher()); 
    } 
} 
+0

Ich gehe in die gleiche Richtung, dein Codebeispiel hilft definitiv sehr. Aber ich wünsche mir immer noch, Microsoft bietet den gleichen Nachrichten-Handler-Mechanismus, um solche Anwendungsfälle zu ermöglichen. – Xiangdong

+0

Der ServiceInstanceListener hat keinen Konstruktorparameter für den Dispatcher auf die gleiche Weise wie der WcfServiceRemotingListener. Wie würde man bei Verwendung von Remoting einen Dispatcher hinzufügen? – SondreB

+0

Problem ist, dass ServiceInstanceListener ICommunicationListener und nicht IServiceRemotingMessageHandler verwendet, und diese Schnittstelle hat keine Methoden, die Nachrichtenheader zurückgibt. – SondreB

0

Ich fragte the same question on the MSDN forum vor ein paar Wochen, aber ich bekam keine Antwort dort.

Ich schaute in den Quellcode der Client-Bibliothek und habe keine Möglichkeit gefunden, Header hinzuzufügen. Ich fürchte, der einzige Weg besteht darin, sie als Teil des Methodenaufrufs hinzuzufügen. Dies könnte erreicht werden, indem Anfrageklassen als Methodenparameter verwendet werden und Vererbung für sie verwendet wird. (z. B. RequestBase-Klasse mit Kopfzeilen [Authorization, ClientInfo, ...]). Sie müssen dann sicherstellen, dass diese Header für jede Anforderung festgelegt werden, indem alle Aufrufe umschlossen oder manuell festgelegt werden.

Eine weitere Klärung durch das Service Fabric-Team wäre sehr willkommen.

+0

Wo id Sie den Client-Quellcode finden? Ich habe die API ausgecheckt, es gibt eine ServiceRemotingHeaders-Klasse, die mich glauben lässt, dass es Möglichkeiten gibt, der ausgehenden Anfrage einen eigenen Header hinzuzufügen. Außerdem scheint der Client die Kommunikation mit wcf durchzuführen. Sollte dies der Fall sein, sollte es möglich sein, den Nachrichteninspektor dem Entwickler zur Verfügung zu stellen. – Xiangdong

+0

@Xiangdong Ich sah Microsoft.ServiceFabric.Services.dll mit ILSpy. ServiceRemotingHeaders scheint der richtige Weg zu sein, ja. Ich habe jedoch keinen Weg gefunden, sie von draußen zu setzen. Ich denke ServiceProxy.InvokeAsync() ist der Ort, der eine Anfrage initiiert und es erstellt die ServiceRemotingMessageHeaders-Variable intern und übergibt sie an den nachgelagerten ServicePartitionClient. Aber vielleicht habe ich etwas verpasst ... –