Laraconf 2016: Construindo e mantendo aplicações multi-tenant (multi-cliente)

Post on 16-Apr-2017

257 views 1 download

Transcript of Laraconf 2016: Construindo e mantendo aplicações multi-tenant (multi-cliente)

Construindo e mantendo aplicações multi-tenant

(multi-cliente)

Aryel Tupinambá#LaraconfBrasil / 2016

Sobre o palestrante

Co-fundador e CTO da LQDI DigitalProjetos para empresas como Porto Seguro, Nestlé, Ticket, Editora FTD, Tishman Speyer e Ambev

13 anos trabalhando com PHPDesde a época que o PHPClasses era a onda :)

Aryel Tupinambá

Single tenant

Um único "cliente" para a aplicação

Forma tradicional, instalada no servidor do cliente

Faz sentido quando a aplicação é um PROJETO

Agora com mais um cliente… e mais outro...

Seu PROJETO se tornou um PRODUTO

Diversos clientes usando a mesma aplicação

Estruturas separadas para cada novo cliente

Nada é compartilhado; tudo é isolado

E agora, como faço...

… atualizações de segurança?… correção de bugs?… features novas para todo mundo?E o espaço que toda essa galera ocupa?E o custo que tudo isso gera?

Arquitetura multi-tenant

Tenant = inquilino

Uma única aplicação para vários clientes

Uma estrutura comum entre os clientes

As benfeitorias servem para todos

A customização de um cliente não interfere nos demais, nem previne que ele utilize da estrutura comum

Principais desafios

Como segmentar a base de dados para cada cliente?

Como segmentar os arquivos enviados?

Como fica o código fonte da aplicação?

Como ficam as customizações?

Como lidamos com updates e novas features?

Como podemos customizar as funcionalidades da aplicação?

Como permitir que atualizações e novas features não sejam impedidas por customizações?

DATA STORAGE CODEBASE CUSTOMIZAÇÃO

Não existe escolha certa ou errada!

O que existe são escolhas que fazem mais sentido para determinados cenários.

Data storage

Três formatos mais comuns

Data storage

Instâncias separadas

Bancos de dados separadas

Banco de dados compartilhado

Cada cliente possui uma instância do seu SGDB (MySQL, Postgres, Mongo, etc), com seus dados isolados.

Mais isolado

Mais compartilhado

Cada cliente tem um banco de dados (ou schema) diferente, na mesma instância

Todos os clientes estão na mesma base de dados; o cliente é identificado por meio de uma coluna nas tabelas (tenantID)

Referência / diagramas: Microsoft - https://msdn.microsoft.com/en-us/library/aa479086.aspx

Data storage

Instâncias separadas

Bancos de dados separadas

Banco de dados compartilhado

Mais isolado

Mais compartilhado

Todos os clientes estão na mesma base de dados; o cliente é identificado por meio de uma coluna nas tabelas (tenantID)

Referência / diagramas: Microsoft - https://msdn.microsoft.com/en-us/library/aa479086.aspx

Data storage

Instâncias separadas

Bancos de dados separadas

Banco de dados compartilhado

Mais isolado

Mais compartilhado

Cada cliente tem um banco de dados (ou schema) diferente, na mesma instância

Referência / diagramas: Microsoft - https://msdn.microsoft.com/en-us/library/aa479086.aspx

Data storage

Instâncias separadas

Bancos de dados separadas

Banco de dados compartilhado

Mais isolado

Mais compartilhado

Cada cliente possui uma instância do seu SGDB (MySQL, Postgres, Mongo, etc), com seus dados isolados.

Referência / diagramas: Microsoft - https://msdn.microsoft.com/en-us/library/aa479086.aspx

Referência / diagramas: Microsoft - https://msdn.microsoft.com/en-us/library/aa479086.aspx

Referência / diagramas: Microsoft - https://msdn.microsoft.com/en-us/library/aa479086.aspx

Data storage

Instâncias separadas

Bancos de dados separadas

Banco de dados compartilhado

Sugestão de uso:

- Aplicações com pouca ou nenhuma variabilidade / customização

- Aplicações em que a principal customização é visual

- Aplicações com alto número de usuários (500k+)

Mais isolado

Mais compartilhado

Data storage

Sugestão de uso:

- Aplicações em que deve haver maior flexibilidade para customização

- Aplicações em que a infra-estrutura sempre será responsabilidade sua

- Planos baseados em volume de consumo ou performance

Instâncias separadas

Bancos de dados separadas

Banco de dados compartilhado

Mais isolado

Mais compartilhado

Data storage

Sugestão de uso:

- Projetos em que a separação física do hardware se faz necessária (instalações on-premises, compliance corporativo ou governamental, decisões de performance);

- Alta disparidade no volume de dados ou de acessos entre clientes (quando alguns clientes consomem demais)

- Quando você precisa monitorar o consumo individual de hardware para cada cliente (e seu SGDB não faz isso por database/schema)

Instâncias separadas

Bancos de dados separadas

Banco de dados compartilhado

Mais isolado

Mais compartilhado

- Em regra geral, a FLEXIBILIDADE necessária deve ser o fator decisório

- Customizar funcionalidades pode ser um desafio quando você tem um modelo de dados fixo

- Use o pattern de "migrations" e "seeds" para criar e manter o database schema

- Você não necessariamente precisa escolhar um único modelo para todos os dados da aplicação

Data storage

Relembrando!Não existe escolha certa ou errada!

Data storage: na prática

Data storage: na práticaModelo compartilhado (via tenant ID)

Data storage: na práticaModelo isolado (instâncias diferentes)

Codebase

Codebase- Dois cenários: uma instância para todos, ou uma instância por tenant

app cliente1.app.com

código fontecliente2.app.com

cliente3.app.com

config 1

config 2

config 3

cliente1.app.com

código fonte

config 1

cliente2.app.com

código fonte

config 2

cliente3.app.com

código fonte

config 3

custom code

Uma instância para todos

Uma instância por cliente

Codebase- Uma instância para todos

- Atualizações são sincronizadas sem custo ou esforço- Nenhum ou pouquíssimo "housekeeping" necessário- Não é muito flexível para customizações- Mais fácil de escalar quando o padrão de consumo de todos os clientes é semelhante

app

código fonte

cliente1.app.com

cliente2.app.com

bigcorp.app.com

config 1

config 2

config 3

Codebase- Uma instância para todos

- Atualizações são sincronizadas sem custo ou esforço- Nenhum ou pouquíssimo "housekeeping" necessário- Não é muito flexível para customizações- Mais fácil de escalar quando o padrão de consumo de todos os clientes é semelhante

app

código fonte

cliente1.app.com

cliente2.app.com

bigcorp.app.com

config 1

config 2

config 3

Nginx sitesvia DB, cachedGit repository

Codebase- Uma instância por cliente

- Atualizações não são sincronizadas, exceto se automatizadas- Necessário um trabalho de "housekeeping" para manutenção das instâncias- Bastante flexível para customizações- Qualquer cliente pode ter sua versão da aplicação "congelada"- O código do próprio "core" da aplicação pode ser forkado e alterado a qualquer momento

(se em algum momento isso fizer sentido para o negócio)

bigcorp.app.com

código fonte

config 1

cliente1.app.com

código fonte

config 2

cliente2.app.com

código fonte

config 3

custom code

Codebase- Uma instância por cliente

- Atualizações não são sincronizadas, exceto se automatizadas- Necessário um trabalho de "housekeeping" para manutenção das instâncias- Bastante flexível para customizações- Qualquer cliente pode ter sua versão da aplicação "congelada"- O código do próprio "core" da aplicação pode ser forkado e alterado a qualquer momento

(se em algum momento isso fizer sentido para o negócio)

bigcorp.app.com

código fonte

config 1

cliente1.app.com

código fonte

config 2

cliente2.app.com

código fonte

config 3

custom code

Git repo

.env files

Codebase- Uma instância por cliente

- Atualizações não são sincronizadas, exceto se automatizadas- Necessário um trabalho de "housekeeping" para manutenção das instâncias- Bastante flexível para customizações- Qualquer cliente pode ter sua versão da aplicação "congelada"- O código do próprio "core" da aplicação pode ser forkado e alterado a qualquer momento

(se em algum momento isso fizer sentido para o negócio)

bigcorp.app.com

código fonte

config 1

cliente1.app.com

código fonte

config 2

cliente2.app.com

código fonte

config 3

custom code

Nginx sites + PHP-FPM pools

v1.4.0 v1.4.1 v1.4.0

Codebase- De novo, o maior fator decisório aqui deve ser a FLEXIBILIDADE: o

quanto você espera que o código da aplicação se altere com customizações de clientes?

- A escalabilidade, embora seja um desafio (e mereceria uma palestra a parte), não deve ser dificultada em nenhum dos cenários, DESDE QUE você automatize todos os processos e fique de olho na consistência

- Instâncias isoladas permitem que você escale clientes mais "barulhentos" (alto volume) para hardware melhor

Variabilidade e customização

Variabilidade e customização

- O calcanhar de aquiles da arquitetura multi-tenant- Requer bastante meditação sobre os requisitos- Aqui é um dos melhores lugares onde design

patterns e uma arquitetura sã e consistente brilham de verdade

- Vou falar sobre algumas técnicas e formatos interessantes

Variabilidade e customização

Para configuração:

Para instâncias de código isoladas: um arquivo de configuração (biblioteca DotEnv)

Para instâncias unificadas: parâmetros de configuração no banco/repositório de tenant data

.env

Variabilidade e customização

Para o data storage:

Migrations: funcionam como um controle de versão do seu modelo de dados

A maioria dos frameworks/ORMs possuem suporte built-in (Laravel, CakePHP, Doctrine), e há libs standalone para outros formatos.

Sempre criar migrations "reversíveis", ou seja, que possam sofrer rollback

Variabilidade e customizaçãoPara o código / funcionalidade: EVENTS

Transação de negócio (ex: novo pedido realizado)

Gerenciador de eventos (via Framework, biblioteca ou hand-made)

Sub-serviços do core app

Módulo customizado: NF-E

Envio de e-mail para o usuário

Registro no log de atividade do usuário

Geração de NF-E

Módulo customizado: Tracking

Registrar nova carga à entregar

dispatchEvent('order_created', $order);

Variabilidade e customizaçãoPara o código / funcionalidade: EVENTS

Transação de negócio (ex: novo pedido realizado)

Gerenciador de eventos (via Framework, biblioteca ou hand-made)

Sub-serviços do core app

Módulo customizado: NF-E

Envio de e-mail para o usuário

Registro no log de atividade do usuário

Geração de NF-E

Módulo customizado: Tracking

Registrar nova carga à entregar

dispatchEvent('order_created', $order);CORE APP

CUSTOM CODE

return [['Entregas','abc.delivery.index'],['Configurar Frete','abc.delivery.config']

];

Variabilidade e customização

Renderizar menu principal

Gerenciador de hooks triggerHook('render_menu');

return [['Pedidos','core.orders.index']];

return [['Estoque','core.inventory.index']];

Módulos do core app

Módulo de Pedidos

Módulo de Estoque

Custom code do cliente ABC

Módulo de Entregas

return [...];

Para o código / funcionalidade: HOOKS

Variabilidade e customização

Order

BillingGatewayContract

PayPalBillingGateway

implementaDI Container

registra

recebe PayPalBillingGateway

pede BillingGatewayContract

Para o código / funcionalidade: DEPENDENCY INJECTION

Variabilidade e customização

Order

BillingGatewayContract

PayPalBillingGateway

Core app

Order

BillingGatewayContract

PayPalBillingGateway

Core app

Order

BillingGatewayContract

PayPalBillingGateway

Core app

TENANT 1 TENANT 2 TENANT 3

Para o código / funcionalidade: DEPENDENCY INJECTION

Variabilidade e customização

Order

BillingGatewayContract

PayPalBillingGateway

Core app

Order

BillingGatewayContract

PayPalBillingGateway

Core app

Order

BillingGatewayContract

PayPalBillingGateway

Core app

TENANT 1 TENANT 2 TENANT 3

Para o código / funcionalidade: DEPENDENCY INJECTION

PagSeguroBillingGateway

Custom code

Variabilidade e customizaçãoPara o front-end / interface: TEMPLATING (Blade, Twig…)

Variabilidade e customizaçãoPara o front-end / interface: SASS / Pré-compiladores

O PHP pode gerar seu config, e rodar o build durante a atualização de um tenant

Variabilidade e customizaçãoPara infra-estrutura / deploy...

Variabilidade e customizaçãoPara infra-estrutura / deploy...

Variabilidade e customização

http://forge.laravel.com

http://deployhq.comhttp://envoyer.io

Use ferramentas ou serviços de automatização de deploy(imagine atualizar manualmente a versão de 600 clientes)

Para infra-estrutura / deploy...

Variabilidade e customização

Use o Composer para gerenciar core app e código customizável

Para infra-estrutura / deploy...

Variabilidade e customização

Automatize (se aplicável) o processo de provisionamento para novos clientes

Novo cliente cadastrado

Script / microservice de PROVISIONAMENTO

Criar pasta no servidor e site no Nginx

Criar banco de dados

Gerar .env de configuração

Criar registro no DB de tenants

Cadastrar no Envoyer e realizar primeiro deploy

Gerar composer.json com Core + Custom code

Disparar e-mail para o cliente

Gerar config do Sass e compilar CSS final

Para infra-estrutura / deploy...

Variabilidade e customização

Automatize (se aplicável) o processo de provisionamento para novos clientes

Novo cliente cadastrado

Script / microservice de PROVISIONAMENTO

Criar pasta no servidor e site no Nginx

Criar banco de dados

Gerar .env de configuração

Criar registro no DB de tenants

Cadastrar no Envoyer e realizar primeiro deploy

Gerar composer.json com Core + Custom code

Disparar e-mail para o cliente

Gerar config do Sass e compilar CSS final

Para infra-estrutura / deploy...

Variabilidade e customização

O custo e tempo para provisionamento interfere diretamente em um KPI de negócio, o CAC (Custo de Aquisição de Cliente)

Provavelmente toda sua infra-estrutura pode ser administrada via API; use isso a seu favor:

- Amazon EC2 e DigitalOcean tem APIs para provisionamento de servidores

- Amazon S3 e Rackspace Cloud tem APIs para criação de novos "buckets" de arquivos

- Amazon Route 51 e DigitalOcean tem APIs para gerenciar o DNS (domínios customizáveis)

Para infra-estrutura / deploy...

TL;DROriente sua arquitetura principalmente pela sua necessidade de flexibilidade e customização

Mais customizável ➜ mais isoladaMais uniforme ➜ mais compartilhada

Use as melhores práticas de SOLID, principalmente no que diz respeito a Inversão de Dependência; a arquitetura multitenant é provavelmente o melhor use-case de substituição de implementações de uma interface em runtime

TL;DRAutomatize TUDO que diz respeito a provisionamento, deploy e housekeeping de infraestrutura: manutenção manual de instâncias é uma eterna dívida técnica que se acumula

TDD é PRIMORDIAL; lembre-se que em um ambiente sincronizado, uma atualização impacta TODOS os seus clientes

Perguntas?

Obrigado!

Telegram: @DfKimeraE-mail / Hangouts: aryel.tupinamba@lqdi.netFacebook: http://facebook.com/aryel.tupinambaTwitter: http://twitter.com/DfKimeraLinkedIn: http://linkedin.com/in/aryeltupinamba

Slides da palestra: http://slideshare.net/aryeltupinamba

http://lqdi.net