Padrão de Hospedagem de Conteúdo EstáticoStatic Content Hosting pattern

Implante conteúdo estático em um serviço de armazenamento baseado em nuvem que pode enviá-lo diretamente para o cliente.Deploy static content to a cloud-based storage service that can deliver them directly to the client. Isso pode reduzir a necessidade de instâncias de computação potencialmente caras.This can reduce the need for potentially expensive compute instances.

Contexto e problemaContext and problem

Aplicativos Web geralmente incluem alguns elementos de conteúdo estático.Web applications typically include some elements of static content. Este conteúdo estático pode incluir páginas HTML e outros recursos como imagens e documentos que estão disponíveis para o cliente, como parte de uma página HTML (tal como imagens embutidas, folhas de estilo e arquivos JavaScript do lado do cliente) ou como downloads separados (como documentos PDF).This static content might include HTML pages and other resources such as images and documents that are available to the client, either as part of an HTML page (such as inline images, style sheets, and client-side JavaScript files) or as separate downloads (such as PDF documents).

Embora os servidores Web sejam otimizados para renderização dinâmica e cache de saída, eles ainda precisarão lidar com solicitações para fazer o download de conteúdo estático.Although web servers are optimized for dynamic rendering and output caching, they still have to handle requests to download static content. Isso consome ciclos de processamento que muitas vezes poderiam ser melhor usados em outros locais.This consumes processing cycles that could often be put to better use.

SoluçãoSolution

Na maioria dos ambientes de hospedagem em nuvem, você pode colocar alguns dos recursos e páginas estáticas do aplicativo em um serviço de armazenamento.In most cloud hosting environments, you can put some of an application's resources and static pages in a storage service. O serviço de armazenamento pode atender solicitações para esses recursos, reduzindo a carga nos recursos de computação que lidam com outras solicitações da Web.The storage service can serve requests for these resources, reducing load on the compute resources that handle other web requests. O custo do armazenamento hospedado em nuvem normalmente é muito menor que o de instâncias de computação.The cost for cloud-hosted storage is typically much less than for compute instances.

Ao hospedar algumas partes de um aplicativo em um serviço de armazenamento, as principais considerações estão relacionadas à implantação do aplicativo e à proteção de recursos que não devem estar disponíveis para os usuários anônimos.When hosting some parts of an application in a storage service, the main considerations are related to deployment of the application and to securing resources that aren't intended to be available to anonymous users.

Problemas e consideraçõesIssues and considerations

Considere os seguintes pontos ao decidir como implementar esse padrão:Consider the following points when deciding how to implement this pattern:

  • O serviço de armazenamento hospedado deve expor um ponto de extremidade HTTP que os usuários podem acessar para baixar os recursos estáticos.The hosted storage service must expose an HTTP endpoint that users can access to download the static resources. Alguns serviços de armazenamento também dão suporte a HTTPS, portanto, é possível hospedar recursos nos serviços de armazenamento que exigem SSL.Some storage services also support HTTPS, so it's possible to host resources in storage services that require SSL.

  • Para obter o máximo de desempenho e disponibilidade, considere usar uma CDN (rede de distribuição de conteúdo) para armazenar em cache o conteúdo do contêiner de armazenamento em vários datacenters ao redor do mundo.For maximum performance and availability, consider using a content delivery network (CDN) to cache the contents of the storage container in multiple datacenters around the world. No entanto, você provavelmente precisará pagar para usar a CDN.However, you'll likely have to pay for using the CDN.

  • Geralmente, as contas de armazenamento são replicados geograficamente por padrão para oferecer resiliência contra eventos que podem afetar um data center.Storage accounts are often geo-replicated by default to provide resiliency against events that might affect a datacenter. Isso significa que o endereço IP pode mudar, mas a URL permanecerá a mesma.This means that the IP address might change, but the URL will remain the same.

  • Quando parte do conteúdo está localizado em uma conta de armazenamento e outras partes do conteúdo estão em uma instância de computação hospedada, é mais difícil implantar e atualizar o aplicativo.When some content is located in a storage account and other content is in a hosted compute instance, it becomes more challenging to deploy and update the application. Pode ser necessário executar implantações separadas e controlar a versão do aplicativo e do conteúdo para gerenciá-la mais facilmente — especialmente quando o conteúdo estático inclui arquivos de script ou componentes de interface do usuário.You might have to perform separate deployments, and version the application and content to manage it more easily—especially when the static content includes script files or UI components. No entanto, se apenas recursos estáticos devem ser atualizados, eles podem simplesmente ser carregados para a conta de armazenamento sem precisar reimplantar o pacote de aplicativos.However, if only static resources have to be updated, they can simply be uploaded to the storage account without needing to redeploy the application package.

  • Os serviços de armazenamento podem não dar suporte ao uso de nomes de domínio personalizados.Storage services might not support the use of custom domain names. Nesse caso é necessário especificar a URL completa dos recursos nos links porque eles estarão em um domínio diferente do conteúdo gerado dinamicamente que contém os links.In this case it's necessary to specify the full URL of the resources in links because they'll be in a different domain from the dynamically-generated content containing the links.

  • Os contêineres de armazenamento devem ser configurados para acesso de leitura público, mas é essencial garantir que eles não estejam configurados para acesso de gravação público para impedir que os usuários possam carregar o conteúdo.The storage containers must be configured for public read access, but it's vital to ensure that they aren't configured for public write access to prevent users being able to upload content.

  • Considere usar uma chave limitada ou token para controlar o acesso aos recursos que não devem estar disponíveis anonimamente.Consider using a valet key or token to control access to resources that shouldn't be available anonymously. Confira o padrão de Chave Limitada para ver mais informações.See the Valet Key pattern for more information.

Quando usar esse padrãoWhen to use this pattern

Esse padrão é útil para:This pattern is useful for:

  • Minimizar o custo de hospedagem de sites e aplicativos que contêm alguns recursos estáticos.Minimizing the hosting cost for websites and applications that contain some static resources.

  • Minimizar o custo de hospedagem de sites compostos somente por conteúdo e recursos estáticos.Minimizing the hosting cost for websites that consist of only static content and resources. Dependendo das funcionalidades do sistema de armazenamento do provedor de hospedagem, seria possível hospedar inteiramente um site totalmente estático em uma conta de armazenamento.Depending on the capabilities of the hosting provider's storage system, it might be possible to entirely host a fully static website in a storage account.

  • Expor os recursos e conteúdo estático para aplicativos em execução em outros ambientes de hospedagem ou nos servidores locais.Exposing static resources and content for applications running in other hosting environments or on-premises servers.

  • Localizar conteúdo em mais de uma área geográfica usando uma rede de distribuição de conteúdo que armazena em cache o conteúdo da conta de armazenamento em vários datacenters ao redor do mundo.Locating content in more than one geographical area using a content delivery network that caches the contents of the storage account in multiple datacenters around the world.

  • Monitorar os custos e uso de largura de banda.Monitoring costs and bandwidth usage. Usar uma conta de armazenamento separada para parte ou todo o conteúdo estático permite que os custos sejam separados mais facilmente dos custos de hospedagem e de tempo de execução.Using a separate storage account for some or all of the static content allows the costs to be more easily separated from hosting and runtime costs.

Esse padrão pode não ser útil nas seguintes situações:This pattern might not be useful in the following situations:

  • O aplicativo precisa executar processamento no conteúdo estático antes de distribuí-lo para o cliente.The application needs to perform some processing on the static content before delivering it to the client. Por exemplo, pode ser necessário adicionar um carimbo de data/hora a um documento.For example, it might be necessary to add a timestamp to a document.

  • O volume do conteúdo estático é muito pequeno.The volume of static content is very small. A sobrecarga de recuperar o conteúdo do armazenamento separado pode superar o benefício de custo de separá-lo do recurso de computação.The overhead of retrieving this content from separate storage can outweigh the cost benefit of separating it out from the compute resource.

ExemploExample

O Armazenamento do Azure dá suporte ao fornecimento de conteúdo estático diretamente de um contêiner de armazenamento.Azure Storage supports serving static content directly from a storage container. Os arquivos são atendidos por meio de solicitações de acesso anônimo.Files are served through anonymous access requests. Por padrão, os arquivos têm uma URL em um subdomínio core.windows.net, como https://contoso.z4.web.core.windows.net/image.png.By default, files have a URL in a subdomain of core.windows.net, such as https://contoso.z4.web.core.windows.net/image.png. Você pode configurar um nome de domínio personalizado e usar a CDN do Azure para acessar os arquivos por HTTPS.You can configure a custom domain name, and use Azure CDN to access the files over HTTPS. Para mais informações, confira Hospedagem de site estático no Armazenamento do Azure.For more information, see Static website hosting in Azure Storage.

Distribuição de partes estáticas de um aplicativo diretamente de um serviço de armazenamento

A hospedagem de site estático torna os arquivos disponíveis para acesso anônimo.Static website hosting makes the files available for anonymous access. Se precisar controlar quem pode acessar os arquivos, você pode armazenar arquivos no armazenamento de blogs do Azure e, em seguida, gerar assinaturas de acesso compartilhado para limitar o acesso.If you need to control who can access the files, you can store files in Azure blob storage and then generate shared access signatures to limit access.

Os links nas páginas distribuídas para o cliente devem especificar a URL completa do recurso.The links in the pages delivered to the client must specify the full URL of the resource. Se o recurso estiver protegido por uma chave limitada, como uma assinatura de acesso compartilhado do Azure, essa assinatura deverá ser incluída na URL.If the resource is protected with a valet key, such as a shared access signature, this signature must be included in the URL.

Um aplicativo de exemplo que demonstra o uso do armazenamento externo para recursos estáticos está disponível no GitHub.A sample application that demonstrates using external storage for static resources is available on GitHub. Este exemplo usa arquivos de configuração que especificam a conta de armazenamento e o contêiner que retém o conteúdo estático.This sample uses configuration files to specify the storage account and container that holds the static content.

<Setting name="StaticContent.StorageConnectionString"
         value="UseDevelopmentStorage=true" />
<Setting name="StaticContent.Container" value="static-content" />

A classe Settings no arquivo Settings.cs do projeto StaticContentHosting.Web contém métodos para extrair esses valores e criar um valor de cadeia de caracteres que contém a URL de contêiner da conta de armazenamento de nuvem.The Settings class in the file Settings.cs of the StaticContentHosting.Web project contains methods to extract these values and build a string value containing the cloud storage account container URL.

public class Settings
{
  public static string StaticContentStorageConnectionString {
    get
    {
      return RoleEnvironment.GetConfigurationSettingValue(
                              "StaticContent.StorageConnectionString");
    }
  }

  public static string StaticContentContainer
  {
    get
    {
      return RoleEnvironment.GetConfigurationSettingValue("StaticContent.Container");
    }
  }

  public static string StaticContentBaseUrl
  {
    get
    {
      var account = CloudStorageAccount.Parse(StaticContentStorageConnectionString);

      return string.Format("{0}/{1}", account.BlobEndpoint.ToString().TrimEnd('/'),
                                      StaticContentContainer.TrimStart('/'));
    }
  }
}

A classe StaticContentUrlHtmlHelper no arquivo StaticContentUrlHtmlHelper.cs expõe um método chamado StaticContentUrl que gera uma URL que contém o caminho para a conta de armazenamento de nuvem se a URL passada para ele começar com o caractere de caminho raiz do ASP.NET (~).The StaticContentUrlHtmlHelper class in the file StaticContentUrlHtmlHelper.cs exposes a method named StaticContentUrl that generates a URL containing the path to the cloud storage account if the URL passed to it starts with the ASP.NET root path character (~).

public static class StaticContentUrlHtmlHelper
{
  public static string StaticContentUrl(this HtmlHelper helper, string contentPath)
  {
    if (contentPath.StartsWith("~"))
    {
      contentPath = contentPath.Substring(1);
    }

    contentPath = string.Format("{0}/{1}", Settings.StaticContentBaseUrl.TrimEnd('/'),
                                contentPath.TrimStart('/'));

    var url = new UrlHelper(helper.ViewContext.RequestContext);

    return url.Content(contentPath);
  }
}

O arquivo Index.cshtml na pasta Views\Home contém um elemento de imagem que usa o método StaticContentUrl para criar a URL para o seu atributo src.The file Index.cshtml in the Views\Home folder contains an image element that uses the StaticContentUrl method to create the URL for its src attribute.

<img src="@Html.StaticContentUrl("~/media/orderedList1.png")" alt="Test Image" />