Você está na página 1de 23

SISTEMA DE MENSAGERIA DISTRIBUÍDO PARA WEB

EM TEMPO REAL

Universidade Paulista
Jundiaí - SP RESUMO

Este trabalho tem como objetivo apresentar o desenvolvi-


Autor(es): mento de uma aplicação de mensageria distribuída, sendo
Eder Oliveira Lima uma abordagem para problemas de escalabilidade para apli-
lima.eder101@gmail.com
Gustavo Marinho Freitas cações web que se utilizem de recursos em tempo real, em
gustavomarinhofreitas@gmail.com
especial para casos em que existe a comunicação entre cli-
Jeferson Oliveira Dos Santos
jefersonoliveira5540@gmail.com ente-servidor. A aplicação foi desenvolvida utilizando a lin-
Marcus V Flausino De A Ribeiro
mvinicius_08@hotmail.com guagem de programação Go e disponibiliza um cliente em
Matheus Lucas Silva Farali
Matifaraliazs@gmail.com
Javascript/Typescript para ser utilizado em aplicações web.

Palavras-Chave: Desenvolvimento. Aplicação. Mensage-

Orientador(a): ria. Distribuída.


Prof. Me. Marcos Paulo Ferreira
Rebello.
marcos.rebello@docente.unip.br

ABSTRACT

This work aims to present the development of a distributed


messaging application as an approach to scalability issues
for web applications that use real-time resources, especially
in cases involving client-server communication. The applica-
tion was developed using the Go programming language and
provides a client in Javascript/Typescript for use in web ap-
plications.

Keywords: Development. Distributed. Messaging.


Application.

1
2

1. INTRODUÇÃO

Aplicações web com interação em tempo real são cada vez mais comuns, seja
para fins de comunicação entre usuários, seja para fins de monitoramento de dados
em tempo real (Murley et al., 2021). Uma grande quantidade de aplicações é
desenvolvida com interatividade e experiência do usuário em mente, e a comunicação
em tempo real é um dos recursos que mais contribuem para isso. Redes sociais são
um exemplo de aplicações que utilizam recursos em tempo real, elas comumente
implementam recursos em tempo real para notificações de novas mensagens, curtidas
ou comentários. Essas interações enriquecem a experiência do usuário, não
necessitando de recarregamento ou ações manuais para que as novas informações
sejam exibidas. Tendo isso em mente, o objetivo desse trabalho é apresentar uma
aplicação alternativa para elaboração de aplicações web com recursos em tempo real,
simplificando a implementação de tais recursos no lado do cliente e do servidor. Além
da aplicação, serão apresentados os resultados de testes de desempenho e
escalabilidade, comparando a aplicação desenvolvida com modelos de arquitetura
padrões para esse tipo de problema.

2. DESENVOLVIMENTO

Este trabalho origina-se das necessidades das aplicações web atuais, em que
cada vez são adicionadas mais funcionalidades no lado do cliente para que a
experiência do usuário seja a melhor possível. Com isso, a complexidade das
aplicações aumenta, e a necessidade de uma comunicação em tempo real entre
cliente e servidor se torna cada vez mais comum (Pereira, 2019). A comunicação em
tempo real entre cliente e servidor é um problema que pode ser resolvido de diversas
formas, e cada uma delas possui suas vantagens e desvantagens.

2.1. APLICAÇÕES WEB E MICROSSERVIÇOS

Originalmente, aplicações web tradicionais eram monolíticas, isto é,


necessitavam de uma única máquina para serem executadas (Valente, 2022). Com o
crescimento da web e a disponibilização de vários serviços com milhares de usuários
através dela, a quantidade de processamento necessária para atender a demanda de
usuários cresceu exponencialmente. Com isso, a necessidade de escalabilidade
também cresceu, e a arquitetura de aplicações web evoluiu para um modelo

Unip – Jundiaí – SP - 2023


3

distribuído, onde a aplicação é executada em várias máquinas, e cada uma delas é


responsável por uma parte da aplicação. Esse modelo de arquitetura é conhecido
como arquitetura de Microsserviços.

Arquiteturas de microsserviços consistem na divisão de uma aplicação em


diversos serviços menores, cada um com sua própria responsabilidade. Isso permite
que a aplicação seja dividida em pequenos módulos, cada um com seu domínio
especializado e seus recursos computacionais. Essa abordagem possibilita que cada
serviço seja escalado individualmente, de acordo com a demanda de cada um. Além
disso, a divisão da aplicação em serviços menores permite que cada serviço seja
desenvolvido utilizando a linguagem de programação mais adequada para o problema
que ele resolve, e que cada serviço seja executado em uma máquina diferente. Isso
permite que a aplicação seja escalada horizontalmente, isto é, que ela seja executada
em várias máquinas ao mesmo tempo, cada uma responsável pelo serviço que lhe foi
atribuído. Essa abordagem é conhecida como escalabilidade horizontal (Newman,
2021; Patil; Singh, 2013).

2.2. ESCALABILIDADE HORIZONTAL E APLICAÇOES EM TEMPO REAL

A escalabilidade horizontal vem com seus próprios desafios, em especial para


aplicações que necessitam de estado. Aplicações web tradicionais, que utilizam o
modelo de arquitetura monolítica, possibilitam o armazenamento de estado, uma vez
que executam em um único servidor, entretanto a escalabilidade desse tipo de
aplicação é limitada e custosa, pois de acordo com Patil e Singh (2013) tal arquitetura
necessita de acréscimo de hardware para aumentar seu poder computacional.

Para aplicações distribuídas, a escalabilidade horizontal facilita o aumento de


poder computacional, sendo necessário apenas adicionar mais servidores em um
cluster (Tailor; Patel, 2016). Porém, esse tipo de escalabilidade apresenta um desafio
para servidores que necessitam manter conexão com o cliente, como é o caso das
aplicações web em tempo real. Nesses casos, é comum ver arquiteturas como
apresentado na Figura 1.

Unip – Jundiaí – SP - 2023


4

Figura 1 - Arquitetura de aplicação em tempo real em clusterização

Fonte: autoria própria.

Segundo Hussein Nasser (cf. Scaling Websockets with Redis..., 2020), nesse
tipo de arquitetura, utiliza-se um serviço de mensageria para notificar servidores de
atualização de estado, para que ele possa distribuir isso para outras máquinas
conectadas em um cluster. Essa é uma das estratégias que serviços que se utilizam
de atualizações em tempo real implementam.

Essa é uma abordagem válida, porém adiciona complexidade na


implementação do sistema, como gerenciamento da infraestrutura do serviço de
mensageria e a implementação da lógica de distribuição de mensagens no servidor
de comunicação, além do gerenciamento de clientes conectados nos servidores.

2.3. SOLUÇÃO PROPOSTA

O intuito da aplicação desenvolvida nesse trabalho é simplificar a complexidade


da arquitetura necessária para desenvolver aplicações em tempo real para a web.
Adicionando um único serviço de mensageria, responsável por receber as
atualizações da aplicação e distribuí-la entre os clientes conectados. A arquitetura
proposta pode ser visualizada na Figura 2.

Unip – Jundiaí – SP - 2023


5

Figura 2 - Arquitetura proposta

Fonte: autoria própria.

A distribuição das mensagens é feita através de tópicos, conforme visto na


Figura 3, no qual cada tópico é responsável por um tipo de mensagem. Os clientes
podem se inscrever em um ou mais tópicos, e o serviço de mensageria distribuí as
mensagens para os clientes inscritos em cada tópico. Essa abordagem simplifica a
implementação de serviços em tempo real, uma vez que para notificar clientes
conectados de uma atualização, é necessário somente a publicação de uma
mensagem para um tópico.
Figura 3 - Distribuição de mensagens através de tópicos

Fonte: autoria própria.

Nesse modelo, para que o cliente receba atualizações de um tópico, ele precisa
se inscrever no tópico desejado. Após a inscrição, o cliente passa a receber
atualizações do tópico, e pode se inscrever em outros tópicos, podendo receber
atualizações de vários tópicos ao mesmo tempo.

Unip – Jundiaí – SP - 2023


6

Para a aplicação, os clientes se conectam utilizando o padrão SSE (Server-


Sent-Events) através do protocolo HTTP, “SSE é uma tecnologia que permite a
comunicação unidirecional entre o servidor e o cliente em tempo real” (Mello, 2023,
Online). O modelo de conexão é apresentado na Figura 4.
Figura 4 - Modelo de conexão

Fonte: autoria própria.

Essa tecnologia possibilita que o servidor envie mensagens para o cliente


através de uma conexão HTTP, sem que o cliente precise fazer requisições
ativamente para o servidor. O cliente pode se conectar ao servidor através de um
endpoint específico, e o servidor pode enviar mensagens para o cliente através de um
outro endpoint específico. O cliente pode se desconectar do servidor a qualquer
momento, e o servidor pode enviar mensagens para o cliente enquanto a conexão
estiver estabelecida.

A principal vantagem do SSE em relação a alternativas como WebSocket é a


simplicidade da implementação e velocidade de desenvolvimento. O SSE é uma
tecnologia nativa do protocolo HTTP, e não necessita de bibliotecas externas para ser
implementado. Além disso, o SSE é um protocolo unidirecional, o que simplifica a
implementação do servidor, uma vez que ele não precisa gerenciar requisições do
cliente.

2.4. PROTOCOLO DE CONSENSO

O sistema funciona em modo de nó único e em cluster. Em modo de nó único,


o sistema executa em uma única máquina, e não é possível adicionar mais nós. Em

Unip – Jundiaí – SP - 2023


7

modo de cluster, o sistema executa em várias máquinas, e é possível adicionar mais


nós ao cluster. O sistema utiliza o protocolo Raft para consenso entre os nós do
cluster, para garantir consistência entre os nós e a entrega da mensagem para os
tópicos entre cada máquina do cluster. Inicialmente os nós contam com um "bootstrap"
para que o cluster seja inicializado, esse nó é responsável por iniciar o cluster e
adicionar novos nós ao cluster.

O processo de replicação no Raft inicia com a eleição de um líder, que é


responsável por coordenar e distribuir as operações para os demais servidores
seguidores. O líder recebe comandos dos clientes, adiciona esses comandos ao seu
log e replica esses logs para os seguidores. Os seguidores, por sua vez, aplicam
esses comandos aos seus estados, mantendo assim a consistência entre os
diferentes servidores no cluster (Ongaro; Ousterhout, 2014).

O Raft lida eficientemente com situações de falha, como a queda de um líder,


ao realizar eleições de forma determinística, garantindo a continuidade operacional do
sistema (Ongaro; Ousterhout, 2014). Além disso, a simplicidade do Raft facilita a
compreensão do protocolo, permitindo uma implementação mais precisa e robusta.

A escolha do Raft em relação a outros protocolos de consenso se dá


principalmente pela facilidade da sua compreensão, em especial quando comparado
com outros protocolos como o Paxos. As principais considerações pela sua escolha
foram

1. simplicidade e entendimento: O Raft é reconhecido por sua clareza e


simplicidade conceitual, facilitando o entendimento e implementação
(Ongaro; Ousterhout, 2014). Em um projeto de tamanha importância como
um sistema de mensageria distribuída, a simplicidade do Raft torna-se uma
vantagem significativa;

2. processo de eleição determinística: O Raft utiliza um processo de eleição


determinística, evitando ambiguidades associadas à eleição em ambientes
complexos. Esse determinismo é crucial para manter a coerência do
sistema em situações de falha (Ongaro; Ousterhout, 2014);

3. manutenção e evolução do código: A clareza do Raft simplifica a


manutenção do código ao longo do tempo. Compreender e modificar o
código é mais acessível, resultando em um desenvolvimento mais eficiente
e menos propenso a erros (Ongaro; Ousterhout, 2014).

Unip – Jundiaí – SP - 2023


8

2.5. IMPLEMENTAÇÃO

A aplicação foi desenvolvida em Go originalmente por se tratar de uma


linguagem compilada e de simples compreensão. A linguagem conta com construções
primitivas de concorrência, que é um dos pontos essenciais para a implementação de
um sistema de mensageria distribuída. Além disso, a linguagem conta com uma
biblioteca padrão extensiva que facilita o desenvolvimento de servidores web.

O servidor conta com uma API REST para gerenciamento de tópicos e um


endpoint SSE para comunicação com os clientes. A API REST é responsável por
gerenciar os tópicos, permitindo a criação, listagem e remoção de tópicos, além de
publicação de mensagens. O endpoint SSE é responsável por distribuir as mensagens
para os clientes conectados.

A premissa base do sistema é a distribuição por tópicos, o que facilita o


roteamento e a distribuição de mensagens entre os clientes. Cada tópico atua como
uma fila de mensagens, de contexto específico e com um conjunto de clientes
inscritos. Quando uma mensagem é publicada em um tópico, ela é distribuída para
todos os clientes inscritos no tópico.

Esse modelo de tópicos resulta em uma distribuição de mensagens mais


eficiente (demonstrado na Figura 5), uma vez que as mensagens são distribuídas
apenas para os clientes inscritos no tópico, e não para todos os clientes conectados
ao servidor. Além disso, esse modelo permite que os clientes se inscrevam em tópicos
específicos, recebendo apenas as mensagens que são relevantes para eles.
Figura 5 - Demonstração de distribuição de mensagens

Fonte: autoria própria.

Unip – Jundiaí – SP - 2023


9

Além disso, o sistema conta com um processo de replicação de mensagens


entre os nós do cluster, garantindo a consistência entre os nós e a entrega das
mensagens para os tópicos. O processo de replicação é feito através do protocolo de
consenso Raft, em que no modo cluster todas as atualizações de estado do sistema
são processadas através de uma máquina de estado finita determinística, da qual
processa cada operação sequencialmente e garante a consistência entre os nós do
cluster.

2.6. COMPARAÇÃO ENTRE SISTEMAS DE MENSAGERIA

Na Tabela 1 apresenta-se uma comparação entre o sistema desenvolvido neste


trabalho (REPL), o Kafka e o Redis Pub/Sub.
Tabela 1 - Comparação entre sistemas de mensageria
Métrica Kafka Redis Pub/Sub REPL (Aplicação)

Cluster Sim Sim Sim

Modelo de
Publish/Subscribe Publish/Subscribe Publish/Subscribe
mensageria

Protocolo de
Zookeeper N/A Raft
consenso

Linguagem de
Java/Scala C Go
programação

Protocolo de
TCP TCP HTTP
comunicação

Mensagens Bytes Bytes JSON

Persistência Sim Sim Não

Tópicos Sim Sim Sim

Garante a entrega
Sim Não Não
da mensagem

Garante a ordem
Sim Não Não
das mensagens

Fonte: autoria própria.

Unip – Jundiaí – SP - 2023


10

2.7. DESENVOLVIMENTO E ARQUITETURA DA APLICAÇÃO

A linguagem escolhida para o desenvolvimento da aplicação foi a linguagem


Go, por se tratar de uma linguagem compilada, com gerenciamento de memória e de
simples compreensão. O Go conta com estruturas primitivas de concorrência como
rotinas de background e canais de comunicação para envio de dados e sincronização
de threads, pontos cruciais para o desenvolvimento de uma aplicação que lida com
larga escala de dados e concorrência.

A aplicação pode ser executada em dois modos, sendo eles standalone e em


cluster. Em modo standalone a aplicação executa em uma única máquina, nesse
modo a performance com relação a publicação de mensagens é maior do que em
modo cluster, pois não necessita de distribuição e replicação de mensagens entre
máquinas.

Em modo cluster a aplicação executa em várias máquinas, e é possível


adicionar mais nós ao cluster. Nesse modo a aplicação conta com um processo de
replicação de mensagens entre os nós utilizando o Raft como protocolo de consenso,
garantindo a consistência entre os nós e a entrega das mensagens para os tópicos.
Cada um dos modos conta com prós e contras, sendo o modo standalone mais
eficiente para publicação de mensagens, e o modo cluster suportando mais conexões.

2.7.1. ESTRUTURAS DE DISTRIBUIÇÃO DE MENSAGENS

Durante o desenvolvimento, um dos principais pontos de atenção era o


desempenho e eficiência da aplicação, uma vez que ela lida com uma grande
quantidade de dados e precisa ser escalável. Para isso, foram realizados testes de
desempenho para avaliar estruturas alternativas de concorrência e distribuição de
mensagens.

A primeira alternativa foi utilizar uma estrutura de distribuição de dados no


padrão broadcast, em que um canal central distribui as mensagens para os clientes
conectados de maneira síncrona. Apesar de ser de fácil compreensão ela se mostrou
ineficiente para o propósito da aplicação, uma vez que chamadas bloqueantes de
escrita entre diferentes threads resultava em um decréscimo de performance
conforme o número de clientes aumentava na aplicação.

Foram realizados outros testes com essa mesma estrutura, efetuando a escrita
das mensagens em um thread de execução separada, para o aumento da

Unip – Jundiaí – SP - 2023


11

performance. Isso resultou em uma melhora do desempenho, entretanto o custo


dessa alternativa foi o aumento de utilização de recursos computacionais. O aumento
do número de threads de execução ocasionou um custo de consumo de memória e
processamento, em especial, para o runtime da própria linguagem. Com a execução
de mais threads e mais alocação de memória, o runtime passou a consumir mais
recursos computacionais para gerenciar os recursos utilizados pela aplicação,
gerando lentidão para desalocar recursos.

A estrutura mais eficiente para o nosso caso de uso foi a distribuição de


mensagens através de um broker, uma vez que a distribuição é feita de maneira
assíncrona, e o servidor de mensageria é responsável por gerenciar a distribuição de
mensagens. Para a IBM (2023), um broker de mensagens é uma estrutura
responsável por armazenar e distribuir mensagens para os respectivos clientes. A
estrutura de broker de mensagens é composta por um servidor de mensageria (como
exemplo temos o Apache Kafka), responsável por receber as mensagens e distribuí-
las para os clientes conectados (IBM, 2023).

A estrutura de broker na aplicação consiste em uma estrutura de dados que


possui uma fila interna de mensagens que é alterada quando uma requisição de
publicação para um determinado tópico é realizada. Essa fila armazena as mensagens
para serem consumidas pelos clientes posteriormente. O broker executa a distribuição
de mensagens removendo os primeiros itens que foram adicionados na fila e
distribuindo para os clientes conectados no tópico.

Essa estrutura se mostrou muito eficiente para a aplicação, resultando em uma


melhora significativa da performance. Por se tratar de uma distribuição assíncrona, a
estrutura pode armazenar as mensagens em uma fila interna e distribuir para os
clientes conectados posteriormente, contrário a estrutura de broadcast, essa
alternativa pode distribuir mensagens em lotes, reduzindo operações de sincronização
na aplicação e chamadas do sistema operacional para escrever nos sockets dos
clientes conectados.

2.7.2. ANÁLISE DE PERFORMANCE E OTIMIZAÇÕES

Um dos principais pontos de atenção durante o desenvolvimento da aplicação


foi a performance de distribuição das mensagens para os clientes conectados. Para
isso, foram realizados testes de desempenho com objetivo de avaliar a performance

Unip – Jundiaí – SP - 2023


12

da aplicação e identificar gargalos de performance, entretanto, também foram


necessárias inspeções no funcionamento da aplicação, como análise de CPU e
análise de alocação de memória durante a execução da aplicação.

A técnica utilizada para inspeção da aplicação é chamada profiling, ela consiste


em executar a aplicação em um ambiente de testes e gerar relatórios de performance
durante a execução da aplicação. Para isso, foram utilizadas ferramentas de profiling
da própria linguagem Go, como o pprof e o trace. Com esses relatórios é possível ver
métricas úteis para a otimização do código, como alocação de memória e tempo de
execução de funções. Na figura 6, podemos ver uma imagem de demonstração do
profiling da memória.
Figura 6 - Demonstração do profiling da memória

Fonte: autoria própria.

A partir dos relatórios gerados pelo profiling da aplicação foi possível analisar e
otimizar pontos que prejudicavam a performance. O ponto principal de otimização foi
com relação a chamadas do sistema operacional (syscalls), observando a
performance de cada chamada e otimizando o código para reduzir o número de
chamadas.

Além das chamadas de sistema operacional também foram otimizadas


operações dentro da aplicação, como operações de serializar JSON. Durante os
testes foi identificado que a escrita de mensagens para os clientes realizava
operações de transformar uma estrutura de dados para uma string por N iterações
para N clientes, resultando em uma complexidade assintótica de O(n²).

Unip – Jundiaí – SP - 2023


13

A solução interna para esse problema de performance foi de publicar as


mensagens, que anteriormente eram estruturas de dados, diretamente em formato de
strings para o broker, removendo assim a necessidade da aplicação de serializar as
mensagens para cada cliente conectado. Essa otimização resultou em uma melhora
significativa da performance, em especial para os casos em que o servidor possuía
uma grande quantidade de clientes conectados.

3. RESULTADOS, ANÁLISE E DISCUSSÃO

Os testes de desempenho foram realizados utilizando a ferramenta wrk para


requisições HTTP e um cliente SSE desenvolvido em Go para simular os clientes. Os
testes foram realizados em um computador com processador Intel I5-10210U e 16GB
de memória RAM, utilizando o sistema operacional Linux Ubuntu 22.04.

3.1. TESTES DE CARGA

Os testes foram realizados em pequenas baterias, com diferentes quantidades


de clientes conectados, aplicações e linguagens de programação diferentes, contando
com implementações em NodeJS e Python. Os testes consistem em 5 baterias,
contando com 50, 100, 500, 1000 e 2000 conexões para cada servidor. Cada bateria
consiste em um teste de carga com intervalo de 10 segundos para cada aplicação,
em que o intuito foi medir a quantidade de mensagens publicadas por segundo,
latência e utilização de recursos da máquina. Esse teste é demonstrativo e compara
a performance da aplicação desenvolvida em modo standalone, executando em uma
única máquina e os seus resultados são apresentados nas tabelas 2, 3, e 4.
Tabela 2 - Performance do NodeJS
Requisições Latência Taxa
Clientes CPU Memória
(RP/s) (1k msg/s) (msg/s)

50 9.601 1.1s 890 37.3% 0.4%

100 6.818 1.4s 720 70.1% 0.5%

500 1.475 6.2s 460 84.9% 0.5%

1000 765 12.9s 77 87% 0.6%

2000 386 25s 38 93.3% 0.7%

Fonte: autoria própria.

Unip – Jundiaí – SP - 2023


14

Tabela 3 - Performance do Python


Requisições Latência Taxa
Clientes CPU Memória
(RP/s) (1k msg/s) (msg/s)

50 2.044 1.8s 550 31.3% 0.3%

100 1.618 2.5s 400 55.4% 0.3%

500 700 8.7s 113 81.8% 0.3%

1000 383 19.3s 52 93.8% 0.4%

2000 198 41s 24 96.9% 0.6%

Fonte: autoria própria.

Tabela 4 - Performance do REPL


Requisições Latência Taxa
Clientes CPU Memória
(RP/s) (1k msg/s) (msg/s)

50 106.598 0.1s 10.000 144% 3%

100 56.927 0.1s 10.000 231% 1.8%

500 9.534 0.15s 6.666 356% 0.4%

1000 4.666 0.3s 3.333 300% 0.6%

2000 2.514 0.6s 1.666 268% 1.1%

Fonte: autoria própria.

A comparação pode ser melhor visualizada através dos gráficos contidos nas
figuras 7, 8 e 9.

Unip – Jundiaí – SP - 2023


15

Figura 7 - Comparação de performance em requisições por segundo

Fonte: autoria própria.

Figura 8 - Comparação de performance em latência

Fonte: autoria própria.

Unip – Jundiaí – SP - 2023


16

Figura 9 - Comparação de performance em mensagens por milissegundo

Fonte: autoria própria.

Os resultados dos testes apresentam uma vantagem da aplicação quando


comparado com implementações alternativas em outras linguagens de programação.
A questão principal é a performance da aplicação, por ser escrita em uma linguagem
compilada, a aplicação desenvolvida em Go se mostrou mais eficiente para o
propósito de distribuição de mensagens, lidando com uma maior quantidade de
clientes simultâneos e uma maior quantidade de mensagens por segundo.

Um detalhe dos resultados é a quantidade de utilização de recursos da


máquina, com o aumento do número de clientes, a aplicação pode se utilizar de uma
maior quantidade de processadores e memória RAM. Contrário das outras linguagens
da demonstração, o Go permite a utilização de múltiplas threads de processamento,
resultando em uma queda de performance menor.

3.2. TESTES DE INTEGRAÇÃO

Realizamos também testes de integração da aplicação, de modo que foram


desenvolvidas 3 demonstrações para exemplificar os modelos arquiteturais descritos
e a performance de cada um:

Unip – Jundiaí – SP - 2023


17

1. Node: NodeJS monolítica, responsável por gerenciar os tópicos e distribuir


as mensagens para os clientes conectados

2. Node + Redis: NodeJS utilizando um sistema de mensageria (Redis) para


distribuição de mensagens

3. Node + REPL: NodeJS utilizando o serviço de mensageria descrito neste


trabalho em modo standalone

Nesse teste, o servidor em NodeJS simula uma aplicação real, com logging e
escritas para um banco de dados SQLite. Assim como no teste anterior, cada bateria
consiste em um teste de carga com intervalo de 10 segundos para cada aplicação, no
qual a ideia foi medir a quantidade de requisições por segundo, a latência de
distribuição de mensagens e a quantidade de mensagens por segundo enviada, com
a quantidade de clientes conectados sendo 50, 100, 500 e 1000 respectivamente. Os
resultados dos testes de integração são apresentados nas tabelas 5, 6 e 7.
Tabela 5 – Node standalone
Latência (1k
Clientes Requisições Taxa (msg/s)
msg/s)

50 984 1s 990

100 557 1.4s 714

500 136 8.2s 120

1000 67 17s 60

Fonte: autoria própria.

Tabela 6 – Node + Redis


Latência (1k
Clientes Requisições Taxa (msg/s)
msg/s)

50 3719 0.25s 3900

100 2382 0.4s 2500

500 646 1.5s 664

1000 279 3.8s 263

Fonte: autoria própria.

Unip – Jundiaí – SP - 2023


18

Tabela 7 – Node + REPL


Latência (1k
Clientes Requisições Taxa (msg/s)
msg/s)

50 2379 0.4s 2500

100 2569 0.4s 2500

500 2471 0.4s 2500

1000 2143 0.5s 1900

Fonte: autoria própria.

A comparação pode ser melhor visualizada através dos gráficos contidos nas
figuras 10, 11 e 12.
Figura 10 - Comparação de performance em requisições por segundo

Fonte: autoria própria.

Unip – Jundiaí – SP - 2023


19

Figura 11 - Comparação de performance em latência

Fonte: autoria própria.

Figura 12 - Comparação de performance em mensagens por segundo

Fonte: autoria própria.

Unip – Jundiaí – SP - 2023


20

Os resultados dos testes de integração apresentam vantagens para diferentes


arquiteturas. No caso da aplicação monolítica, nota-se a queda de performance
conforme a quantidade de clientes aumenta, mesmo com uma quantidade baixa de
clientes nota-se a diferença com relação a alternativa utilizando o Redis. Um ponto
que contribui para essa diferença de performance é a natureza assíncrona de
publicação de mensagem no Redis, liberando o servidor para processar outras
requisições enquanto a mensagem é eventualmente distribuída para os clientes.

A arquitetura utilizando um sistema de mensageria como o Redis possui uma


eventual limitação por conta de a distribuição de mensagens ser realizada diretamente
pelo servidor Node e a quantidade de clientes conectados ser limitada pela
capacidade de processamento do servidor. Isso pode ser um problema para
aplicações que necessitam de uma grande quantidade de clientes conectados
simultaneamente.

O problema dessa arquitetura é notado quanto comparamos diretamente com


a arquitetura utilizando o serviço de mensageria desenvolvido neste trabalho. A
distribuição de mensagens é feita por outro servidor, o que permite que o servidor
Node se concentre apenas em lidar com as regras de negócio, como salvar as
mensagens no banco de dados e realizar outros processamentos. Isso permite que o
servidor processe com uma maior quantidade de requisições por não precisar
executar a distribuição de mensagens.

Outro detalhe a ser mencionado para o teste de integração é a pequena


variação de requisições por segundo, latência e taxa de mensagens com a arquitetura
utilizando o NodeJS com o REPL, na qual a limitação foi a quantidade de requisições
que o servidor em Node consegue enviar para o REPL.

Apesar das vantagens quantitativas da implementação dessa arquitetura,


temos também vantagens qualitativas, como a facilidade de implementação e
manutenção. A implementação de uma arquitetura distribuída utilizando o REPL é
mais simples do que a implementação de uma arquitetura utilizando um sistema de
mensageria como o Redis, uma vez que o REPL é responsável por gerenciar a
distribuição de mensagens para os clientes conectados, e o servidor Node é
responsável apenas por publicar as mensagens para o REPL.

Unip – Jundiaí – SP - 2023


21

4. CONCLUSÃO

O objetivo deste trabalho foi apresentar uma aplicação alternativa para


elaboração de aplicações web com recursos em tempo real, simplificando a
implementação de tais recursos no lado do cliente e do servidor. Além da aplicação,
foram apresentados os resultados de testes de desempenho e escalabilidade,
comparando a aplicação desenvolvida com modelos de arquitetura padrões para esse
tipo de problema.

A aplicação desenvolvida se mostrou mais eficiente para distribuição de


mensagens, lidando com uma maior quantidade de clientes simultâneos e uma maior
quantidade de mensagens por segundo.

Apesar de não ser completa para utilização em cenários reais, necessitando de


estratégias de autenticação e autorização, regras de publicação de mensagens e
outras necessidades de segurança, a aplicação apresenta uma estratégia alternativa
a alguns dos padrões de arquitetura atuais, resultando em ganhos significativos de
performance e escalabilidade.

Unip – Jundiaí – SP - 2023


22

REFERÊNCIAS

IBM. O que são message brokers?. 2023. Disponível em:


https://www.ibm.com/br-pt/topics/message-brokers. Acesso em: 02 nov. 2023.

MELLO, Mayderson. Server-Sent Events (SSE) e como implementar: O que


é SSE?. 2023. Disponível em: https://dev.to/mayderson/server-sent-events-sse-
e-como-implementar-
10ik#:~:text=SSE%20%C3%A9%20uma%20alternativa%20aos,e%20menor%2
0uso%20de%20recursos. Acesso em: 13 out. 2023.

MURLEY, Paul et al. WebSocket adoption and the landscape of the real-time
web. In: Proceedings of the Web Conference 2021. 2021. p. 1192-1203.
Disponível em:
https://faculty.cc.gatech.edu/~mbailey/publications/www21_websocket.pdf.
Acesso em 02 maio 2023.

ONGARO, Diego; OUSTERHOUT, John. In search of an understandable


consensus algorithm (extended version). In: Proceeding of USENIX annual
technical conference, USENIX ATC. 2014. p. 19-20. Disponível em:
https://raft.github.io/raft.pdf. Acesso em 02 nov. 2023.

PATIL, Rajni; SINGH, R. Scaling in cloud computing. International Journal of


Advance Research, IJOAR, v. 1, p. 21-27, 2013. Disponível em:
http://www.ijoar.org/journals/IJOARCS/papers/Scaling-in-Cloud-Computing.pdf.
Acesso em: 22 abr. 2023.

PEREIRA, C. S. Sistemas Distribuídos. Londrina: Educacional S.A., 2019.


Disponível em: https://cm-kls-
content.s3.amazonaws.com/201901/INTERATIVAS_2_0/SISTEMAS_DISTRIB
UIDOS/U1/LIVRO_UNICO.pdf. Acesso em: 8 set. 2023.

Scaling Websockets with Redis, HAProxy and Node JS - High-availability


Group Chat Application. Video: 20min35s. Publicado pelo canal Hussein
Nasser. 15 maio 2020. Disponível em:
https://www.youtube.com/watch?v=gzIcGhJC8hA. Acesso em: 20 out. 2023.

TAILOR, Ushma; PATEL, Puja. A survey on comparative analysis of horizontal


scaling and vertical scaling of cloud computing resources. Int J Sci Adv Res
Technol, v. 2, n. 6, p. 2395-1052, 2016. Disponível em:
https://d1wqtxts1xzle7.cloudfront.net/52711973/IJSARTV2I63514-
libre.pdf?1492671007=&response-content-
disposition=inline%3B+filename%3DA_Survey_on_Comparative_Analysis_of_
Hori.pdf&Expires=1682178356&Signature=G00rhltUrhfB5NzPPsIYH8V7oJoUO
wfSbR9zXqeaWVrPhLbyURSGGYwjjj-
dSKa8LVex6nTxTPIfWBz0K878jI9dE99yU7lS0QewRcPFaNKFxyr3ok1GuRe7
Q2twadUIIH8~ZB3oWag7Uw6K~puM8beSgrEOsOLMe0XqAJyuY7xdJOaIdPIG
zB-
wplGTOH5YAlnS3IAoh5zFIKBEGigZkczp~b9Lz3TtdYovi1lZg9CyASliMpt0stG1
Ctmckoc93qMIkhlKNC9R9-R126jEcEw9TMGz-
6GL4K~7BzRANpA9vtfoezgB0pTnkWuFoK1~pKfKNoq1CfgnaP8OYNk7Tw__&
Key-Pair-Id=APKAJLOHF5GGSLRBV4ZA. Acesso em 22 abr. 2023.

Unip – Jundiaí – SP - 2023


23

VALENTE, M. T. Engenharia de Software Moderna: Princípios e práticas para


desenvolvimento de software com produtividade. 2022. Disponível em:
https://analisederequisitos.com.br/wp-content/uploads/2023/06/Engenharia-de-
Software-Moderna-completo.pdf. Acesso em: 8 set. 2023.

Unip – Jundiaí – SP - 2023

Você também pode gostar