Migrar aplicativos Tomcat para Aplicativos de Contêiner do Azure

Este guia descreve o que você deve estar ciente quando deseja migrar um aplicativo Tomcat existente para ser executado em Aplicativos de Contêiner do Azure (ACA).

Pré-migração

Para garantir uma migração bem-sucedida, antes de começar, conclua as etapas de avaliação e inventário descritas nas seções a seguir.

Inventariar os recursos externos

Os recursos externos, como origens de dados, mediadores de mensagens JMS, entre outros, são injetados através de Java Naming and Directory Interface (JNDI). Alguns desses recursos podem precisar de migração ou reconfiguração.

Na aplicação

Inspecione o ficheiro META-INF/context.xml. Procure elementos <Resource> dentro do elemento <Context>.

No servidor ou servidores da aplicação

Inspecione os ficheiros $CATALINA_BASE/conf/context.xml e $CATALINA_BASE/conf/server.xml, bem como os ficheiros .xml e localizados nos diretórios $CATALINA_BASE/conf/[engine-name]/[host-name].

Nos ficheiros context.xml, os recursos JNDI serão descritos pelos elementos <Resource> dentro do elemento <Context> de nível superior.

Nos ficheiros server.xml, os recursos JNDI serão descritos pelos elementos <Resource> dentro do elemento <GlobalNamingResources>.

Origens de Dados

Origens de dados e recursos JNDI com o atributo type definido como javax.sql.DataSource. Documente a seguinte informação de cada origem de dados:

  • Qual é o nome da origem de dados?
  • Qual é a configuração do conjunto de ligações?
  • Onde posso obter o ficheiro JAR do controlador JDBC?

Para obter mais informações, veja o MANUAL DE INSTRUÇÕES da Origem de Dados do JNDI na documentação do Tomcat.

Todos os outros recursos externos

Não é exequível documentar todas as dependências externas possíveis neste guia. Cabe à sua equipa verificar que pode satisfazer todas as dependências externas da sua aplicação após a migração.

Inventariar segredos

Palavras-passe e cadeias protegidas

Procure cadeias de segredos e palavras-passe nas propriedades e nos ficheiros de configuração do servidor ou servidores de produção. Não se esqueça de verificar server.xml e context.xml em $CATALINA_BASE/conf. Também poderá encontrar ficheiros de configuração com palavras-passe ou credenciais dentro da aplicação. Esses ficheiros podem incluir META-INF/context.xml e, para aplicações Spring Boot, application.properties ou application.yml.

Determinar se e como é que o sistema de ficheiros é utilizado

Qualquer utilização do sistema de ficheiros no servidor de aplicações irá exigir uma reconfiguração ou, em casos raros, alterações da arquitetura. Poderá identificar alguns ou todos os cenários seguintes.

Conteúdo estático só de leitura

Se a sua aplicação servir conteúdo estático atualmente, precisa de uma localização alternativa para o mesmo. Pode considerar mover o conteúdo estático para o Armazenamento de Blobs do Azure e adicionar a CDN do Azure para obter transferências super-rápidas a nível global. Para obter mais informações, consulte Hospedagem de site estático no Armazenamento do Azure e Guia de início rápido: integrar uma conta de armazenamento do Azure com a CDN do Azure. Você também pode implantar diretamente o conteúdo estático em um aplicativo no plano do Azure Spring Apps Enterprise. Para obter mais informações, consulte Implantar arquivos estáticos da Web.

Conteúdo estático publicado dinamicamente

Se a sua aplicação permitir conteúdo estático carregado/produzido pela mesma, mas que é imutável após a criação, pode utilizar o Armazenamento de Blobs do Azure e a CDN do Azure conforme descrito acima, com uma função das Funções do Azure que lide com os carregamentos e as atualizações da CDN. Disponibilizamos uma implementação de exemplo que pode utilizar, em Uploading and CDN-preloading static content with Azure Functions (Carregamento e pré-carregamento da CDN de conteúdo estático com as Funções do Azure). Você também pode implantar diretamente o conteúdo estático em um aplicativo no plano do Azure Spring Apps Enterprise. Para obter mais informações, consulte Implantar arquivos estáticos da Web.

Identificar o mecanismo de persistência de sessão

Para identificar o gestor de persistência de sessão que está a ser utilizado, inspecione os ficheiros context.xml que se encontram na sua aplicação e a configuração do Tomcat. Procure o elemento <Manager> e, em seguida, veja o valor do atributo className.

As implementações integradas do Tomcat PersistentManager, como StandardManager ou FileStore, não foram projetadas para uso com uma plataforma distribuída e dimensionada, como o ACA. O ACA pode balancear a carga entre várias instâncias e reiniciar qualquer instância de forma transparente a qualquer momento, portanto, não é recomendável persistir o estado mutável em um sistema de arquivos.

Se a persistência da sessão for necessária, você precisará usar uma implementação alternativa PersistentManager que gravará em um armazenamento de dados externo, como o VMware Tanzu Session Manager com Cache Redis.

Casos especiais

Certos cenários de produção podem exigir mais alterações ou impor mais limitações. Embora esses cenários possam ser pouco frequentes, é importante garantir que eles sejam inaplicáveis ao seu aplicativo ou resolvidos corretamente.

Determinar se a aplicação depende de tarefas agendadas

As tarefas agendadas, tais como tarefas do Quartz Scheduler ou do Cron, não podem ser utilizadas com implementações Tomcat em contentor. Se a sua aplicação estiver ampliada, uma tarefa agendada pode ser executada mais de uma vez por período agendado. Esta situação pode provocar consequências não intencionais.

Faça o inventário de todas as tarefas agendadas, dentro ou fora do servidor de aplicações.

Determinar se a aplicação contem código de SO específico

Se a sua aplicação contiver código com dependências no SO anfitrião, terá de a refatorizar para remover essas dependências. Por exemplo, poderá ter de substituir qualquer utilização de / ou \ em caminhos do sistema de ficheiros por File.Separator ou Paths.get.

Determinar se o MemoryRealm está a ser utilizado

O MemoryRealm necessita de um ficheiro XML persistente. No ACA, você precisará adicionar esse arquivo à imagem do contêiner ou carregá-lo no armazenamento compartilhado disponibilizado para contêineres. (Para mais informações, consulte o Identificar a seção do mecanismo de persistência da sessão.) O pathName parâmetro terá de ser modificado em conformidade.

Para determinar se o MemoryRealm está a ser utilizado atualmente, inspecione os seus ficheiros server.xml e context.xml e procure elementos <Realm> nos quais o atributo className está definido como org.apache.catalina.realm.MemoryRealm.

Testes no local

Antes de criar imagens de contêiner, migre seu aplicativo para o JDK e o Tomcat que você pretende usar no ACA. Teste a sua aplicação de forma minuciosa para garantir a compatibilidade e o desempenho.

Parametrizar a configuração

É provável que na fase de pré-migração tenha identificado segredos e dependências externas, tais como origens de dados, nos ficheiros server.xml e context.xml. Para cada item identificado como tal, substitua todos os nomes de utilizador, palavras-passe, cadeias de ligação ou URLs por uma variável de ambiente.

Por exemplo, imagine que o ficheiro context.xml contém o seguinte elemento:

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="jdbc:postgresql://postgresdb.contoso.com/wickedsecret?ssl=true"
    driverClassName="org.postgresql.Driver"
    username="postgres"
    password="t00secure2gue$$"
/>

Neste caso, pode mudá-lo conforme mostrado no seguinte exemplo:

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="${postgresdb.connectionString}"
    driverClassName="org.postgresql.Driver"
    username="${postgresdb.username}"
    password="${postgresdb.password}"
/>

Migração

Nota

Algumas implementações do Tomcat poderão ter múltiplas aplicações em execução num único servidor Tomcat. Se for este o caso na sua implementação, recomendamos vivamente que execute cada aplicação num pod separado. Isto permite-lhe otimizar a utilização de recursos para cada aplicação e, ao mesmo tempo, minimizar a complexidade e o acoplamento.

Preparar os artefactos de implementação

Clone o repositório Tomcat on Containers Quickstart GitHub. Este repositório contém um Dockerfile e arquivos de configuração Tomcat com muitas otimizações recomendadas. Nas etapas abaixo, descrevemos as modificações que você provavelmente precisará fazer nesses arquivos antes de criar a imagem de contêiner e implantar no ACA.

Adicionar recursos JNDI

Editar servidor.xml para adicionar os recursos que você preparou nas etapas de pré-migração, como Fontes de Dados, conforme mostrado no exemplo a seguir:

<!-- Global JNDI resources
      Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml"
               />

    <!-- Migrated datasources here: -->
    <Resource
        name="jdbc/dbconnection"
        type="javax.sql.DataSource"
        url="${postgresdb.connectionString}"
        driverClassName="org.postgresql.Driver"
        username="${postgresdb.username}"
        password="${postgresdb.password}"
    />
    <!-- End of migrated datasources -->
</GlobalNamingResources>

Para obter instruções adicionais da origem de dados, veja as seguintes secções do Manual de Instruções da Origem de Dados do JNDI na documentação do Tomcat:

Criar e emitir a imagem

A maneira mais simples de criar e carregar a imagem no Azure Container Registry (ACR) para uso pelo ACA é usar o az acr build comando. Este comando não exige que o Docker esteja instalado no teu computador. Por exemplo, se você tiver o Dockerfile do repositório tomcat-container-quickstart e o pacote de aplicativos petclinic.war no diretório atual, poderá criar a imagem do contêiner no ACR com o seguinte comando:

az acr build \
    --registry $acrName \
    --image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" 
    --build-arg APP_FILE=petclinic.war \
    --build-arg SERVER_XML=prod.server.xml .

Pode omitir o parâmetro --build-arg APP_FILE... se o seu ficheiro WAR se chamar ROOT.war. Pode omitir o parâmetro --build-arg SERVER_XML... se o seu ficheiro XML de servidor se chamar server.xml. Estes dois ficheiros têm de estar no mesmo diretório do Dockerfile.

Como alternativa, você pode usar a CLI do Docker para criar a imagem localmente usando os comandos a seguir. Esta abordagem pode simplificar os testes e refinar a imagem antes da implementação inicial no ACR. No entanto, exige que a CLI do Docker esteja instalada e que o daemon do Docker esteja em execução.

# Build the image locally.
sudo docker build . --build-arg APP_FILE=petclinic.war -t "${acrName}.azurecr.io/petclinic:1"

# Run the image locally.
sudo docker run -d -p 8080:8080 "${acrName}.azurecr.io/petclinic:1"

# You can now access your application with a browser at http://localhost:8080.

# Sign in to ACR.
sudo az acr login --name $acrName

# Push the image to ACR.
sudo docker push "${acrName}.azurecr.io/petclinic:1"

Para obter mais informações, consulte Criar e armazenar imagens de contêiner com o Registro de Contêiner do Azure.

Implantar em aplicativos de contêiner do Azure

O comando a seguir mostra um exemplo de implantação:

az containerapp create \
    --resource-group <RESOURCE_GROUP> \
    --name <APP_NAME> \
    --environment <ENVIRONMENT_NAME> \
    --image <IMAGE_NAME> \
    --target-port 8080 \
    --ingress 'external' \
    --registry-server <REGISTRY_SERVER> \
    --min-replicas 1

Para obter um início rápido mais detalhado, consulte Guia de início rápido: implantar seu primeiro aplicativo de contêiner.

Pós-migração

Agora que você migrou seu aplicativo para o ACA, verifique se ele funciona como esperado. Posto isto, temos algumas recomendações que podem tornar a sua aplicação mais nativa da nuvem.

Recomendações

  • Crie e implemente uma estratégia de continuidade de negócio e recuperação após desastre. Caso a aplicação seja crítica para a missão, considere uma arquitetura de implementação multirregiões. Para obter mais informações, consulte Práticas recomendadas para continuidade de negócios e recuperação de desastres no Serviço Kubernetes do Azure (AKS).

  • Avalie os itens que se encontram no ficheiro logging.properties. Considere eliminar ou reduzir parte das saídas de registo para melhorar o desempenho.

  • Considere monitorar o tamanho do cache de código e adicionar os parâmetros -XX:InitialCodeCacheSize e -XX:ReservedCodeCacheSize a JAVA_OPTS variável no Dockerfile para otimizar ainda mais o desempenho. Para obter mais informações, veja Codecache Tuning (Otimização de Codecache), na documentação da Oracle.

  • Considere adicionar regras de alerta e grupos de ação do Azure Monitor para detetar e resolver rapidamente condições aberrantes.

  • Considere replicar a implantação dos Aplicativos de Contêiner do Azure em outra região para obter menor latência e maior confiabilidade e tolerância a falhas. Use o Gerenciador de Tráfego do Azure para balancear a carga entre implantações ou use o Azure Front Door para adicionar descarregamento SSL e Firewall de Aplicativo Web com proteção contra DDoS.

  • Se a replicação geográfica não for necessária, considere adicionar um Gateway de Aplicativo do Azure para adicionar descarregamento SSL e Firewall de Aplicativo Web com proteção contra DDoS.