Operazioni di Gridwich per Archiviazione di Azure

Archiviazione di Azure

Gridwich Archiviazione di Azure Service, Gridwich.SagaParticipants.Storage.AzureStorage, fornisce operazioni blob e contenitori per gli account Archiviazione di Azure configurati per Gridwich. Le operazioni di archiviazione di esempio sono Crea BLOB, Rimuovi contenitore, Copia BLOB o Modifica livello di archiviazione.

Gridwich richiede che i meccanismi di archiviazione funzionino sia per i BLOB in blocchi che per i contenitori Archiviazione di Azure. Con classi distinte e operazioni del servizio di archiviazione per BLOB e contenitori, non c'è ambiguità se una determinata operazione di archiviazione è correlata a un BLOB o a un contenitore. Questo articolo si applica sia ai BLOB che ai contenitori, tranne dove indicato.

Gridwich espone la maggior parte delle operazioni di archiviazione a sistemi esterni all'interno del Storage.AzureStorage partecipante della saga. Altri partecipanti della saga usano il servizio di archiviazione per attività come la copia di BLOB tra contenitori o account diversi quando configurano flussi di lavoro di codifica.

Questo articolo descrive in che modo Gridwich Archiviazione di Azure Service soddisfa i requisiti della soluzione e si integra con meccanismi come i gestori eventi. I collegamenti puntano al codice sorgente corrispondente, che contiene commenti più estesi su contenitori, classi e meccanismi.

SDK Archiviazione di Azure

Gridwich usa classi di SDK Archiviazione di Azure per interagire con Archiviazione di Azure, invece di creare richieste REST. All'interno del provider di archiviazione, le classi SDK BlobBaseClient e BlobContainerClient gestiscono le richieste di archiviazione.

Queste classi client SDK attualmente consentono solo l'accesso indiretto alle due intestazioni HTTP Gridwich deve modificare, x-ms-client-request-id per il contesto dell'operazione e ETag per la versione dell'oggetto.

In Gridwich una coppia di classi provider distribuisce la funzionalità BlobBaseClientProvider e BlobContainerClientProvider in unità denominate sleeve. Per informazioni dettagliate sugli sleeve, consultare la sezione Sleeve di archiviazione.

Il diagramma seguente illustra la struttura delle classi SDK e Gridwich e il modo in cui le istanze sono correlate tra loro. Le frecce indicano "ha un riferimento a".

Diagramma che mostra le relazioni tra le istanze dell'oggetto client tra le classi di Storage SDK.

Criteri per pipeline

Impostare l'hook per modificare le intestazioni HTTP come istanza dei criteri della pipeline quando si crea l'istanza client. È possibile impostare questo criterio solo in fase di creazione dell'istanza client e non è possibile modificare il criterio. Il codice del provider di archiviazione che usa il client deve essere in grado di modificare i valori di intestazione durante l'esecuzione. La sfida consiste nel fare in modo che il provider di archiviazione e la pipeline interagiscono in modo pulito.

Per i criteri della pipeline gridwich, vedere la classe BlobClientPipelinePolicy .

Memorizzazione nella cache del servizio di archiviazione

L'impostazione della connessione TCP e l'autenticazione creano sovraccarico quando un'istanza dell'oggetto client SDK invia la prima richiesta a Archiviazione di Azure. Più chiamate allo stesso BLOB in una richiesta di sistema esterna, ad esempio Recupera metadati, quindi Elimina BLOB, complicano l'overhead.

Per ridurre il sovraccarico, Gridwich gestisce una cache di un'istanza client per ogni BLOB o contenitore di archiviazione, a seconda delle classi SDK usate dal contesto dell'operazione. Gridwich mantiene questa istanza client e può usare l'istanza per più operazioni di Archiviazione di Azure sullo stesso BLOB o contenitore per la durata di una richiesta di sistema esterna.

Le classi client fornite da Azure SDK richiedono che le istanze dell'oggetto client SDK siano specifiche di un singolo BLOB o contenitore in fase di creazione. Anche le istanze non sono sicure per l'uso simultaneo in thread diversi. Poiché un contesto dell'operazione rappresenta una singola richiesta, Gridwich basa la memorizzazione nella cache sulla combinazione di blob o nome del contenitore con il contesto dell'operazione.

Questo riutilizzo dell'istanza, combinato con la struttura client Archiviazione di Azure SDK, richiede codice di supporto aggiuntivo per bilanciare l'efficienza e la chiarezza del codice.

Argomento context

Quasi tutte le operazioni del servizio di archiviazione gridwich richiedono un argomento di contesto speciale di tipo StorageClientProviderContext. Questo argomento di contesto soddisfa i requisiti seguenti:

  • Fornisce al sistema esterno risposte, che includono il valore del contesto di operazione univoco basato su JSON per richiesta specificato dal sistema esterno nella richiesta Gridwich. Per maggiori informazioni, consultare la sezione Contesto di operazione.

  • Consente ai chiamanti del servizio di archiviazione come i gestori eventi Gridwich di controllare quali risposte sono visibili al sistema esterno. Questo controllo impedisce al servizio di inondare il sistema esterno con eventi di notifica irrilevanti. Per maggiori informazioni, consultare la sezione Muting contesto.

  • È conforme alle convenzioni Archiviazione di Azure per garantire richieste e risposte coerenti in un ambiente che consenta una combinazione di lettori e writer paralleli. Ad esempio, supporta il rilevamento ETag. Per maggiori informazioni, consultare la sezione ETag.

Contesto di archiviazione

Il contesto per i tipi di archiviazione BLOB e contenitori è StorageClientProviderContext, simile al seguente:

    string  ClientRequestID { get; }
    JObject ClientRequestIdAsJObject { get; }
    bool    IsMuted { get; set; }
    string  ETag { get; set; }
    bool    TrackingETag { get; set; }

Le prime due proprietà sono rappresentazioni diverse del contesto dell'operazione usato per inizializzare l'istanza StorageClientProviderContext . La classe ha vari costruttori, incluso un costruttore di copia. Altri metodi includono ResetTo, per consentire la duplicazione dello stato sul posto e un metodo statico CreateSafe per garantire che le inizializzazioni problematiche non generino eccezioni.

La classe contiene anche una gestione speciale per la creazione di contesti basati su GUID e stringhe vuote. I gestori di notifica Archiviazione di Azure per BLOB Creati ed Eliminati, che elaborano anche le notifiche derivanti da agenti esterni, richiedono il modulo GUID.

Muting del contesto

La proprietà IsMuted controlla se l'applicazione prevede che il servizio pubblicherà nuovamente le notifiche risultanti al chiamante, ad esempio nel sistema esterno. In un'operazione disattivata, il servizio non pubblica eventi risultanti.

Un esempio è rappresentato da copie BLOB eseguite da un codificatore per disporre i BLOB in Archiviazione di Azure come input per un'attività di codifica. Il sistema esterno non è preoccupato per questi dettagli, ma solo sullo stato del processo di codifica e dove può recuperare gli output codificati. Per riflettere questi problemi, il codificatore:

  1. Crea un contesto di archiviazione non disattivato in base al contesto dell'operazione di richiesta, ad esempio ctxNotMuted.

  2. Crea un contesto di archiviazione disattivato, ad esempio ctxMuted, usando il costruttore di copia della classe di contesto o creando una nuova istanza. Entrambe le opzioni avranno lo stesso valore del contesto dell'operazione.

  3. Specifica ctxMuted per le operazioni di archiviazione coinvolte nella configurazione per la codifica. Il sistema esterno non visualizza alcuna indicazione di queste operazioni in corso.

  4. Specifica il contesto ctxNotMuted per le operazioni di archiviazione che riflettono il completamento della codifica, ad esempio la copia di un file di output in un contenitore di destinazione. I gestori Gridwich pubblicano gli eventi di notifica Archiviazione di Azure risultanti nel sistema esterno.

Il chiamante controlla la visibilità finale delle operazioni. Sia le operazioni disattivate che le operazioni non disattivate sono basate su un valore equivalente operationContext. Lo scopo della disattivazione del contesto è semplificare l'esecuzione della diagnosi dei problemi dai log di traccia eventi, perché è possibile visualizzare le operazioni di archiviazione correlate a una richiesta, indipendentemente dallo stato di disattivazione dell'operazione.

ResponseBaseDTO ha una proprietà booleanaDoNotPublish, che utilizza l'invio di eventi per determinare la decisione finale sulla pubblicazione. L'invio di eventi, a sua volta, imposta la proprietà DoNotPublish in base alla proprietà IsMuted del contesto.

Il servizio trasmette l'impostazione di disattivazione a Archiviazione di Azure, che imposta quindi l'oggetto clientRequestId negli eventi di notifica di archiviazione che presenta ai due gestori gridwich, Created e Deleted. Questi due gestori sono impostati su DoNotPublish in modo da riflettere la disattivazione richiesta dal chiamante.

ETag per la coerenza di destinazione

Archiviazione di Azure usa l'intestazione HTTP ETag per le sequenze di richiesta che devono avere coerenza di destinazione. Un esempio consiste nel garantire che un BLOB non sia cambiato tra le operazioni di recupero dei metadati e di archiviazione dei metadati di aggiornamento.

Per allinearsi all'utilizzo HTTP standard, questa intestazione ha un valore opaco la cui interpretazione è che se il valore dell'intestazione cambia, l'oggetto sottostante è stato modificato. Se una richiesta invia il valore corrente ETag per l'oggetto e non corrisponde al valore corrente del servizio ETag di archiviazione, la richiesta ha immediatamente esito negativo. Se la richiesta non include un valore ETag, Archiviazione di Azure ignora tale controllo e non blocca la richiesta.

ETag nel servizio di archiviazione

Per Gridwich, ETag è un dettaglio interno tra il servizio di archiviazione gridwich e Archiviazione di Azure. Nessun altro codice deve essere a conoscenza di ETag. Il servizio di archiviazione usa per ETag sequenze come get blob metadata, delete blob operations for processing a BlobDelete Event request. L'uso ETag di garantisce che l'operazione Elimina BLOB sia destinata esattamente alla stessa versione del BLOB dell'operazione Recupera metadati .

Per utilizzare ETag per l'esempio precedente:

  1. Inviare la richiesta Get Metadata con un valore vuoto ETag.
  2. Salvare il valore ETag dalla risposta.
  3. Aggiungere il valore salvato ETag alla richiesta Elimina BLOB .

Se i due valori ETag sono diversi, l'operazione di eliminazione non riesce. L'errore implica che un'altra operazione ha modificato il BLOB tra i passaggi 2 e 3. Ripetere il processo dal passaggio 1.

ETag è un parametro di costruttori e una proprietà stringa della classe StorageClientProviderContext. Solo l'oggetto specifico BlobClientPipelinePolicydi Gridwich modifica il valore ETag.

Uso di ETag per il controllo

La proprietà TrackingETag controlla se inviare il valore ETag alla richiesta successiva. Il valore true indica che il servizio invia un oggetto ETag se disponibile.

Una richiesta Archiviazione di Azure con un valore ETag che non corrisponde al BLOB oggetto o al contenitore genera un errore nell'operazione. Questo errore è per progettazione, perché ETag è il modo HTTP standard di esprimere "la versione esatta di destinazione della richiesta". Le richieste possono includere la TrackingETag proprietà per dichiarare che deve ETags corrispondere o non includere la TrackingETag proprietà per indicare che i ETag valori non sono importanti.

La pipeline recupera sempre un valore ETag da un'operazione Archiviazione di Azure se presente in tale risposta REST. La pipeline aggiorna sempre la proprietà di contesto ETag, se possibile, a partire dall'ultima operazione. Il flag TrackingETag controlla solo se la richiesta successiva dalla stessa istanza client invia il valore della proprietà ETag. Se il valore ETag è null o vuoto, la richiesta corrente non imposta alcun valore HTTP ETag, indipendentemente dal valore di TrackingETag.

Sleeve di archiviazione

Gridwich richiede che i meccanismi di archiviazione funzionino sia per i BLOB in blocchi che per i contenitori Archiviazione di Azure. Esistono classi distinte e operazioni del servizio di archiviazione per BLOB e contenitori, non c'è ambiguità se una determinata operazione di archiviazione è correlata a un BLOB o a un contenitore.

Una coppia di classi provider, una per BLOB e l'altra per contenitori, eroga i due set di funzionalità in unità denominate sleeve. Gli sleeve contengono istanze di classi helper di archiviazione che fanno parte di Azure SDK. L'inizializzazione del servizio di archiviazione crea i provider e li rende direttamente disponibili ai metodi del servizio di archiviazione.

Struttura sleeve

Lo sleeve è un contenitore per l'istanza dell'oggetto client SDK e un contesto di archiviazione. Le funzioni del provider di archiviazione fanno riferimento allo sleeve tramite le due proprietà Client e Context. Esiste un tipo di sleeve per BLOB e un altro per contenitori, che hanno rispettivamenteClient proprietà di tipo BlobBaseClient e BlobContainerClient.

La struttura generale degli sleeve per i BLOB è simile alla seguente:

BlobBaseClient Client { get; }
BlobServiceClient Service { get; }
StorageClientProviderContext Context { get; }

La proprietà Service sullo sleeve è una comodità. Alcune delle operazioni finali correlate al codificatore che usano la classe BLOBServiceClient SDK richiedono credenziali dell'account di archiviazione. Questo requisito ha portato all'aggiunta di un'istanza client del servizio ai due tipi di sleeve esistenti, anziché produrre un provider separato.

Utilizzo degli sleeve

I provider di archiviazione client distribuisce le istanze di sleeve. Il codice del servizio di archiviazione è simile alla sequenza di codice con annotazioni seguente, con i tipi evidenziati per maggiore chiarezza:

public bool DeleteBlob(Uri sourceUri, StorageClientProviderContext context)
{
    . . .
    StorageBlobClientSleeve sleeve = _blobBaseClientProvider.GetBlobBaseClientForUri(sourceUri, context); // Line A
    BlobProperties propsIncludingMetadata = sleeve.Client.GetProperties(); // Line B
    sleeve.Context.TrackingETag = true;   // Send ETag from GetProperties()
    var wasDeleted = sleeve.Client.DeleteBlob(); // Line C
    sleeve.Context.TrackingETag = false;
    var someResult = sleeve.Client.AnotherOperation(); // Line D
    . . .
}
  1. Gridwich popola automaticamente il contesto dell'operazione nel contesto dello sleeve alla riga A. TrackingETag è False per impostazione predefinita.
  2. Dopo la riga B, sleeve.Context contiene ETag dalla riga A e mantiene lo stesso valore ClientRequestID.
  3. La riga C invia sia il valore ETag dalla riga B che ClientRequestId.
  4. Dopo la riga C, il contesto ha un nuovo valore ETag, come restituito nella risposta Delete().
  5. La riga D non invia un valore ETag alla richiesta per AnotherOperation().
  6. Dopo la riga D, il contesto ha un nuovo valore ETag, come restituito nella risposta AnotherOperation().

Il servizio di archiviazione è attualmente impostato come Transient nella configurazione di inserimento delle dipendenze, il che implica che la memorizzazione nella cache basata su sleeve è basata su richiesta. Per maggiori informazioni, consultare la sezione Servizio di archiviazione e inserimento dipendenze.

Alternative al servizio di archiviazione

Le sezioni seguenti descrivono approcci alternativi che non fanno parte della soluzione di archiviazione di Gridwich corrente.

Nascondere i criteri della pipeline tramite la sottoclasse

La sottoclasse dei tipi di client SDK aggiunge due proprietà semplici al client, una per ogni valore di intestazione HTTP, per nascondere completamente l'interazione con i criteri della pipeline. Tuttavia, a causa di un bug Moq, non è possibile creare unit test tramite mock per questi tipi derivati. Gridwich usa Moq, quindi non ha usato questo approccio di sottoclasse.

Il bug Moq si riferisce alla gestione errata della sottoclasse tra assembly in presenza di funzioni virtuali con ambito interno. Le classi client SDK usano funzioni virtuali con ambito interno che coinvolgono tipi di ambito interno invisibili ai normali utenti esterni. Quando Moq tenta di creare mock della sottoclasse, che si trova in uno degli assembly Gridwich, non riesce in fase di esecuzione del test perché non riesce a trovare le macchine virtuali con ambito interno nelle classi client dell'SDK da cui derivano le classi Gridwich. Non esiste alcuna soluzione alternativa senza modifiche nella generazione del proxy Moq Castle.

Inserimento di dipendenze e servizio di archiviazione

Gridwich registra attualmente il servizio di archiviazione come servizio di inserimento delle dipendenze Transient. Ovvero, ogni volta che viene richiesto l'inserimento delle dipendenze per il servizio, viene creata una nuova istanza. Il codice corrente dovrebbe funzionare correttamente anche se la registrazione cambia in Scoped, implicando un'istanza per richiesta, ad esempio la richiesta del sistema esterno.

Tuttavia, si verificano problemi se la registrazione cambia in Singleton, un'istanza nell'app per le funzioni Gridwich. Il meccanismo di memorizzazione nella cache Gridwich per sleeve e intervalli di byte di dati non distingue tra richieste diverse. Inoltre, il modello di cache non è un estratto, quindi Gridwich non rimuove l'istanza dalla cache mentre è in uso. Poiché le classi client SDK non sono necessariamente thread-safe, il coordinamento richiederebbe molte modifiche.

Per questi motivi, non modificare il servizio di archiviazione di Gridwich, così come è, alla registrazione dell'inserimento delle dipendenze Singleton. Gridwich segue questa regola nella registrazione dell'inserimento delle dipendenze e include uno unit test, CheckThatStorageServiceIsNotASingleton per applicarla.

Passaggi successivi

Documentazione sui prodotti:

Moduli di Microsoft Learn: