Personalizar cadeias de conexão usando manifestos do .NET Aspire

Concluído

Ferramentas de implantação como o Visual Studio ou o Azure Developer CLI criam arquivos de manifesto que descrevem o conteúdo de uma solução do .NET Aspire. Se você quiser personalizar sua implantação, poderá fazer alterações diretamente no arquivo de manifesto.

Em seu varejista de equipamentos ao ar livre, você decidiu usar uma instância existente do Cache do Azure para Redis para hospedar o cache de saída do microsserviço do aplicativo Web. Você deseja garantir que o serviço de aplicativo Web se conecte à instância correta do Cache do Azure para Redis.

Nesta unidade, você aprenderá a alterar cadeias de conexão para serviços de backup no arquivo de manifesto do .NET Aspire.

Gerar um arquivo de manifesto usando a CLI do .NET

Durante o desenvolvimento local e a depuração, o .NET Aspire não cria um arquivo de manifesto. Quando se trata de implantação, o .NET deve descrever o conteúdo da solução .NET Aspire, incluindo seus microsserviços, serviços de backup e configuração. O arquivo de manifesto atende a essa finalidade. Ele descreve a solução no formato JSON.

Para criar o arquivo de manifesto, o Visual Studio e o Azure Developer CLI executam um comando run da CLI do .NET com um destino específico. Você pode executar manualmente o mesmo comando para criar seu próprio arquivo de manifesto como este:

dotnet run --project eShop.AppHost\eShop.AppHost.csproj `
    --publisher manifest `
    --output-path ../aspire-manifest.json

Observação

Especifique o projeto de host de aplicativo com a opção --project.

Esse comando gera uma saída semelhante a este texto:

Building...
info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 8.0.1+a6e341ebbf956bbcec0dda304109815fcbae70c9
info: Aspire.Hosting.Publishing.ManifestPublisher[0]
      Published manifest to: C:\repos\eShop\aspire-manifest.json

Você também pode usar um perfil de inicialização para executar o comando dotnet. Um perfil de inicialização é um grupo de configurações que configura um projeto .NET quando ele é executado. Por exemplo, o modelo .NET Aspire Starter cria estes perfis de inicialização:

"profiles": {
  "https": {
    "commandName": "Project",
    "dotnetRunMessages": true,
    "launchBrowser": true,
    "applicationUrl": "https://localhost:17170;http://localhost:15281",
    "environmentVariables": {
      "ASPNETCORE_ENVIRONMENT": "Development",
      "DOTNET_ENVIRONMENT": "Development",
      "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21147",
      "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22239"
    }
  },
  "http": {
    "commandName": "Project",
    "dotnetRunMessages": true,
    "launchBrowser": true,
    "applicationUrl": "http://localhost:15281",
    "environmentVariables": {
      "ASPNETCORE_ENVIRONMENT": "Development",
      "DOTNET_ENVIRONMENT": "Development",
      "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19197",
      "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20233"
    }
  }
}

Adicione um perfil de inicialização para criar um arquivo de manifesto com código JSON semelhante a este texto:

"profiles": {
  "generate-manifest": {
    "commandName": "Project",
    "launchBrowser": false,
    "dotnetRunMessages": true,
    "commandLineArgs": "--publisher manifest --output-path aspire-manifest.json"
  }
}

No Visual Studio, você pode escolher o perfil generate-manifest ao iniciar a depuração. Na linha de comando, use a opção --launch-profile:

dotnet run --launch-profile generate-manifest

Formato do arquivo de manifesto

O manifesto é um arquivo JSON com um único elemento de nível superior chamado resources. Dentro desse objeto, você encontra um objeto para cada microsserviço e serviço de backup. Para cada um desses objetos, as configurações incluem cadeias de conexão, variáveis de ambiente e nomes de imagem de contêiner.

Aqui está um manifesto de exemplo para o modelo .NET Aspire Starter sem modificações. A solução usa um Cache Redis:

{
  "resources": {
    "cache": {
      "type": "container.v0",
      "connectionString": "{cache.bindings.tcp.host}:{cache.bindings.tcp.port}",
      "image": "docker.io/library/redis:7.2",
      "bindings": {
        "tcp": {
          "scheme": "tcp",
          "protocol": "tcp",
          "transport": "tcp",
          "targetPort": 6379
        }
      }
    },
    "apiservice": {
      "type": "project.v0",
      "path": "AspireStarter.ApiService/AspireStarter.ApiService.csproj",
      "env": {
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
        "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true"
      },
      "bindings": {
        "http": {
          "scheme": "http",
          "protocol": "tcp",
          "transport": "http"
        },
        "https": {
          "scheme": "https",
          "protocol": "tcp",
          "transport": "http"
        }
      }
    },
    "webfrontend": {
      "type": "project.v0",
      "path": "AspireStarter.Web/AspireStarter.Web.csproj",
      "env": {
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
        "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
        "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true",
        "ConnectionStrings__cache": "{cache.connectionString}",
        "services__apiservice__http__0": "{apiservice.bindings.http.url}",
        "services__apiservice__https__0": "{apiservice.bindings.https.url}"
      },
      "bindings": {
        "http": {
          "scheme": "http",
          "protocol": "tcp",
          "transport": "http",
          "external": true
        },
        "https": {
          "scheme": "https",
          "protocol": "tcp",
          "transport": "http",
          "external": true
        }
      }
    }
  }
}

Cadeias de conexão e referências de associação

No exemplo de manifesto, há três recursos:

  • webfrontend: Esse recurso é o microsserviço que apresenta uma interface da Web para os clientes.
  • apiservice: Esse recurso é a API REST que o webfrontend chama. No modelo, essa chamada é para obter dados meteorológicos.
  • cache: Esse recurso é o cache Redis, usado para otimizar o desempenho do microsserviço webfrontend.

Observe que cada um dos três recursos inclui uma seção bindings que especifica os protocolos que você pode usar para se conectar a esse recurso.

No arquivo Program.cs do host do aplicativo, o projeto webfrontend depende do cache e do apiservice:

var cache = builder.AddRedis("cache");

var apiService = builder.AddProject<Projects.AspireStarter_ApiService>("apiservice");

builder.AddProject<Projects.AspireStarter_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WithReference(apiService);

No arquivo de manifesto, essas dependências são expressas como variáveis de ambiente:

"env": {
  "ConnectionStrings__cache": "{cache.connectionString}",
  "services__apiservice__http__0": "{apiservice.bindings.http.url}",
  "services__apiservice__https__0": "{apiservice.bindings.https.url}"
}

Diagrama mostrando como as dependências em um projeto do .NET Aspire geram referências em um arquivo de manifesto.

As dependências usam cadeias de caracteres de espaço reservado que fazem referência à estrutura do arquivo de manifesto. Por exemplo, a terceira dependência faz referência à associação HTTPS do serviço de API:

Diagrama mostrando como os espaços reservados são construídos em um arquivo de manifesto do .NET Aspire.

Saiba mais