Migre seu aplicativo Linux para a nuvem Amazon, Parte 3: Construindo Escalabilidade

Entregar mais tráfego com facilidade

Se você acompanhou a série até este ponto, nosso aplicativo Linux® de amostra foi migrado para a nuvem e configuramos alguns recursos de confiabilidade básicos. Neste artigo, o terceiro da série sobre migração de um aplicativo para a nuvem Amazon, é o momento de aproveitar a natureza dinâmica da nuvem fazendo crescer e reduzindo a infraestrutura em resposta à carga e empurrar alguns dos recursos estáticos para a borda da nuvem.

Sean A. Walberg, Senior Network Engineer

Photo of Sean WalbergSean Walberg trabalha com Linux e UNIX desde 1994 em ambientes acadêmicos, corporativos e de provedores de serviço de Internet. Escreveu muito sobre administração de sistemas nos últimos anos. É possível entrar em contato com ele pelo e-mail sean@ertw.com.



05/Nov/2010

Parte 1 desta série começou observando uma oferta software como serviço chamada SmallPayroll.ca. O aplicativo foi escolhido e movido para o Amazon Elastic Compute Cloud (Amazon EC2). Depois, na A Parte 2, o aplicativo foi tornado mais robusto com a inclusão de redundância, backups e discos mais confiáveis.

Agora é hora de olhar além da estabilidade e em direção à escalabilidade. Como os servidores são alugados por hora, faria mais sentido executar servidores extras somente quando necessário? E quanto às tarefas processadas de maneira assíncrona?

As redes de distribuição de conteúdo (CDNs), que armazenam em cache conteúdo estático na borda da rede, tinham alto custo. A computação em nuvem tornou as CDNs acessíveis até mesmo para o menor dos sites. Ocorre um grande impulso no desempenho quando é usada uma CDN, por isso vamos configurar uma também.

Implementação automática

Um elemento principal ao se fazer a infraestrutura crescer dinamicamente é que uma nova instância precisará ser anexada ao ambiente de produção sem intervenção humana. Seria possível reconfigurar os pacotes de uma Amazon Machine Instance (AMI) continuamente após cada mudança, como uma implementação de código ou mudança do banco de dados. No entanto, um pouco de script significa que um servidor pode implementar a si próprio sem muito trabalho.

SmallPayroll.ca tem um processo de implementação semelhante à maioria dos outros aplicativos:

  1. Puxe o código do repositório, como Subversion ou git.
  2. Inicie os servidores de aplicativos.
  3. Verifique se o aplicativo iniciou corretamente.
  4. Inclua o novo servidor no conjunto do balanceador de carga.

A instância terá também de configurar um servidor de banco de dados em /etc/hosts.

Puxando o código do repositório

O código base SmallPayroll.ca está armazenado em um repositório Subversion. Subversion é um sistema de controle de código base que controla as mudanças no código base e permite aos desenvolvedores repartir e mesclar código para trabalhar em recursos em um ambiente separado.

No nível mais simples, um aplicativo Rails pode executar diretamente de uma cópia verificada do código de origem. Quando forem feitas mudanças, o servidor de produção executa uma atualização e é reiniciado. Uma Ruby Gem chamada Capistrano gerencia essas implementações de uma maneira que permite controle centralizado de múltiplos servidores e retrocesso fácil se forem encontrados problemas.

Em vez de verificar o código manualmente, um novo servidor autoinicializa o Capistrano . Isso é mais trabalho diretamente, mas significa que Capistrano pode mais tarde gerenciar o servidor com muita facilidade. A Listagem 1 mostra o conteúdo do Capfile inicial, que será colocado no diretório inicial do usuário da folha de pagamento.

Listagem 1. Um Capfile para autoinicializar a implementação do Capistrano
load 'deploy' 

# Where is the code? This will need to be customized!
set :repository,  "http://svn.smallpayroll.ca/svn/payroll/trunk/"
set :scm_username, "DEPLOY_USERNAME"
set :scm_password, "DEPLOY_PASSWORD"

# Deploy to the local server
server "localhost", :app, :web, :db, :primary => true

# By default Capistrano tries to do some things as root through sudo - disable this
set :use_sudo, false

# Define where everything goes
set :home, '/home/payroll'
set :deploy_to, "#{home}"
set :rails_env, "production"

O Capfile é executado pelo cap . Capistrano espera que estará usando o Secure Shell (SSH) para conectar a um servidor, mesmo se for o host local. A Listagem 2, que deve ser executada como o usuário do aplicativo, prepara o servidor de modo que o usuário do aplicativo pode usar SSH para conectar ao servidor local como ele próprio e as tarefas do Capistrano podem ser executadas.

Listagem 2. Preparando o ambiente
# Create the SSH directory and generate a secure key pair
mkdir .ssh
chmod 700 .ssh
ssh-keygen -b 1024 -t dsa -q -f .ssh/id_dsa -N ""

# Allow the user to SSH in to the server without a password
cat .ssh/id_dsa.pub >> .ssh/authorized_keys
# SSH is very fussy about permissions! Nothing should be readable
# by other users
chmod 600 .ssh/*

# SSH in once, ignoring host keys, so that the server will save the host key
ssh 127.0.0.1 -o StrictHostKeyChecking=false /bin/false

A Listagem 2 está dividida em três seções:

  • Os dois primeiros comandos criam um diretório SSH que pode ser lido somente pelo usuário do aplicativo. O terceiro comando cria uma chave Digital Signature Algorithm (DSA) de 1024 bits (-b 1024 -t dsa), desliga a saída (-q) e especifica o nome da chave e que não há senha.
  • Copia a chave pública do usuário para o arquivo, o que permite ao usuário que possui a chave privada correspondente efetuar login sem uma senha. Certifique-se de que ninguém mais pode ler arquivos no diretório.
  • Sem uma chave de host salva, SSH e prompt do Capistrano para verificar a chave, o que quebra a implementação automatizada. O último comando efetua login no servidor local, ignorando chaves de host e executa /bin/false. Isso é suficiente para salvar a chave de host.

A etapa final do processo cria o ambiente e implementa a versão atual do aplicativo. A Listagem 3 mostra como usar o Capistrano para cuidar dessas tarefas.

Listagem 3. Implementando o aplicativo com Capistrano
cap deploy:setup
chmod 700 /home/payroll
cap deploy

A Listagem 3 executa a tarefa deploy:setup , que cria a estrutura de diretório debaixo do diretório inicial do aplicativo que consiste nos diretórios denominados shared e releases. Cada implementação vai em seu próprio diretório na pasta de releases. O diretório compartilhado é usado para logs e outros elementos que podem ser compartilhados entre implementações separadas.

Antes de implementar o aplicativo, o segundo comando altera as permissões no diretório inicial para ser 700. Esse é um artefato de implementar a para o diretório inicial em vez de um subdiretório, pois a tarefa de configuração abre as permissões do diretório de implementação para permitir gravações de grupo. O daemon SSH não permite autenticação baseada em chave do diretório inicial se pessoas diferentes do usuário puderem gravar nele.

A tarefa deploy é finalmente executada, o que verifica o código fora de Subversion, coloca-o em um diretório de release e faz um link simbólico (symlink) chamado current. Com esse symlink estabelecido e cada implementação em um diretório separado, é fácil rolar de volta para versões anteriores do aplicativo.


Ativando servidores de aplicativos automaticamente

Embora seja possível construir um sistema que inclui automaticamente mais servidores da Web quando a carga fica alta, não é sempre uma grande ideia. O tráfego da Web flutua consideravelmente, por isso é necessário ter certeza de que o tráfego irá permanecer antes de ativar um outro servidor. Serão necessários aproximadamente 10 minutos para determinar se a carga que estiver sendo observada merece um novo servidor, depois outros 5 a 10 minutos para ativar uma instância e ter um novo servidor da Web no pool. Esse processo pode não ser efetivo para um servidor da Web, mas pode funcionar bem para servidores de tarefas.

Ainda é possível fazer crescer e reduzir os aplicativos da Web em um planejamento. Por exemplo, a maioria dos usuários do aplicativo SmallPayroll.ca faz isso entre 8h e 21h nos dias úteis. Para melhorar o tempo de resposta para os usuários registrados e reduzir os custos de servidor, três servidores serão executados nos dias úteis das 8h às 21h e dois servidores durante o resto do horário. Os scripts de implementação já estão escritos: tudo que é necessário fazer é iniciar o servidor e incluí-lo no balanceador de carga.

Ativando servidores no cron

A facilidade cron parece ser o lugar natural para ligar e desligar a instância extra em um planejamento predefinido. O crontab ideal teria aparência semelhante à Listagem 4.

Listagem 4. Um crontab que inicia e para servidores automaticamente
0  8 * * 1-5 $BASEDIR/servercontrol launch app
0 21 * * 1-5 $BASEDIR/servercontrol terminate app

O código na Listagem 4 é inserido no crontab de um usuário em uma máquina fora do ambiente virtual. Às 8h nos dias 1 a 5 (segunda a sexta), um script denominado servercontrol é executado com os parâmetros launch app. Às 21h, o mesmo comando é executado com parâmetros de terminate app. O script entenderá esses parâmetros para ser uma operação e uma função de servidor. Por enquanto, as funções serão sempre app.

Escrevendo o script de controle

A próxima etapa é escrever o script de controle de servidor, que é executado no cron para iniciar servidores on demand. A Listagem 5 mostra o script.

Listagem 5. O script de controle de servidor
#!/bin/bash

AMI=ami-ad7e95c4 OP=$1
ROLE=$2

if [ "$OP" == "" -o "$ROLE" == "" ]; then
  echo You\'re doing it wrong.
  echo $0 operation number role
  exit
fi

case "$OP" in
  "launch")

    # Ative a instância e analise os dados para obter o ID da instância
    DATA=`ec2-run-instances -k main -d "DB=10.126.17.1;ROLE=$ROLE" $AMI`
    INSTANCE=`echo $DATA | grep INSTANCE  | cut -f 6 -d ' '`
    echo $INSTANCE is your instance

    # Continue verificando até o estado ficar "running"
    STATE=""
    while [ "$STATE" != "running" ]; do
      STATE=`ec2-describe-instances  $INSTANCE |awk '/^INSTANCE/ {print $6}'`
      echo the state is $STATE
      sleep 10
    done
    # Controle quais instâncias foram iniciadas por esse método
    echo $INSTANCE >> $HOME/.ec2-$ROLE

    # Agora que a instância está em execução, capture o endereço IP
    IP=`ec2-describe-instances $INSTANCE |awk '/^INSTANCE/ {print $13}'`

    # Se for para ser um servidor de aplicativos...
    if [ "$ROLE" == "app" ]; then
      # Verifique o servidor da Web para garantir que ele retorna nosso conteúdo
      UP=0
      while [ $UP -eq 0 ]; do
        OUTPUT=`curl -s -m 5 http://$IP`
        if [ $? -eq 0 ]; then # curl was successful
          echo $OUTPUT | grep -qi 'welcome'
          if [ $? -eq 0 ]; then
            UP=1
          else
            sleep 5
          fi
        fi
      done

      # Registre com o balanceador de carga
      elb-register-instances-with-lb smallpayroll-http --instances $INSTANCE
    fi

  ;;

  "terminate")
     # Capture o ID da instância. É a última linha do arquivo
     FILE=.ec2-$ROLE

     # Presumindo que o arquivo existe, naturalmente
     if [ ! -f $FILE ]; then
        echo No dynamic instances have been started for the $ROLE role
        exit
     fi

     # A última instância iniciada é a última linha do arquivo
     INSTANCE=`tail -1 $HOME/.ec2-$ROLE`

     # Presumindo que não há nada nesse arquivo, ou seja
     if [ "$INSTANCE" == "" ]; then
         echo No dynamic instances have been started for the $ROLE role
         exit
     fi

     # Finalize a instância
     ec2-terminate-instances $INSTANCE

     # Tire a instância do balanceador de carga
     elb-deregister-instances-from-lb smallpayroll-http --instances $INSTANCE

     # Exclua a última linha do arquivo
     sed -i '$d' $FILE
  ;;

   *) echo "You may only launch or terminate"
      exit
  ;;
esac

Esse script pode parecer longo, mas uma boa parte é verificação de erro. O script inicia analisando parâmetros e quebrando as funções launch eterminate em uma declaração de caso. Para a ativação, o script inicia a instância e aguarda até a instância entrar no estado running . Em seguida, o script obtém o endereço IP da instância e aguarda até um pedido da Web ao servidor retornar com sucesso e conter a palavra welcome.

Parar a instância é muito mais fácil. Os IDs são gravados em um dotfile no diretório inicial do usuário, com instâncias mais novas sendo anexadas ao arquivo. Para parar a instância, o script lê a última linha do arquivo para obter o ID da instância da instância iniciada mais recentemente, emite um comando de encerramento, remove a instância do balanceador de carga e exclui a última linha do arquivo que contém as instâncias.

Observe que cada função tem seu próprio arquivo. Neste momento há somente a função da Web, mas isso será expandido mais tarde.

Um item curioso da Listagem 5 é o parâmetro -d que foi passado para ec2-run-instances. Esse parâmetro contém informações que a instância pode ler visitando um URI especial que é acessível somente à instância. Essas informações estão na forma de uma cadeia de caractere. Na Listagem 5, a função do servidor e o servidor de banco de dados são passados para a instância.

Escrevendo o script inicial

O script de inicialização é executado durante o boot do sistema e configura a instância com uma versão atual do aplicativo, junto com o início da configuração apropriada do aplicativo. A Listagem 6 usa as informações passadas do script de controle para tomar essas decisões de configuração. O código nessa listagem pode ser parte do script de inicialização SYSV ou pode ir no arquivo rc.local para ser executado uma vez na inicialização.

Listagem 6. O script de inicialização do aplicativo
USER=payroll
HOME=/home/payroll
SRC=/etc/smallpayroll

# If this is a fresh AMI, set up the application directories
if [ ! -d $HOME/releases ]; then
echo "Setting up environment"
cp $SRC/Capfile $HOME
# Listing 2
su - $USER -c "cd $HOME && sh $SRC/setup_environment"
fi

echo "Deploying the application"
su - $USER -c "cd $HOME && /opt/ree/bin/cap deploy"

# Grab the user supplied data. 169.254.169.254 returns data unique to the instance.
USER_DATA=`/usr/bin/curl -s http://169.254.169.254/2007-01-19/user-data`
DBHOST=`echo $USER_DATA | sed 's/.*DB=\([0-9\.]*\).*/\1/'`
ROLE=`echo $USER_DATA | sed 's/.*ROLE=\([a-zA-Z]*\).*/\1/'`
logger "Starting application with DBHOST=$DBHOST and ROLE=$ROLE"

# If available, put the dbhost in /etc/hosts
if [ "$DBHOST" != "" ]; then
sed -i '/dbhost/d' /etc/hosts
echo "$DBHOST dbhost" >> /etc/hosts
fi

# Depending on the role...
case "$ROLE" in
'app')
# Web server... start up mongrel
su - $USER -c "mongrel_rails cluster::start \
-C $HOME/current/config/mongrel_cluster.yml"
;;
*)
logger "$ROLE doesn't make sense to me"
;;
esac

A Listagem 6 começa inicializando algumas variáveis. Em seguida, o diretório inicial do usuário do aplicativo é verificado para ver se a tarefa cap deploy:setup foi executada antes; se não foi, a tarefa é executada. Em seguida, uma implementação é executada para que o código mais recente esteja disponível.

Agora que o código está disponível, o script verifica os metadados que foram passados para a instância e, com uma certa mágica sed , extrai os componentes para as variáveis. Se a variável DBHOST estiver configurada, esse valor é colocado no /etc/hosts para que o aplicativo saiba onde localizar o banco de dados. A função é verificada; se o servidor estiver destinado a ser um servidor de aplicativos, os servidores mongrel são iniciados.

Juntas, a Listagem 5 e a Listagem 6 constituem um bit de código justo, mas definem os fundamentos para automatizar o início e a parada de qualquer tipo de servidor. Com o crontab da Listagem 4 estabelecido, o servidor extra entrará on-line durante os períodos de pico e desligará quando o site estiver menos ocupado. Em seguida, essa estrutura é estendida para ativar diferentes tipos de servidores.


Processamento de tarefa assíncrona

Uma técnica comum para tornar os sites da Web dinâmicos mais eficientes é mover os pedidos de longa execução para um processo em segundo plano. Essas tarefas de longa execução geralmente não são tão sensíveis ao tempo quanto um pedido real. Um aplicativo poderá enviar um pedido para executar um relatório em um sistema de processamento de tarefa e, usando Asynchronous JavaScript + Extensible Markup Language (Ajax), pesquisar a conclusão do segundo plano. O usuário vê algum tipo de spinner que indica que o aplicativo está operando, mas o usuário não está amarrando um processo mongrel que poderia entregar mais pedidos interativos.

Essa abordagem não remove a necessidade de ter recursos amplos disponíveis para processar as tarefas. Se a fila de tarefas ficar muito longa, os usuários ficarão cansados de aguardar seus relatórios. Esse parece ser um caso de uso ideal para ativação dinâmica de servidor. Alguma coisa monitora a lista não processada de tarefas; se a lista não processada ultrapassar um limite determinado, um novo servidor será ativado para ajudar. Após algum tempo o servidor será desativado.

Não há ativações grátis

Executar novos servidores não é grátis, por isso há algumas considerações econômicas a se fazer ao decidir quando ativar novos servidores.

A instância m1.small que esta série tem usado custa aproximadamente US$ 8,5 centavos por hora ou parte de uma hora. Assim, ao lançar uma instância, mesmo durante um minuto, você está comprando uma hora. Se decidir usar instâncias maiores para fazer mais trabalho, o custo por hora irá subir.

Certifique-se de que entende os custos de ativação de um novo servidor e os custos de não fazê-lo. Serviço mais lento significa clientes insatisfeitos. Serviço mais rápido significa clientes mais satisfeitos, mas custos mais altos.

O processamento de segundo plano é fornecido pelo excelente gem delayed_job—, especificamente, a bifurcação collectiveidea (consulte Recursos). Esse gem permite disparar tarefas em uma linha de código e implementa uma fila de prioridade para as tarefas importantes não aguardarem atrás de tarefas de rotina. O daemon de processamento de tarefa executa no diretório de aplicativos do Rails e usa o banco de dados para pedir trabalho. Isso significa que é possível estender os scripts atuais para tratar os daemons delayed_job .

Atualizando o script de inicialização para suportar servidores de processamento de tarefa

Rechamada de A listagem 6 que o script verifica seus metadados de instância para ver o que foi passado do script de controle de servidor. O parâmetro ROLE declara a tarefa do servidor, com app significando um servidor de aplicativos. As instruções para cada tipo de servidor são quebradas em uma instrução de caso. A Listagem 7 estende essa instrução de caso para tratar funções delayed_job .

Listagem 7. Tratando a reinicialização de um servidor delayed_job
case "$ROLE" in
  'app')
    # Para um servidor de aplicativos, inicie os
    su - payroll -c "/opt/ree/bin/mongrel_rails cluster::start \
      -C /home/payroll/current/config/mongrel_cluster.yml"
  ;;
  'job')
    # Para um servidor de tarefas, descubra que tipo de máquina é execute
    # um número apropriado de daemons de processamento de tarefa
    TYPE=`curl -s http://169.254.169.254/2007-08-29/meta-data/instance-type`
    case "$TYPE" in
      'm1.small') NUM=2 ;; # 2 per ECU * 1 ECU
      'm1.large') NUM=8 ;; # 2 per ECU * 4 ECUs
      *) NUM=2 ;;
    esac
    su - payroll -c "RAILS_ENV=production $HOME/current/script/delayed_job -n $NUM start"
  ;;
  *)
  logger "$ROLE doesn't make sense to me"
  ;;
esac

O script verifica a função do servidor. Se o servidor for um servidor de aplicativos, mongrels são iniciados. Se o servidor for um servidor de tarefa, os scripts verificam para descobrir em que tipo de instância ele está executando. Essas informações estão disponíveis de outra URL no host virtual 169.254.169.254. Como estimativa grosseira, o script ativa dois trabalhadores delayed_job por Elastic Compute Unit (ECU). A sua carga de trabalho pode ser diferente.

Neste ponto, o script servercontrol pode ativar um novo servidor de tarefa passando launch job na linha de comando.

Monitorando a fila

Existem várias maneiras de monitorar a lista não processada da fila. Seria possível incluir uma tarefa e medir o tempo que leva para ser processada, iniciando um novo servidor se o tempo estiver fora de um limite. O lado negativo desse método é que se realmente foi feito backup da fila, levará um longo tempo para determinar que foi feito backup. A solução mais simples é consultar o banco de dados para saber o número de pedidos pendentes e entregar isso em um controlador. A Listagem 8 mostra um controlador.

Listagem 8. Um controlador que mostra o comprimento da fila
class QueueController < ApplicationController
  def length
    render :text => Delayed::Job.count(
      :conditions => "priority > 0 AND failed_at IS NULL").to_s
  end
end

A Listagem 8 simplesmente mostra o comprimento da fila—especificamente, tarefas com uma prioridade maior que 0 e as que não foram processadas (ou seja, não falharam)—e renderiza esse número diretamente em vez de passá-lo para um modelo. Navegando até /queue/length pode-se obter a lista não processada da fila atual.

Ativando novos servidores de tarefa em resposta à demanda

Agora que é possível determinar com facilidade o comprimento da fila, é necessário um script para agir sobre esses dados. A Listagem 9 mostra esse script.

Listagem 9. Ativando mais servidores de tarefa, se necessário
#!/bin/bash

# Qual é o comprimento da fila
QUEUE=`curl -s http://app.smallpayroll.ca/queue/length`
# Quantos servidores estão em execução agora? (zero se a fila não existir)
SERVERS=`wc -l $HOME/.ec2-job`
if [ "$SERVERS" == "" ]; then SERVERS=0; fi

# lançar até dois servidores enquanto a fila estiver acima de 20
if [ $SERVERS -le 2 -a $QUEUE -gt 20 ]; then
  servercontrol launch job
fi

# Finalizar uma instância se a fila estiver abaixo de 5
if [ $SERVERS -gt 0 -a $QUEUE -lt 5 ]; then
  export TZ=/usr/share/zoneinfo/UTC
  LAST=`tail -1 $HOME/.ec2-job`
  # But only if the server has run for at least 45 minutes
  UPTIME=`ec2-describe-instances $LAST | \
    awk '/INSTANCE/ {t=$10; gsub(/[\-:T\+]/, " ", t); print systime() - mktime(t) }'`
  if [ $UPTIME -gt 2700 ]; then
    servercontrol terminate job
  fi
fi

Lógica de negócios

A Listagem 9 implementa um algoritmo simples. É suficiente demonstrar os princípios que estão por trás da ativação dinâmica de servidores, mas poderiam ter mais inteligência. Por exemplo, o script poderia observar o comprimento da fila ao longo do tempo e desligar servidores após um período de estabilidade em vez da versão simples que existe hoje.

O código na Listagem 9 deverá ser executado do cron a cada 5 minutos. O código obtém primeiro o comprimento da fila e o número de servidores de tarefa atualmente em execução. O número de servidores de tarefa é obtido do comprimento do arquivo .ec2-job que contém os IDs das instâncias dos servidores executados dinamicamente. Se o comprimento da fila for mais que 20 e houver menos que dois servidores de tarefa extras em execução, um servidor é ativado. Se houver mais que um servidor em execução e a fila for menor que 5, o script faz uma verificação para ver se deveria finalizar uma instância.

O script primeiro determina o fuso horário da Hora Universal Coordenada (UTC) definindo a variável de ambiente TZ. Em seguida, obtém o ID da instância do servidor de tarefa executado por último e consulta para obter o horário da inicialização. Esse horário é alimentado em alguma substituição awk para chegar ao tempo, em segundos, que o servidor está ativo. Se o servidor estiver ativo há mais de 45 minutos, a instância pode ser desligada. Caso contrário, o servidor permanece ativo.

A barreira de 45 minutos está estabelecida para impedir o desligamento prematuro de um servidor. Se a fila diminuir e depois aumentar novamente, o servidor ainda estará lá.


Usando uma rede de distribuição de conteúdo

Quando alguém acessa seu Web site, está também carregando imagens, Cascading Style Sheets (CSS) e código JavaScript. Serviços chamados CDNs armazenam em cache os recursos estáticos e os distribuem por muitos servidores na Internet. Como resultado, pode ser fornecido acesso mais rápido dos seus usuários a esses recursos e pode-se permitir que transfiram por download múltiplos arquivos em paralelo. A Amazon fornece um serviço CDN chamado Amazon CloudFront—uma oferta "pague pelo uso" como seus outros serviços.

Os recursos que devem ser entregues de um CDN são pedidos de um servidor diferente, assim a URL mudará. Como exemplo, http://app.smallpayroll.ca/stylesheets/style.css irá carregar a folha de estilo do servidor de aplicativos, mas http://cdn0.smallpayroll.ca/stylesheets/style.css carrega do CDN. Se o CDN não tiver o recurso, puxa o recurso de origin antes de armazenar em cache e passar o recurso para o usuário.

CloudFront é ligeiramente diferente de outros CDNs porque a origem é um depósito Amazon Simple Storage Service (Amazon S3). Para usar CloudFront, é necessário primeiro preencher um depósito Amazon S3 com os recursos estáticos e, em seguida, regravar as URLs para usar hosts CloudFront.

Configurando o CloudFront

Na página principal do CloudFront (consulte Recursos para obter um link), clique no link para inscrever-se. Será necessário aguardar um e-mail de ativação antes de continuar.

Ao receber a confirmação da ativação, acesse a página do console Amazon Web Services e clique em Amazon CloudFront Você verá a página mostrada na Figura 1.

Figura 1. O painel CloudFront Distributions
O painel CloudFront Distributions

Observe que nenhuma distribuição foi criada. Uma distribution é simplesmente um depósito de arquivos que será ligado de volta a um depósito Amazon S3. Clique em Create Distribution para obter a página mostrada na Figura 2.

Figura 2. Criando uma distribuição
Criando uma distribuição

Execute as seguintes tarefas:

  1. Para Delivery Method, selecione Download.
  2. Na lista suspensa Origin selecione o nome de um depósito Amazon S3 ou elabore um que criará com sua ferramenta de opção no Amazon S3.
  3. Para Logging, selecione =Off a menos que planeje usar esses logs.
  4. No campo CNAMEs digite quatro nomes abaixo do seu domínio, como cdn0.smallpayroll.ca a cdn3.smallpayroll.ca.
  5. Em Comments, insira o texto que desejar.
  6. Para Distribution Status, selecione Enabled.

Ao clicar em Create, será levado de volta à guia CloudFront , onde verá a distribuição que acabou de criar (consulte a Figura 3).

Figura 3. Uma distribuição configurada
Uma distribuição configurada

Nessa página há um nome de domínio, como djdzxdmb99068.cloudfront.net. Agora é necessário acessar o servidor DNS, configurar os quatro CNAMEs e fazê-los apontar para o nome de domínio da distribuição. Amazon Elastic Load Balancing funciona de maneira semelhante, exceto que são criados quatro nomes numerados.

Coloque um arquivo de teste no depósito Amazon S3 que associou à distribuição. Deverá ser possível ver esse documento navegando até o nome de domínio da distribuição, como http://djdzxdmb99068.cloudfront.net/test.htm, para visualizar um arquivo chamado test.htm dentro do depósito. Se você obtiver um erro de acesso negado, certifique-se de ter o acesso público ativado nos arquivos (as instruções variam dependendo da ferramenta usada para gerenciar o depósito Amazon S3). Se o teste anterior funcionou, agora é possível tentar usar o CNAMEs que foi criado anteriormente, como http://cdn1.smallpayroll.ca/test.htm.

Sincronizando os arquivos

O conteúdo do diretório público deve ser copiado para o depósito Amazon S3 de origem. A maneira mais simples de fazer isso é executar:

s3sync.rb -r -p public/ smallpayroll-cdn:

no diretório-raiz do aplicativo Rails. A opção -r significa que a cópia deve ser recursiva. A opção -p torna todos os arquivos legíveis publicamente.

Para automatizar esse procedimento, verifique Recursos para obter um link para um gem que trate a tarefa.

Atualizando seu aplicativo

Em um nível simples é possível alterar todos os links de imagem, JavaScript e CSS para apontarem para um dos links CDN em vez de para o servidor da Web. Se foram usados auxiliares de URL do Rails como image_tag, é possível fazer o Rails executar o trabalho para você. Inclua a seguinte linha em config/environments/production.rb:

ActionController::Base.asset_host = "cdn%d.smallpayroll.ca"

Esse código inclui uma única linha à configuração de produção—especificamente, quais recursos estáticos devem ser entregues do host definido como asset_hosts. A opção %d é, por padrão, expandida aos números 0 a 3, assim está sendo dito ao Rails para girar entre cdn0.smallpayroll.ca, cdn1.smallpayroll.ca, cdn2.smallpayroll.ca e cdn3.smallpayroll.ca. Esses são os mesmos hosts para os quais o CloudFront foi configurado para responder. Com quatro hosts, pode-se esperar que os navegadores transfiram por download até oito recursos de cada vez, pois os navegadores geralmente são limitados a duas conexões por host.

Agora o aplicativo usará o CDN onde possível. Desfrute a velocidade melhorada!


conclusão

O seu aplicativo usa um Amazon CloudFront como um CDN, o que irá acelerar os carregamentos de páginas tornando os downloads mais rápidos e permitindo download paralelo pelo cliente. O aplicativo também foi atualizado para fazer crescer e reduzir dinamicamente os recursos de computação. Parte da ativação e do encerramento é feita em um planejamento e parte é feita em resposta à carga. Existem alguns scripts que podem ser estendidos para tratar muitos outros casos também.

Um item que falta é gerenciamento. Em qualquer momento determinado, provavelmente não se sabe exatamente quantos computadores estão em execução. As implementações não estão automatizadas ainda porque a lista de servidores está sempre em fluxo. Realmente não se sabe como os próprios servidores estão executando. Procure o artigo final desta série para tratar desses problemas.

Recursos

Aprender

Obter produtos e tecnologias

  • Agora que você obteve múltiplos AMIs no Amazon S3, poderá desejar remover alguns antigos. A opção Amazon S3 File Manager é um gerenciador de arquivos que rivaliza os recursos de muito aplicativos independentes ou plug-ins do navegador. Se excluir um AMI, não se esqueça de ec2-deregister .
  • S3Sync é uma ferramenta útil para copiar arquivos do e para o Amazon S3 e também para manipular seus depósitos.
  • Capistrano é um pacote de implementação popular que age de maneira semelhante ao Rake.
  • delayed_job é um servidor de tarefa em segundo plano que integra bem com Rails e ActiveRecord. Esse link é para a bifurcação collectiveidea do projeto, que parece ser o fluxo mantido atualmente.
  • synch_s3_asset_host é um gem que torna muito fácil a sincronização do depósito Amazon S3 de origem e os arquivos estáticos do aplicativo.
  • Avalie os produtos IBM da maneira que for melhor para você: faça download da versão de teste de um produto, avalie um produto on-line, use-o em um ambiente de nuvem ou passe algumas horas na SOA Sandbox aprendendo a implementar Arquitetura Orientada a Serviços de modo eficiente.

Discutir

  • Participe da comunidade do My developerWorks. Entre em contato com outros usuários do developerWorks, enquanto explora os blogs, fóruns, grupos e wikis orientados ao desenvolvedor.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux, Cloud computing, Software livre
ArticleID=577088
ArticleTitle=Migre seu aplicativo Linux para a nuvem Amazon, Parte 3: Construindo Escalabilidade
publish-date=11052010