Introduzione a Reliable ServicesGet started with Reliable Services

Questo articolo illustra le nozioni fondamentali di Reliable Services di Azure Service Fabric e le procedure per creare e distribuire una semplice applicazione Reliable Services scritta in Java.This article explains the basics of Azure Service Fabric Reliable Services and walks you through creating and deploying a simple Reliable Service application written in Java. Questo video di Microsoft Virtual Academy illustra anche come creare un servizio Reliable Services senza stato:

This Microsoft Virtual Academy video also shows you how to create a stateless Reliable service:


Installazione e configurazioneInstallation and setup

Prima di iniziare, assicurarsi che nel computer sia configurato l'ambiente di sviluppo di Service Fabric.Before you start, make sure you have the Service Fabric development environment set up on your machine. Se è necessario configurarlo, andare alla guida introduttiva per Mac o alla guida introduttiva per Linux.If you need to set it up, go to getting started on Mac or getting started on Linux.

Concetti di baseBasic concepts

Per iniziare a usare Reliable Services, è sufficiente comprendere solo alcuni concetti di base:To get started with Reliable Services, you only need to understand a few basic concepts:

  • Tipo di servizio: si tratta dell'implementazione del servizio.Service type: This is your service implementation. Viene definito dalla classe scritta che estende StatelessService e qualsiasi altro codice o dipendenze usate, insieme al nome e al numero della versione.It is defined by the class you write that extends StatelessService and any other code or dependencies used therein, along with a name and a version number.
  • Istanza di servizio denominata: per eseguire il servizio, si creano le istanze denominate del tipo di servizio, analogamente al modo in cui si creano le istanze di un oggetto di un tipo di classe.Named service instance: To run your service, you create named instances of your service type, much like you create object instances of a class type. Le istanze del servizio sono, di fatto, istanze di oggetto della classe del servizio che si scrive.Service instances are in fact object instantiations of your service class that you write.
  • Host del servizio: le istanze del servizio denominate che si creano devono essere eseguite all'interno di un host.Service host: The named service instances you create need to run inside a host. L'host del servizio è semplicemente un processo in cui eseguire le istanze del servizio.The service host is just a process where instances of your service can run.
  • Registrazione del servizio: la registrazione raccoglie tutti gli elementi.Service registration: Registration brings everything together. Il tipo di servizio deve essere registrato con il runtime di Service Fabric in un host del servizio per consentire a Service Fabric di creare istanze per l'esecuzione.The service type must be registered with the Service Fabric runtime in a service host to allow Service Fabric to create instances of it to run.

Creare un servizio senza statoCreate a stateless service

Iniziare a creare un'applicazione di Service Fabric.Start by creating a Service Fabric application. Service Fabric SDK per Linux include un generatore Yeoman per la creazione dello scaffolding per un'applicazione di Service Fabric con un servizio senza stato.The Service Fabric SDK for Linux includes a Yeoman generator to provide the scaffolding for a Service Fabric application with a stateless service. Iniziare eseguendo il comando Yeoman seguente:Start by running the following Yeoman command:

$ yo azuresfjava

Seguire le istruzioni per creare un servizio di Reliable Service senza stato.Follow the instructions to create a Reliable Stateless Service. Per questa esercitazione, denominare l'applicazione "HelloWorldApplication" e il servizio "HelloWorld".For this tutorial, name the application "HelloWorldApplication" and the service "HelloWorld". Il risultato include le directory per HelloWorldApplication e HelloWorld.The result includes directories for the HelloWorldApplication and HelloWorld.

HelloWorldApplication/
├── build.gradle
├── HelloWorld
│   ├── build.gradle
│   └── src
│       └── statelessservice
│           ├── HelloWorldServiceHost.java
│           └── HelloWorldService.java
├── HelloWorldApplication
│   ├── ApplicationManifest.xml
│   └── HelloWorldPkg
│       ├── Code
│       │   ├── entryPoint.sh
│       │   └── _readme.txt
│       ├── Config
│       │   └── _readme.txt
│       ├── Data
│       │   └── _readme.txt
│       └── ServiceManifest.xml
├── install.sh
├── settings.gradle
└── uninstall.sh

Registrazione del servizioService registration

I tipi del servizio devono essere registrati nel runtime di Service Fabric.Service types must be registered with the Service Fabric runtime. Il tipo di servizio è definito nel ServiceManifest.xml e nella classe di servizio che implementa StatelessService.The service type is defined in the ServiceManifest.xml and your service class that implements StatelessService. La registrazione del servizio viene eseguita nel punto di ingresso principale del processo.Service registration is performed in the process main entry point. In questo esempio il punto di ingresso principale del processo è HelloWorldServiceHost.java:In this example, the process main entry point is HelloWorldServiceHost.java:

public static void main(String[] args) throws Exception {
    try {
        ServiceRuntime.registerStatelessServiceAsync("HelloWorldType", (context) -> new HelloWorldService(), Duration.ofSeconds(10));
        logger.log(Level.INFO, "Registered stateless service type HelloWorldType.");
        Thread.sleep(Long.MAX_VALUE);
    }
    catch (Exception ex) {
        logger.log(Level.SEVERE, "Exception in registration:", ex);
        throw ex;
    }
}

Implementare il servizioImplement the service

Aprire HelloWorldApplication/HelloWorld/src/statelessservice/HelloWorldService.java.Open HelloWorldApplication/HelloWorld/src/statelessservice/HelloWorldService.java. Questa classe definisce il tipo di servizio e può eseguire qualsiasi codice.This class defines the service type, and can run any code. L'API del servizio fornisce due punti di ingresso per il codice:The service API provides two entry points for your code:

  • Un metodo del punto di ingresso aperto denominato runAsync(), che consente di iniziare a eseguire qualsiasi carico di lavoro, inclusi carichi di lavoro di calcolo con esecuzione prolungata.An open-ended entry point method, called runAsync(), where you can begin executing any workloads, including long-running compute workloads.
@Override
protected CompletableFuture<?> runAsync(CancellationToken cancellationToken) {
    ...
}
  • Un punto di ingresso di comunicazione a cui è possibile collegare lo stack di comunicazione desiderato.A communication entry point where you can plug in your communication stack of choice. In questo punto è possibile iniziare a ricevere richieste da utenti e da altri servizi.This is where you can start receiving requests from users and other services.
@Override
protected List<ServiceInstanceListener> createServiceInstanceListeners() {
    ...
}

Questa esercitazione si concentra sul metodo del punto di ingresso runAsync().This tutorial focuses on the runAsync() entry point method. In questo punto è possibile iniziare immediatamente a eseguire il codice.This is where you can immediately start running your code.

RunAsyncRunAsync

La piattaforma chiama questo metodo quando si inserisce un'istanza di un servizio pronta per l'esecuzione.The platform calls this method when an instance of a service is placed and ready to execute. Per un servizio senza stato, la piattaforma chiama il metodo quando l'istanza del servizio viene aperta.For a stateless service, that means when the service instance is opened. Viene fornito un token di annullamento che determina quando è necessario chiudere l'istanza del servizio.A cancellation token is provided to coordinate when your service instance needs to be closed. In Service Fabric questo ciclo di apertura e chiusura di un'istanza del servizio può verificarsi più volte per tutta la durata del servizio nel suo complesso.In Service Fabric, this open/close cycle of a service instance can occur many times over the lifetime of the service as a whole. Questa situazione può verificarsi per vari motivi, tra cui:This can happen for various reasons, including:

  • Il sistema sposta le istanze del servizio per il bilanciamento delle risorse.The system moves your service instances for resource balancing.
  • Si verificano errori nel codice.Faults occur in your code.
  • Viene aggiornato il sistema o l'applicazione.The application or system is upgraded.
  • Si verifica un'interruzione nell'hardware sottostante.The underlying hardware experiences an outage.

Questa orchestrazione viene gestita da Service Fabric per assicurare l'elevata disponibilità e il corretto bilanciamento del servizio.This orchestration is managed by Service Fabric to keep your service highly available and properly balanced.

runAsync() non deve bloccarsi in modo sincrono.runAsync() should not block synchronously. L'implementazione di runAsync deve restituire un valore CompletableFuture per consentire al runtime di procedere.Your implementation of runAsync should return a CompletableFuture to allow the runtime to continue. Se il carico di lavoro deve implementare un'attività a esecuzione prolungata, tale operazione deve essere completata entro il valore specificato da CompletableFuture.If your workload needs to implement a long running task that should be done inside the CompletableFuture.

AnnullamentoCancellation

L'annullamento del carico di lavoro è un'operazione cooperativa coordinata dal token di annullamento fornito.Cancellation of your workload is a cooperative effort orchestrated by the provided cancellation token. Il sistema attende la fine dell'attività (per esito positivo, annullamento o errore) prima di continuare.The system waits for your task to end (by successful completion, cancellation, or fault) before it moves on. È importante rispettare il token di annullamento, completare le operazioni e chiudere runAsync() il più rapidamente possibile quando viene richiesto l'annullamento dal sistema.It is important to honor the cancellation token, finish any work, and exit runAsync() as quickly as possible when the system requests cancellation. L'esempio seguente mostra come gestire un evento di annullamento:The following example demonstrates how to handle a cancellation event:

@Override
protected CompletableFuture<?> runAsync(CancellationToken cancellationToken) {

    // TODO: Replace the following sample code with your own logic
    // or remove this runAsync override if it's not needed in your service.

    return CompletableFuture.runAsync(() -> {
        long iterations = 0;
        while(true)
        {
        cancellationToken.throwIfCancellationRequested();
        logger.log(Level.INFO, "Working-{0}", ++iterations);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex){}
        }
    });
}

In questo esempio di servizio senza stato il conteggio è archiviato in una variabile locale.In this stateless service example, the count is stored in a local variable. Tuttavia, poiché si tratta di un servizio senza stato, il valore archiviato esiste soltanto per il ciclo di vita corrente dell'istanza del servizio.But because this is a stateless service, the value that's stored exists only for the current lifecycle of its service instance. Quando si posta o si riavvia il servizio, il valore viene perso.When the service moves or restarts, the value is lost.

Creare un servizio con statoCreate a stateful service

Service Fabric introduce un nuovo tipo di servizio con stato.Service Fabric introduces a new kind of service that is stateful. Un servizio con stato può mantenere lo stato affidabile all'interno del servizio stesso, con percorso condiviso con il codice che lo usa.A stateful service can maintain state reliably within the service itself, co-located with the code that's using it. L'elevata disponibilità dello stato è assicurata da Service Fabric, senza dover rendere persistente lo stato mediante un archivio esterno.State is made highly available by Service Fabric without the need to persist state to an external store.

Per convertire un valore del contatore da senza stato a elevata disponibilità e persistenza anche quando il servizio viene spostato o riavviato, è necessario un servizio con stato.To convert a counter value from stateless to highly available and persistent, even when the service moves or restarts, you need a stateful service.

Nella stessa directory dell'applicazione HelloWorld è possibile aggiungere un nuovo servizio eseguendo il comando yo azuresfjava:AddService.In the same directory as the HelloWorld application, you can add a new service by running the yo azuresfjava:AddService command. Specificare il "Servizio Reliable con stato" per il framework e assegnare al servizio il nome "HelloWorldStateful".Choose the "Reliable Stateful Service" for your framework and name the service "HelloWorldStateful".

A questo punto l'applicazione ha due servizi: il servizio senza stato HelloWorld e il servizio con stato HelloWorldStateful.Your application should now have two services: the stateless service HelloWorld and the stateful service HelloWorldStateful.

Un servizio con stato ha gli stessi punti di ingresso di un servizio senza stato.A stateful service has the same entry points as a stateless service. La differenza principale è data dalla disponibilità di un provider di stato che può archiviare lo stato in modo affidabile.The main difference is the availability of a state provider that can store state reliably. Service Fabric include un'implementazione del provider di stato denominata Reliable Collections, che permette di creare strutture di dati replicate tramite Reliable State Manager.Service Fabric comes with a state provider implementation called Reliable Collections, which lets you create replicated data structures through the Reliable State Manager. Un servizio Reliable Services con stato usa questo provider di stato per impostazione predefinita.A stateful Reliable Service uses this state provider by default.

Aprire HelloWorldStateful.java in HelloWorldStateful -> src, che contiene il metodo RunAsync seguente:Open HelloWorldStateful.java in HelloWorldStateful -> src, which contains the following RunAsync method:

@Override
protected CompletableFuture<?> runAsync(CancellationToken cancellationToken) {
    Transaction tx = stateManager.createTransaction();
    return this.stateManager.<String, Long>getOrAddReliableHashMapAsync("myHashMap").thenCompose((map) -> {
        return map.computeAsync(tx, "counter", (k, v) -> {
            if (v == null)
                return 1L;
            else
                return ++v;
            }, Duration.ofSeconds(4), cancellationToken)
                .thenCompose((r) -> tx.commitAsync())
                .whenComplete((r, e) -> {
            try {
                tx.close();
            } catch (Exception e) {
                logger.log(Level.SEVERE, e.getMessage());
            }
        });
    });
}

RunAsyncRunAsync

RunAsync() funziona in modo simile sia nei servizi con stato che nei servizi senza stato.RunAsync() operates similarly in stateful and stateless services. In un servizio con stato la piattaforma esegue tuttavia operazioni aggiuntive per conto dell'utente prima di eseguire RunAsync().However, in a stateful service, the platform performs additional work on your behalf before it executes RunAsync(). Tali operazioni possono includere la verifica che Reliable State Manager e Reliable Collections siano pronti per l'uso.This work can include ensuring that the Reliable State Manager and Reliable Collections are ready to use.

Reliable Collections e Reliable State ManagerReliable Collections and the Reliable State Manager

ReliableHashMap<String,Long> map = this.stateManager.<String, Long>getOrAddReliableHashMapAsync("myHashMap")

ReliableHashMap è un'implementazione di dizionario che permette di archiviare in modo affidabile lo stato nel servizio.ReliableHashMap is a dictionary implementation that you can use to reliably store state in the service. Grazie a Service Fabric e a Reliable HashMaps, è possibile archiviare i dati direttamente nel servizio, senza la necessità di un archivio esterno persistente.With Service Fabric and Reliable HashMaps, you can store data directly in your service without the need for an external persistent store. Reliable HashMaps garantisce la disponibilità elevata dei dati.Reliable HashMaps make your data highly available. A tale scopo, Service Fabric crea e gestisce automaticamente più repliche del servizio.Service Fabric accomplishes this by creating and managing multiple replicas of your service for you. Offre anche un'API che consente di evitare le complessità di gestione di tali repliche e delle relative transizioni di stato.It also provides an API that abstracts away the complexities of managing those replicas and their state transitions.

Le raccolte Reliable Collections possono archiviare qualsiasi tipo Java, inclusi quelli personalizzati, con alcuni avvertimenti:Reliable Collections can store any Java type, including your custom types, with a couple of caveats:

  • Service Fabric garantisce la disponibilità elevata dello stato replicando lo stato nei nodi, mentre Reliable HashMap archivia i dati nel disco locale a ogni replica.Service Fabric makes your state highly available by replicating state across nodes, and Reliable HashMap stores your data to local disk on each replica. Questo significa che tutti gli elementi archiviati in Reliable HashMaps devono essere serializzabili.This means that everything that is stored in Reliable HashMaps must be serializable.
  • Quando si esegue il commit di transazioni in Reliable HashMaps, gli oggetti vengono replicati per assicurare disponibilità elevata.Objects are replicated for high availability when you commit transactions on Reliable HashMaps. Gli oggetti archiviati in Reliable HashMaps vengono conservati nella memoria locale del servizio.Objects stored in Reliable HashMaps are kept in local memory in your service. Ciò significa che è presente un riferimento locale all'oggetto.This means that you have a local reference to the object.

    È importante non apportare modifiche alle istanze locali degli oggetti senza prima eseguire un'operazione di aggiornamento sulla raccolta Reliable Collections in una transazione.It is important that you do not mutate local instances of those objects without performing an update operation on the reliable collection in a transaction. Le modifiche apportate alle istanze locali di oggetti, infatti, non vengono replicate automaticamente.This is because changes to local instances of objects will not be replicated automatically. È necessario inserire nuovamente l'oggetto nel dizionario oppure usare uno dei metodi di aggiornamento nel dizionario.You must reinsert the object back into the dictionary or use one of the update methods on the dictionary.

Reliable State Manager gestisce automaticamente Reliable HashMaps.The Reliable State Manager manages Reliable HashMaps for you. In qualunque momento e in qualsiasi posizione del servizio è possibile chiedere a Reliable State Manager una raccolta Reliable Collections indicandone il nome.You can ask the Reliable State Manager for a reliable collection by name at any time and at any place in your service. Reliable State Manager restituirà un riferimento.The Reliable State Manager ensures that you get a reference back. Non si consiglia di salvare riferimenti alle istanze di raccolte Reliable Collections in proprietà o variabili membri di classe.We don't recommend that you save references to reliable collection instances in class member variables or properties. Prestare particolare attenzione per assicurarsi che il riferimento sia sempre impostato su un'istanza durante il ciclo di vita del servizio.Special care must be taken to ensure that the reference is set to an instance at all times in the service lifecycle. Reliable State Manager gestisce queste operazioni automaticamente ed è ottimizzato per le visite ripetute.The Reliable State Manager handles this work for you, and it's optimized for repeat visits.

Operazioni transazionali e asincroneTransactional and asynchronous operations

return map.computeAsync(tx, "counter", (k, v) -> {
    if (v == null)
        return 1L;
    else
        return ++v;
    }, Duration.ofSeconds(4), cancellationToken)
        .thenCompose((r) -> tx.commitAsync())
        .whenComplete((r, e) -> {
    try {
        tx.close();
    } catch (Exception e) {
        logger.log(Level.SEVERE, e.getMessage());
    }
});

Le operazioni su Reliable HashMaps sono asincrone.Operations on Reliable HashMaps are asynchronous. Questo avviene perché le operazioni di scrittura sulle raccolte Reliable Collections eseguono operazioni di I/O per replicare e rendere persistenti i dati su disco.This is because write operations with Reliable Collections perform I/O operations to replicate and persist data to disk.

Le operazioni su Reliable HashMaps sono transazionali e consentono di mantenere lo stato coerente tra più Reliable HashMaps e operazioni.Reliable HashMap operations are transactional, so that you can keep state consistent across multiple Reliable HashMaps and operations. Ad esempio, è possibile ottenere un elemento di lavoro da un oggetto Reliable Dictionary, eseguire un'operazione su tale elemento e salvare il risultato in un altro oggetto Reliable HashMap, il tutto all'interno di una singola transazione.For example, you may get a work item from one Reliable Dictionary, perform an operation on it, and save the result in another Reliable HashMap, all within a single transaction. Questa viene considerata come un'operazione atomica e garantisce la riuscita o il rollback dell'intera operazione.This is treated as an atomic operation, and it guarantees that either the entire operation will succeed or the entire operation will roll back. Se si verifica un errore dopo aver rimosso l'elemento dalla coda ma prima di aver salvato il risultato, viene eseguito il rollback dell'intera transazione e l'elemento rimane nella coda per l'elaborazione.If an error occurs after you dequeue the item but before you save the result, the entire transaction is rolled back and the item remains in the queue for processing.

Compilare l'applicazione.Build the application

Lo scaffolding Yeoman include uno script Gradle per compilare l'applicazione e script Bash per distribuire ed eliminare l'applicazione.The Yeoman scaffolding includes a gradle script to build the application and bash scripts to deploy and remove the application. Per eseguire l'applicazione, prima di tutto compilarla con Gradle:To run the application, first build the application with gradle:

$ gradle

Questa operazione genera un pacchetto dell'applicazione Service Fabric che può essere distribuito tramite l'interfaccia della riga di comando di Service Fabric.This produces a Service Fabric application package that can be deployed using Service Fabric CLI.

Distribuire l'applicazioneDeploy the application

Dopo aver compilato l'applicazione, è possibile distribuirla nel cluster locale.Once the application is built, you can deploy it to the local cluster.

  1. Connettersi al cluster locale di Service Fabric.Connect to the local Service Fabric cluster.

    sfctl cluster select --endpoint http://localhost:19080
    
  2. Eseguire lo script di installazione messo a disposizione nel modello per copiare il pacchetto dell'applicazione nell'archivio immagini del cluster, registrare il tipo di applicazione e creare un'istanza dell'applicazione.Run the install script provided in the template to copy the application package to the cluster's image store, register the application type, and create an instance of the application.

    ./install.sh
    

La distribuzione dell'applicazione compilata è uguale a quella di qualsiasi altra applicazione di Service Fabric.Deploying the built application is the same as any other Service Fabric application. Per istruzioni dettagliate, vedere la documentazione sulla gestione di un'applicazione di Service Fabric con l'interfaccia della riga di comando di Service Fabric.See the documentation on managing a Service Fabric application with the Service Fabric CLI for detailed instructions.

I parametri per questi comandi si trovano nei manifesti generati nel pacchetto dell'applicazione.Parameters to these commands can be found in the generated manifests inside the application package.

Dopo la distribuzione dell'applicazione, aprire un browser e passare a Service Fabric Explorer all'indirizzo http://localhost:19080/Explorer.Once the application has been deployed, open a browser and navigate to Service Fabric Explorer at http://localhost:19080/Explorer. Espandere quindi il nodo Applicazioni, nel quale sarà ora presente una voce per il tipo di applicazione e un'altra per la prima istanza del tipo.Then, expand the Applications node and note that there is now an entry for your application type and another for the first instance of that type.

Importante

Per distribuire l'applicazione a un cluster Linux protetto in Azure, è necessario configurare un certificato per convalidare l'applicazione con il runtime di Service Fabric. In questo modo i servizi di Reliable Services possono comunicare con le API di runtime di Service Fabric sottostanti. Per altre informazioni, vedere Configure a Reliable Services app to run on Linux clusters (Configurare un'app di Reliable Services da eseguire su cluster Linux).

Passaggi successiviNext steps