Iniciando o design arquitetural de um "serviço para armazenar e compartilhar arquivos" (como o Dropbox)

I don’t need a hard disk in my computer if I can get to the server faster… carrying around these non-connected computers is byzantine by comparison.
Steve Jobs

No passado era comum que usuários “perdessem” arquivos importantes ao trocar de equipamento ou “formatar o HD”. Seja por desorganização ou por incapacidade técnica, o fato é que algum arquivo importante sempre acabava “esquecido” – sem cópias de segurança – e definitivamente perdido.

Compartilhar arquivos também já foi um grande desafio – disquetes, pendrives e outras mídias exóticas, frequentemente corrompidas, contendo múltiplas versões de conteúdo importante.

Garantir a manutenção e compartilhamento de arquivos ficou muito mais fácil com o advento da nuvem e o surgimento de serviços como o Dropbox. Um serviço na nuvem que permite a sincronização de arquivos em múltiplos dispositivos, upload/download e compartilhamento facilitado.

História do Dropbox

A ideia do Dropbox surgiu quando por acaso um dos seus futuros criadores (Drew Houston) esqueceu seu pendrive quando viajava em um ônibus e precisava dele para uma consultoria que daria em uma empresa. Frustrado com a perda, Drew começou a escrever um código sem nenhuma pretensão, e que futuramente viria se chamar Dropbox.

Drew também cita em entrevistas que já estava saturado de ter que ficar abrindo seu e-mail a todo instante para anexar arquivos e poder acessá-los remotamente mais tarde. Seu trabalho inicial era apenas para resolver seu problema pessoal, só depois, Houston viu que sua ideia tinha um bom potencial de mercado.

Formado no MIT em ciência da computação, Drew deu inicio a seus trabalhos no projeto, e convidou seu colega Arash Ferdowsi a participar do mesmo. Arash na época ainda não tinha se formado no MIT e interrompeu seu curso para ajudar no projeto. Eles conseguiram um contrato com a empresa de aceleração de crescimento Y Combinator em 2007, se mudaram para o Vale do Silício, para sediar a empresa, e colocaram o produto no ar em 2008.

Fonte: Wikipedia.

Nesse capítulo vamos iniciar a arquitetura de um serviço para armazenamento e compartilhamento de arquivos” (como o Dropbox). A ideia não é completar a arquitetura, até porque a arquitetura de um sistema só está completa quando o sistema está completo. Nosso desejo é dar os “primeiros passos”

Coletando informações para o Haiku

Em nosso cenário fictício, desejamos criar um serviço de armazenamento de arquivos, similar ao DropBox, Google Drive e Onedrive.

As principais features desse serviço são: upload e download de arquivos, sincronização dos arquivos armazenados com uma pasta local especificada (sync folder) e, finalmente, manter um “histórico de versões” para cada arquivo.

Estima-se 5 milhões de usuários ativos diários (DAU), com 50 milhões de requisições diárias. Estima-se que os arquivos armazenados no serviço tenham, em média, 3 MB. Há um limite de de 10GB por usuário ativo.

Lembre-se, Gigabyte (GB) é diferente de Gigabit (Gb)

NÃO há demanda por criptografar conteúdo armazenado.

Os atributos de qualidade mais importantes são disponibilidade e desempenho.

Algumas estimativas de “papel de pão”

Com base nas informações levantadas com o negócio, em nosso cenário fictício, é possível elaborar algumas estimativas, grosseiras, mas já suficientes para orientar algumas decisões de design.

A ideia não é, necessariamente, chegar a precisão decimal, mas “compartilhar a visão” de números mais tangíveis e começar a estabelecer restrições.

Explicitando as principais features

Como indicado no Haiku, as principais features são:

  1. upload e download de arquivos;
  2. sincronização dos arquivos armazenados com uma pasta local especificada (sync folder)
  3. manter um “histórico de versões” para cada arquivo.

Essas três funcionalidades principais estão consolidadas na visão do modelo abaixo.

Proposta ingênua

Ingenuamente, podemos assumir que manter um sistema de armazenamento de arquivos consiste apenas na implementação upload e download, com alguma estrutura simples de dados para indicar versionamento (ou seja, para um determinado arquivo, modificado algumas vezes, ordenar as “versões” cronologicamente).

Upload e download de arquivos inteiros são operações triviais e fáceis de implementar. Entretanto, como desejamos manter históricos de arquivos, é importante considerar que, quando estivermos lidando com arquivos maiores, teremos muitas duplicações, onerando o armazenamento, e tráfego de dados, onerando largura de banda. Dessa forma, impactando negativamente o desempenho e o custo.

Para cada arquitetura, tente determinar quais são as variáveis que exercem maior influência no custo e no risco.

How we've scaled Dropbox

Excelente palestra, Kevin Modzelewski explica um pouco da história do Dropbox e a arquitetura da plataforma em 2012.

Acessar vídeo

Organizando informações para as primeiras ADRs

A partir das informações obtidas para formulação do Haiku e da “solução ingênua”, já é possível indicar algumas ADRs com status de “aberta para discussão”. Essas ADRs indicariam a “inclinação arquitetural” para diversos aspectos importantes, possibilitando debates entre especialistas.

Utilizar S3 (Simple Storage Service) ou Azure Blob

Manter arquivos, garantindo disponibilidade, não é tarefa simples. É importante desenvolver estratégias de replicação e consistência que não são nada fáceis de obter, principalmente considerando a escala.

Felizmente, embora este seja um problema complexo, as soluções disponíveis hoje em dia, no mercado, são quase commodities.

Definição: Commodity

Produtos ou serviços que não se diferem independente de quem os produziu ou origem, sendo seu preço uniformemente determinado pela oferta e procura.

Concentre-se no desenvolvimento do que agrega valor para o negócio. Adote soluções de mercado para problemas comuns.

Fracionar arquivos em “blocos”

Uma alternativa candidata para minimizar o volume de dados armazenados e o tráfego na rede, seria fracionar arquivos da pasta sincronizada em blocos, com um tamanho máximo pré-determinado. Um arquivo de 10 MB, por exemplo, poderia ser fracionado em 10 blocos com 1 MB cada.

Toda vez que um arquivo for modificado, realiza-se apenas o upload do(s) bloco(s) afetado(s) para o serviço. Da mesma forma, apenas blocos modificados poderiam ser “baixados” para clientes para realizar atualização.

No servidor, cada arquivo haveria uma lista de “versões”, onde cada versão, por sua vez, relacionaria uma lista ordenada de blocos correspondentes.

Um mesmo “bloco” de um arquivo, poderia estar disponível em mais de uma versão.

Para fins de comparação, cada bloco pode ser identificado por um hash.

Adotar sincronização diferencial

Além da estratégia de fracionamento de arquivos, visando reduzir armazenamento e tráfego de dados na rede, é importante, também, considerar alguma abordagem de sincronização diferencial. Dentre as mais famosas, há o algoritmo rsync.

O algoritmo rsync

Uma boa descrição do algoritmo rsync pode ser encontrada na wikipedia. Trata-se da base do utilitário com mesmo nome, disponível para Linux desde a década de 1990.

Acessar artigo

Sincronização diferencial (Google TechTalks)

Palestra sobre sincronização diferencial, ministrada por especialistas da Google. Ótima referência, inclusive explicando a lógica de funcionamento do Google Docs.

Acessar vídeo

Implementar de um “cliente inteligente” para o Sync

Para a funcionalidade sincronização de arquivos, tão importante quanto o serviço na nuvem é uma aplicação inteligente instalada em cada dispositivo.

Essa aplicação inteligente deve ser capaz de fracionar os arquivos da pasta sincronizada em blocos, computar hashs desses blocos, de forma a compará-los como a versão remota, otimizando downloads e uploads.

Autonomous Computing

Pat Helland criou, há décadas, o conceito de computação autônoma. Ele utiliza analogias, como feudos e emissários, para explicar papéis dos diversos artefatos em sistemas distribuídos. Leitura mais do que recomendada!

Acessar artigo

A aplicação cliente precisa ter pelo menos quatro capacidades.

  1. Watcher – identificando mudanças na pasta sincronizada, tais como adições, modificações ou remoções de arquivos; modificações na estrutura de subpastas, movimentações de arquivos nas subpastas.
  2. Chuncker – particionando arquivos em blocos e orquestrando downloads e uploads destes blocos para um serviço de armazenamento mais simples.
  3. Indexer – que gerencia informações relacionadas aos arquivos tratados, como conflitos e os endereços remotos para os blocos processados pelo chunker. O indexer, também deve ser o responsável por “notificar” o synchronizer remoto quanto as modificações que ocorrerem e, finalmente, ser notificado por ele quando modificações acontecerem em outros devices, aplicando-as localmente.
  4. Synchronizer – mantem uma fila local com todas as modificações notificadas pelo indexar, enviando-as para o serviço remoto quando uma conexão estiver disponível e, também, obtendo atualizações.

A visão do modelo abaixo condensa a estrutura indicada acima.

O design arquitetural sempre trata da modularização – distribuição das responsabilidades em componentes – de um sistema ou da forma como as “conexões” entre os diversos artefatos modulares se comunicam.

Request & Response queues

A natureza da comunicação entre o serviço de armazenamento e compartilhamento e os agentes para sincronização é naturalmente assíncrona.

Agentes locais de sincronização podem, a todo momento, estar ou não conectados a internet. Por isso, é necessária a construção de duas filas:

  1. Request queues – local, gerenciada por cada agente de sincronização, contendo o histórico de modificações endereçadas pelo indexer.
  2. Response queues – centralizada, mantida no servidor, contendo tópicos dedicados para cada agente local de sincronização.

Pontos que ainda necessitam reflexão

O processo de elaboração da arquitetura deve ser incremental. Tão importante quanto relacionar decisões realizadas é indicar claramente o que ainda precisa ser ponderado.

Com relação ao sistema que estamos projetando é importante, ainda, considerar:

  • Rate Limiting, visando mitigar o risco potencial de usuários mal-intencionados enviarem um número esmagadoramente grande de atualizações.
  • Segurança dos dados no lado do servidor, considerando alternativas para criptografia

Takeaways

A elaboração desse “início de trabalho arquitetural” para um “serviços para armazenamento e compartilhamento de arquivos” permite alguns aprendizados importantes:

  1. Em sistemas massivamente distribuídos, é importante sinalizar “feudos e emissários”;
  2. Soluções triviais para pequenos volumes de dados raramente funcionam em grandes escalas;
  3. Em cada arquitetura, determine o mais cedo possível as variáveis que mais influenciam em custo e risco;
  4. Arquitetura é, em grande parte, a arte de “dividir responsabilidades em módulos”;
  5. Utilize commodities no lugar de “reinventar a roda”.

Dúvidas ou sugestões? Deixe suas contribuições nos comentários.

 

Compartilhe este capítulo:

Compartilhe:

Comentários

Participe da construção deste capítulo deixando seu comentário:

Inscrever-se
Notify of
guest
0 Comentários
Feedbacks interativos
Ver todos os comentários

Fundador e CEO da EximiaCo, atua como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Mentoria

para arquitetos de software

Imersão, em grupo, supervisionada por Elemar Júnior, onde serão discutidos tópicos avançados de arquitetura de software, extraídos de cenários reais, com ênfase em systems design.

Consultoria e Assessoria em

Arquitetura de Software

EximiaCo oferece a alocação de um Arquiteto de Software em sua empresa para orientar seu time no uso das melhores práticas de arquitetura para projetar a evolução consistente de suas aplicações.

ElemarJúnior

Fundador e CEO da EximiaCo, atua como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

+55 51 99942-0609 |  contato@eximia.co

+55 51 99942-0609  contato@eximia.co

0
Quero saber a sua opinião, deixe seu comentáriox
()
x