Grani di lavoro senza stato

Per impostazione predefinita, il runtime di Orleans crea non più di un'attivazione di una granularità all'interno del cluster. Si tratta dell'espressione più intuitiva del modello Virtual Actor con ogni granularità corrispondente a un'entità con un tipo/identità univoco. Tuttavia, esistono anche dei casi in cui un'applicazione deve eseguire delle operazioni senza stato funzionali che non sono associate a una determinata entità nel sistema. Ad esempio, se il client invia richieste con payload compressi che devono essere decompressi prima che possano essere indirizzati alla granularità di destinazione per l'elaborazione, tale logica di decompressione/routing non è associata a un'entità specifica nell'applicazione e può facilmente aumentare il numero di istanze.

Quando l’oggetto StatelessWorkerAttribute viene applicato a una classe granulare, indica al runtime Orleans che i grani di tale classe devono essere considerati come grani di lavoro senza stato. I grani di lavoro senza stato hanno le proprietà seguenti che rendono l'esecuzione molto diversa da quella delle classi di granularità normali.

  1. Il runtime Orleans può e creerà più attivazioni di un grano di lavoro senza stato in diversi silo del cluster.
  2. Le richieste effettuate ai grani di lavoro senza stato vengono eseguite localmente finché il silo è compatibile e pertanto non comportano costi di rete o serializzazione. Se il silo locale non è compatibile, le richieste vengono inoltrate a un silo compatibile.
  3. Il runtime di Orleans crea automaticamente attivazioni aggiuntive di un livello di lavoro senza stato se quelle già esistenti sono occupate. Il numero massimo di attivazioni di un grano di lavoro senza stato creato dal runtime per silo è limitato per impostazione predefinita dal numero di core CPU nel computer, a meno che non sia specificato in modo esplicito dall'argomento maxLocalWorkers facoltativo.
  4. A causa di 2 e 3, le attivazioni con granularità di lavoro senza stato non sono indirizzabili singolarmente. Due richieste successive a una granularità di lavoro senza stato possono essere elaborate da attivazioni diverse.

I grani di lavoro senza stato offrono un modo semplice per creare un pool gestito automaticamente di attivazioni granulari che aumentano e riducono automaticamente in base al carico effettivo. Il runtime analizza sempre le attivazioni della granularità di lavoro senza stato disponibili nello stesso ordine. Per questo motivo, invia sempre le richieste alla prima attivazione locale inattiva che riesce a trovare, e ottiene solo l'ultima se tutte le attivazioni precedenti sono occupate. Se tutte le attivazioni sono occupate e il limite di attivazione non è stato raggiunto, crea un'altra attivazione alla fine dell'elenco e invia la richiesta. Ciò significa che quando aumenta la frequenza delle richieste a un limite di lavoro senza stato e le attivazioni esistenti sono tutte occupate, il runtime espande il pool di attivazioni fino al limite. Viceversa, quando il carico scende e può essere gestito da un numero minore di attivazioni del livello di lavoro senza stato, le attivazioni alla fine dell'elenco non riceveranno le richieste inviate. Diventeranno inattive e alla fine disattivate dal processo di raccolta di attivazione standard. Di conseguenza, il pool di attivazioni si ridurrà in modo che corrisponda al carico.

Nell'esempio seguente viene definita una classe MyStatelessWorkerGrain di granularità di lavoro senza stato con il limite massimo di attivazione predefinito.

[StatelessWorker]
public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
{
    // ...
}

L'esecuzione di una chiamata a un grano di lavoro senza stato è identica a qualsiasi altra granularità. L'unica differenza è che nella maggior parte dei casi viene usato un singolo ID granulare, ad esempio 0 o Guid.Empty. È possibile usare più ID granulari quando si hanno più pool di granularità di lavoro senza stato, è consigliabile uno per ID.

var worker = GrainFactory.GetGrain<IMyStatelessWorkerGrain>(0);
await worker.Process(args);

Questo definisce una classe di granularità di lavoro senza stato, senza più di un'attivazione granulare per silo.

[StatelessWorker(1)] // max 1 activation per silo
public class MyLonelyWorkerGrain : ILonelyWorkerGrain
{
    //...
}

Si noti che StatelessWorkerAttribute non modifica la rientranza della classe di granularità di destinazione. Proprio come qualsiasi altro granello, i grani di lavoro senza stato non sono rientranti per impostazione predefinita. Possono essere resi rientranti in modo esplicito aggiungendo un oggetto ReentrantAttribute alla classe granulare.

Provincia

La parte "senza stato" del "ruolo di lavoro senza stato" non significa che un ruolo di lavoro senza stato non possa avere uno stato e che sia limitato solo all'esecuzione di operazioni funzionali. Come qualsiasi altro tipo di granularità, un grano di lavoro senza stato può caricare e mantenere in memoria qualsiasi stato necessario. È solo perché è possibile creare più attivazioni di un grano di lavoro senza stato nello stesso e in diversi silo del cluster, non esiste un meccanismo semplice per coordinare lo stato mantenuto da attivazioni diverse.

Diversi modelli utili comportano il mantenimento dello stato del ruolo di lavoro senza stato.

Elementi della cache ad accesso frequente con scalabilità orizzontale

Per gli elementi della cache ad accesso frequente con velocità effettiva elevata, il mantenimento di ogni elemento in un grano di lavoro senza gli consente di:

  1. Aumentare automaticamente il numero di istanze all'interno di un silo e in tutti i silo nel cluster e;
  2. Rendere i dati sempre disponibili in locale nel silo che ha ricevuto la richiesta client tramite il gateway client, in modo che le richieste possano essere risposte senza un hop di rete aggiuntivo a un altro silo.

Ridurre l'aggregazione di stili

In alcuni scenari, le applicazioni devono calcolare determinate metriche in tutti i grani di un particolare tipo nel cluster e segnalare periodicamente le aggregazioni. Esempi sono la segnalazione di diversi giocatori per mappa di gioco, la durata media di una chiamata VoIP e così via. Se ognuno dei migliaia o milioni di grani dovesse segnalare le metriche a un singolo aggregatore globale, l'aggregatore verrebbe immediatamente sovraccaricato, incapace di elaborare le inondazioni di report. L'approccio alternativo consiste nel trasformare questa attività in un passaggio a 2 (o più) per ridurre l'aggregazione dello stile. Il primo livello di aggregazione viene eseguito segnalando granularità tramite l’invio delle metriche a un grano di pre-aggregazione del ruolo di lavoro senza stato. Il runtime Orleans creerà automaticamente più attivazioni del livello di lavoro senza stato con ogni silo. Poiché tutte queste chiamate verranno elaborate in locale senza chiamate remote o serializzazione dei messaggi, il costo di tale aggregazione sarà significativamente inferiore rispetto a un caso remoto. Ora ognuna delle attivazioni della granularità di lavoro senza stato di pre-aggregazione, indipendentemente o in coordinamento con altre attivazioni locali, può inviare i report aggregati all'aggregatore finale globale (o a un altro livello di riduzione, se necessario) senza sovraccaricarlo.