Editar

Share via


Operações de Gridwich para o Armazenamento do Azure

Azure Storage

O Serviço de Armazenamento do Azure Gridwich, Gridwich.SagaParticipants.Storage.AzureStorage, fornece operações de blob e contêiner para Contas de Armazenamento do Azure configuradas para Gridwich. Exemplos de operações de armazenamento são Criar blob, Excluir contêiner, Copiar blob ou Alterar camada de armazenamento.

O Gridwich exige que seus mecanismos de armazenamento funcionem para blobs e contêineres de bloco de Armazenamento do Azure. Com classes e operações de Serviço de Armazenamento distintas para blobs e contêineres, não há ambiguidade sobre se uma determinada operação de armazenamento está relacionada a um blob ou a um contêiner. Este artigo aplica-se a blobs e contêineres, exceto onde indicado.

Gridwich expõe a maioria das operações de armazenamento a sistemas externos dentro do participante da Storage.AzureStoragesaga. Outros participantes da saga usam o serviço de armazenamento para tarefas como copiar blobs entre diferentes contêineres ou contas quando configuram fluxos de trabalho de codificação.

Este artigo descreve como o Serviço de Armazenamento do Azure Gridwich atende aos requisitos da solução e se integra a mecanismos como manipuladores de eventos. Os links apontam para o código-fonte correspondente, que contém comentários mais extensos sobre os contêineres, classes e mecanismos.

SDK de Armazenamento do Azure

Gridwich usa classes do SDK de Armazenamento do Azure para interagir com o Armazenamento do Azure, em vez de criar manualmente solicitações REST. Dentro do provedor de armazenamento, as classes SDK BlobBaseClient e BlobContainerClient gerenciam solicitações de armazenamento.

Essas classes de cliente SDK atualmente permitem apenas acesso indireto aos dois cabeçalhos HTTP que Gridwich precisa manipular, x-ms-client-request-id para contexto de operação e ETag para versão do objeto.

Em Gridwich, um par de classes de provedor dispensa a funcionalidade BlobBaseClientProvider e BlobContainerClientProvider em unidades chamadas sleeves. Para obter detalhes sobre mangas, consulte Mangas de armazenamento.

O diagrama a seguir ilustra a estrutura das classes SDK e Gridwich e como as instâncias se relacionam entre si. As setas indicam "tem uma referência a".

Diagram showing client object instance relationships between the Storage SDK classes.

Política de gasodutos

Você define o gancho para manipular os cabeçalhos HTTP como uma instância de política de pipeline ao criar a instância do cliente. Você pode definir essa política somente no momento da criação da instância do cliente e não pode alterá-la. O código do provedor de armazenamento usando o cliente deve ser capaz de manipular os valores de cabeçalho durante a execução. O desafio é fazer com que o provedor de armazenamento e o pipeline interajam de forma limpa.

Para a política de pipeline de Gridwich, consulte a classe BlobClientPipelinePolicy .

Cache do Serviço de Armazenamento

O estabelecimento da conexão TCP e a autenticação criam sobrecarga quando uma instância de objeto cliente SDK envia sua primeira solicitação ao Armazenamento do Azure. Várias chamadas para o mesmo blob em uma solicitação de sistema externo, por exemplo , Obter metadados e, em seguida , Excluir blob, compõem a sobrecarga.

Para reduzir a sobrecarga, o Gridwich mantém um cache de uma instância de cliente para cada blob ou contêiner de armazenamento, dependendo das classes SDK usadas pelo contexto da operação. Gridwich retém essa instância de cliente e pode usá-la para várias operações de Armazenamento do Azure no mesmo blob ou contêiner durante uma solicitação de sistema externo.

As classes de cliente fornecidas pelo SDK do Azure exigem que as instâncias de objeto do cliente SDK sejam específicas de um único blob ou contêiner no momento da criação. As instâncias também não são garantidas seguras para uso simultâneo em threads diferentes. Como um contexto de operação representa uma única solicitação, o Gridwich baseia o cache na combinação de blob ou nome de contêiner com contexto de operação.

Essa reutilização de instância, combinada com a estrutura de cliente do SDK de Armazenamento do Azure, requer código de suporte adicional para equilibrar a eficiência e a clareza do código.

Argumento de contexto

Quase todas as operações do Gridwich Storage Service exigem um argumento de contexto especial do tipo StorageClientProviderContext. Este argumento de contexto preenche os seguintes requisitos:

  • Fornece ao sistema externo respostas, que incluem o valor de contexto de operação baseado em JSON exclusivo por solicitação que o sistema externo especificou na solicitação de Gridwich. Para obter mais informações, consulte Contexto da operação.

  • Permite que chamadores do Serviço de Armazenamento, como manipuladores de eventos Gridwich, controlem quais respostas são visíveis para o sistema externo. Esse controle impede que o serviço inunde o sistema externo com eventos de notificação irrelevantes. Para obter mais informações, consulte Silenciamento de contexto.

  • Está em conformidade com as convenções de Armazenamento do Azure para garantir solicitações e respostas coerentes em um ambiente que permite uma combinação de leitores e gravadores paralelos. Por exemplo, suporta rastreamento ETag. Para obter mais informações, consulte ETags.

Contexto de armazenamento

O contexto para os tipos de armazenamento de blob e contêiner é o StorageClientProviderContext, que se parece com:

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

As duas primeiras propriedades são representações diferentes do contexto de operação que foi usado para inicializar a instância StorageClientProviderContext . A classe tem vários construtores, incluindo um construtor copy. Os métodos adicionais incluem ResetTo, para permitir a duplicação de estado in-loco e um método estático CreateSafe para garantir que inicializações problemáticas não gerem exceções.

A classe também contém manipulação especial para criar contextos com base em GUIDs e cadeias de caracteres vazias. Os manipuladores de Notificação de Armazenamento do Azure para blob Criado e Excluído, que também processam notificações decorrentes de agentes externos, exigem o formulário GUID.

Silenciamento de contexto

A IsMuted propriedade controla se o aplicativo espera que o serviço publique as notificações resultantes de volta para o chamador, por exemplo, para o sistema externo. Em uma operação silenciada, o serviço não publica os eventos resultantes.

Um exemplo são as cópias de blob que um codificador executa para organizar blobs no Armazenamento do Azure como entrada para uma tarefa de codificação. O sistema externo não está preocupado com esses detalhes, mas apenas com o status do trabalho de codificação e onde ele pode recuperar as saídas codificadas. Para refletir essas preocupações, o codificador:

  1. Cria um contexto de armazenamento não silenciado com base no contexto da operação de solicitação, por exemplo ctxNotMuted.

  2. Cria um contexto de armazenamento silenciado, por exemploctxMuted, usando o construtor de cópia de classe de contexto ou criando uma nova instância. Qualquer uma das opções terá o mesmo valor de contexto de operação.

  3. Especifica ctxMuted as operações de armazenamento envolvidas na configuração para codificação. O sistema externo não vê qualquer indicação de que essas operações estejam ocorrendo.

  4. Especifica o contexto para operações de armazenamento que refletem a ctxNotMuted conclusão da codificação, por exemplo, copiar um arquivo de saída para um contêiner de destino. Os manipuladores de Gridwich publicam os eventos de notificação do Armazenamento do Azure resultantes no sistema externo.

O chamador controla a visibilidade final das operações. As operações silenciadas e não silenciadas baseiam-se num valor equivalente operationContext . A intenção do silenciamento de contexto é facilitar a execução do diagnóstico de problemas a partir de logs de rastreamento de eventos, pois é possível ver as operações de armazenamento relacionadas a uma solicitação, independentemente do status de silenciamento da operação.

O ResponseBaseDTO tem uma propriedade DoNotPublishbooleana , que o despacho de eventos usa para ditar a decisão final sobre a publicação. O envio de eventos, por sua vez, define a DoNotPublish propriedade com base na IsMuted propriedade do contexto.

O serviço transmite a configuração de silenciamento para o Armazenamento do Azure, que define os clientRequestId eventos de notificação de armazenamento apresentados aos dois manipuladores de Gridwich, Criado e Excluído. Esses dois manipuladores são definidos DoNotPublish para refletir o silenciamento solicitado pelo chamador.

ETags para consistência de alvos

O Armazenamento do Azure usa o cabeçalho HTTP ETag para sequências de solicitação que devem ter consistência de destino. Um exemplo é garantir que um blob não tenha sido alterado entre as operações de armazenamento Recuperar Metadados e Atualizar Metadados .

Para alinhar com o uso HTTP padrão, esse cabeçalho tem um valor opaco cuja interpretação é que, se o valor do cabeçalho mudar, o objeto subjacente também foi alterado. Se uma solicitação enviar seu valor atual para o objeto e não corresponder ao valor atual ETag do Serviço de Armazenamento ETag , a solicitação falhará imediatamente. Se a solicitação não incluir um ETag valor, o Armazenamento do Azure ignorará essa verificação e não bloqueará a solicitação.

ETags no serviço de armazenamento

Para Gridwich, o é um detalhe interno entre o Serviço de Armazenamento de Gridwich e o ETag Armazenamento do Azure. Nenhum outro código precisa estar ciente do ETag. O Serviço de Armazenamento usa as sequências for, como as ETag operações Obter Metadados de Blob, Excluir Blob para processar uma BlobDelete Event solicitação. O uso do garante que a operação Excluir Blob tenha como alvo exatamente a mesma versão do ETag blob que a operação Obter Metadados.

Para usar o ETag exemplo anterior:

  1. Envie a solicitação Obter metadados com um arquivo em branco ETag.
  2. Salve o ETag valor da resposta.
  3. Adicione o valor salvo ETag à solicitação Excluir Blob .

Se os dois ETag valores forem diferentes, a operação de exclusão falhará. A falha implica que alguma outra operação alterou o blob entre as etapas 2 e 3. Repita o processo da etapa 1.

ETag é um parâmetro de construtores e uma propriedade string da classe StorageClientProviderContext. Somente o BlobClientPipelinePolicy específico de Gridwich manipula o ETag valor.

Controlar o uso do ETag

A TrackingETag propriedade controla se o ETag valor deve ser enviado na próxima solicitação. O valor true significa que o serviço envia um ETag se estiver disponível.

Uma solicitação de Armazenamento do Azure com um ETag valor que não corresponde ao blob ou contêiner de assunto resulta na falha da operação. Essa falha é por design, porque ETag é a maneira HTTP padrão de expressar "a versão exata que a solicitação está direcionando". As solicitações podem incluir a propriedade para declarar que a deve corresponder ou não incluir a TrackingETagETagsTrackingETag propriedade para indicar que os ETag valores não importam.

O pipeline sempre recupera um valor de uma operação de Armazenamento do Azure se houver um ETag presente nessa resposta REST. O pipeline sempre atualiza a ETag propriedade context, se possível, a partir da última operação. O TrackingETag sinalizador controla apenas se a próxima solicitação da mesma instância do cliente envia o valor da ETag propriedade. Se o ETag valor for nulo ou vazio, a solicitação atual não definirá nenhum valor HTTP ETag , independentemente do valor de TrackingETag.

Mangas de arrumação

Gridwich exige que seus mecanismos de armazenamento funcionem para blobs de bloco e contêineres do Armazenamento do Azure. Há classes e operações de Serviço de Armazenamento distintas para blobs e contêineres, portanto, não há ambiguidade sobre se uma determinada operação de armazenamento está relacionada a um blob ou a um contêiner.

Um par de classes de provedor, uma para blobs e outra para contêineres, dispensam os dois conjuntos de funcionalidade em unidades chamadas mangas. As mangas contêm instâncias de classes auxiliares de armazenamento que fazem parte do SDK do Azure. A inicialização do Serviço de Armazenamento cria os provedores e os disponibiliza diretamente para os métodos do Serviço de Armazenamento.

Estrutura da manga

A manga é um contêiner para a instância do objeto SDK Client e um contexto de armazenamento. As funções do provedor de armazenamento fazem referência à manga por meio das duas propriedades Client e Context. Há um tipo de manga para blobs e outro para contêineres, que têm Client propriedades de tipo BlobBaseCliente BlobContainerClient, respectivamente.

A estrutura geral da manga para bolhas tem a seguinte aparência:

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

A Service propriedade na manga é uma conveniência. Algumas das operações finais relacionadas ao codificador que usam a classe SDK BlobServiceClient exigem chaves de Conta de Armazenamento. Esse requisito levou à adição de uma instância de cliente de serviço aos dois tipos de manga existentes, em vez de produzir um provedor separado.

Utilização da manga

Os provedores de armazenamento do cliente dispensam instâncias de manga. O código do serviço de armazenamento é semelhante à seguinte sequência de código anotada, com tipos escritos para maior clareza:

    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. O Gridwich preenche automaticamente o contexto da operação no contexto da manga na linha A. TrackingETag o padrão é false.
  2. Após a linha B, sleeve.Context contém a ETag linha A e mantém o mesmo ClientRequestID valor.
  3. A Linha C envia o ETag valor da Linha B e do ClientRequestId.
  4. Após a Linha C, o contexto tem um novo ETag valor, conforme retornado na Delete() resposta.
  5. A linha D não envia um ETag valor na solicitação de AnotherOperation().
  6. Após a Linha D, o contexto tem um novo ETag valor, conforme retornado na AnotherOperation() resposta.

O Serviço de Armazenamento está atualmente definido como Transient na configuração de injeção de dependência, o que implica que o cache baseado em manga é por solicitação. Consulte Serviço de armazenamento e injeção de dependência para obter mais informações.

Alternativas ao serviço de armazenamento

As seções a seguir descrevem abordagens alternativas que não fazem parte da solução de armazenamento Gridwich atual.

Gridwich AzureStorageManagement classe

Em conjunto com o membro sleeveService, que é uma instância da classe BlobServiceClient do SDK do Azure, Gridwich também tem a classe AzureStorageManagement. O método do Serviço de Armazenamento e o método da GetStoreByNameAsync codificação Telerek usam essa classe para obter chaves de conta de GetConnectionStringForAccount armazenamento. A classe é atualmente baseada na estrutura Fluent. Adições à classe SDK BlobServiceClient devem eventualmente substituir essa classe, permitindo uma recuperação de informações mais focada do que a grande variedade na interface Fluent IAzure.

Ocultar a política de pipeline por meio de subclassificação

A subclassificação dos tipos de cliente SDK adiciona duas propriedades simples ao cliente, uma para cada valor de cabeçalho HTTP, para ocultar completamente a interação com a política de pipeline. Mas por causa de um bug profundo do Moq , não é possível criar testes de unidade via mock para esses tipos derivados. Gridwich usa Moq, então não usou essa abordagem de subclassificação.

O bug do Moq está relacionado ao seu manuseio incorreto da subclassificação entre montagens na presença de funções virtuais de escopo interno. As classes de cliente SDK fazem uso de funções virtuais de escopo interno envolvendo tipos de escopo interno que são invisíveis para usuários externos normais. Quando o Moq tenta criar um da subclasse, que está em um mock dos assemblies Gridwich, ele falha no tempo de execução do teste, pois não consegue encontrar os virtuais de escopo interno nas classes de cliente SDK das quais as classes Gridwich são derivadas. Não há solução alternativa sem alterações na geração de proxy do Moq Castle.

Serviço de armazenamento e injeção de dependência

Atualmente, Gridwich registra o Serviço de Armazenamento como um Transient serviço de injeção de dependência. Ou seja, cada vez que a injeção de dependência é solicitada para o serviço, ela cria uma nova instância. O código atual também deve funcionar corretamente se o registro mudar para Scoped, implicando uma instância por solicitação, por exemplo, a solicitação do sistema externo.

No entanto, haverá problemas se o registro mudar para Singleton, uma instância no aplicativo Função Gridwich. O mecanismo de cache de Gridwich para mangas e intervalos de bytes de dados não fará distinção entre solicitações diferentes. Além disso, o modelo de cache não é de check-out, portanto, o Gridwich não remove a instância do cache enquanto ela estiver em uso. Como não é garantido que as classes de cliente SDK sejam thread-safe, a coordenação exigiria muitas alterações.

Por esses motivos, não altere o Gridwich Storage Service, como está, para Singleton o registro de injeção de dependência. Gridwich segue essa regra no registro de injeção de dependência e inclui um teste de unidade, CheckThatStorageServiceIsNotASingleton, para impô-la.

Próximos passos

Documentação do produto:

Módulos do Microsoft Learn: