Otimizando o desempenho de transferência de arquivos e diretórios entre servidores e serviços de armazenamento em nuvem André Rocha Agostinho - IPT (Mestrado Profissional – Engenharia de Computação)
Com o uso cada vez maior de serviços de armazenamento em nuvem, a necessidade em migrar, replicar ou sincronizar arquivos armazenados localmente para serviços de armazenamento remoto pode se tornar uma tarefa árdua para administradores de sistemas que muitas vezes não dispõem de soluções adequadas para atender necessidades específicas de uma organização. Esta proposta pretende abordar algorítmos, técnicas de otimização em linguagem de programação e boas práticas em configurações de infraestrutura de servidores para ganhos em desempenho na transferência de arquivos e diretórios entre servidores e serviços de armazenamento em nuvem. Para comprovar os resultados, a proposta utilizará de um estudo de caso real para uma empresa no segmento B2B, comprovando eficiência em ganhos de desempenho e abrindo discussões para soluções técnicas em cenários diversos
Semelhante a Otimizando o desempenho de transferência de arquivos e diretórios entre servidores e serviços de armazenamento em nuvem André Rocha Agostinho - IPT (Mestrado Profissional – Engenharia de Computação)
Semelhante a Otimizando o desempenho de transferência de arquivos e diretórios entre servidores e serviços de armazenamento em nuvem André Rocha Agostinho - IPT (Mestrado Profissional – Engenharia de Computação) (20)
Lei geral de proteção de dados por Kleber Silva e Ricardo Navarro (Pise4)
Otimizando o desempenho de transferência de arquivos e diretórios entre servidores e serviços de armazenamento em nuvem André Rocha Agostinho - IPT (Mestrado Profissional – Engenharia de Computação)
1. OTIMIZANDO O DESEMPENHO DE TRANSFERÊNCIA DE
ARQUIVOS E DIRETÓRIOS ENTRE SERVIDORES E SERVIÇOS DE
ARMAZENAMENTO EM NUVEM
André Rocha Agostinho <andre@magnadev.com.br>
Instituto de Pesquisas Tecnológicas de São Paulo – IPT-USP
10, de maio de 2017
Abstract
Com o uso cada vez maior de serviços de
armazenamento em nuvem, a necessidade em migrar,
replicar ou sincronizar arquivos armazenados
localmente para serviços de armazenamento remoto
pode se tornar uma tarefa árdua para administradores
de sistemas que muitas vezes não dispõem de
soluções adequadas para atender necessidades
específicas de uma organização. Esta proposta
pretende abordar algoritmos, técnicas de otimização
em linguagem de programação e boas práticas em
configurações de infraestrutura de servidores para
ganhos em desempenho na transferência de arquivos
e diretórios entre servidores e serviços de
armazenamento em nuvem. Para comprovar os
resultados, a proposta executará experimentos
utilizando o conhecimento obtido no levantamento de
boas práticas para comprovar ou não eficiência em
ganhos de desempenho e abrindo discussões para
soluções técnicas em cenários diversos.
1. Introdução
Com a ascenção do uso da computação em nuvem
em organizações nos últimos anos, pesquisas
apontam (RIGHTSCALE 2017) que 85% de
profissionais de tecnologia e empresas adotam
estratégias múltiplas para infraestrutura em nuvem
sendo elas públicas, privadas ou híbridas. Com um
mercado que movimenta mais de 200 bilhões de
dólares ao ano (GARTNER 2013), os serviços de
armazenamento de arquivos em nuvem são
classificados como serviços básicos, portanto
essenciais para organizações assim como serviços de
computação e rede. Os sistemas de arquivos
distribuídos em nuvem permitem que arquivos possam
ser acessados em qualquer canto do planeta
suportando operações básicas de acesso como
criação, exclusão, modificação, leitura e escrita de
dados, proporcionando princípios básicos da
computação em nuvem [1] como: facilidade de acesso
à infraestrutura, escalabididade e disponibilidade.
Este artigo se propõe a selecionar um serviço de
armazenamento em nuvem, levantar e analisar boas
práticas de utilização com foco em ganhos de
desempenho na transferência de arquivos e diretórios
entre servidores, demostrando, relatando e
comprovando resultados através de experimentos em
ambiente controlado.
2. Motivação
Os requisitos não funcionais são frequentemente
negligenciados, trabalhos apresentados por Cysneiros
[26] enfatizam premissas apresentadas por Chung [25]
de que a falta de integração dos requisitos não
funcionais aos requisitos funcionais pode resultar em
maiores custos com manutenção em um projeto de
software.
Com a maturidade dos serviços de computação em
nuvem, benefícios como facilidade de acesso a
infraestrutura, escalabilidade e disponibilidade são
fatores essenciais (RIGHTSCALE 2017) para justificar o
uso de computação em nuvem, por outro lado o
requisito não funcional de desempenho está
posicionado entre os últimos benefícios mais
procurados.
Com base nessas informações, a primeira motivação
do artigo considera possíveis evidências que
desempenho pode ser considerado como uma
preocupação secundária para administradores de
sistemas que sem conhecimento adequado, pode vir a
utilizar serviços de armazenamento de arquivos na
nuvem com apenas o propósito de depósito de dados
não estruturados, não se atentando à problemas de
degradação de desempenho [5][14] que podem vir a
ocorrer com o tempo.
A segunda motivação do artigo vem de um estudo
[17] de como aumentar o desempenho na transferência
de arquivos utilizando o serviço de armazenamento
Simple Storage Service da empresa Amazon Web
Services.
Este estudo foi realizado para resolver um problema
pontual de migração de arquivos para uma empresa de
internet no segmento Business To Business. O estudo
2. conseguiu comprovar ganhos de até 90% na
transferência de arquivos utilizando técnicas de
programação paralela e algoritimos de recursividade.
Com base nas motivações elencadas e na
experiência adquirida em trabalhos relacionados na
área [4][5][6] o artigo utilizará o serviço de
armazenamento na nuvem Simple Storage Service da
empresa Amazon Web Services para abordar
questões de desempenho considerando configurações
de infraestrutura à otimização de linguagem de
programação.
3. Definição de sistema de armazenamento de
arquivos na nuvem
Para encontrar uma definição coerente para
sistema de armazenamento de arquivos na nuvem é
necessário se apoiar em definições sobre sistema de
arquivos e sistema distribuído de arquivos.
Segundo Tanenbaum e Woodhull (Operating
Systems, Design and Implementation, 1987), um
sistema de arquivos pode ser definido como “Uma
coleção de arquivos, atributos, diretórios e blocos de
dados que são implementados em conjunto como um
dispositivo de bloco lógico”.
Na definição de sistema distribuído de arquivos,
Tanbaum e Van Steen (Distributed systems principles
and paradigms, 2007), definem que ”Sistemas de
arquivos distribuídos permitem múltiplos processos
compartilharem dados ao longo de períodos de tempo
de uma forma segura e confiável. Como tal, eles tem
sido utilizados como a camada básica para sistemas
distribuídos e aplicações”.
Em um sistema distribuído de arquivos, a
arquitetura cliente-servidor permite a manipulação de
arquivos em diferentes dispositivos de
armazenamento, não se limitando mais em armazenar
dados em um meio físico local.
Um sistema de armazenamento de arquivos na
nuvem pode ser definido como um sistema de
arquivos distribuídos baseado em clusters, com a
possibilidade de repartir arquivos em diferentes
servidores. Segundo Tanembaum (Distributed
systems principles and paradigms, 2007) “Distribuição
de um arquivo grande ou não em vários servidores,
tornando-se possível buscar suas partes
paralelamente”.
As características de um sistema de arquivos
distribuídos baseado em cluster são:
- Suporte à operações como: criação, exclusão,
modificação, leitura e escrita.
- Escalabilidade e eslasticidade no compartilhamento
de dados.
- Capacidade de particionamento de arquivos em
diversas partes denominadas “chunks”, sendo possível
alocar cada chunk em máquinas remotas.
- Paralelismo de requisições de PUT e GET.
Em um sistema de arquivos distribuídos baseado em
cluster existem diferentes formas de compartilhamento
de dados, o que exatamente se proporciona em um
sistema de arquivos distribuídos em nuvem, porém
requisitos não funcionais como confiabilidade,
disponibilidade e integridade são peças fundamentais
para assegurar segurança uma vez que a informação
passa a estar disponível ao longo da rede.
Figura 1: Sistema de arquivos do Google (GFS). A figura é
descrita em Ghemawat et al. (2003).
4. Objetivos e métodos aplicados
O objetivo principal deste artigo é otimizar a
transferência de arquivos para serviços de
armazenamento em nuvem e utilizará o serviço de
armazenamento Simple Storage Service da empresa
Amazon Web Services como exemplo.
O objetivo principal do artigo está divido em duas
partes:
1. Reunir e apresentar informações de como melhorar o
desempenho na transferência de arquivos para as
operações de PUT, GET e LIST com base nas
seguintes fontes:
a. Documentos oficiais do serviço Simple Storage
Service (White papers) disponibilizados pela
empresa Amazon Web Services.
b. Referências de uso na comunidade de profissionais
de tecnologia que utilizam o serviço Simple Storage
Service e relataram experiências com desempenho.
c. Referências acadêmicas diversas que possam criar
sustentação aos tópicos abordados.
d. Utilização do conhecimento e experiência obtida
em trabalhos relacionados [17].
3. 2. Selecionar e utilizar soluções apresentadas no item
1 para rodar experimentos que possam comprovar
ou não melhorias no desempenho de transferência
de arquivos através de métodos quantitativos.
5. Sobre o serviço de amarzenamento Simple
Storage Service
O Simple Storage Service (AWS S3) é um serviço
de armazenamento de objetos da empresa Amazon
Web Services com uma interface de web service
simples para armazenar e recuperar qualquer volume
de dados de qualquer parte da internet. O AWS S3 é
utilizado para armazenamento de dados não
estruturados, distribuição de conteúdo, backup e
arquivamento, recuperação de desastres e
hospedagem de websites estáticos.
Em sua principal função pode ser utilizado para
armazenar e distribuir conteúdo web e mídias. Os
conteúdos podem ser entregues diretamente via AWS
S3 [3] através de URLs únicas de acesso via protocolo
HTTP ou HTTPs, como pode ser usado como
amarzenamento fonte para serviços de entregas de
conteúdo (CDN). Por ser acessível via protocolo
HTTP/HTTPS o serviço AWS S3 também pode
hospedar conteúdos estáticos como páginas HTML
contendo imagens, videos e scripts client-side como
Javascript.
O serviço AWS S3 tem sua arquitetura de
armazenamento baseado em buckets, que funcionam
como depósitos para armazenamento de objetos não
estruturados, onde cada objeto armazenado recebe
um endereço único de URL através da combinação do
nome do bucket e keynames. Existem duas formas de
uso para o AWS S3, acesso padrão para propósitos
gerais de acesso frequente e acesso infrequente para
armazenamento de longa duração, porém sem acesso
recorrente a arquivos.
A utilização do serviço AWS S3 ocorre por meio de
arquitetura REST [20] e pode ser acessado através de
API REST ou bibliotecas específicas (SDKs) para um
determinado tipo de linguagem de programação.
A arquitetura REST permite a execução das
seguintes operações para manipulação de objetos nos
buckets: PUT para enviar objetos, GET para obter
objetos, DELETE para excluir objetos, LIST para listar
objetos e HEAD para saber se um bucket existe ou se
tem permissão para acesso.
6. Análise e levantamento de boas práticas para
omitização de desempenho
Para o serviço de armazenamento Simple Storage
Service os seguintes tópicos serão abordados para
otimização de desempenho: a) configuração de
regiões de armazenamento, b) configuração das
instâncias de servidores virtualizados, c) construção de
keynames, d) operações de manipulação de objetos, e)
aceleração de transferência e f) maximização de uso de
portas TCP.
a. Configuração de regiões de armazenamento
Na criação de um bucket é necessário informar a
região onde o serviço de armazenamento irá operar. A
Amazon Web Services oferece o serviço AWS S3 em
quatorze regiões distribuídas por quatro continentes:
América, Europa, Ásia e Oceania.
É aconselhável [3] que o bucket a ser criado esteja
se possível na mesma região ou na região mais próxima
dos recursos consumidores para se evitar altas latências
de rede durante transferência de objetos.
Como forma de comprovar a importância na
configuração de regiões, a ferramenta de
monitoramento de serviços em nuvem CloudHarmony
foi executada para averiguar a incidência de latência de
rede considerando o seguinte cenário: recursos
consumidores representados como servidores AWS
EC2 configurados na região São Paulo, América do Sul
(sa-east-1) e serviços AWS S3 configurados na região
N. Virgínia, América do Norte (us-east-1) e região São
Paulo, América do Sul (sa-east-1). Os testes realizados
registraram latência de 127ms na comunicação entre
sa-east-1 e us-east-1 contra 10ms na comunicação
entre sa-east-1 e sa-east-1.
Caso seja necessário atuar em diversas regiões, é
possível ativar o recurso de replicação cross-region [7]
no serviço AWS S3 ou o recurso de acelerador de
transferência [12], que permite obter altas taxas de
transferências independentes da região selecionada.
b. Configuração das instâncias de servidores
virtualizados
Quando utilizado serviços de computação na nuvem
junto ao serviço de armazenamento AWS S3, o tipo de
serviço de computação influenciará diretamente em
processamento para a capacidade e execução de
requisições API como operações PUT ou GET, e na
capacidade de rede para transferência de pacotes
juntamente com a capacidade de largura de banda
contratada.
Na Amazon Web Services é oferecido o serviço de
computação na nuvem AWS EC2 para virtualização de
computadores com classificações de tipos de instâncias,
cada uma delas com um desempenho diferente.
O serviço AWS EC2, quando utilizado como serviço
consumidor junto ao serviço AWS S3 devido as suas
características de processamento, memória e rede
influenciam, conforme desmontrado na Figura 4, no
desempenho de transferência de arquivos, devido a sua
4. capacidade computacional de execução de threads
em núcleos de processadores e sua capacidade de
interface de rede ao transmitir e receber pacotes.
Figura 2: Desempenho de rede diferente entre tipos de
instâncias ao usar o serviço AWS S3.
No exemplo um servidor de classe c4.4xlarge com
16 vCPUs e 30 gigabytes de memória RAM, e um
servidor c4.8xlarge com 32 vCPUs e 60 gigabytes de
memória RAM, realizando a mesma tarefa de
transferência de arquivos (explicado na seção 7)
obtêm taxas de transferência de rede diferentes
devido a sua capacidade de rede. O servidor
c4.4xlarge com rede gigabit consegue uma taxa de
transferência de 124.040.113 B/sec contra
204.236.552 B/sec do servidor c4.8xlarge utilizando
uma rede 10 gigabit.
c. Construção de keynames
Uma keyname [3] é um identificador único para um
objeto em um bucket. Cada bucket deve ter um nome
único, independente da região e cada objeto em um
bucket tem exatamente uma keyname. A combinação
do nome do bucket com a keyname é o que garante a
integridade de um endereço único para um objeto
disponível no serviço de armazenamento AWS S3,
impossibilitando assim de existirem URLs iguais.
O serviço AWS S3 mantêm um índice de objetos
“keynames” para cada região, onde cada uma delas é
armazenada em binário (UTF-8) e ordenada em
partições lógicas. O agrupamento do sistema de
índice utiliza dos prefixos das keynames para agrupar
e armazenar em partições por similaridade dos
prefixos.
Por este funcionamento, é recomendado [3][4][6]
que na composição das keynames os prefixos tenham
um valor não sequencial e se possível aleatório,
permitindo assim que o sistema de agrupamento de
índice do serviço AWS S3 possa particionar as
referências em diferentes partições balanceando
assim as cargas de consultas.
Ao usar um prefixo sequencial como por exemplo
composição de data ou alfabético aumentará a
probabilidade de se alocar uma específica partição para
um grande volume de keynames simplesmente pelo
agrupamento de prefixo.
A utilização de um prefixo sequencial é uma prática
ruim e irá influenciar em desempenho de requisições
GET e LIST. Ao utilizar um hash no prefixo da keyname,
como por exemplo, GUID ou MD5, forca-se o sistema de
agrupamento de índice do AWS S3 a realocar
keynames em partições diversas.
Independente ou não do alto uso de requisições no
serviço AWS S3, considerar a construção de keynames
com prefixos aleatórios é considerado uma boa prática
[3][4][6] e visa iniciar o uso corretamente do serviço, não
precisando se preocupar futuramente com eventuais
gargalos em seu uso. Entretando existem parâmetros [7]
que podem ser utilizados como justificativa na
otimização de keyname. Um processo considerado
rotineiro com cem ou mais solicitações por segundos
usando operações como PUT, DELETE, GET e LIST,
deve aplicar imediatamente as boas práticas de prefixos
de keynames.
Figura 3: Exemplo de sobrecarga de partição no sistema
de índices de keynames do AWS S3.
d. Operações de manipulação de objetos
As operações para manipulação de objetos PUT,
GET e LIST fornecidas pela arquitetura REST podem
ser otimizadas proporcionando ganhos ao recurso
consumidor do serviço AWS S3. Para cada operação de
manipulação de objetos é mencionado neste artigo um
meio de otimização seguindo boas práticas do
fabricante [3] e da comunidade [4][5].
Otimizando operações GET e LIST
i. Serviço de entrega de conteúdo
Uma rede de fornecimento de conteúdo (CDN)
permite distribuir conteúdos de forma massiva pela rede
com benefícios que incluem reduzir custos de banda,
melhorar o tempo de carregamento e aumentar
5. globalmente a disponibilidade de conteúdos como
imagens, vídeos, documentos e outros tipos de
objetos. O serviço CDN junto ao serviço AWS S3, atua
como uma camada intermediária de entrega aos
recursos consumidores utilizando-se dos buckets do
serviço AWS S3 como fonte de objetos.
O serviço Amazon Cloud Front (AWS CloudFront)
é um serviço de fornecimento de conteúdo
disponibilizado pela Amazon Web Services que pode
ser combinado junto ao serviço AWS S3, com mais de
cinquenta camadas localizadas em todo o mundo, o
serviço AWS Cloud Front fornece baixas latências e
altas taxas de transferência para operações de leitura
e reduz o número de requisições GET aos buckets e
fornece gestão e aplicação de cacheamento de
objetos.
Figura 4: As requisições com o uso do serviço AWS
Cloudfront carregaram em média 32% mais rápido.
Para comprovar a eficiência do uso de uma CDN, o
serviço AWS CloudFront foi configurado e um cenário
de teste criado contendo: um arquivo denominado
image2.jpg com um tamanho de 9.70MB armazenado
em um bucket rotulado magnadev-public. Como
exemplo de um recurso consumidor foi configurado
um servidor AWS EC2 de instância c4.large com 2
vCPUs e 3.75GB de memória RAM rodando o sistema
operacional Windows Server 2016 com um serviço de
webserver configurado IIS 10.
A execução do cenário de teste considerou utilizar
o navegador de internet Google Chrome em modo de
inspeção de rede ativado para a realização de oito
requisições ao arquivo image2.jpg, sendo quatro
requisições provenientes do serviço AWS CloudFront
e quatro requisições provenientes do serviço AWS S3.
Com o uso do serviço AWS CloudFront foi possível
comprovar uma redução de 32% no tempo de
conclusão das requisições, as requisições com o
serviço AWS Cloudfront carregaram em média 156
ms, contra 230.50 ms sem o uso do serviço de
entrega de conteúdo.
ii. Aplicação de cacheamento HTTP
A aplicação de cacheamento HTTP em objetos
permite que os recursos consumidores descartem
uma nova requisição à sua fonte, no exemplo do artigo o
serviço AWS S3 e faça a recuperação do objeto
diretamente do cache do navegador cliente. Todo
navegador é fornecido com uma implementação de um
cache de HTTP [15], e para implementá-lo é necessário
garantir que cada resposta de servidor forneça as
diretivas de cabeçalho HTTP corretas para instruir o
navegador sobre quando e por quanto tempo o pode se
armazenar a resposta em cache. Quando o servidor
retorna uma resposta, também emite uma coleção de
cabeçalhos HTTP, descrevendo o tipo de conteúdo, o
comprimento, as diretivas de armazenamento em cache,
o token de validação (E-Tag) e outras informações. Para
aplicar cache HTTP em objetos é necessário especificar
a metatag CacheControl e E-Tag no cabeçalho de cada
objeto armazenado no AWS S3.
A metatag CacheControl permite a definição de
diretivas como: public ou private para tornar ou não o
cacheamento do objeto público pelo navegador e
qualquer cache intermediário, no-cache ou no-store para
definir se a resposta da requisão é armazenável ou não
e max-age, para especificar um tempo de expiração do
cache para cada objeto.
A metatag ETag tem o funcionamento como um
token de validação que permite verificações eficientes
de atualização de recursos onde nenhum dado é
transferido se o recurso não foi alterado. A metatag
ETag é criada e gerenciada automaticamente no serviço
AWS S3, ou seja para cada novo objeto enviado ou
alterado ela é reescrita com um novo valor de token.
Para comprovar a eficiência do uso do cacheamento
HTTP o seguinte cenário de teste foi criado contendo:
uma página HTML com uma imagem referenciada no
documento denominada imagem2.jpg com um tamanho
de 9.70 megabytes armazenado em um bucket rotulado
magnadev-public.
Como exemplo de um recurso consumidor foi
configurado um servidor AWS EC2 de instância c4.large
com 2 vCPUs e 3.75GB de memória RAM rodando o
sistema operacional Windows Server 2016 com um
serviço de webserver configurado IIS 10.
Figura 5: O objeto image2.jpg é retornado diretamente do
cache do navegador reduzindo o tempo de carregamento.
A execução do cenário de teste considerou utilizar o
navegador de internet Google Chrome em modo de
inspeção de rede ativado para a realização de duas
requisições ao arquivo image2.jpg, uma requisição sem
6. cache HTTP e uma requisição com cache HTTP. A
requisição com cacheamento HTTP, foi especificado
com CacheControl: max-age 3600, ou seja um
cacheamento de objeto por 3600 segundos.
Com o uso do cacheamento HTTP foi possível
comprovar uma redução de 207 milesegundos no
tempo de requisição do objeto image2.jpg. A utiliza do
cache HTTP, faz o navegador requisitar o conteúdo do
objeto diretamente do cache cliente, não necessitando
efetuar uma nova a requisição ao objeto no serviço
AWS S3.
iii. Uso do protocolo HTTP 2
Para páginas web, a utilização do protocolo HTTP
2.0 provém um grande ganho em desempenho [21]
para as operações GET, maximizando as requisições
com o uso do paralelismo de requisições, recurso
esse disponível na grande maioria de navegadores
[22].
Com a utilização do protocolo HTTP 2, os objetos
armazenados no serviço AWS S3, utilizando ou não
de um serviço de entrega de conteúdo (CDN), são
transferidos para os recursos consumidores com
maior eficiência, utilizando do potencial da arquitetura
REST [20] do serviço AWS S3, que fornece
nativamente a capacidade de multi-threading para as
operações de objetos, premissas estipuladas [1] pra
um sistema de arquivos distribuídos em nuvem.
Figura 6: Gráfica cascata de carregamento de recursos
da página HTML thumb.html via protocolo HTTP 1.1
O HTTP 2 é uma redefinição de como o fluxo
semântico do HTTP atua sobre conexões TCP. A
principal vantagem do HTTP 1.1 foi utilizar conexões
persistentes para múltiplas requisições de serviços em
sequência. No HTTP 2, uma conexão persistente
pode ser usada para múltiplas requisições de serviços
simultaneamente.
Para comprovar a eficiência do uso do protocolo
HTTP 2.0 o seguinte cenário de teste foi criado
contendo: uma página HTML thumb.html contendo
nove imagens referenciadas no documento. As
imagens foram armazenadas em um bucket rotulado
magnadev-public, com tamanhos variados que vão de
1.5 kilobytes à 467 megabytes totalizando em 1.250
kilobytes.
Como exemplo de um recurso consumidor foi
configurado um servidor AWS EC2 de instância c4.large
com 2 vCPUs e 3.75GB de memória RAM rodando o
sistema operacional Windows Server 2016 com um
serviço de webserver configurado IIS 10 e com suporte
à HTTPS, permitindo o protocolo HTTP 2.0 funcionar
por meio de uma conexão TLS.
A execução do cenário de teste considerou utilizar o
navegador de internet Google Chrome em modo de
inspeção de rede ativado para a realização de duas
requisições à pagina HTML thumb.html, uma requisição
por meio do protoloco HTTP 1.1 e uma requisição por
meio do protocolo HTTP 2.
Figura 7: Gráfico cascata de carregamento de recursos da
página HTML thumb.html via protocolo HTTP 2
No primeiro caso, por meio do protocolo HTTP 1.1,
as imagens foram carregadas sequencialmente em
formato cascata, ou seja, cada requisição apresentou
uma dependência entre as demais ocasionando gargá-
lo para concluir todas as requisições. Por meio do
protocolo HTTP 2.0, as nove imagens foram carregadas
de forma não sequencial e paralelamente, o que
possibitou concluir todas as requisições em 82
milisegundos contra 355 milisegundos via protocolo
HTTP 1.1.
Otimizando operação PUT
i. Implementação de transferência com segmentação
de arquivos
A segmentação de arquivos com multipart upload,
transfere um único objeto como um conjunto de partes.
As partes dos objetos podem ser transferidas em
qualquer ordem, e o serviço AWS S3 os recebem
remontando o objeto ao fim da transferência. O upload
multipart é indicado [3] para arquivos maiores que 100
megabytes e oferece as seguintes vantagens: controle
no progresso de envio, possibilidade de enviar partes
em paralelo e controle de falha com possibilidade de
reenvio. A transferência de objetos com segmentação
de arquivos pode criar partes com tamanhos entre 5
7. megabytes e 5 gigabytes com um comprimento de
parte entre 1 e 10.000.
A implementação da segmentação de arquivos
deve ser feito diretamente na aplicação usando a
arquitetura REST fornecida pela o serviço AWS S3. A
aplicação deve seguir os seguintes passos para
implementação do multipart upload:
a) separar o objeto a ser enviado em múltiplas
partes (chunks). A separação deve ser lógica e
especificado quantos pedaços do objeto serão
enviados e o tamanho especificado de cada pedaço.
b) Iniciar a transferência das partes e receber de
retorno um número de identificação de transferência
(Upload Id). A requisição para AWS S3 deve incluir
todos os cabeçalhos de solicitação que normalmente
acompanham uma operação PUT.
c) Transferir cada parte do objeto acompanhado do
Upload ID e um número para especificação da parte
(Part Number), que deve ser definido entre 1 a 10.000.
Os números das partes não precisam ser contínuos,
porém sua ordem determinará a posição de cada
parte do objeto ao ser remontado. Para carte parte
transferida o AWS S3 irá retornar um valor ETag como
retorno
d) Finalizar a transferência fornecendo o ID de
transferência e os pares de chaves: número da parte
transferida e o valor ETag de cada parte.
Figura 8: Funcionamento da transferência com
segmentação de arquivos. Do objeto original,
transferência dos chunks e remontagem final do objeto.
ii. Implementação de multithreading para chamadas
API REST
A implementação da segmentação de arquivos é
fornecido por meio da arquitetura REST e pode ser
acessado através de API REST [3] ou bibliotecas
específicas (SDKs) para um determinado tipo de
linguagem de programação. Porém casos onde exista
a necessidade de uma implementação específica e
eficiente, que possa utilizar ao máximo o poder
computacional (CPU) e tirar o máximo de proveito do
uso de rede (bandwith) para enviar objetos para o
AWS S3, o uso das APIs REST devem ser
empregadas em conjunto com técnicas de linguagem de
programação e algoritmos.
O artigo utiliza esta seção para referenciar um
estudo de uma solução criada para este propósito, o
CopyFasterToS3, um utilitário prompt desenvolvido com
a linguagem de programação C#, disponibilizado em
código aberto [24] e com um estudo de bechmarking
[17] relatado.
Figura 9: Resultados apresentadas no estudo de
otimização de transferência de arquivos usando o
CopyFasterToS3.
O utilitário CopyFasterToS3, aumenta a velocidade
de transferência de objetos usando o paralelismo de
threads e escalando execuções de operações PUT nas
unidades de CPU do computador cliente. Para uma
melhor eficiência, o computador cliente deve ter mais de
um núcleo de processamento e uma rede maior que 100
megabits/segundo.
Na seção 7, experimentos são executados utilizando
o CopyFasterToS3, e detalhes de seu funcionamento
são abordados neste artigo.
e. Aceleração de transferência
O serviço de aceleração para AWS S3 (AWS S3
Transfer Accelaration) é indicado para ganhos de
perfomance na transferência de arquivos para buckets
em regiões diversas. O S3 Transfer Accelaration, faz
intermediação com os endpoints do AWS S3 carregando
todo o tráfego HTTP/HTTPS para uma ponte de rede
otimizada que funciona entre a camada de entrega de
conteúdo mais próxima da região onde estão os buckets
do serviço AWS S3.
Figura 10: Exemplo de uso da ferramenta de comparação
usando a ferramenta Amazon S3 Transfer Acceleration
Speed Comparison
Em um exemplo de uso do serviço do AWS S3
Transfer Acceleration através de uma ferramenta de
comparação fornecida, o AWS S3 Transfer Acceleration
8. Speed Comparison, é possível simular um
computador cliente configurado na região de São
Paulo, América do Sul (sa-east-1), consumindo
buckets nas regiões São Francisco e Oregon, América
do norte (us-west-1 e us-west-2) e comparar a
velocidade de transferência utilizando o serviço AWS
S3 Transfer Accelaration e o padrão de acesso AWS
S3.
f. Maximização de uso de portas TCP
As conexões com o serviço AWS S3 ocorrem
através de portas dinâmicas, também conhecidas
comos portas efêmeras. As portas efêmeras do termo
efêmero (com vida curta), não sugere que as portas
devam ter uma vida útil curta. Por exemplo, as portas
usadas para o protocolo de transferência de hipertexto
são fechadas imediatamente após a conclusão da
transferência de dados. Efêmero se refere ao fato de
que as portas do aplicativo cliente têm vida
relativamente curta (abrem no máximo durante o
período em que o aplicativo estiver sendo executado)
em comparação às portas do aplicativo do servidor,
normalmente abertas durante todo o período em que o
computador servidor estiver sendo executado. O
computador cliente usa uma porta efêmera, no lugar
da porta conhecida, para impedir conflitos com um
serviço local que possa usar esta porta.
De acordo com o IANA (Internet Assigned
Numbers Authority), as portas efêmeras [13] são
especificadas com o comprimento de 49.152 a 65.535.
O sistema operacional Windows geralmente trabalha
com o comprimento de 49.152 a 65.535 portas, e o
sistema operacional Linux (versões mais recentes)
operam com o comprimento de portas entre 32.768 à
61.000 portas.
Em cenários onde um computador cliente consome
o serviço AWS S3 com uma carga elevada de uso
com operações GET ou PUT, pode ser necessário
que o comprimento de portas efêmeras seja ampliado,
evitando problemas de desempenho de rede e em
cenários mais críticos, queda de servidor por exaustão
de portas dinâmicas.
A exaustão de portas [11] ocorre quando o sistema
operacional esgota o escalonamento de portas
efêmeras para aplicações e não consegue atribuir
uma nova porta e destinar para o seu uso,
ocasionando assim erros de enfileiramento onde o
buffer de rede é insuficiente para escalonar novas
portas. A causa de exaustão de portas pode ser
devido a grande utilização de portas, que é maior que
o comprimento destinado ao sistema operacional, ou
pela quantidade de portas que estão em estado
TIME_WAIT, ou seja ainda não foram liberadas pelo
sistema operacional para reutililização no
escolonamento de portas. Aumentar o comprimento
de portas quando o cenário exigir uma alta demanda
pode ajudar a prevenir exaustão de portas.
Em servidores usando Windows Server, como é o
caso dos exemplos citados neste artigo, para aumentar
o comprimento de portas dinâmicas é necessário
executar o comando netsh no utilitário command
prompt, como por exemplo: netsh int ipv4 set
dynamicport tcp start=1025 num=64510.
Após a execução do comando, o Windows Server
passará a trabalhar com um comprimento de até 63.485
portas dinâmicas, 30.717 portas efêmeras a mais que a
configuração inicial seguindo o padrão IANA.
O tempo de espera que uma conexão fechada
espera para que possa ser liberada para reutilização é
representado pelo estado TIME_WAIT. A RFC 793 [23]
aconselha manter uma conexão fechada em um
intervalo de ao menos duas vezes o tempo de vida
máximo de um segmento de rede (120 segundos). Em
servidores Windows Server, a configuração de
TIME_WAIT é especificada em 240 segundos. Em
servidores Linux, como por exemplo RedHat5 a
configuração de TIME_WAIT é especificada em 60
segundos.
Em cenários onde é detecado exaustão de portas
[11], tendo realizado ou não o aumento do comprimento
de portas dinâmicas, diminuir o valor de TIME_WAIT
permite o TCP liberar mais rapidamente conexões
fechadas, porém se o valor é tão baixo [12], o sistema
operacional pode liberar recursos antes da conexão
estar completa, requerindo ao computador adicionar
esforços para restabelece-la. A redução e TIME_WAIT é
encorajada para melhorar o desempenho de rede [10]
porém cabe ao administrador adotar o valor que melhor
se encaixa com a realidade de uso de rede do
computador administrado.
7. Experimentos para a transferência de arquivos
entre servidores e serviço de armazenamento na
nuvem
O objetivo desta seção é executar dois experimentos
de replicação de arquivos para o serviço AWS S3, um
experimento usando técnicas de multithreading e um
experimento sem técnicas de multihreading. Ao fim dos
testes, informações serão coletadas e confrontadas para
mensurar ganhos de desempenho na transferência de
objetos.
Para executar o experimento A non-multithreading,
sem técnicas de paralelismo e experimento B
multithreading, são considerados os seguintes tópicos:
1. Uso de servidores AWS EC2 em três diferentes
tipos de instância.
2. Criação do bucket no AWS S3 na mesma região
dos servidores EC2.
9. 3. Uma ferramenta de transferência multi-
threading criada especificamente para a
replicação de dados.
O experimento não contempla: construção de
keynames com hash, maximização de portas TCP,
upload usando multi-part (chunks) e ativação do S3
Transfer Acceleration.
a) Especificação de casos de testes
Para testar os experimentos um diretório
denominado samplefolder foi criado com quatro
arquivos: arquivo1.pdf com 1.001 kilobytes,
arquivo2.jpg com 8 kilobytes, arquivo3.jpg com 462
kilobytes e arquivo4.jpg com 528 kilobytes. Ao todo o
diretório totaliza 1.94 megabytes. O diretório
samplefolder foi replicado para compor 3 casos de
testes: caso de teste 1 com 8.000 arquivos, caso de
teste 2 com 30.000 arquivos e caso de teste 3 com
100.000 arquivos. Abaixo detalhes de cada caso de
teste:
Id Arquivos Pastas Níveis Distr. GB
1 8.000 2.000 1 4 3.80
2 30.000 3.000 3 10 6.69
3 100.000 25.000 1 4 47.5
b) Configuração do ambiente para a realização dos
experimentos
Para a execução dos casos de testes foi
considerado a seguinte configuração de ambiente:
três computadores EC2 como palco dos
experimentos, processadores Intel Xeon E5-2666 v3
(Haswell) de alta frequência, otimizados
especificamente para o EC2 classe de instância c4,
disco SSDs e suporte a redes aperfeiçoadas (SR-
IOV). Abaixo detalhes de configuração de cada
computador EC2:
Tipo Memória vCPU Disco Rede
C4.large 3.75 GB 2 500 Mbps Moderada
C4.xlarge 7.5 GB 4 750 Mbps Alta
C4.2xlarge 15 GB 8 1000 Mbps Alta
c) Ferramenta de replicação de objetos
Para execução dos experimentos foi utilizado uma
ferramenta utilitária, a CopyFasterToS3 [17], que foi
desenvolvida para auxiliar na replicação rápida de
objetos utilizando-se de técnicas de programação
paralela. A solução apresenta as seguintes
especificações técnicas:
1. Linguagem de programação .Net C# 4.5
2. Utilização da biblioteca S3 .Net versão 3.3.5
3. Paralelismo de execução usando C# Parallels.
4. Aplicação do algorítimo de recursividade em
cauda para busca em profundidade de
diretórios.
5. Implementação da classe Stopwatch
(System.Diagnostics) para benchmarking dos
resultados.
Figura 11: Código do experimento B utilizando algorítimo
de recursividade e técnicas de paralelismo.
No experimento A, nos laços de repetições para
busca em profundidade não é utilizado nenhuma técnica
de multithreading e já no experimento B, a estrutura de
laços é substituída por laços ForEach Parallel,
fornecidos pela biblioteca C# Parallels, o qual permite
que blocos de instruções sejam executadas por diversas
threads, escalonando assim execuções em vários
núcleos de processamento. Abaixo alguns detalhes de
técnicas aplicadas na ferramenta CopyFasterToS3:
Experimento
Recursividade em
diretórios e arquivos
Multihreading
C# Parallels
A Sim Não
B Sim Sim
d) Resultados obtidos
O experimento B mostrou-se 90% mais eficiente que
o experimento A e finalizou a transferência de um total
de 414.000 arquivos totalizando 173.97 gigabytes em
um tempo decorrido de 44 minutos enquanto que o
experimento A realizou o mesmo cenário porém com
um esforço de 469 minutos para a conclusão de todos
os casos de testes.
Os resultados foram interpretados em tabelas
cruzando os casos de testes executados com os
ambientes utilizados para a execução. Dois gráficos
foram produzidos para demonstrar a taxa de
transferência em megabytes por segundos de cada
experimento realizado e um gráfico para mostrar em
minutos o tempo de execução de cada experimento.
10. Figura 12 e 13: Tabelas com resultados de tempo corrido dos casos de testes do experimentos A e B.
Gráficos de taxa de transferência dos casos de testes dos experimentos A e B.
Figura 14: Tabela com resultados de tempo corrido dos experimentos A e B.
Gráfico de tempo total gasto dos experimentos A e B.
11. 8. Conclusão
O artigo produziu duas conclusões sendo uma
conclusão para cada tópico abordado. Na seção 6 as
práticas e recomendações de uso do serviço Amazon
S3 apresentadas puderam demonstrar melhorias no
desempenho de operações PUT, GET e LIST. As
práticas de uso do serviço com base em referências
do fornecedor [3][7][8][12] podem ser combinadas
com configurações de servidores [9][11][15][16] e
técnicas de linguagem de programação [17] podendo
assim potencializar o desempenho de transferências
de arquivos.
Na seção 7, os experimentos executados
comprovam a eficiência nas técnicas de linguagem de
programação com o uso do algoritimo de recursidade
em cauda com laços de repetição utilizando
processamento paralelo (multithreading).
As técnicas demonstradas quando empregadas ao
uso das APIs do serviço de armazenamento Amazon
S3, assegurou que o experimento B fosse 90% mais
eficiente que o experimento A e comprovou ser eficaz
em termos de velocidade de transferência de objetos.
Os conceitos empregados nos experimentos
podem ser reproduzidos em qualquer cenário de
migração de um sistema de arquivos padrão para
serviços de armazenamento em nuvem independente
da linguagem de programação e do serviço contrato.
9. Trabalhos futuros
O artigo abre discussões para soluções técnicas
em cenários diversos oferecendo possibilidades para
trabalhos futuros como, por exemplo, aplicar os
mesmos experimentos realizados neste artigo com
diferentes fornecedores de serviço de armazenamento
com o intuito de extrair informações de benchmarking
e identificar possíveis melhorias em cada caso.
Outra possibilidade para trabalho futuro é aplicar
um estudo de caso real com o intuito de comprovar ou
não eficiência com os tópicos abordados.
10.Referências
[1] Tanembaum S. Andrew and Van S. Maarten,
“Distributed systems principles and paradigms”,
Pearson, (2007).
[2] Tanembaum S. Andrew and Woodhull S. Albert,
“Operating Systems Design and Implementation”,
Prentice Hall, (2006).
[3] Amazon Web Services, Inc, “AWS Storage
Services - Overview - A Look at Storage Services”,
(2015).
https://d0.awsstatic.com/whitepapers/AWS%20Storage
%20Services%20Whitepaper-v9.pdf
[4] Garcia F., “Maximizing Amazon S3 Performance”,
AWS re: Invent, (2014).
https://www.slideshare.net/AmazonWebServices/pfc403-
maximizing-amazon-s3-performance-aws-reinvent-2014
[5] Levy J. e Zier S., “10 Things You Might Not Know
About Using S3”, Sumo Logic, (2016).
https://www.sumologic.com/aws/s3/10-things-might-not-
know-using-s3/
[6] Goldin E., “AWS S3 Performance Tuning”, Cloud
Native, (2015).
https://cloudnative.io/blog/2015/01/aws-s3-performance-
tuning
[7] Amazon Simple Storage Service Developer,
“Request Rate- Perfomance Considerations”, (2016).
http://docs.aws.amazon.com/AmazonS3/latest/dev/requ
est-rate-perf-considerations.html
[8] Amazon Simple Storage Service Developer Guide,
“TCP Window Scaling”, (2016).
http://docs.aws.amazon.com/AmazonS3/latest/dev/TCP
WindowScaling.html
[9] V. Jacobson, R. Braden e D. Borman “TCP
Extensions for High Performance”, Network Working
Group,IETF, (1992).
http://www.ietf.org/rfc/rfc1323.txt
[10] Faber T., Touch J. e Yue W., “The TIME-WAIT
state in TCP and Its Effect on Busy Servers”, University
of Southern California. IEEE Infocom, pp. 1573-1583,
(1999).
[11] Huffman C. “Detecting ephemeral port exhaustion” ,
Microsoft Technet , (2013).
https://blogs.technet.microsoft.com/clinth/2013/08/09/det
ecting-ephemeral-port-exhaustion/
[12] Amazon Simple Storage Service Developer Guide,
“Amazon S3 Transfer Acceleration”, (2016).
http://docs.aws.amazon.com/AmazonS3/latest/dev/transf
er-acceleration-examples.html
[13] Touch J et al, "Service Name and Transport
Protocol Port Number Registry", (2017).
https://www.iana.org/assignments/service-names-port-
numbers/service-names-port-numbers.xhtml
[14] Bjornson Z., "AWS S3 vs Google Cloud vs Azure:
Cloud Storage Performance", (2015).
12. http://blog.zachbjornson.com/2015/12/29/cloud-
storage-performance.html
[15] Grigorik, I. "Http Caching, Perfomance", Google
Developers, (2017).
https://developers.google.com/web/fundamentals/perfo
rmance/optimizing-content-efficiency/http-caching
[16] Wagner, J. "A Comprehensive Guide To HTTP/2
Server Push", Smashing Magazine, (2017).
https://www.smashingmagazine.com/2017/04/guide-
http2-server-push/s
[17] Agostinho, A. "Using C# Parallel to copy files to
S3", (2015).
http://aragostinho.github.io/2015/03/11/using-c-
parallel-to-copy-files-to-s3.html
[18] RightScale, "Cloud Computing Trends: 2017 State
of the Cloud Survey", (2017).
http://www.rightscale.com/blog/cloud-industry-
insights/cloud-computing-trends-2017-state-cloud-
survey
[19] Zhang J. "Top 10 Cloud Storage Trends IT
Providers Should Know About Now", (2011).
https://www.gartner.com//it/content/2375000/2375017/j
une_3_top_10_cloud_storage_jzhang.pdf?userId=971
56630
[20] Booth D. et al., “Web Services Architecture”, W3C
Working Group Note, (2004).
https://www.w3.org/TR/2004/NOTE-ws-arch-
20040211/#relwwwrest
[21] M. Belshe, et al. “Hypertext Transfer Protocol
Version 2 (HTTP/2)”, IETF Internet Engineering Task
Force, (2015).
https://tools.ietf.org/html/rfc7540
[22] Andrew R. "Getting Ready For HTTP2: A Guide
For Web Designers And Developers", Smashing
Magazine, (2016).
https://www.smashingmagazine.com/2016/02/getting-
ready-for-http2/
[23] Darpa Internet Program, "Transmission Control
Protocol - Protocol Specification", Defense Advanced
Research Projects Agency Information Processing
Techniques Office, (1981).
https://tools.ietf.org/html/rfc793
[24] Agostinho, A. "CopyFasterToS3", (2015).
https://github.com/aragostinho/CopyFasterToS3
[25] Chung L., “Representing and Using Non- Functional
Requirements: AProcess Oriented Approach” Ph.D.
Thesis, Dept. of Comp. Science.University of Toronto,
(1993).
[26] Cysneiros, L.M. and Leite, J.C.S.P. ‘Integrating Non-
FunctionalRequirements into data model” 4th
International Symposium on Requirements Engineering
– Ireland (1999).