Escalando uma plataforma de e-mail transacional: SMTP ... · Escalando uma plataforma de ... -...

Post on 01-Dec-2018

228 views 0 download

Transcript of Escalando uma plataforma de e-mail transacional: SMTP ... · Escalando uma plataforma de ... -...

Escalando uma plataforma de e-mail transacional:

aprendizado das trincheiras

Celso Crivelaro (@celsocrivelaro)Fabio Perrella (@fabioperrella)

SMTP Locaweb

Fabio Perrella- Eng Computação- Dev Ruby, Php, Python, Javascript- Locaweb, time de Email- 1a geração do projeto do SMTP

@fabioperrella

http://fabioperrella.blogspot.com

Celso Crivelaro- Engenheiro e Mestre em Engenharia de Computação- Dev Ruby / Python / Java- Dev do SMTP Locaweb há 1 ano e meio

@celsocrivelaro

http://crivelaro.me

SMTP Locaweb - Produto- Plataforma para envio de e-mails transacionais- Envio de grandes quantidades com velocidade e qualidade- Relatórios “ao vivo” para acompanhar os envios- Envio por SMTP e API HTTP- Webhooks para devoluções de e-mails (bounces)- 2,5 milhões de e-mails por dia- Há + de 2 anos no ar- Mais de 2.000 contas ativas

O que é email transacional?- Disparos granulares- Notificação de eventos- Entrega rápida- Exemplos de uso: CRM, E-commerce, Billing, Websites

Processamento Lento

Processamento Rápido

Arquitetura

Autenticação Tratamento da Mensagem MTA ProvedoresUsuário

Processamento da Mensagem Consolidação Painel

SMTP Locaweb- Arquitetura distribuída- Painel e APIs -> Ruby on Rails- Workers -> Ruby- Postfix milters -> Python- DB -> Postgres- Caches e Filas -> Redis- MTA -> PowerMTA

Desafios- Estabilidade- Escalabilidade- Performance- Relatórios em “tempo real”- Combater fraudes- Manter qualidade da entrega (https://returnpath.

com/downloads/the-ultimate-guide-to-email-deliverability)

Apostas que deram certo!

http://www.lafayetterealestatenews.com/wp-content/uploads/2015/08/Success.jpg

Postgres Schemas- Posgresql >= 9.3- http://www.postgresql.org/docs/9.3/static/ddl-schemas.html

SET search_path TO myschema,public;

Public

Tabelas menores

Tabelas em comum

Migração default

Privado (Conta)

Tabelas maiores

Dados de uma conta

Migração ao criar conta

Postgres Schemas

Prós

Isolamento dados

Tamanho das tabelas

Contras

Complexidade migrações

Relatórios consolidados

Postgres Schemas

Exportação de Relatórios

Postgres Copy - Exportação de dadosProblema:

- Geração de arquivos > 100mil linhas- Código ruby iterando do DB e gerando CSV- Podia levar horas para finalizar geração de arquivo

Separação das Apps

Apps por funcionalidade

Milters(python)

WorkersPainel

Core Api

Provisionador

DB

API envio

Open-Click

Auth Policy

Gem “models” para compartilhar código- Modelos, Migrações, Códigos em comum extraídos para gem- Facilidade para usar Activerecord- Atenção na atualização de novas versões da gem- Dica: http://ryanbigg.com/2013/08/bundler-local-paths

Apps por funcionalidade

Milters(python)

WorkersPainel

Core Api

Provisionador

DB

API envio

Open-Click

Auth Policy

Problemas- Ambiente distribuído- Testes de integração eram essenciais!- Configuração do Postfix, Milters, Nginx não é trivial- Dev novo não conseguia levantar ambiente completo- Incompatibilidades Mac OS X / Linux- Versionamento de dependencias (ex: Redis)

Docker com ambiente completo- Docker-compose! (https://docs.docker.com/compose)- Mailcatcher (https://mailcatcher.me)- Fluxo completo do email- Base para configuração de produção

DockerPor onde começar:

https://training.docker.com/self-paced-training

Vale gastar um tempo!

Logs

Archive de logs centralizado- Syslog ajuda!- Log rotate a cada 15min- Archive em storage organizado por servidor/data- Grep em multiplos servidores/datas

- Cuidado: limite de caracteres syslog (aprox 1500 p/ mensagem)

Caches e filas no Redis- Milters dependem de dados das contas (API)- Performance- TTL- Facilidade para debug / “queries” (comparando com memcache)

$ redis-cli monitor | grep “qquer coisa”

- Estruturas de dados: string, hashes, arrays, sets- Operações atômicas / garantia para concorrência

Redis- Sharding com twemproxy (https://github.com/twitter/twemproxy)- Persistência desligada: app deve saber “esquentar” o cache!- Alternativa: Master / Slave (local)- Futuro: Redis Cluster- Atenção à versão do Redis, pode não ser a mesma da sua

máquina (docker nele!)

https://github.com/locaweb/heartcheck

Heartcheck

Redis DB Sidekiq Telnet

ProcessosAPIs Mount Points

DNS

Gráficos!

Painel de monitoração (cockpit)- Ajuda saber quando precisamos aumentar capacidade e onde- Investigação de problemas- Grafana ( http://grafana.org )- New Relic / AppSignal

Painel de monitoração (cockpit)

Deploy contínuo(quase...)

Toggler - Feature Toggle- Deploy contínuo sem impacto- Exibir/esconder feature nova para determinadas contas- Ligar/desligar features sem deploy

De MVP para 2,5 MM

Processamento Lento

Processamento Rápido

Voltando ao diagrama...

Autenticação Tratamento da Mensagem MTA ProvedoresUsuário

Processamento da Mensagem Consolidação

Requisitos não funcionais

Alta Disponibilidade Performance

EscalabilidadeResiliência

Estabilidade

Isole os componentes críticos

Aplicação Painel

Painel Web API Interna - HTTP

Recursos

Pool de Conexões App Server Regras de

Negócio Integrações

Aplicação API InternaAplicação Painel

Painel Web API Interna - HTTP

Recursos

Pool de Conexões

App Server

Regras de Negócio Integrações

Recursos

Pool de Conexões

App Server

Regras de Negócio Integrações

Separação de Máquinas por Aplicação

Mesma máquina

Interdependência de libs

Consumo de Recursos

Versão da Linguagem

Máquina separada

Lib por App

Aplicação não afeta outra

Upgrades podem ser feitos em separado

Poucos Componentes=

Pouca Manutenção

API InternaPainel

Novas Funcionalidades Estabilidade/Performance

Muitas atualizações Poucas atualizações

Framework para Web Framework para API

Quebrou: ninguém morre Quebrou: ponto central de falha

Usar tecnologia que não domina...

Postfix Milter libmilter

pymilter

app

Protoco Milter

- Libs=

+ Alegria

Escalabilidade

Busque o dado de memórias + rápidas e de

lugares pertos

Estratégia de Cache Padrão

App

Cache

Fonte

1

2

3

1a Estratégia de Cache

App

Fonte App Cache

App

TTL curto

2a Estratégia de Cache

App

Fonte App

Cache

App

Cache

Cache

TTL curto

TTL curto

TTL curto

3a Estratégia de Cache

App

Fonte App

CacheSlave

App

CacheSlave

CacheSlave

TTL longo

TTL longo

TTL longo

CacheMaster

4a Estratégia de Cache

App

Fonte App

CacheSlave

App

CacheSlave

CacheSlave

TTL longo

TTL longo

TTL longo

CacheMaster

Cache Manager

Balanceamento de Carga

App

Client App

App

Load Balancer

App

Client

App

App

Load Balancer

App

App

App

Load Balancer

Load Balancer

Client Load Balancer Cache

Client Load Balancer Cache

Use SEMPRE pool de recursos

Problemas com Pool de Recursos

Não explode erros no início

Esperar de liberação de recurso

Timeouts são esporádicos Deadlocks

Timeouts baixos=

Fail Fast

Coisas que devíamos ter feito

Documentação de Arquitetura- Documentação sobre decisões de arquitetura

http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions

- Faltou documentação de decisões

Worker com Ruby puro- Fizemos um grande workers de processamento de mensagens- Em Ruby puro…- Sem recursos de mensageria- Difícil ver errors, retentativa, tamanho da fila….

Não reinvente a roda

Saiba os limites...

Teste de Carga

Teste de Estresse

Teste de Pico

Algumas referências

Obrigado!!!

Desconto especial ao evento: bit.ly/smtpqcon