Você está na página 1de 7

Eduardo Marconi Araujo Silva – 2011411

Os doze Fatores

1 – Base de Código

Uma cópia da base de dados do rastreamento de revisões é conhecido como repositório de


código, normalmente abreviado como repositório ou repo.

Uma base de código é um único repo (em um sistema de controle de versão centralizado como
Subversion), ou uma série de repositórios que compartilham um registro raiz.

Existe sempre uma correlação um-para-um entre a base de código e a aplicação:

• Se existem várias bases de código, isto não é uma app – é um sistema distribuído. Cada
componente do sistema é uma app, e cada uma pode individualmente ser compatível
com os 12 fatores.
• Múltiplas apps compartilhando uma base de código é uma violação dos 12 fatores. A
solução aqui é dividir o código compartilhado entre bibliotecas que podem ser
incluídas através do gerenciador de dependências.

Existe apenas uma base de código por aplicação, mas existirão vários deploys da mesma.
Um deploy (ou implantação) é uma instância executando a aplicação. Isto é tipicamente um
local de produção, e um ou mais locais de testes.

Ferramentas: Git, Mercurial, ou Subversion.

2 – Dependências

Uma aplicação doze-fatores nunca confia na existência implícita de pacotes em todo o sistema.
Ela declara todas as dependências, completa e exatamente, por meio de um manifesto de
declaração de dependência. Além disso, ela usa uma ferramenta de isolamento de
dependência durante a execução para garantir que não há dependências implícitas
“vazamento” a partir do sistema circundante. A completa e explícita especificação de
dependências é aplicada de maneira uniforme tanto para produção quanto para
desenvolvimento.

Por exemplo, Bundler para Ruby oferece o formato de manifesto Gemfile para declaração de
dependência e bundle exec para isolamento das mesmas. Em Python existem duas
ferramentas separadas para estas etapas – Pip é utilizado para declaração e Virtualenv para
isolamento. Mesmo C tem Autoconf para declaração de dependência, e vinculação estática
pode fornecer o isolamento. Não importa qual o conjunto de ferramentas, declaração de
dependência e isolamento devem ser sempre usados juntos – apenas um ou o outro não é
suficiente para satisfazer doze-fatores.

Ferramentas: CPAN para Perl ou Rubygems para Ruby.

3 – Configurações

A configuração de uma aplicação é tudo o que é provável variar entre deploys (homologação,
produção, ambientes de desenvolvimento, etc). Isto inclui:

• Recursos para a base de dados, Memcached, e outros serviços de apoio


• Credenciais para serviços externos como Amazon S3 ou Twitter
• Valores por deploy como o nome canônico do host para o deploy

Aplicações às vezes armazenam as configurações no código como constantes. Isto é uma


violação da doze-fatores, a qual exige uma estrita separação entre configuração e código.
Configuração varia substancialmente entre deploys, código não.

A prova de fogo para saber se uma aplicação tem todas as configurações corretamente
consignadas fora do código é saber se a base de código poderia ter seu código aberto ao
público a qualquer momento, sem comprometer as credenciais.

Note que esta definição de “configuração” não inclui configuração interna da aplicação, como
config/routes.rb em Rails, ou como módulos de códigos são conectados em Spring. Este tipo
de configuração não varia entre deploys, e por isso é melhor que seja feito no código.

Ferramentas: Configuração de uma aplicação, homologação, ambientes de desenvolvimento e


produção.

4 – Serviços de apoio.

Um serviço de apoio é qualquer serviço que o app consuma via rede como parte de sua
operação normal. Exemplos incluem armazenamentos de dados (como MySQL ou CouchDB),
sistemas de mensagens/filas (tais como RabbitMQ ou Beanstalkd), serviços SMTP para emails
externos (tais como Postfix), e sistemas de cache (tais como Memcached).

Serviços de apoio como o banco de dados são tradicionalmente gerenciados pelos mesmos
administradores de sistema do servidor de deploy de tempo de execução do app.
Adicionalmente à esses serviços localmente gerenciados, o app pode ter serviços providos e
gerenciados por terceiros. Exemplos incluem serviços SMTP (tais como Postmark), serviços de
colheita de métricas (tais como New Relic ou Loggly), serviços de ativos binários (tais como
Amazon S3), e até serviços de consumidores acessíveis via API (tais como Twitter, Google
Maps, ou Last.fm).

O código para um app doze-fatores não faz distinção entre serviços locais e de terceiros. Para o
app, ambos são recursos anexados, acessíveis via uma URL ou outro localizador/credenciais na
config. Um deploy do app doze-fatores devem ser capaz de trocar um banco de dados MySQL
por um gerenciado por terceiros (tais como Amazon RDS) sem realizar quaisquer mudanças no
código do app. Da mesma forma, um servidor local SMTP poderia ser trocado por um serviço
de terceiros (tais como Postmark) sem as mudanças em código. Em ambos os casos, apenas o
identificador de recurso precisa mudar.

Ferramentas: MySQL e CouchDB.

5 - Construa, lance, execute

Uma base de código é transformada num deploy (de não-desenvolvimento) através de três
estágios:

• O estágio de construção é uma transformação que converte um repositório de código


em um pacote executável conhecido como construção. Usando uma versão do código
de um commit especificado pelo processo de desenvolvimento, o estágio de
construção obtém e fornece dependências e compila binários e ativos.
• O estágio de lançamento pega a construção produzida pelo estágio de construção e a
combina com a atual configuração do deploy. O lançamento resultante contém tanto a
construção quanto a configuração e está pronta para execução imediata no ambiente
de execução.
• O estágio de execução roda o app no ambiente de execução, através do início de
alguns dos processos do app com um determinado lançamento.

O app doze-fatores usa separação estrita entre os estágios de construção, lançamento e


execução. Por exemplo, é impossível alterar código em tempo de execução, já que não há
meios de se propagar tais mudanças de volta ao estágio de construção.

Ferramentas para deploy tipicamente oferecem ferramentas de gestão de lançamento, mais


notadamente a habilidade de se reverter à um lançamento prévio. Por exemplo, a ferramenta
de deploy Capistrano armazena lançamentos em um subdiretório chamado releases, onde o
lançamento atual é um link simbólico para o diretório de lançamento atual. Seu comando
rollback torna fácil reverter para um lançamento prévio.

Cada lançamento deve sempre ter um identificador de lançamento único, tal qual o timestamp
do lançamento (como 2011-04-06-20:32:17) ou um número incremental (como v100).
Lançamentos são livro-razões onde apenas se acrescenta informações, ou seja, uma vez criado
o lançamento não pode ser alterado. Qualquer mudança deve gerar um novo lançamento.

Ferramenta: Capistrano

6 – Processos
No caso mais simples, o código é um script autônomo, o ambiente de execução é o laptop local
de um desenvolvedor com o runtime da linguagem instalado, e o processo é iniciado pela linha
de comando (por exemplo, python my_script). Na outra extremidade do espectro, o deploy em
produção de uma aplicação sofisticada pode utilizar vários tipos de processos, instanciado em
zero ou mais processos em andamento.

Processos doze-fatores são stateless(não armazenam estado) e share-nothing. Quaisquer


dados que precise persistir deve ser armazenado em um serviço de apoio stateful(que
armazena o seu estado), tipicamente uma base de dados.

O espaço de memória ou sistema de arquivos do processo pode ser usado como um breve,
cache de transação única. Por exemplo, o download de um arquivo grande, operando sobre
ele, e armazenando os resultados da operação no banco de dados. A aplicação doze-fatores
nunca assume que qualquer coisa cacheada na memória ou no disco estará disponível em uma
futura solicitação ou job – com muitos processos de cada tipo rodando, as chances são altas de
que uma futura solicitação será servida por um processo diferente. Mesmo quando rodando
em apenas um processo, um restart (desencadeado pelo deploy de um código, mudança de
configuração, ou o ambiente de execução realocando o processo para uma localização física
diferente) geralmente vai acabar com todo o estado local (por exemplo, memória e sistema de
arquivos).

Ferramenta: Executada no ambiente de execução local.

7 – Vinculo de Portas.

O aplicativo doze-fatores é completamente auto-contido e não depende de injeções de tempo


de execução de um servidor web em um ambiente de execução para criar um serviço que
defronte a web. O app web exporta o HTTP como um serviço através da vínculação a uma
porta, e escuta as requisições que chegam na mesma.

Num ambiente de desenvolvimento local, o desenvolvedor visita a URL de um serviço como


http://localhost:5000/ para acessar o serviço exportado pelo seu app. Num deploy, uma
camada de roteamento manipula as requisições de rotas vindas de um hostname público para
os processos web atrelados às portas.

Isso é tipicamente implementado usando declaração de dependências para adicionar uma


biblioteca de servidor ao app, tal como Tornado para Python, Thin para Ruby, ou Jetty para
Java e outra linguagens baseadas na JVM. Isso acontece completamente no espaço do usuário,
isso é, dentro do código do app. O contrato com o ambiente de execução é vincular a uma
porta para servir requisições.

HTTP não é o único serviço que pode ser exportado via vínculo de portas. Quase todos os tipos
de software servidores podem rodar via um processo vinculado a uma porta e aguardar as
requisições chegar. Exemplos incluem ejabberd (comunicando via XMPP), e Redis
(comunicando via protocolo Redis).

Ferramentas: Apache HTTPD e Tomcat


8 – Concorrência

Qualquer programa de computador, uma vez executado, está representado por um ou mais
processos. Aplicações web têm tomado uma variedade de formas de processo de execução.
Por exemplo, processos PHP rodam como processos filhos do Apache, iniciados sob demanda
conforme necessário por volume de requisições. Processos Java tomam o caminho inverso,
com a JVM proporcionando um processo uber maciço que reserva um grande bloco de
recursos do sistema (CPU e memória) na inicialização, com concorrência gerenciada
internamente via threads. Em ambos os casos, o(s) processo(os) em execução são apenas
minimamente visíveis para os desenvolvedores da aplicação.

Escala é expressado como processos em execução, a diversidade da carga de trabalho é


expressada como tipos de processo.

Na aplicação doze-fatores, processos são cidadãos de primeira classe. Processos na aplicação


doze-fatores utilizam fortes sugestões do modelo de processos UNIX para execução de
serviços daemon, o desenvolvedor pode arquitetar a aplicação dele para lidar com diversas
cargas de trabalho, atribuindo a cada tipo de trabalho a um tipo de processo. Por exemplo,
solicitações HTTP podem ser manipuladas para um processo web, e tarefas background de
longa duração pode ser manipuladas por um processo trabalhador.

Ferramentas: PHP e Apache.

9 – Descartabilidade.

Os processos de um app doze-fatores são descartáveis, significando que podem ser iniciados
ou parados a qualquer momento. Isso facilita o escalonamento elástico, rápido deploy de
código ou mudanças de configuração, e robustez de deploys de produção.

Processos devem empenhar-se em minimizar o tempo de inicialização. Idealmente, um


processo leva alguns segundos do tempo que o comando de inicialização é executado até o
ponto que ele estará pronto para receber requisições ou tarefas. Períodos curtos de
inicialização provém mais agilidade para o processo de release e de escalonamento; e ele
adiciona robustez, pois o gestor de processos pode mais facilmente mover processos para
outras máquinas físicas quando necessário.

Processos desligam-se graciosamente quando recebem um sinal SIGTERM do seu gestor de


processos. Para um processo web, desligamento gracioso é alcançado quando cessa de escutar
à porta de serviço (consequentemente recusando quaisquer requisições novas), permitindo
qualquer requisição em andamento terminar, e então desligando. Implícito neste modelo é
que as requisições HTTP são curtas (não mais que alguns poucos segundos), ou no caso de um
longo polling, o cliente deve ser capaz de transparentemente tentar se reconectar quando a
conexão for perdida.

Para um processo de trabalho (worker), desligamento gracioso é alcançado retornando a


tarefa atual para fila de trabalho. Por exemplo, no RabbitMQ o trabalhador pode enviar um
NACK; no Beanstalkd, a tarefa é retornada para a fila automaticamente sempre que um
trabalhador se desconecta. Sistemas baseados em trava como o Delayed Job precisam se
certificar de soltar a trava no registro da tarefa. Implícito neste modelo é que todas as tarefas
são reentrantes, o que tipicamente é atingindo envolvendo os resultados numa transação, ou
tornando a operação idempotente.

Ferramenta: RabbitMQ

10 – Paridade entre desenvolvimento e produção

O App doze-fatores é projetado para implantação contínua deixando a lacuna entre


desenvolvimento e produção pequena. Olhando às três lacunas descritas acima:

• Diminua a lacuna de tempo: um desenvolvedor pode escrever código e ter o deploy


feito em horas ou até mesmo minutos depois.
• Diminua a lacuna de pessoal: desenvolvedores que escrevem código estão
proximamente envolvidos em realizar o deploy e acompanhar seu comportamento em
produção.
• Diminua a lacuna de ferramentas: mantenha desenvolvimento e produção o mais
similares possível.

Serviços de apoio, como o banco de dados do app, sistema de filas, ou cache, são uma área
onde paridade entre desenvolvimento e produção é importante. Muitas linguagens oferecem
diferentes bibliotecas que simplificam o acesso ao serviço de apoio, incluindo adaptadores
para os diferentes tipos de serviços.

Ferramentas: Nginx, SQLite, e OS X

11 – Logs

Logs provém visibilidade no comportamento de um app em execução. Em ambientes de


servidor eles são comumente escritos num arquivo em disco (um “logfile”); mas este é apenas
um formato de saída.

Logs são o fluxo de eventos agregados e ordenados por tempo coletados dos fluxos de saída
de todos os processos em execução e serviços de apoio. Logs na sua forma crua são
tipicamente um formato de texto com um evento por linha (apesar que pilhas de exceção
podem ocupar várias linhas). Logs não tem começos ou términos fixos, mas fluem
continuamente enquanto o app estiver operante.

Um app doze-fatores nunca se preocupa com o roteamento ou armazenagem do seu fluxo de


saída. Ele não deve tentar escrever ou gerir arquivos de logs. No lugar, cada processo em
execução escreve seu próprio fluxo de evento, sem buffer, para o stdout. Durante o
desenvolvimento local, o desenvolvedor verá este fluxo no plano de frente do seu terminal
para observar o comportamento do app.

Em deploys de homologação ou produção, cada fluxo dos processos será capturado pelo
ambiente de execução, colados com todos os demais fluxos do app, e direcionados para um ou
mais destinos finais para visualização e arquivamento de longo prazo. Estes destinos de
arquivamento não são visíveis ou configuráveis pelo app, e ao invés disso, são completamente
geridos pelo ambiente de execução. Roteadores de log open source (tais como Logplex e
Fluentd) estão disponíveis para este propósito.

Ferramentas: Hadoop/Hive.

12 - Processos administrativos

A formação de processos é o conjunto de processos que são usados para fazer as negociações
regulares da app como ela é executada (tais como manipulação de requisições web).
Separadamente, os desenvolvedores, muitas vezes desejam fazer tarefas pontuais de
administração ou manutenção para a app, tais como:

• Executar migrações de base de dados (ex: manage.py migrate no Django, rake


db:migrate no Rails).
• Executar um console (também conhecido como um REPL shell) para rodar código
arbitrário ou inspecionar os modelos da app ao vivo no banco de dados. A maioria das
linguagens fornece um REPL para rodar o interpretador sem nenhum argumento (ex:
python or perl) ou em alguns casos tem um comando separado (ex: irb para Ruby, rails
console para Rails).
• Executar uma vez os scripts comitados no repositório da app (ex: php
scripts/fix_bad_records.php).

Processos administrativos pontuais devem ser executados em um ambiente idêntico, como os


processos regulares de longa execução da app. Eles rodam uma versão, usando a mesma base
de código e configuração como qualquer processo executado com essa versão. Códigos de
administração devem ser fornecidos com o código da aplicação para evitar problemas de
sincronização.

Ferramentas: Django e Rails

Você também pode gostar