SlideShare uma empresa Scribd logo
1 de 38
Multipart Upload,
Streaming e Criptografia
Desafios de um serviço de armazenamento de arquivos feito em GO
There is More to Know | Neoway
Marcelo Aymone
marcelo.aymone@neoway.com.br
Desenvolvedor de software na Neoway há quase 2 anos, atua na
manutenção e evolução da arquitetura de indexação e pesquisas
do motor de buscas. Além de produzir software ama cozinhar e
jogar RPG online.
Diogo Giassi
diogo.giassi@neoway.com.br
Desenvolvedor de software na Neoway a mais de cinco anos onde
atualmente conduz um Squad com foco em solucionar desafios
que envolvem integrações automatizadas entre plataformas para
ingestão e extração de dados. Aficionado por solucionar
problemas, encontrou a mais de dez anos no desenvolvimento de
software uma forma de unir trabalho e paixão.
A Neoway
Resolvemos problemas reais de
empresas que precisam vender
mais ou perder menos.
Usamos o Big Data como uma
ferramenta de descoberta de
oportunidades mercadológicas, tornando
o grande volume de dados facilmente
navegável, as análises intuitivas e as
decisões mais seguras.
https://www.neoway.com.br
O Projeto
There is More to Know | Neoway
Neoway Drive
Lançado em Fevereiro de 2018, o
Neoway Drive, tem o propósito
de servir como um repositório
persistente para arquivos
importados/exportados pelo
usuário a partir dos diversos
outros apps. Organizado por um
diretório raíz e sub-diretórios, os
arquivos são armazenados
durante um determinado
período de tempo, até que
sejam finalmente expirados.
Aplicação
Componente
There is More to Know | NeowayThere is More to Know | Neoway
Requisitos Técnicos
● Possível instalação em ambientes Cloud ou
OnPremises;
● Transferência e armazenamento dos arquivos de
forma criptografada;
● Possibilitar o armazenamento de arquivos com
até 5 Gigas de tamanho;
● Extração de Metadados durante o processo de
Upload (Ex.: Contagem de linhas, Checksum);
● Upload através do Browser com barra de
progresso;
● Centralizar os pontos de recebimento e entrega
de arquivos aos usuários da plataforma.
There is More to Know | Neoway
Application Cluster
Arquitetura / Integrações
DRIVE
WebApp
DRIVE
API - Gateway
DRIVE
Service
Mongo
DB
AWS
S3
HUB
WebApp
HUB
API - Gateway
MATCHING
Service
PV
BIN
META
DRIVE
SEARCHBAR
WebApp
SEARCHBAR
API - Gateway
EXPORT
Service
PV
PV
DriveLayer
BIN
META
Front Layer Gateway Layer
Service Layer StoragesComponents
Legenda
Temporary Storage
Mongo
DB
Mongo
DB
Desafios
There is More to Know | NeowayThere is More to Know | Neoway
Desafios
● Extração de metadados baseados no tipo e
conteúdo do arquivo;
● Feedback de progresso para o usuário nos
processos de Upload e Download;
● Complexidade da arquitetura da Neoway;
● Trafegar arquivos de até 5GB entre as camadas
garantindo:
○ Ausência de timeouts;
○ Baixo consumo de recursos;
○ Segurança no tráfego e armazenamento de
dados;
● Calcular o Checksum do arquivo.
There is More to Know | Neoway
Application Cluster
Baseada em Microsserviços
Gatekeepers Cluster
Node 1
Node 2Node 2
Node 1
NGINX
Reverse-Proxy
Arquitetura - Neoway
Mongo
DB
AWS
S3
BIN
META
BIN
META
DRIVE
Service
PV
DRIVE
API - Gateway
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
NGINX
Reverse-Proxy
AZURE-LOADBALANCER
Load-Balancer
AZURE-LOADBALANCER
Load-Balancer
NGINX
Reverse-Proxy
DRIVE
Service
PV
DRIVE
API - Gateway
NGINX
Reverse-Proxy
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
DriveServiceLayer
CLOUDFLARE
ServidorDNS
There is More to Know | Neoway
Application Cluster
Redundância
Gatekeepers Cluster
Node 1
Node 2Node 2
Node 1
NGINX
Reverse-Proxy
Arquitetura - Neoway
Mongo
DB
AWS
S3
BIN
META
BIN
META
DRIVE
API - Gateway
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
NGINX
Reverse-Proxy
NGINX
Reverse-Proxy
DRIVE
API - Gateway
NGINX
Reverse-Proxy
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
DriveServiceLayer
CLOUDFLARE
ServidorDNS
AZURE-LOADBALANCER
Load-Balancer
AZURE-LOADBALANCER
Load-Balancer
Redundância de serviços
DRIVE
Service
DRIVE
Service
PV
PV
There is More to Know | Neoway
Application Cluster
Timeouts
Gatekeepers Cluster
Node 1
Node 2Node 2
Node 1
NGINX
Reverse-Proxy
Arquitetura - Neoway
Mongo
DB
AWS
S3
BIN
META
BIN
META
DRIVE
Service
PV
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
NGINX
Reverse-Proxy
NGINX
Reverse-Proxy
DRIVE
Service
PV
NGINX
Reverse-Proxy
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
DriveServiceLayer
CLOUDFLARE
ServidorDNS
Timeout de 60 segundos em várias
camadas e a sessão do usuário
AZURE-LOADBALANCER
Load-Balancer
AZURE-LOADBALANCER
Load-Balancer
DRIVE
API - Gateway
DRIVE
API - Gateway
There is More to Know | Neoway
Application Cluster
Consumo de Memória
Gatekeepers Cluster
Node 1
Node 2Node 2
Node 1
NGINX
Reverse-Proxy
Arquitetura - Neoway
Mongo
DB
AWS
S3
BIN
META
BIN
META
DRIVE
Service
PV
DRIVE
API - Gateway
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
NGINX
Reverse-Proxy
NGINX
Reverse-Proxy
DRIVE
Service
PV
DRIVE
API - Gateway
NGINX
Reverse-Proxy
HEIMDALL
Vulcand-Proxy
LOKI
Authorization
Server
DriveServiceLayer
CLOUDFLARE
ServidorDNS
Middlewares sem suporte a stream
levando a um alto consumo de memória
AZURE-LOADBALANCER
Load-Balancer
AZURE-LOADBALANCER
Load-Balancer
Conceitos e Solução
There is More to Know | Neoway
Leitura e Escrita
Source io.Reader
Targetio.Writer
Transfer Buffer []byte
io.Reader
● É a interface que envolve o método básico de leitura: Read(p []byte) (n int, err error).
io.Writer
● É a interface que envolve o método básico de escrita: Write(p []byte) (n int, err error).
Transfer Buffer []byte
There is More to Know | Neoway
io.Copy
Stream
Targetio.Writer
Transfer Buffer []byte
Source io.Reader
io.Copy
● O método io.Copy realiza a cópia da origem para o destino;
● Retorna o número de bytes copiados e o primeiro erro encontrado durante a cópia, se
houver;
● Possui um tamanho padrão de buffer de 32 KB. Caso precise de um buffer de tamanho
diferente utilizar io.CopyBuffer.
There is More to Know | Neoway
io.Copy
Stream - Analisando Dados
Targetio.Writer
Transfer Buffer []byte
Source io.Reader io.TeeReader
io.Writer Target
io.TeeReader
● O método io.TeeReader retorna um io.Reader que escreve para um Destino o que lê de uma
Origem. Todas as leituras realizadas através dele são correspondidas com as gravações
correspondentes para o novo Destino informado;
● Não há buffer interno - a gravação deve ser concluída antes da leitura ser concluída.
There is More to Know | Neoway
io.Copy
Stream - Criptografando Dados
Targetio.Writer
Transfer Buffer []byte
Source io.Reader cipher.StreamReader
cipher.Stream
● Representa uma cifra de fluxo;
cipher.StreamReader
● Agrupa um fluxo em um io.Reader. Ele chama XORKeyStream da interface cipher.Stream para
processar cada fatia de dados que passa.
There is More to Know | Neoway
Stream - Criptografando Dados
aes.NewCipher
● Retorna um novo cifrador de blocos (cipher.Block), baseado em uma chave AES de 16, 24 ou
32 Bytes para selecionar o algoritmo AES-128, AES-192 ou AES-256.
cipher.NewOFB
● Retorna um fluxo que pode criptografar ou descriptografar usando uma cifrador de bloco no
modo Output Feedback (OFB).
func BuildOFBStreamReader(key string, reader io.Reader) (io.Reader, error) {
block, err := aes.NewCipher([]byte(key))
if err != nil {
return nil, err
}
var iv [aes.BlockSize]byte
stream := cipher.NewOFB(block, iv[:])
return &cipher.StreamReader{S: stream, R: reader}, nil
}
There is More to Know | Neoway
Download
io.Copy AWS SDK
Upload / Download
AWS
S3
http.ResponseWriter
io.Writer
cipher.OFB
cipher.StreamReader
Buffer
io.ReaderUser
Storage
Upload
AWS SDK
AWS
S3
io.TeeReader
cipher.OFB
cipher.StreamReader
Metadata
Extractor
io.Writer
sha256.Hash
io.Writer
io.TeeReader
Size
Rows
SHA-256
META
Buffer
http.Request.Body
io.Reader
User
Storage
There is More to Know | NeowayThere is More to Know | Neoway
Desafios (Solucionados)
● ✔ Extração de metadados baseados no tipo e
conteúdo do arquivo;
● Feedback de progresso para o usuário nos
processos de Upload e Download;
● Complexidade da arquitetura da Neoway;
● Trafegar arquivos de até 5 GB entre as camadas
garantindo:
○ Ausência de timeouts;
○ ✔ Baixo consumo de recursos;
○ ✔ Segurança no tráfego e armazenamento
de dados;
● ✔ Calcular o Checksum do arquivo.
There is More to Know | Neoway
Dividindo Arquivos
Chunked Transfer Encoding (HTTP 1.1)
● Conexão TCP persistente
● Cabeçalho “Transfer-Encoding: chunked”
● Tela parada até finalizar
● Buffer em camadas de roteamento
Técnica Multipart
● Múltiplas requests
● Envio paralelo de chunks
● Suporta barra de progresso
● Suporta pausar e continuar
● Controle de requests concorrentes
● Precisa codificar
Multipart
client server
Open
Close
Chunked Transfer
client server
Open
Close
Open
Open
Close
Close
There is More to Know | Neoway
Dividindo Arquivos
Blob
● Um objeto Blob representa um objeto do tipo arquivo, com dados brutos imutáveis.
hello world = 68 65 6c 6c 6f 20 77 6f 72 6c 64
string (11) = []byte
Blob Slice
● Novo objeto Blob contendo os dados do intervalo especificado de bytes(3) da fonte Blob.
hello world = 68 65 6c 6c 6f 20 77 6f 72 6c 64
3 bytes
There is More to Know | Neoway
Dividindo Arquivos - Frontend
Browser Upload
● Dividindo arquivos em múltiplas requisições.
Definições para multipart
● Tamanho dos chunks (bytes)
○ 1mb = 1.000.000 bytes
● Quantidade de chunks
○ filesize / chunksize
○ ceil(54234543 / 1000000) = 55
● Cabeçalho do envio
○ “Content-Range: bytes 1000-2000/10000”
● Controle de progresso
○ (1 / 55) * 100 = 1.8%
// set mimetype
let contentType = blob.type;
// set header from params
let rangeheader = `bytes ${start}-${end}/${size}`;
// create chunk from slice
let chunk = blob.slice(start, end, contentType);
// send request
const xhr = new XMLHttpRequest();
xhr.open('PUT', UPLOAD_URL, true);
xhr.setRequestHeader('Content-
Range',rangeheader);
xhr.setRequestHeader('Content-Type', contentType);
xhr.send(chunk);
There is More to Know | Neoway
Dividindo Arquivos - Frontend
There is More to Know | Neoway
Backend
● Endpoints:
○ Registrar o upload;
○ Enviar os chunks;
○ Finalizar o envio;
● Recombinar os chunks:
○ Ordenar (Chunk Id);
○ Agrupar;
○ Enviar (S3);
○ Limpar temporários;
Dividindo Arquivos - Backend
----------------------------------------
POST /v1/files
header Content-Type: "text/csv"
Response 201 Created
{ fileId: “5d74027c79f40700077c1950” }
----------------------------------------
PUT /v1/files/:fileId/chunked-upload
header Content-Range: "bytes 0-1000/10000"
Response 206 Partial Content
----------------------------------------
PUT /v1/files/:fileId/finish-upload
Response 202 Accepted
There is More to Know | Neoway
Backend
● Endpoints:
○ Registrar o upload;
○ Enviar os chunks;
○ Finalizar o envio;
● Recombinar os chunks:
○ Ordenar (Chunk Id);
○ Agrupar;
○ Enviar (S3);
○ Limpar temporários;
Dividindo Arquivos - Backend
type chunk struct {
name string // 0000-1000
start int64 // 0000
end int64 // 1000
}
type chunkSorter []*chunk
func (s chunkSorter) Len() int {
return len(s)
}
func (s chunkSorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s chunkSorter) Less(i, j int) bool {
a := s[i].start + s[i].end // 0000 + 1000 = 1000
b := s[j].start + s[j].end // 2000 + 3000 = 5000
return a < b
}
infos, err := ioutil.ReadDir(dirname) // []os.FileInfo
chunks := getChunks(infos) // parse chunk data from
os.fileInfo
sort.Sort(chunkSorter(chunks)) // sort after parse chunk metadata
Ordenação quicksort
There is More to Know | Neoway
Backend
● Endpoints:
○ Registrar o upload;
○ Enviar os chunks;
○ Finalizar o envio;
● Recombinar os chunks:
○ Ordenar (Chunk Id);
○ Agrupar;
○ Enviar (S3);
○ Limpar temporários;
Dividindo Arquivos - Backend
// open fileout to append chunks from list
fileOut, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
for _, chunk := range chunks {
// open chunk buffer
chunkBuffer, err := os.Open(dirName + “/” + chunk.name))
if err != nil {
return nil, err
}
// copy chunk buffer to fileOut in append mode
if _, err := io.Copy(fileOut, chunkBuffer); err != nil {
return nil, err
}
err = chunkBuffer.Close()
if err != nil {
return nil, err
}
//flush fileout buffer direct to disk
err = fileOut.Sync()
if err != nil {
return nil, err
}
There is More to Know | Neoway
Merging
Chunks
Chunk
Upload
io.Copy
io.Copy
Finish
Upload
AWS SDK
Dividindo Arquivos - Upload
os.File
io.Writer
Buffer
http.Request.Body
io.Reader
Local
Storage
AWS
S3
User
Storage
Local
Storage
os.File
io.Reader
io.TeeReader
cipher.OFB
cipher.StreamReader
Metadata
Extractor
io.Writer
sha256.Hash
io.Writer
io.TeeReader
Size
Rows
SHA-256
META
os.File
io.ReaderLocal
Storage
os.File
io.Writer
Local
Storage
Buffer
Buffer
os.File
io.Reader
os.File
io.Reader
There is More to Know | NeowayThere is More to Know | Neoway
Desafios (Solucionados)
● ✔ Extração de metadados baseados no tipo e
conteúdo do arquivo;
● ✔ Feedback de progresso para o usuário nos
processos de Upload e Download;
● ✔ Complexidade da arquitetura da Neoway;
● ✔ Trafegar arquivos de até 5 GB entre as
camadas garantindo:
○ ✔ Ausência de timeouts;
○ ✔ Baixo consumo de recursos;
○ ✔ Segurança no tráfego e armazenamento
de dados;
● ✔ Calcular o Checksum do arquivo.
Resultados
There is More to Know | Neoway
Resultados
Após um ano e meio do
lançamento do serviço em
produção estes são as
integrações e formas de uso do
serviço.
Utilização
Integrações
● Componente de Upload utilizado em 3 aplicativos
desenvolvidos em AngularJS e VueJS;
● Integrado com 7 serviços desenvolvidos em NodeJS e
GO que utilizam para:
○ Armazenamento temporário de dados exportados
em arquivos CSV, XLSX e ZIP.
○ Armazenamento de dossiês em arquivos PDF e
HTML por períodos de até 5 anos;
○ Área temporária para importação de dados
através de arquivos CSV.
There is More to Know | Neoway
Resultados
Utilização
Volume
● Mais de 168 mil arquivos armazenados dos seguintes
formatos: XLSX, PDF, CSV, HTML e ZIP;
● Em torno de 100 GB em arquivos armazenados;
● Crescimento mensal em 2019 na média de 15 mil
arquivos e 9 GB em espaço de armazenamento.
Custo S3 (AWS)
● Total de $ 3,05 dólares no mês de Agosto de 2019.
Após um ano e meio do
lançamento do serviço em
produção estes são os dados de
utilização e consumo de
recursos.
There is More to Know | Neoway
Consumo de Recursos
CPU
● Média de 0.2% em uma máquina Azure -
Standard D4s (v3) equipada com 4
processadores Intel Xeon® E5-2673 de 2,4 GHz.
Memória
● Média de 16 MB constantes indiferente do
tamanho dos arquivos trafegados.
Melhorias Futuras
There is More to Know | NeowayThere is More to Know | Neoway
Melhorias Futuras
● Não trabalhar com discos baseados em rede
como storage local;
● Expirar os arquivos para o Amazon S3 Glacier
visando a redução do custo;
● Permitir reiniciar da onde parou Uploads
interrompidos por problemas de comunicação;
● Não precisar informar de forma diferente ao
servidor que o Upload acabou, o mesmo saber por
entender que todas as partes chegaram;
● Melhorar o algoritmo de junção de partes para já
ir juntando as partes no decorrer do Upload.
Dúvidas?
Diogo Giassi
dagostindiogo@gmail.com
linkedin.com/in/diogo-giassi-dagostin
github.com/dagostindiogo
Marcelo Aymone
mbaymone@gmail.com.br
linkedin.com/in/marceloaymone
github.com/aymone
There is More to Know | Neoway
Referências
● https://developer.mozilla.org/pt-BR/docs/Web/API/Blob
● https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
● https://golang.org/pkg/io
● https://medium.com/learning-the-go-programming-language/streaming-io-in-go-
d93507931185
● https://developer.mozilla.org/pt-BR/docs/Web/API/Blob
● https://developer.mozilla.org/pt-BR/docs/Web/API/Blob/slice
● https://developers.google.com/drive/api/v3/manage-uploads#multipart
● https://pt.wikipedia.org/wiki/Quicksort
There is More to Know | Neoway

Mais conteúdo relacionado

Semelhante a Multipart Upload, Streaming e Criptografia - Desafios de um serviço de armazenamento de arquivos feito em GO

TDC2018SP | Trilha Serveless - Pra que SERVErless?
TDC2018SP | Trilha Serveless - Pra que SERVErless?TDC2018SP | Trilha Serveless - Pra que SERVErless?
TDC2018SP | Trilha Serveless - Pra que SERVErless?tdc-globalcode
 
Economize o Consumo de Link WAN com o BranchCache
Economize o Consumo de Link WAN com o BranchCacheEconomize o Consumo de Link WAN com o BranchCache
Economize o Consumo de Link WAN com o BranchCacheRodrigo Immaginario
 
ASP.Net Performance – A pragmatic approach - Luis Paulino
ASP.Net Performance – A pragmatic approach - Luis PaulinoASP.Net Performance – A pragmatic approach - Luis Paulino
ASP.Net Performance – A pragmatic approach - Luis PaulinoComunidade NetPonto
 
Apresentação GT - Digital Preservation
Apresentação GT - Digital PreservationApresentação GT - Digital Preservation
Apresentação GT - Digital PreservationRoberto Beraldo Chaiben
 
Desenvolvimento Ágil de Aplicações Web com Python e Django
Desenvolvimento Ágil de Aplicações Web com Python e DjangoDesenvolvimento Ágil de Aplicações Web com Python e Django
Desenvolvimento Ágil de Aplicações Web com Python e DjangoMatheus Pereira
 
Rails: Porque programar deve ser divertido
Rails: Porque programar deve ser divertidoRails: Porque programar deve ser divertido
Rails: Porque programar deve ser divertidoLuiz Carvalho
 
Git e Github - Comandos e conceitos básicos
Git e Github - Comandos e conceitos básicos Git e Github - Comandos e conceitos básicos
Git e Github - Comandos e conceitos básicos Jonathan Célio
 
Palestra Zend Framework na Campus Party 2011
Palestra Zend Framework na Campus Party 2011Palestra Zend Framework na Campus Party 2011
Palestra Zend Framework na Campus Party 2011Flávio Lisboa
 
BigQuery Performance Improvements Storage API
BigQuery Performance Improvements Storage APIBigQuery Performance Improvements Storage API
BigQuery Performance Improvements Storage APIAlvaro Viebrantz
 
Otimizacao de websites em PHP
Otimizacao de websites em PHPOtimizacao de websites em PHP
Otimizacao de websites em PHPFelipe Ribeiro
 
Workshop Hands-On APIX 2018 - Trilha Básica
Workshop Hands-On APIX 2018 - Trilha BásicaWorkshop Hands-On APIX 2018 - Trilha Básica
Workshop Hands-On APIX 2018 - Trilha BásicaSensedia
 
MongoDB - Apresentação
MongoDB - ApresentaçãoMongoDB - Apresentação
MongoDB - ApresentaçãoTerra / Neo
 
E-book sobre HTML 5 (Devmedia)
E-book sobre HTML 5 (Devmedia)E-book sobre HTML 5 (Devmedia)
E-book sobre HTML 5 (Devmedia)Devmedia
 
Apresentacao gt cnc-workshop_iniciliazicao_fase2
Apresentacao gt cnc-workshop_iniciliazicao_fase2Apresentacao gt cnc-workshop_iniciliazicao_fase2
Apresentacao gt cnc-workshop_iniciliazicao_fase2Lucas Silva
 
TDC 2017 - Borg até o Prometheus: Site Reliability Engineering
TDC 2017 - Borg até o Prometheus: Site Reliability EngineeringTDC 2017 - Borg até o Prometheus: Site Reliability Engineering
TDC 2017 - Borg até o Prometheus: Site Reliability EngineeringFelipe Klerk Signorini
 
REST - The right way
REST - The right wayREST - The right way
REST - The right waysantosluis87
 

Semelhante a Multipart Upload, Streaming e Criptografia - Desafios de um serviço de armazenamento de arquivos feito em GO (20)

TDC2018SP | Trilha Serveless - Pra que SERVErless?
TDC2018SP | Trilha Serveless - Pra que SERVErless?TDC2018SP | Trilha Serveless - Pra que SERVErless?
TDC2018SP | Trilha Serveless - Pra que SERVErless?
 
Economize o Consumo de Link WAN com o BranchCache
Economize o Consumo de Link WAN com o BranchCacheEconomize o Consumo de Link WAN com o BranchCache
Economize o Consumo de Link WAN com o BranchCache
 
ASP.Net Performance – A pragmatic approach - Luis Paulino
ASP.Net Performance – A pragmatic approach - Luis PaulinoASP.Net Performance – A pragmatic approach - Luis Paulino
ASP.Net Performance – A pragmatic approach - Luis Paulino
 
Apresentação GT - Digital Preservation
Apresentação GT - Digital PreservationApresentação GT - Digital Preservation
Apresentação GT - Digital Preservation
 
Django
DjangoDjango
Django
 
Desenvolvimento Ágil de Aplicações Web com Python e Django
Desenvolvimento Ágil de Aplicações Web com Python e DjangoDesenvolvimento Ágil de Aplicações Web com Python e Django
Desenvolvimento Ágil de Aplicações Web com Python e Django
 
Rails: Porque programar deve ser divertido
Rails: Porque programar deve ser divertidoRails: Porque programar deve ser divertido
Rails: Porque programar deve ser divertido
 
Git e Github - Comandos e conceitos básicos
Git e Github - Comandos e conceitos básicos Git e Github - Comandos e conceitos básicos
Git e Github - Comandos e conceitos básicos
 
De 1 a 1.000.00 de usuários
De 1 a 1.000.00 de usuáriosDe 1 a 1.000.00 de usuários
De 1 a 1.000.00 de usuários
 
Palestra Zend Framework na Campus Party 2011
Palestra Zend Framework na Campus Party 2011Palestra Zend Framework na Campus Party 2011
Palestra Zend Framework na Campus Party 2011
 
BigQuery Performance Improvements Storage API
BigQuery Performance Improvements Storage APIBigQuery Performance Improvements Storage API
BigQuery Performance Improvements Storage API
 
Otimizacao de websites em PHP
Otimizacao de websites em PHPOtimizacao de websites em PHP
Otimizacao de websites em PHP
 
Workshop Hands-On APIX 2018 - Trilha Básica
Workshop Hands-On APIX 2018 - Trilha BásicaWorkshop Hands-On APIX 2018 - Trilha Básica
Workshop Hands-On APIX 2018 - Trilha Básica
 
MongoDB - Apresentação
MongoDB - ApresentaçãoMongoDB - Apresentação
MongoDB - Apresentação
 
E-book sobre HTML 5 (Devmedia)
E-book sobre HTML 5 (Devmedia)E-book sobre HTML 5 (Devmedia)
E-book sobre HTML 5 (Devmedia)
 
Apresentacao gt cnc-workshop_iniciliazicao_fase2
Apresentacao gt cnc-workshop_iniciliazicao_fase2Apresentacao gt cnc-workshop_iniciliazicao_fase2
Apresentacao gt cnc-workshop_iniciliazicao_fase2
 
Asa cpbr4
Asa cpbr4Asa cpbr4
Asa cpbr4
 
Mongo db slides
Mongo db slidesMongo db slides
Mongo db slides
 
TDC 2017 - Borg até o Prometheus: Site Reliability Engineering
TDC 2017 - Borg até o Prometheus: Site Reliability EngineeringTDC 2017 - Borg até o Prometheus: Site Reliability Engineering
TDC 2017 - Borg até o Prometheus: Site Reliability Engineering
 
REST - The right way
REST - The right wayREST - The right way
REST - The right way
 

Multipart Upload, Streaming e Criptografia - Desafios de um serviço de armazenamento de arquivos feito em GO

  • 1. Multipart Upload, Streaming e Criptografia Desafios de um serviço de armazenamento de arquivos feito em GO
  • 2. There is More to Know | Neoway Marcelo Aymone marcelo.aymone@neoway.com.br Desenvolvedor de software na Neoway há quase 2 anos, atua na manutenção e evolução da arquitetura de indexação e pesquisas do motor de buscas. Além de produzir software ama cozinhar e jogar RPG online. Diogo Giassi diogo.giassi@neoway.com.br Desenvolvedor de software na Neoway a mais de cinco anos onde atualmente conduz um Squad com foco em solucionar desafios que envolvem integrações automatizadas entre plataformas para ingestão e extração de dados. Aficionado por solucionar problemas, encontrou a mais de dez anos no desenvolvimento de software uma forma de unir trabalho e paixão. A Neoway Resolvemos problemas reais de empresas que precisam vender mais ou perder menos. Usamos o Big Data como uma ferramenta de descoberta de oportunidades mercadológicas, tornando o grande volume de dados facilmente navegável, as análises intuitivas e as decisões mais seguras. https://www.neoway.com.br
  • 4. There is More to Know | Neoway Neoway Drive Lançado em Fevereiro de 2018, o Neoway Drive, tem o propósito de servir como um repositório persistente para arquivos importados/exportados pelo usuário a partir dos diversos outros apps. Organizado por um diretório raíz e sub-diretórios, os arquivos são armazenados durante um determinado período de tempo, até que sejam finalmente expirados. Aplicação Componente
  • 5. There is More to Know | NeowayThere is More to Know | Neoway Requisitos Técnicos ● Possível instalação em ambientes Cloud ou OnPremises; ● Transferência e armazenamento dos arquivos de forma criptografada; ● Possibilitar o armazenamento de arquivos com até 5 Gigas de tamanho; ● Extração de Metadados durante o processo de Upload (Ex.: Contagem de linhas, Checksum); ● Upload através do Browser com barra de progresso; ● Centralizar os pontos de recebimento e entrega de arquivos aos usuários da plataforma.
  • 6. There is More to Know | Neoway Application Cluster Arquitetura / Integrações DRIVE WebApp DRIVE API - Gateway DRIVE Service Mongo DB AWS S3 HUB WebApp HUB API - Gateway MATCHING Service PV BIN META DRIVE SEARCHBAR WebApp SEARCHBAR API - Gateway EXPORT Service PV PV DriveLayer BIN META Front Layer Gateway Layer Service Layer StoragesComponents Legenda Temporary Storage Mongo DB Mongo DB
  • 8. There is More to Know | NeowayThere is More to Know | Neoway Desafios ● Extração de metadados baseados no tipo e conteúdo do arquivo; ● Feedback de progresso para o usuário nos processos de Upload e Download; ● Complexidade da arquitetura da Neoway; ● Trafegar arquivos de até 5GB entre as camadas garantindo: ○ Ausência de timeouts; ○ Baixo consumo de recursos; ○ Segurança no tráfego e armazenamento de dados; ● Calcular o Checksum do arquivo.
  • 9. There is More to Know | Neoway Application Cluster Baseada em Microsserviços Gatekeepers Cluster Node 1 Node 2Node 2 Node 1 NGINX Reverse-Proxy Arquitetura - Neoway Mongo DB AWS S3 BIN META BIN META DRIVE Service PV DRIVE API - Gateway HEIMDALL Vulcand-Proxy LOKI Authorization Server NGINX Reverse-Proxy AZURE-LOADBALANCER Load-Balancer AZURE-LOADBALANCER Load-Balancer NGINX Reverse-Proxy DRIVE Service PV DRIVE API - Gateway NGINX Reverse-Proxy HEIMDALL Vulcand-Proxy LOKI Authorization Server DriveServiceLayer CLOUDFLARE ServidorDNS
  • 10. There is More to Know | Neoway Application Cluster Redundância Gatekeepers Cluster Node 1 Node 2Node 2 Node 1 NGINX Reverse-Proxy Arquitetura - Neoway Mongo DB AWS S3 BIN META BIN META DRIVE API - Gateway HEIMDALL Vulcand-Proxy LOKI Authorization Server NGINX Reverse-Proxy NGINX Reverse-Proxy DRIVE API - Gateway NGINX Reverse-Proxy HEIMDALL Vulcand-Proxy LOKI Authorization Server DriveServiceLayer CLOUDFLARE ServidorDNS AZURE-LOADBALANCER Load-Balancer AZURE-LOADBALANCER Load-Balancer Redundância de serviços DRIVE Service DRIVE Service PV PV
  • 11. There is More to Know | Neoway Application Cluster Timeouts Gatekeepers Cluster Node 1 Node 2Node 2 Node 1 NGINX Reverse-Proxy Arquitetura - Neoway Mongo DB AWS S3 BIN META BIN META DRIVE Service PV HEIMDALL Vulcand-Proxy LOKI Authorization Server NGINX Reverse-Proxy NGINX Reverse-Proxy DRIVE Service PV NGINX Reverse-Proxy HEIMDALL Vulcand-Proxy LOKI Authorization Server DriveServiceLayer CLOUDFLARE ServidorDNS Timeout de 60 segundos em várias camadas e a sessão do usuário AZURE-LOADBALANCER Load-Balancer AZURE-LOADBALANCER Load-Balancer DRIVE API - Gateway DRIVE API - Gateway
  • 12. There is More to Know | Neoway Application Cluster Consumo de Memória Gatekeepers Cluster Node 1 Node 2Node 2 Node 1 NGINX Reverse-Proxy Arquitetura - Neoway Mongo DB AWS S3 BIN META BIN META DRIVE Service PV DRIVE API - Gateway HEIMDALL Vulcand-Proxy LOKI Authorization Server NGINX Reverse-Proxy NGINX Reverse-Proxy DRIVE Service PV DRIVE API - Gateway NGINX Reverse-Proxy HEIMDALL Vulcand-Proxy LOKI Authorization Server DriveServiceLayer CLOUDFLARE ServidorDNS Middlewares sem suporte a stream levando a um alto consumo de memória AZURE-LOADBALANCER Load-Balancer AZURE-LOADBALANCER Load-Balancer
  • 14. There is More to Know | Neoway Leitura e Escrita Source io.Reader Targetio.Writer Transfer Buffer []byte io.Reader ● É a interface que envolve o método básico de leitura: Read(p []byte) (n int, err error). io.Writer ● É a interface que envolve o método básico de escrita: Write(p []byte) (n int, err error). Transfer Buffer []byte
  • 15. There is More to Know | Neoway io.Copy Stream Targetio.Writer Transfer Buffer []byte Source io.Reader io.Copy ● O método io.Copy realiza a cópia da origem para o destino; ● Retorna o número de bytes copiados e o primeiro erro encontrado durante a cópia, se houver; ● Possui um tamanho padrão de buffer de 32 KB. Caso precise de um buffer de tamanho diferente utilizar io.CopyBuffer.
  • 16. There is More to Know | Neoway io.Copy Stream - Analisando Dados Targetio.Writer Transfer Buffer []byte Source io.Reader io.TeeReader io.Writer Target io.TeeReader ● O método io.TeeReader retorna um io.Reader que escreve para um Destino o que lê de uma Origem. Todas as leituras realizadas através dele são correspondidas com as gravações correspondentes para o novo Destino informado; ● Não há buffer interno - a gravação deve ser concluída antes da leitura ser concluída.
  • 17. There is More to Know | Neoway io.Copy Stream - Criptografando Dados Targetio.Writer Transfer Buffer []byte Source io.Reader cipher.StreamReader cipher.Stream ● Representa uma cifra de fluxo; cipher.StreamReader ● Agrupa um fluxo em um io.Reader. Ele chama XORKeyStream da interface cipher.Stream para processar cada fatia de dados que passa.
  • 18. There is More to Know | Neoway Stream - Criptografando Dados aes.NewCipher ● Retorna um novo cifrador de blocos (cipher.Block), baseado em uma chave AES de 16, 24 ou 32 Bytes para selecionar o algoritmo AES-128, AES-192 ou AES-256. cipher.NewOFB ● Retorna um fluxo que pode criptografar ou descriptografar usando uma cifrador de bloco no modo Output Feedback (OFB). func BuildOFBStreamReader(key string, reader io.Reader) (io.Reader, error) { block, err := aes.NewCipher([]byte(key)) if err != nil { return nil, err } var iv [aes.BlockSize]byte stream := cipher.NewOFB(block, iv[:]) return &cipher.StreamReader{S: stream, R: reader}, nil }
  • 19. There is More to Know | Neoway Download io.Copy AWS SDK Upload / Download AWS S3 http.ResponseWriter io.Writer cipher.OFB cipher.StreamReader Buffer io.ReaderUser Storage Upload AWS SDK AWS S3 io.TeeReader cipher.OFB cipher.StreamReader Metadata Extractor io.Writer sha256.Hash io.Writer io.TeeReader Size Rows SHA-256 META Buffer http.Request.Body io.Reader User Storage
  • 20. There is More to Know | NeowayThere is More to Know | Neoway Desafios (Solucionados) ● ✔ Extração de metadados baseados no tipo e conteúdo do arquivo; ● Feedback de progresso para o usuário nos processos de Upload e Download; ● Complexidade da arquitetura da Neoway; ● Trafegar arquivos de até 5 GB entre as camadas garantindo: ○ Ausência de timeouts; ○ ✔ Baixo consumo de recursos; ○ ✔ Segurança no tráfego e armazenamento de dados; ● ✔ Calcular o Checksum do arquivo.
  • 21. There is More to Know | Neoway Dividindo Arquivos Chunked Transfer Encoding (HTTP 1.1) ● Conexão TCP persistente ● Cabeçalho “Transfer-Encoding: chunked” ● Tela parada até finalizar ● Buffer em camadas de roteamento Técnica Multipart ● Múltiplas requests ● Envio paralelo de chunks ● Suporta barra de progresso ● Suporta pausar e continuar ● Controle de requests concorrentes ● Precisa codificar Multipart client server Open Close Chunked Transfer client server Open Close Open Open Close Close
  • 22. There is More to Know | Neoway Dividindo Arquivos Blob ● Um objeto Blob representa um objeto do tipo arquivo, com dados brutos imutáveis. hello world = 68 65 6c 6c 6f 20 77 6f 72 6c 64 string (11) = []byte Blob Slice ● Novo objeto Blob contendo os dados do intervalo especificado de bytes(3) da fonte Blob. hello world = 68 65 6c 6c 6f 20 77 6f 72 6c 64 3 bytes
  • 23. There is More to Know | Neoway Dividindo Arquivos - Frontend Browser Upload ● Dividindo arquivos em múltiplas requisições. Definições para multipart ● Tamanho dos chunks (bytes) ○ 1mb = 1.000.000 bytes ● Quantidade de chunks ○ filesize / chunksize ○ ceil(54234543 / 1000000) = 55 ● Cabeçalho do envio ○ “Content-Range: bytes 1000-2000/10000” ● Controle de progresso ○ (1 / 55) * 100 = 1.8% // set mimetype let contentType = blob.type; // set header from params let rangeheader = `bytes ${start}-${end}/${size}`; // create chunk from slice let chunk = blob.slice(start, end, contentType); // send request const xhr = new XMLHttpRequest(); xhr.open('PUT', UPLOAD_URL, true); xhr.setRequestHeader('Content- Range',rangeheader); xhr.setRequestHeader('Content-Type', contentType); xhr.send(chunk);
  • 24. There is More to Know | Neoway Dividindo Arquivos - Frontend
  • 25. There is More to Know | Neoway Backend ● Endpoints: ○ Registrar o upload; ○ Enviar os chunks; ○ Finalizar o envio; ● Recombinar os chunks: ○ Ordenar (Chunk Id); ○ Agrupar; ○ Enviar (S3); ○ Limpar temporários; Dividindo Arquivos - Backend ---------------------------------------- POST /v1/files header Content-Type: "text/csv" Response 201 Created { fileId: “5d74027c79f40700077c1950” } ---------------------------------------- PUT /v1/files/:fileId/chunked-upload header Content-Range: "bytes 0-1000/10000" Response 206 Partial Content ---------------------------------------- PUT /v1/files/:fileId/finish-upload Response 202 Accepted
  • 26. There is More to Know | Neoway Backend ● Endpoints: ○ Registrar o upload; ○ Enviar os chunks; ○ Finalizar o envio; ● Recombinar os chunks: ○ Ordenar (Chunk Id); ○ Agrupar; ○ Enviar (S3); ○ Limpar temporários; Dividindo Arquivos - Backend type chunk struct { name string // 0000-1000 start int64 // 0000 end int64 // 1000 } type chunkSorter []*chunk func (s chunkSorter) Len() int { return len(s) } func (s chunkSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s chunkSorter) Less(i, j int) bool { a := s[i].start + s[i].end // 0000 + 1000 = 1000 b := s[j].start + s[j].end // 2000 + 3000 = 5000 return a < b } infos, err := ioutil.ReadDir(dirname) // []os.FileInfo chunks := getChunks(infos) // parse chunk data from os.fileInfo sort.Sort(chunkSorter(chunks)) // sort after parse chunk metadata Ordenação quicksort
  • 27. There is More to Know | Neoway Backend ● Endpoints: ○ Registrar o upload; ○ Enviar os chunks; ○ Finalizar o envio; ● Recombinar os chunks: ○ Ordenar (Chunk Id); ○ Agrupar; ○ Enviar (S3); ○ Limpar temporários; Dividindo Arquivos - Backend // open fileout to append chunks from list fileOut, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend) for _, chunk := range chunks { // open chunk buffer chunkBuffer, err := os.Open(dirName + “/” + chunk.name)) if err != nil { return nil, err } // copy chunk buffer to fileOut in append mode if _, err := io.Copy(fileOut, chunkBuffer); err != nil { return nil, err } err = chunkBuffer.Close() if err != nil { return nil, err } //flush fileout buffer direct to disk err = fileOut.Sync() if err != nil { return nil, err }
  • 28. There is More to Know | Neoway Merging Chunks Chunk Upload io.Copy io.Copy Finish Upload AWS SDK Dividindo Arquivos - Upload os.File io.Writer Buffer http.Request.Body io.Reader Local Storage AWS S3 User Storage Local Storage os.File io.Reader io.TeeReader cipher.OFB cipher.StreamReader Metadata Extractor io.Writer sha256.Hash io.Writer io.TeeReader Size Rows SHA-256 META os.File io.ReaderLocal Storage os.File io.Writer Local Storage Buffer Buffer os.File io.Reader os.File io.Reader
  • 29. There is More to Know | NeowayThere is More to Know | Neoway Desafios (Solucionados) ● ✔ Extração de metadados baseados no tipo e conteúdo do arquivo; ● ✔ Feedback de progresso para o usuário nos processos de Upload e Download; ● ✔ Complexidade da arquitetura da Neoway; ● ✔ Trafegar arquivos de até 5 GB entre as camadas garantindo: ○ ✔ Ausência de timeouts; ○ ✔ Baixo consumo de recursos; ○ ✔ Segurança no tráfego e armazenamento de dados; ● ✔ Calcular o Checksum do arquivo.
  • 31. There is More to Know | Neoway Resultados Após um ano e meio do lançamento do serviço em produção estes são as integrações e formas de uso do serviço. Utilização Integrações ● Componente de Upload utilizado em 3 aplicativos desenvolvidos em AngularJS e VueJS; ● Integrado com 7 serviços desenvolvidos em NodeJS e GO que utilizam para: ○ Armazenamento temporário de dados exportados em arquivos CSV, XLSX e ZIP. ○ Armazenamento de dossiês em arquivos PDF e HTML por períodos de até 5 anos; ○ Área temporária para importação de dados através de arquivos CSV.
  • 32. There is More to Know | Neoway Resultados Utilização Volume ● Mais de 168 mil arquivos armazenados dos seguintes formatos: XLSX, PDF, CSV, HTML e ZIP; ● Em torno de 100 GB em arquivos armazenados; ● Crescimento mensal em 2019 na média de 15 mil arquivos e 9 GB em espaço de armazenamento. Custo S3 (AWS) ● Total de $ 3,05 dólares no mês de Agosto de 2019. Após um ano e meio do lançamento do serviço em produção estes são os dados de utilização e consumo de recursos.
  • 33. There is More to Know | Neoway Consumo de Recursos CPU ● Média de 0.2% em uma máquina Azure - Standard D4s (v3) equipada com 4 processadores Intel Xeon® E5-2673 de 2,4 GHz. Memória ● Média de 16 MB constantes indiferente do tamanho dos arquivos trafegados.
  • 35. There is More to Know | NeowayThere is More to Know | Neoway Melhorias Futuras ● Não trabalhar com discos baseados em rede como storage local; ● Expirar os arquivos para o Amazon S3 Glacier visando a redução do custo; ● Permitir reiniciar da onde parou Uploads interrompidos por problemas de comunicação; ● Não precisar informar de forma diferente ao servidor que o Upload acabou, o mesmo saber por entender que todas as partes chegaram; ● Melhorar o algoritmo de junção de partes para já ir juntando as partes no decorrer do Upload.
  • 37. There is More to Know | Neoway Referências ● https://developer.mozilla.org/pt-BR/docs/Web/API/Blob ● https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation ● https://golang.org/pkg/io ● https://medium.com/learning-the-go-programming-language/streaming-io-in-go- d93507931185 ● https://developer.mozilla.org/pt-BR/docs/Web/API/Blob ● https://developer.mozilla.org/pt-BR/docs/Web/API/Blob/slice ● https://developers.google.com/drive/api/v3/manage-uploads#multipart ● https://pt.wikipedia.org/wiki/Quicksort
  • 38. There is More to Know | Neoway