Outro mecanismo criado pelos provedores de e-mail para diminuir o volume de
spam foi criar quotas de envio para limitar o volume de e-mails enviados por endereço IP
ou por um endereço de correio eletrônico do remetente, por exemplo.
Quando a quota do remetente é atingido, o provedor de e-mail realiza o bloqueio temporário do remetente e o notifica sobre o ocorrido. Caso o remetente continue enviando mensagens sem respeitar o bloqueio temporário, ele será taxado como um emissor de spam podendo sofrer um bloqueio permanente e ainda ser adicionado a alguma base pública de spam, conhecido como spam blacklists.
Uma blacklist trata-se de uma lista de e-mails, domínios ou endereços IP, reconhe- cidamente fontes de spam. Geralmente, utiliza-se este recurso (blacklist) para bloquear os e-mails suspeitos de serem spam no servidor de e-mails.
3.1.6
Considerações
Esta seção fez uma introdução sobre o e-mail e sua arquitetura a fim de apresentar os conceitos necessários para entender como o Hermod deve utilizar esta tecnologia. Como dito antes o e-mail é a tecnologia de base para o Hermod. Além disso apresentamos dois problemas que o Hermod precisa resolver que é o rastreio de e-mails e lidar com as regras de spam que os provedores de e-mail possui.
O que discutimos na seção 3.1.4 Rastreio de e-mails enviados será usado para a implementação de um componente no Hermod que será o responsável por gerenciar o rastreio dos e-mails. Os detalhes sobre o funcionamento e implementação deste componente estão descritos na seção 4.2.2.4 Componente de monitorar e-mail.
Outro ponto desta seção que teve impacto sobre o desenvolvimento do Hermod foi a pesquisa realizada na seção 3.1.5 Proteção contra SPAM. Entendemos como funcionam as práticas dos provedores sobre classificar as mensagens como spam e como eles julgam que um remetente pode ser um spammer. A pesquisa sobre este item impactou sobre o desenvolvimento do Componente de envio de e-mail, através da implementação de regras de envio e inclusão de cabeçalhos especiais (detalhes na seção 4.2.2.2 Componente de envio de e-mail) e sobre o componente responsável por trazer elasticidade aos servidores de e-mail, aumentando ou diminuindo a quantidade de servidores acordo com a demanda (mais detalhes na seção 4.2.2.5 Componente de elasticidade).
3.2
Middleware orientado a mensagens (MOM)
No capítulo2foi feita uma análise do módulo de envio da Arquitetura SIG e um dos problemas apresentados foi Perda da fila de envio. Este era um problema que a plataforma
44 Capítulo 3. Fundamentação Teórica
Hermod não poderia repetir e portanto buscávamos uma solução que contemplasse as seguintes capacidades:
Mensagens persistentes As mensagens deve continuar existindo mesmo após alguma
falha no servidor ou que o servidor precise ser reiniciado.
Permita múltiplos clientes O Hermod terá capacidade de funcionar replicado, dessa
forma é preciso que a solução de armazenamento consiga atender várias instâncias do Hermod ao mesmo tempo.
Estrutura de fila As primeiras mensagens que foram armazenadas devem ser as primeiras
a serem consumidas para o envio.
Diantes dessas condições escolhemos usar um middleware orientado a mensagens, que por suas características — um cliente pode enviar e receber mensagens de forma assíncrona de qualquer outro cliente, conectados a um agente especial que fornece facilidades para criar, enviar, receber e ler mensagens — se encaixa perfeitamente ao problema. Nesta categoria avaliamos o uso de três tecnologias: API JMS (Java Message Service), Protocolo AMQP (Advanced Message Queuing Protocol) e Protocolo MQTT (Message Queue Telemetry Transport).
3.2.1
Java Message Service (JMS)
O JMS é uma especificação madura e robusta que provê uma API padronizada de mensagens para a Plataforma Java. Uma das vantagens de se adotar esta tencologia, é que possibilita alternar a implementação do servidor (também conhecido como broker ) por qualquer outro servidor que siga a especificação do JMS (JMS Compilant) sem que seja necessário trocar nenhuma linha do código da aplicação. (RICHARDS, 2011)
É importante salientar que o JMS fornece interoperabilidade dentro da Plataforma Java, ou seja, é muito fácil integrar uma aplicação Java com uma outra desenvolvida em Scala ou Groovy. Entretanto, integração da Plataforma Java com outra plataforma que não seja Java (como .Net ou Ruby) apesar de ser possível, não é algo trivial. Para conseguir realizar a interoperabilidade é preciso encontrar um broker que em uma ponta seja compatível com JMS e na outra ponta seja compatível com o formato que a outra plataforma reconhece. Por exemplo, se de um lado temos uma aplicação Java (JMS) e do outro lado uma aplicação Ruby (a escolha mais popular no mundo Ruby é o protocolo STOMP) então seria necessário escolher um broker que fosse compatível com essas duas tecnologias. (RICHARDS, 2011)
3.2. Middleware orientado a mensagens (MOM) 45
3.2.2
Advanced Message Queuing Protocol (AMQP)
A necessidade por um serviço de mensagens que permitisse a interoperabilidade entre diferentes plataformas foi a razão da criação do AMQP (RICHARDS, 2011). Este protocolo permite a troca de mensagens assíncronas entre diferentes aplicações e/ou serviços. Diferentemente do JMS, o AMQP não fornece uma especificação de uma API em alto nível. Ela fornece uma especificação em baixo nível de um protocolo binário que descreve como a mensagem deve ser estruturada para ser enviada através da rede.
Figura 8 – Comparação do sistema de rota do JMS vs AMQP
A figura 8ilustra algumas diferenças substanciais em relação ao JMS sobre como cada um realiza o roteamento de mensagens (message rounting), ou seja, o caminho que a mensagem percorre ao ser enviada de um produto até ser recebido por um consumidor. O JMS usa um esquema simples de roteamento onde tanto o produtor quanto o consumidor estão conectados à mesma fila ou tópico. Já no AMQP (Advanced Message Queuing
46 Capítulo 3. Fundamentação Teórica
Protocol) é um pouco diferente, a mensagem não é publicada diretamente na fila, em vez disso, as mensagens são enviadas para o exchange.
O exchange é o objeto que aceita a mensagem de um produtor e a encaminha para as filas de acordo com um critério pré-definido. Esse critério é chamado de binding. O exchange é basicamente um sistema de rotas, que inspeciona a mensagem e usando sua tabela de critérios decide como a encaminhar as mensagens, seja para uma fila de mensagem ou para outro exchange.
De maneira geral, para fazer o roteamento das mensagens o exchange examina as propriedades da mensagem, cabeçalho e conteúdo, e possivelmente de outras fontes. Na maioria dos casos o exchange examina um único campo, que é chamado de routing
key. Este campo nada mais é do que um endereço virtual que o exchange pode usar para
encaminhar a mensagem. Cada exchange representa um modelo de comunicação e os quatro possíveis são:
Direct Esse modelo baseia-se em entregar as mensagens para uma fila baseada no nome
da rota, ou seja, encaminha mensagens para a fila com base em uma correspondência exata entre a chave de roteamento da mensagem e a chave usada na vinculação para ligar a fila ao exchange (processo conhecido como binding). É ideal para comunicações
unicast (uma comunicação ponto-a-ponto) e uma ótima opção para trabalhar com
diversos consumidores de maneira balanceada já que o algoritmo utilizado para distribuição de mensagens entre os consumidores é o round-robin.
Fanout Esse modelo simplesmente ignora a rota. Seu comportamento resume-se em
mandar uma cópia das mensagens para todas as filas que estão associadas a ele. Se
n filas estão ligadas (binding) ao exchange, quando uma mensagem é publicada em
um fanout, todas as filas ligadas receberão uma cópia.
Topic Roteia uma mensagem de um exchange para uma ou mais filas com base na
correspondência entre a chave de roteamento da mensagem e um padrão que foi usado para fazer a ligação com a fila. Este modelo de exchange é frequentemente utilizado para implementar um modelo publish/subscribe e muito comum em comunicações
multicast.
Headers Este tipo ignora a rota e encaminha as mensagens usando seu cabeçalho. Então
se existe a necessidade de fazer um roteamento mais complexo onde uma routing key não é o suficiente para encaminhar a mensagem, esse exchange vai ser útil. Com ele é possível usar um ou mais atributos do cabeçalho da mensagem para realizar o roteamento para a fila correta.
3.2. Middleware orientado a mensagens (MOM) 47
3.2.3
Message Queue Telemetry Transport (MQTT)
Uma outra abordagem para o problema analisada foi o uso do protocolo MQTT (Message Queuing Telemetry Transport) — apesar de ter fila (Queuing) como parte do nome, não possui fila —, originalmente desenvolvida pela equipe de computação pervasiva da IBM — hoje em dia é opensource — que assim como o AMQP é um protocolo para envio de mensagens assíncronos. Seu diferencial é que foi projetado desde o início para dispositivos móveis, por isso possui um baixo overhead para envio de dados pela rede. (COHN, 2011)
Em contraste com o AMQP que suporta quatro modelos de comunicação, o MQTT suporta somente o paradigma publish/subscribe em tópicos para a troca de mensagens. Os clientes podem configurar diferentes níveis de qualidade de serviço (QoS) para garantir a entrega de mensagens. A especificação prevê três níveis de qualidade de serviço:
QoS 0 Assemelha-se ao protocolo de transporte UDP, onde não se tem confirmações
de entrega de mensagem. Quem envia também não tem a obrigação de manter a mensagem armazenada para futuras retransmissões.
QoS 1 Neste nível existe a confirmação de entrega de uma mensagem. Atende situações
onde quem envia acaba gerando várias mensagens iguais possivelmente por um atraso na chegada de confirmação de recebimento. Neste caso, é garantido que uma delas terá o reconhecimento realizado. Note que existe um armazenamento da mensagem por parte de quem envia até a posterior confirmação.
QoS 2 Garante que a mensagem seja entregue exatamente uma vez, com envio de confirma-
ções de recebimento e confirmações de recebimento de confirmações de recebimento. Enquanto uma mensagem não é confirmada, ela é mantida pelo cliente. É um caso mais próximo do protocolo de transporte TCP.
Uma diferença fundamental entre esses dois protocolos é que no AMQP as men- sagens são armazenadas e entregues (store-and-forward). O MQTT ao contrário, não se destina a lidar com mensagens duráveis e persistentes. Ele não pode ser considerado para implementar o padrão store-and-forward. Embora os serviços de mensagens tradicionais sejam projetados para entrega confiável de mensagens entre aplicativos corporativos, o MQTT é um protocolo mais simples projetado para conectar dispositivos — sua API também é simples, possui apenas cinco métodos. Ele não pode ser usado como o middleware para sistemas transacionais.
De uma forma geral, o MQTT não é tão sofisticado quanto o AMQP (Advanced Message Queuing Protocol), que possui mais funcionalidades e cenários de uso, mas é simples o suficiente sem deixar de contemplar características como segurança, qualidade de serviço e facilidade de implementação.
48 Capítulo 3. Fundamentação Teórica
3.2.4
Considerações
A pesquisa desta seção serviu de base para a implementação do Componente de fila descrito na seção 4.2.2.1 Componente de fila. A conclusão que chegamos é cada uma delas tem capacidade de ajudar o Componente de fila a resolver os problemas que este componente propoe resolver. Todas as as soluções analisadas são referência dentro da industria de software, possuem casos de sucesso e ampla documentação.