Está à procura de um sistema de filas? Ou, quem sabe, procura uma opção superior? Encontrará aqui toda a informação que necessita!
Os sistemas de filas são um dos segredos mais bem guardados no desenvolvimento de backend.
Sem tentar escrever um poema em louvor dos sistemas de filas, diria que um programador backend júnior evolui para um programador backend de nível intermédio assim que aprende a integrar filas no sistema. As filas melhoram a experiência do cliente (como veremos), reduzem a complexidade e aumentam a fiabilidade de um sistema.
É verdade que, para aplicações web muito simples, com tráfego quase nulo, ou simples sites informativos, as filas podem ser desnecessárias (e até impossíveis de instalar, se estiver num ambiente de hospedagem partilhada), mas as aplicações mais complexas ganham com a implementação de sistemas de filas e as aplicações de grande escala são inviáveis sem recorrer a filas.
Antes de começarmos, um aviso: se já estiver familiarizado com sistemas de filas e pretende comparar as diversas opções, as próximas secções introdutórias poderão aborrecê-lo. 🙂 Por isso, sinta-se à vontade para avançar. As secções introdutórias destinam-se àqueles que têm apenas uma ideia vaga sobre sistemas de filas ou que ouviram falar deles de passagem.
O que é um sistema de filas?
Comecemos por compreender o que é uma fila.
Uma fila é uma estrutura de dados em ciência da computação que imita as filas do mundo real que vemos no nosso quotidiano. Se for a uma bilheteira, por exemplo, terá de ficar no final da fila, enquanto a pessoa que estiver no início da fila será atendida primeiro. É o que chamamos de fenómeno “primeiro a chegar, primeiro a ser servido”. Em ciência da computação, é possível criar programas que armazenam as suas tarefas desta forma numa fila, processando-as uma a uma pela mesma ordem de chegada.
Note que a fila não efetua nenhum processamento propriamente dito. É apenas um tipo de armazenamento temporário onde as tarefas aguardam até serem processadas por algo. Se tudo isto lhe parece um pouco abstrato, não se preocupe. É um conceito abstrato, mas veremos exemplos concretos na próxima secção. 🙂
Por que precisa de sistemas de filas?
Sem entrar em grandes explicações, diria que a principal razão para usar sistemas de filas é o processamento em segundo plano, a execução paralela e a recuperação de erros. Vamos ver alguns exemplos:
Processamento em segundo plano
Imagine que está a executar uma campanha de marketing para uma loja online, onde o tempo é crucial, e a sua aplicação foi criada para enviar um e-mail de confirmação imediatamente antes do cliente concluir a compra e visualizar a página de agradecimento. Se o servidor de e-mail ao qual está a conectar-se não estiver a funcionar, a página web simplesmente deixará de funcionar, prejudicando a experiência do utilizador.
Imagine a quantidade de pedidos de suporte que receberia! Neste caso, o ideal é enviar esta tarefa de envio de e-mail para uma fila de trabalho e mostrar ao cliente a página de confirmação.
Execução paralela
Muitos programadores, especialmente aqueles que desenvolvem aplicações mais simples e com menos tráfego, têm o hábito de usar cron jobs para processamento em segundo plano. Isso funciona bem até que a quantidade de dados de entrada seja tão grande que não seja possível processar tudo. Por exemplo, imagine que tem um cron job que compila relatórios analíticos e os envia por e-mail aos utilizadores e que o seu sistema consegue processar 100 relatórios por minuto.
À medida que a sua aplicação cresce e começa a receber mais de 100 pedidos por minuto em média, o processamento começará a atrasar-se cada vez mais e nunca conseguirá concluir todas as tarefas.
Num sistema de filas, esta situação pode ser evitada ao configurar vários “workers”, que podem selecionar uma tarefa (contendo 100 relatórios a serem processados cada) e trabalhar em paralelo para concluir a tarefa muito mais rapidamente.
Recuperação de falhas
Normalmente, nós, programadores web, não pensamos em falhas. Partimos do princípio de que os nossos servidores e as APIs que usamos estarão sempre online. Mas a realidade é diferente: as falhas de rede são muito comuns e as APIs que usamos podem ficar inativas devido a problemas de infraestrutura (antes de dizer “comigo isso não acontece!”, não se esqueça da enorme falha do Amazon S3). Voltando ao exemplo do relatório, se uma parte da geração do relatório exigir que se conecte à API de pagamentos e essa ligação ficar inativa durante 2 minutos, o que acontece aos 200 relatórios que não foram concluídos?
No entanto, os sistemas de filas envolvem custos adicionais significativos. A curva de aprendizagem é bastante acentuada, pois está a entrar num domínio totalmente novo, a complexidade da sua aplicação e implementação aumenta e os trabalhos na fila nem sempre podem ser controlados com 100% de precisão. Dito isto, há situações em que criar uma aplicação sem filas simplesmente não é viável.
Com isto esclarecido, vamos analisar algumas das opções mais comuns entre backends/sistemas de filas atualmente.
Redis
Redis é conhecido como um armazenamento chave-valor que apenas armazena, atualiza e recupera strings de dados, sem se preocupar com a estrutura dos dados. Embora isto possa ter sido verdade no passado, hoje o Redis oferece estruturas de dados eficientes e altamente úteis, como listas, conjuntos ordenados e até um sistema Pub-Sub, o que o torna muito interessante para implementações de filas.
As vantagens do Redis são:
- Base de dados totalmente em memória, o que resulta em leitura/escrita mais rápidas.
- Altamente eficiente: consegue suportar facilmente mais de 100 000 operações de leitura/escrita por segundo.
- Sistema de persistência muito flexível. Pode optar pelo máximo desempenho, ao custo de uma possível perda de dados em caso de falhas, ou configurar o modo totalmente conservador para sacrificar o desempenho em favor da consistência.
- Clusters com suporte nativo.
Note que o Redis não tem abstrações de mensagens/filas/recuperação, pelo que terá de usar uma biblioteca ou criar um sistema ligeiro. Um exemplo é o facto de o Redis ser o backend de filas padrão para o framework Laravel PHP, onde um agendador foi implementado pelos criadores do framework.
Aprender Redis é fácil.
RabbitMQ
Existem algumas diferenças subtis entre o Redis e o RabbitMQ, por isso, vamos começar por analisá-las.
Em primeiro lugar, o RabbitMQ tem um papel mais específico e bem definido e, por isso, foi criado a pensar nisso: mensagens. Ou seja, o seu ponto forte é atuar como intermediário entre dois sistemas, o que não é o caso do Redis, que atua como base de dados. Como resultado, o RabbitMQ oferece mais funcionalidades que faltam no Redis: roteamento de mensagens, tentativas de repetição, distribuição de carga, etc.
Se pensar bem, as filas de tarefas também podem ser vistas como um sistema de mensagens, onde o agendador, os “workers” e os que “submetem” tarefas podem ser encarados como entidades que participam na passagem de mensagens.
O RabbitMQ tem as seguintes vantagens:
- Melhores abstrações para transmissão de mensagens, reduzindo o trabalho ao nível da aplicação se a transmissão de mensagens for o que precisa.
- Maior resiliência a falhas e interrupções de energia (em comparação com o Redis, pelo menos por padrão).
- Suporte de cluster e federação para implementações distribuídas.
- Ferramentas úteis para gerir e monitorizar as suas implementações.
- Suporte para praticamente todas as linguagens de programação existentes.
- Implementação com a ferramenta que preferir (Docker, Chef, Puppet, etc.).
Quando usar o RabbitMQ? Diria que é uma excelente opção quando sabe que precisa de usar a transmissão de mensagens assíncrona, mas não está preparado para lidar com a enorme complexidade de algumas das outras opções de filas desta lista (veja abaixo).
ActiveMQ
Se trabalha no setor empresarial (ou está a criar uma aplicação altamente distribuída e de grande escala) e não quer ter de reinventar a roda a toda a hora (e cometer erros ao longo do processo), vale a pena analisar o ActiveMQ.
O ActiveMQ destaca-se nestes aspetos:
- É implementado em Java e, por isso, tem uma integração Java muito interessante (segue o padrão JMS).
- Suporta vários protocolos: AMQP, MQTT, STOMP, OpenWire, etc.
- Lida com segurança, roteamento, expiração de mensagens, análises, etc., tudo pronto a usar.
- Suporte integrado para padrões populares de mensagens distribuídas, o que poupa tempo e erros dispendiosos.
Isto não quer dizer que o ActiveMQ só esteja disponível para Java. Tem clientes para Python, C/C++, Node, .Net e outros ecossistemas, pelo que não deve haver preocupações quanto a um possível colapso no futuro. Além disso, o ActiveMQ foi criado com base em padrões completamente abertos e criar os seus próprios clientes ligeiros deverá ser fácil.
Posto isto, tenha em atenção que o ActiveMQ é apenas um intermediário e não inclui um backend. Terá de usar um dos backends compatíveis para armazenar as mensagens. Incluí-o aqui porque não está ligado a uma linguagem de programação específica (como outras soluções populares como Celery, Sidekiq, etc.).
Amazon MQ
O Amazon MQ merece uma menção rápida, mas importante. Se considera que o ActiveMQ é a solução ideal para as suas necessidades, mas não quer lidar com a criação e manutenção da infraestrutura por conta própria, o Amazon MQ oferece um serviço gerido para o fazer. Suporta todos os protocolos que o ActiveMQ oferece (não há diferença nas funcionalidades), pois usa o próprio ActiveMQ por baixo dos panos.
A vantagem é que se trata de um serviço gerido, pelo que não precisa de se preocupar com nada além da sua utilização. Faz ainda mais sentido para implementações que estão na AWS, pois pode tirar partido de outros serviços e ofertas diretamente a partir da sua implementação (transferências de dados mais rápidas, por exemplo).
Amazon SQS
Não podemos esperar que a Amazon fique quieta quando se trata de componentes críticos de infraestrutura, certo? 🙂
E assim temos o Amazon SQS, que é um serviço de filas simples e totalmente hospedado (literalmente) pela conhecida gigante AWS. Mais uma vez, as diferenças subtis são importantes, pelo que deve ter em atenção que o SQS não tem o conceito de transmissão de mensagens. Tal como o Redis, é um backend simples para aceitar e distribuir tarefas em filas.
Então, quando deve usar o Amazon SQS? Eis algumas razões:
- É fã da AWS e não quer usar mais nada (sinceramente, há muitas pessoas assim e não vejo nada de errado nisso).
- Precisa de uma solução hospedada para garantir que a taxa de falhas seja zero e que nenhuma tarefa seja perdida.
- Não quer criar um cluster e ter de o monitorizar. Ou pior, ter de criar ferramentas de monitorização quando podia estar a usar esse tempo para desenvolver de forma produtiva.
- Já tem investimentos consideráveis na plataforma da AWS e manter-se bloqueado faz sentido para a sua empresa.
- Quer um sistema de filas simples e direcionado, sem nenhum dos problemas associados à transmissão de mensagens, protocolos e outros “enfeites”.
Em suma, o Amazon SQS é uma escolha sólida para quem pretende incorporar filas de tarefas no seu sistema e não precisa de se preocupar em instalar/monitorizar tudo por conta própria.
Beanstalkd
O Beanstalkd existe há muito tempo e é um backend rápido, fácil e testado em combate para filas de tarefas. Existem algumas características do Beanstalkd que o diferenciam consideravelmente do Redis:
- É estritamente um sistema de filas de trabalho e nada mais. Envia tarefas para ele, que são processadas mais tarde por “workers”. Por isso, se a sua aplicação precisar de alguma transmissão de mensagens, deve evitar o Beanstalkd.
- Não tem estruturas de dados avançadas, como conjuntos, filas de prioridade, etc.
- O Beanstalkd funciona como uma fila First In, First Out (FIFO). Não é possível organizar tarefas por prioridade.
- Não tem opções de clustering.
Posto isto, o Beanstalkd cria um sistema de filas rápido e ágil para projetos simples que funcionam num único servidor. Para muitos, é mais rápido e estável que o Redis. Por isso, se está a ter problemas com o Redis que não consegue resolver, por muito que tente, e as suas necessidades são simples, vale a pena experimentar o Beanstalkd.
Conclusão
Se leu até aqui (ou chegou aqui apenas a ler por alto 😉), é muito provável que esteja interessado em sistemas de filas ou que precise de um. Nesse caso, a lista apresentada nesta página será útil, a menos que esteja à procura de um sistema de filas específico de uma linguagem/framework.
Gostaria de lhe dizer que as filas são simples e 100% fiáveis, mas não são. São confusas e, como tudo se passa em segundo plano e muito rápido, os erros podem passar despercebidos e tornar-se muito dispendiosos. No entanto, as filas são indispensáveis a partir de um determinado ponto e descobrirá que são uma arma poderosa (talvez a mais poderosa) no seu arsenal. Boa sorte! 🙂