Come usare le API di comunicazione di Reliable ServicesHow to use the Reliable Services communication APIs

Azure Service Fabric è una piattaforma completamente indipendente dalle comunicazioni tra servizi.Azure Service Fabric as a platform is completely agnostic about communication between services. Sono accettabili tutti i protocolli e gli stack, da UDP a HTTP.All protocols and stacks are acceptable, from UDP to HTTP. Dipende dallo sviluppatore del servizio scegliere la modalità di comunicazione tra servizi.It's up to the service developer to choose how services should communicate. Il framework applicazione di Reliable Services offre gli stack di comunicazione predefiniti nonché le API che è possibile usare per creare componenti di comunicazione personalizzati.The Reliable Services application framework provides built-in communication stacks as well as APIs that you can use to build your custom communication components.

Impostare la comunicazione tra serviziSet up service communication

L'API di Reliable Services usa una semplice interfaccia per la comunicazione tra servizi.The Reliable Services API uses a simple interface for service communication. Per aprire un endpoint del servizio, è sufficiente implementare questa interfaccia:To open an endpoint for your service, simply implement this interface:


public interface ICommunicationListener
{
    Task<string> OpenAsync(CancellationToken cancellationToken);

    Task CloseAsync(CancellationToken cancellationToken);

    void Abort();
}
public interface CommunicationListener {
    CompletableFuture<String> openAsync(CancellationToken cancellationToken);

    CompletableFuture<?> closeAsync(CancellationToken cancellationToken);

    void abort();
}

Aggiungere quindi l'implementazione del listener di comunicazione restituendola in un override del metodo della classe di base del servizio.You can then add your communication listener implementation by returning it in a service-based class method override.

Per i servizi senza stato:For stateless services:

class MyStatelessService : StatelessService
{
    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        ...
    }
    ...
}
public class MyStatelessService extends StatelessService {

    @Override
    protected List<ServiceInstanceListener> createServiceInstanceListeners() {
        ...
    }
    ...
}

Per i servizi con stato:For stateful services:

Nota

Reliable Services con stato non è ancora supportato in Java.Stateful reliable services are not supported in Java yet.

class MyStatefulService : StatefulService
{
    protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
    {
        ...
    }
    ...
}

In entrambi i casi restituire una raccolta di listener.In both cases, you return a collection of listeners. Ciò consente al servizio di rimanere in ascolto su più endpoint, potenzialmente tramite protocolli diversi, usando più listener.This allows your service to listen on multiple endpoints, potentially using different protocols, by using multiple listeners. Può essere ad esempio presente un listener HTTP e un listener WebSocket separato.For example, you may have an HTTP listener and a separate WebSocket listener. Ogni listener riceve un nome e la raccolta risultante di coppie nome : indirizzo è rappresentata come oggetto JSON quando un client richiede gli indirizzi di ascolto per un'istanza o una partizione del servizio.Each listener gets a name, and the resulting collection of name : address pairs are represented as a JSON object when a client requests the listening addresses for a service instance or a partition.

In un servizio senza stato l'override restituisce una raccolta di ServiceInstanceListener.In a stateless service, the override returns a collection of ServiceInstanceListeners. Un oggetto ServiceInstanceListener contiene una funzione per creare un'interfaccia ICommunicationListener(C#) / CommunicationListener(Java) e assegnarle un nome.A ServiceInstanceListener contains a function to create an ICommunicationListener(C#) / CommunicationListener(Java) and gives it a name. Per i servizi con stato l'override restituisce una raccolta di ServiceReplicaListener.For stateful services, the override returns a collection of ServiceReplicaListeners. Questo è un comportamento leggermente diverso rispetto a quello del servizio senza stato, perché l'oggetto ServiceReplicaListener dispone di un'opzione per aprire l'interfaccia ICommunicationListener nelle repliche secondarie.This is slightly different from its stateless counterpart, because a ServiceReplicaListener has an option to open an ICommunicationListener on secondary replicas. Ciò consente non solo di usare più listener di comunicazione in un servizio, ma anche di specificare quali listener accettano le richieste nelle repliche secondarie e quali si limitano a rimanere in ascolto sulle repliche primarie.Not only can you use multiple communication listeners in a service, but you can also specify which listeners accept requests on secondary replicas and which ones listen only on primary replicas.

Ad esempio, un oggetto ServiceRemotingListener può gestire le chiamate RPC solo sulle repliche primarie, mentre un secondo listener personalizzato può accettare le richieste di lettura sulle repliche secondarie tramite HTTP:For example, you can have a ServiceRemotingListener that takes RPC calls only on primary replicas, and a second, custom listener that takes read requests on secondary replicas over HTTP:

protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
    return new[]
    {
        new ServiceReplicaListener(context =>
            new MyCustomHttpListener(context),
            "HTTPReadonlyEndpoint",
            true),

        new ServiceReplicaListener(context =>
            this.CreateServiceRemotingListener(context),
            "rpcPrimaryEndpoint",
            false)
    };
}

Nota

Quando si creano più listener per un servizio, a ogni listener deve essere assegnato un nome univoco.When creating multiple listeners for a service, each listener must be given a unique name.

Descrivere infine gli endpoint necessari per il servizio nel manifesto del servizio , nella sezione relativa agli endpoint.Finally, describe the endpoints that are required for the service in the service manifest under the section on endpoints.

<Resources>
    <Endpoints>
      <Endpoint Name="WebServiceEndpoint" Protocol="http" Port="80" />
      <Endpoint Name="OtherServiceEndpoint" Protocol="tcp" Port="8505" />
    <Endpoints>
</Resources>

Il listener di comunicazione può accedere alle risorse di endpoint allocate da CodePackageActivationContext in ServiceContext.The communication listener can access the endpoint resources allocated to it from the CodePackageActivationContext in the ServiceContext. Quando viene aperto, il listener può avviare l'ascolto delle richieste.The listener can then start listening for requests when it is opened.

var codePackageActivationContext = serviceContext.CodePackageActivationContext;
var port = codePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
CodePackageActivationContext codePackageActivationContext = serviceContext.getCodePackageActivationContext();
int port = codePackageActivationContext.getEndpoint("ServiceEndpoint").getPort();

Nota

Le risorse di endpoint sono comuni all'intero pacchetto del servizio e vengono allocate da Service Fabric quando viene attivato il pacchetto del servizio.Endpoint resources are common to the entire service package, and they are allocated by Service Fabric when the service package is activated. Più repliche di servizio ospitate nella stessa istanza di ServiceHost possono condividere la stessa porta.Multiple service replicas hosted in the same ServiceHost may share the same port. Ciò significa che il listener di comunicazione deve supportare la condivisione delle porte.This means that the communication listener should support port sharing. Il metodo consigliato per eseguire questa operazione consiste nell'uso dell'ID partizione e dell'ID replica/istanza da parte del listener di comunicazione durante la generazione dell'indirizzo di ascolto.The recommended way of doing this is for the communication listener to use the partition ID and replica/instance ID when it generates the listen address.

Registrazione dell'indirizzo del servizioService address registration

Nei cluster di Service Fabric viene eseguito un servizio di sistema denominato servizio Naming .A system service called the Naming Service runs on Service Fabric clusters. Il servizio Naming è un registrar per i servizi e i relativi indirizzi su cui è in ascolto ogni istanza o replica del servizio.The Naming Service is a registrar for services and their addresses that each instance or replica of the service is listening on. Quando il metodo OpenAsync(C#) / openAsync(Java) di un oggetto ICommunicationListener(C#) / CommunicationListener(Java) viene completato, il valore restituito viene registrato nel servizio Naming.When the OpenAsync(C#) / openAsync(Java) method of an ICommunicationListener(C#) / CommunicationListener(Java) completes, its return value gets registered in the Naming Service. Questo valore restituito che viene pubblicato nel servizio Naming è una stringa il cui valore può essere costituito da qualsiasi valore.This return value that gets published in the Naming Service is a string whose value can be anything at all. Questo valore stringa è il valore che i client vendono quando richiedono a Naming Service un indirizzo per il servizio.This string value is what clients see when they ask for an address for the service from the Naming Service.

public Task<string> OpenAsync(CancellationToken cancellationToken)
{
    EndpointResourceDescription serviceEndpoint = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint");
    int port = serviceEndpoint.Port;

    this.listeningAddress = string.Format(
                CultureInfo.InvariantCulture,
                "http://+:{0}/",
                port);

    this.publishAddress = this.listeningAddress.Replace("+", FabricRuntime.GetNodeContext().IPAddressOrFQDN);

    this.webApp = WebApp.Start(this.listeningAddress, appBuilder => this.startup.Invoke(appBuilder));

    // the string returned here will be published in the Naming Service.
    return Task.FromResult(this.publishAddress);
}
public CompletableFuture<String> openAsync(CancellationToken cancellationToken)
{
    EndpointResourceDescription serviceEndpoint = serviceContext.getCodePackageActivationContext.getEndpoint("ServiceEndpoint");
    int port = serviceEndpoint.getPort();

    this.publishAddress = String.format("http://%s:%d/", FabricRuntime.getNodeContext().getIpAddressOrFQDN(), port);

    this.webApp = new WebApp(port);
    this.webApp.start();

    /* the string returned here will be published in the Naming Service.
     */
    return CompletableFuture.completedFuture(this.publishAddress);
}

Service Fabric fornisce le API che consentono ai client e ad altri servizi di richiedere questo indirizzo in base al nome del servizio.Service Fabric provides APIs that allow clients and other services to then ask for this address by service name. Questo aspetto è importante perché l'indirizzo del servizio non è statico.This is important because the service address is not static. I servizi vengono spostati nel cluster ai fini del bilanciamento del carico e della disponibilità delle risorse.Services are moved around in the cluster for resource balancing and availability purposes. Questo meccanismo consente ai client di risolvere l'indirizzo di ascolto per un servizio.This is the mechanism that allow clients to resolve the listening address for a service.

Nota

Per una procedura dettagliata completa di come scrivere un listener di comunicazione, vedere Service Fabric Web API services with OWIN self-hosting (Servizi API Web di Service Fabric con self-hosting OWIN) per C#, mentre per Java è possibile scrivere la propria implementazione di server HTTP, vedere l'esempio di applicazione EchoServer in https://github.com/Azure-Samples/service-fabric-java-getting-started.For a complete walk-through of how to write a communication listener, see Service Fabric Web API services with OWIN self-hosting for C#, whereas for Java you can write your own HTTP server implementation, see EchoServer application example at https://github.com/Azure-Samples/service-fabric-java-getting-started.

Comunicazione con un servizioCommunicating with a service

L'API di Reliable Services offre le librerie seguenti per la scrittura di client che comunicano con i servizi.The Reliable Services API provides the following libraries to write clients that communicate with services.

Risoluzione degli endpoint di servizioService endpoint resolution

Il primo passaggio per la comunicazione con un servizio è risolvere un indirizzo di endpoint della partizione o dell'istanza del servizio con cui si vuole comunicare.The first step to communication with a service is to resolve an endpoint address of the partition or instance of the service you want to talk to. La classe di utilità ServicePartitionResolver(C#) / FabricServicePartitionResolver(Java) è una classe primitiva di base che consente ai client di determinare l'endpoint di un servizio in fase di esecuzione.The ServicePartitionResolver(C#) / FabricServicePartitionResolver(Java) utility class is a basic primitive that helps clients determine the endpoint of a service at runtime. Nella terminologia di Service Fabric, il processo di determinazione dell'endpoint di un servizio è denominato risoluzione degli endpoint di servizio.In Service Fabric terminology, the process of determining the endpoint of a service is referred to as the service endpoint resolution.

Per connettersi ai servizi all'interno di un cluster, è possibile creare un oggetto ServicePartitionResolver usando le impostazioni predefinite.To connect to services within a cluster, ServicePartitionResolver can be created using default settings. È l'utilizzo consigliato nella maggior parte dei casi:This is the recommended usage for most situations:

ServicePartitionResolver resolver = ServicePartitionResolver.GetDefault();
FabricServicePartitionResolver resolver = FabricServicePartitionResolver.getDefault();

Per connettersi ai servizi in un cluster diverso, è possibile creare un oggetto ServicePartitionResolver con un set di endpoint del gateway del cluster.To connect to services in a different cluster, a ServicePartitionResolver can be created with a set of cluster gateway endpoints. Si noti che gli endpoint del gateway sono solo endpoint diversi per la connessione allo stesso cluster.Note that gateway endpoints are just different endpoints for connecting to the same cluster. Ad esempio:For example:

ServicePartitionResolver resolver = new  ServicePartitionResolver("mycluster.cloudapp.azure.com:19000", "mycluster.cloudapp.azure.com:19001");
FabricServicePartitionResolver resolver = new  FabricServicePartitionResolver("mycluster.cloudapp.azure.com:19000", "mycluster.cloudapp.azure.com:19001");

In alternativa, è possibile assegnare alla classe ServicePartitionResolver la funzione per la creazione di un oggetto FabricClient da usare internamente:Alternatively, ServicePartitionResolver can be given a function for creating a FabricClient to use internally:

public delegate FabricClient CreateFabricClientDelegate();
public FabricServicePartitionResolver(CreateFabricClient createFabricClient) {
...
}

public interface CreateFabricClient {
    public FabricClient getFabricClient();
}

FabricClient è l'oggetto usato per comunicare con il cluster di Service Fabric per varie operazioni di gestione nel cluster.FabricClient is the object that is used to communicate with the Service Fabric cluster for various management operations on the cluster. È utile quando si vuole avere un maggiore controllo sul modo in cui un risolutore di partizioni del servizio interagisce con il cluster.This is useful when you want more control over how a service partition resolver interacts with your cluster. FabricClient esegue la memorizzazione nella cache internamente ed è in genere dispendioso da creare, quindi è importante riusare le istanze di FabricClient quanto più possibile.FabricClient performs caching internally and is generally expensive to create, so it is important to reuse FabricClient instances as much as possible.

ServicePartitionResolver resolver = new  ServicePartitionResolver(() => CreateMyFabricClient());
FabricServicePartitionResolver resolver = new  FabricServicePartitionResolver(() -> new CreateFabricClientImpl());

Un metodo di risoluzione viene quindi usato per recuperare l'indirizzo di un servizio o una partizione del servizio per i servizi partizionati.A resolve method is then used to retrieve the address of a service or a service partition for partitioned services.

ServicePartitionResolver resolver = ServicePartitionResolver.GetDefault();

ResolvedServicePartition partition =
    await resolver.ResolveAsync(new Uri("fabric:/MyApp/MyService"), new ServicePartitionKey(), cancellationToken);
FabricServicePartitionResolver resolver = FabricServicePartitionResolver.getDefault();

CompletableFuture<ResolvedServicePartition> partition =
    resolver.resolveAsync(new URI("fabric:/MyApp/MyService"), new ServicePartitionKey());

L'indirizzo di un servizio può essere risolto facilmente con ServicePartitionResolver, ma per garantire che l'indirizzo risolto possa essere usato correttamente è necessaria una procedura più complessa.A service address can be resolved easily using a ServicePartitionResolver, but more work is required to ensure the resolved address can be used correctly. Il client deve rilevare se il tentativo di connessione non è riuscito a causa di un errore temporaneo (ad esempio, nel caso in cui il servizio è stato spostato o è temporaneamente non disponibile) ed è quindi possibile eseguire un nuovo tentativo o a causa di un errore permanente (ad esempio, nel caso in cui il servizio è stato eliminato o la risorsa richiesta non esiste più).Your client needs to detect whether the connection attempt failed because of a transient error and can be retried (e.g., service moved or is temporarily unavailable), or a permanent error (e.g., service was deleted or the requested resource no longer exists). Le istanze del servizio o le repliche possono essere spostate da un nodo all'altro in qualsiasi momento per vari motivi.Service instances or replicas can move around from node to node at any time for multiple reasons. L'indirizzo del servizio risolto tramite ServicePartitionResolver potrebbe essere non aggiornato quando il codice client prova a connettersi.The service address resolved through ServicePartitionResolver may be stale by the time your client code attempts to connect. Il client dovrà in tal caso risolvere di nuovo l'indirizzo.In that case again the client needs to re-resolve the address. Fornendo l'oggetto ResolvedServicePartition precedente si indica che il resolver deve riprovare anziché recuperare semplicemente un indirizzo memorizzato nella cache.Providing the previous ResolvedServicePartition indicates that the resolver needs to try again rather than simply retrieve a cached address.

Non è necessario, in genere, che il codice client funzioni direttamente con l'oggetto ServicePartitionResolver.Typically, the client code need not work with the ServicePartitionResolver directly. Il codice viene creato e passato alle factory di client di comunicazione nell'API di Reliable Services.It is created and passed on to communication client factories in the Reliable Services API. Le factory usano il resolver internamente per generare un oggetto client da poter usare per comunicare con i servizi.The factories use the resolver internally to generate a client object that can be used to communicate with services.

Client e factory di comunicazioneCommunication clients and factories

La libreria di factory di comunicazione implementa un tipico schema di ripetizione dei tentativi per la gestione degli errori che semplifica la ripetizione dei tentativi di connessioni agli endpoint del servizio risolti.The communication factory library implements a typical fault-handling retry pattern that makes retrying connections to resolved service endpoints easier. La libreria di factory fornisce il meccanismo di ripetizione dei tentativi mentre l'utente fornisce i gestori di errori.The factory library provides the retry mechanism while you provide the error handlers.

ICommunicationClientFactory(C#) / CommunicationClientFactory(Java) definisce l'interfaccia di base implementata da una factory di client di comunicazione che produce client che possono comunicare con un servizio di Service Fabric.ICommunicationClientFactory(C#) / CommunicationClientFactory(Java) defines the base interface implemented by a communication client factory that produces clients that can talk to a Service Fabric service. L'implementazione dell'oggetto CommunicationClientFactory dipende dallo stack di comunicazione usato dal servizio di Service Fabric con cui il client vuole comunicare.The implementation of the CommunicationClientFactory depends on the communication stack used by the Service Fabric service where the client wants to communicate. L'API di Reliable Services include un oggetto CommunicationClientFactoryBase<TCommunicationClient>,The Reliable Services API provides a CommunicationClientFactoryBase<TCommunicationClient>. che offre un'implementazione di base dell'interfaccia CommunicationClientFactory e consente di eseguire attività comuni a tutti gli stack di comunicazione.This provides a base implementation of the CommunicationClientFactory interface and performs tasks that are common to all the communication stacks. Tali attività includono l'uso di un ServicePartitionResolver per determinare l'endpoint di servizio.(These tasks include using a ServicePartitionResolver to determine the service endpoint). I client in genere implementano la classe astratta CommunicationClientFactoryBase per gestire la logica specifica dello stack di comunicazione.Clients usually implement the abstract CommunicationClientFactoryBase class to handle logic that is specific to the communication stack.

Il client di comunicazione riceve solo un indirizzo e lo usa per connettersi a un servizio.The communication client just receives an address and uses it to connect to a service. Il client può usare qualsiasi protocollo desidera.The client can use whatever protocol it wants.

class MyCommunicationClient : ICommunicationClient
{
    public ResolvedServiceEndpoint Endpoint { get; set; }

    public string ListenerName { get; set; }

    public ResolvedServicePartition ResolvedServicePartition { get; set; }
}
public class MyCommunicationClient implements CommunicationClient {

    private ResolvedServicePartition resolvedServicePartition;
    private String listenerName;
    private ResolvedServiceEndpoint endPoint;

    /*
     * Getters and Setters
     */
}

La factory del client è responsabile principalmente della creazione dei client di comunicazione.The client factory is primarily responsible for creating communication clients. Per i client che non mantengono una connessione permanente, ad esempio un client HTTP, la factory deve solo creare e restituire il client.For clients that don't maintain a persistent connection, such as an HTTP client, the factory only needs to create and return the client. Gli altri protocolli che mantengono una connessione permanente, ad esempio alcuni protocolli binari, devono anche essere convalidati dalla factory per determinare se la connessione deve essere ricreata.Other protocols that maintain a persistent connection, such as some binary protocols, should also be validated by the factory to determine whether the connection needs to be re-created.

public class MyCommunicationClientFactory : CommunicationClientFactoryBase<MyCommunicationClient>
{
    protected override void AbortClient(MyCommunicationClient client)
    {
    }

    protected override Task<MyCommunicationClient> CreateClientAsync(string endpoint, CancellationToken cancellationToken)
    {
    }

    protected override bool ValidateClient(MyCommunicationClient clientChannel)
    {
    }

    protected override bool ValidateClient(string endpoint, MyCommunicationClient client)
    {
    }
}
public class MyCommunicationClientFactory extends CommunicationClientFactoryBase<MyCommunicationClient> {

    @Override
    protected boolean validateClient(MyCommunicationClient clientChannel) {
    }

    @Override
    protected boolean validateClient(String endpoint, MyCommunicationClient client) {
    }

    @Override
    protected CompletableFuture<MyCommunicationClient> createClientAsync(String endpoint) {
    }

    @Override
    protected void abortClient(MyCommunicationClient client) {
    }
}

Un gestore di eccezioni, infine, è responsabile della determinazione dell'azione da intraprendere quando si verifica un'eccezione.Finally, an exception handler is responsible for determining what action to take when an exception occurs. Le eccezioni vengono suddivise nelle categorie con possibilità di ritentare e senza possibilità di ritentare.Exceptions are categorized into retryable and non retryable.

  • Le eccezioni senza possibilità di ritentare vengono semplicemente restituite al chiamante.Non retryable exceptions simply get rethrown back to the caller.
  • Le eccezioni con possibilità di ritentare si suddividono a propria volta in due categorie: temporanee e non temporanee.retryable exceptions are further categorized into transient and non-transient.
    • temporanee sono quelle per cui è possibile ripetere il tentativo senza risolvere di nuovo l'indirizzo dell'endpoint del servizio.Transient exceptions are those that can simply be retried without re-resolving the service endpoint address. Includono problemi di rete temporanei o risposte di errore del servizio diversi da quelli che indicano che l'indirizzo dell'endpoint del servizio non esiste.These will include transient network problems or service error responses other than those that indicate the service endpoint address does not exist.
    • Non-transient sono quelle per cui è necessario risolvere di nuovo l'indirizzo dell'endpoint del servizio.Non-transient exceptions are those that require the service endpoint address to be re-resolved. Includono eccezioni che indicano che l'endpoint del servizio non è raggiungibile, ad esempio perché il servizio è stato spostato in un altro nodo.These include exceptions that indicate the service endpoint could not be reached, indicating the service has moved to a different node.

L'oggetto TryHandleException prende una decisione su una determinata eccezione.The TryHandleException makes a decision about a given exception. Se non sa quali decisioni prendere in merito a un'eccezione, restituirà false.If it does not know what decisions to make about an exception, it should return false. Se sa quale decisione prendere, imposterà il risultato di conseguenza e restituirà true.If it does know what decision to make, it should set the result accordingly and return true.

class MyExceptionHandler : IExceptionHandler
{
    public bool TryHandleException(ExceptionInformation exceptionInformation, OperationRetrySettings retrySettings, out ExceptionHandlingResult result)
    {
        // if exceptionInformation.Exception is known and is transient (can be retried without re-resolving)
        result = new ExceptionHandlingRetryResult(exceptionInformation.Exception, true, retrySettings, retrySettings.DefaultMaxRetryCount);
        return true;


        // if exceptionInformation.Exception is known and is not transient (indicates a new service endpoint address must be resolved)
        result = new ExceptionHandlingRetryResult(exceptionInformation.Exception, false, retrySettings, retrySettings.DefaultMaxRetryCount);
        return true;

        // if exceptionInformation.Exception is unknown (let the next IExceptionHandler attempt to handle it)
        result = null;
        return false;
    }
}
public class MyExceptionHandler implements ExceptionHandler {

    @Override
    public ExceptionHandlingResult handleException(ExceptionInformation exceptionInformation, OperationRetrySettings retrySettings) {        

        /* if exceptionInformation.getException() is known and is transient (can be retried without re-resolving)
         */
        result = new ExceptionHandlingRetryResult(exceptionInformation.getException(), true, retrySettings, retrySettings.getDefaultMaxRetryCount());
        return true;


        /* if exceptionInformation.getException() is known and is not transient (indicates a new service endpoint address must be resolved)
         */
        result = new ExceptionHandlingRetryResult(exceptionInformation.getException(), false, retrySettings, retrySettings.getDefaultMaxRetryCount());
        return true;

        /* if exceptionInformation.getException() is unknown (let the next ExceptionHandler attempt to handle it)
         */
        result = null;
        return false;

    }
}

RiassumendoPutting it all together

Con ICommunicationClient(C#) / CommunicationClient(Java), ICommunicationClientFactory(C#) / CommunicationClientFactory(Java) e IExceptionHandler(C#) / ExceptionHandler(Java) basati su un protocollo di comunicazione, un oggetto ServicePartitionClient(C#) / FabricServicePartitionClient(Java) esegue il wrapping di tutti gli elementi e fornisce il ciclo di risoluzione degli indirizzi della partizione del servizio e di gestione degli errori in base a tali componenti.With an ICommunicationClient(C#) / CommunicationClient(Java), ICommunicationClientFactory(C#) / CommunicationClientFactory(Java), and IExceptionHandler(C#) / ExceptionHandler(Java) built around a communication protocol, a ServicePartitionClient(C#) / FabricServicePartitionClient(Java) wraps it all together and provides the fault-handling and service partition address resolution loop around these components.

private MyCommunicationClientFactory myCommunicationClientFactory;
private Uri myServiceUri;

var myServicePartitionClient = new ServicePartitionClient<MyCommunicationClient>(
    this.myCommunicationClientFactory,
    this.myServiceUri,
    myPartitionKey);

var result = await myServicePartitionClient.InvokeWithRetryAsync(async (client) =>
   {
      // Communicate with the service using the client.
   },
   CancellationToken.None);
private MyCommunicationClientFactory myCommunicationClientFactory;
private URI myServiceUri;

FabricServicePartitionClient myServicePartitionClient = new FabricServicePartitionClient<MyCommunicationClient>(
    this.myCommunicationClientFactory,
    this.myServiceUri,
    myPartitionKey);

CompletableFuture<?> result = myServicePartitionClient.invokeWithRetryAsync(client -> {
      /* Communicate with the service using the client.
       */
   });

Passaggi successiviNext steps