Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Sugestão técnica - Processamento pesado para uma gama de CPFs (~50 mil)

Olá pessoal. Sou colaborador de uma empresa pública do estado do paraná, e tenho uma demanda específica em um software que está em fase de construção.

Gostaria de uma sugestão técnica de como implementar determinada solução. Tenho um serviço REST do tipo POST, que recebe em seu body um json no seguinte formato:

{
    "cpfs": [ "<cpf_x>", "<cpf_y>" ... ],
    "channel": [ "SMS", "EMAIL" ],
    "messageTitle":"<mensagemTitle>",
    "message":"<mensagem>",
}

Reparem que o field cpfs é um array. Como é um software que estou construindo do zero, preciso cuidar com um requisito não-funcional previamente mapeado, atrelado a categoria de performance. Levando em consideração o limite de 10 MB por default que pode ser trafegado (encapsulado no body da requisição), possivelmente terei uma solicitação com vários cpfs. Imaginem cerca de 40 à 50 mil cpfs informados nesse array.

A questão é, preciso notificar todos esses 50 mil cidadãos aproximadamente, enviando a mensagem para o canal informado (veja que nesse exemplo tenho dois, mas posso ter que notificar em até 4 canais), ou seja, é um processamento pesado. Além disso, pra cada cidadão (cada cpf), existem algumas regras de negócio (porém são poucas e bem simples).

Para mim está claro que devo realizar todo esse processamento de forma assíncrona (óbvio). Neste caso pretendo devolver um http 202 para o cliente, dizendo a ele que aceitei a solicitação e vou processar.

Porém a minha dúvida é, qual seria a melhor maneira de implementar tal processamento. Pensei em usar ExecutorService e separar todo esse processamento em várias Threads. Ou então, utilizar fila JMS.

Alguém teria alguma sugestão ?

Obrigado.

8 respostas

Sugiro criar uma macro (pode ser em qualquer linguagem desktop que consiga ) que acesse o outlook ou seu servidor de email e monte para você esses milhares de emails um a um e já vai disparando quando montado. Se for mandar uma unica vez esses emails não tem muito problema de fazer em uma thread. Deixa rodando e vai fazer outras coisas. Só não esquecer de programar pra quando mandar o e-mail limpar ele da caixa de saída.

Veja, o foco da minha pergunta não está no canal de entrega em si, pois além de e-mail tenho outras formas de entregar a mensagem ao cidadão. A questão é que para cada cpf, tenho algumas validações (regras de negócio, porém simples), mas como tenho muito cpfs por requisição (estou chutando que possa vir cerca de 40 a 50 mil), gostaria de uma sugestão. Tenho dúvidas, se o JMS poderia me ajudar nesse processamento assíncrono, ou se poderia utilizar o ExecutorService (java.util.concurrent). Ou até mesmo se alguém teria alguma outra sugestão.

Obs.: Já existe um componente interno na empresa, desenvolvido por outra área que já faz a entrega de mensagem ao cidadão. Basta passar o cpf do destinatário, o canal de comunicação e a mensagem. Esse meu fluxo assíncrono ao final das validações para cada cpf, irá invocar este componente, nem preciso me preocupar com o que vai acontecer daqui para frente.

Dá uma olhada nessa página e veja se te atende. https://www.devmedia.com.br/jms-api-como-desenvolver-sistemas-baseados-em-mensageria/30073

Rsrs, por favor alguém que de fato entenda do assunto poderia ajudar ?

Oi Gustavo,

a primeira coisa que eu faria é persistir os dados da requisição mas imagino que vc já chegou a essa conclusão :) Como vc está recebendo um json talvez pode usar o mongodb.

Depois experimentaria o Apache Camel para processar os CPFs com as regras. O Spring Batch tbm seria uma opção.

abs

Obs: Temos um curso sobre Camel na Alura (tbm sobre JMS, mas nao vejo como ajudar).

Grande Nico. Pra ser sincero estava dando uma olhada no curso de Threads 2, relembrando alguns recursos mais avançados. Estou pensando em processar essa lista de CPFs, utilizando Threads mesmo.

Pois é, realmente já pensei. Na realidade a primeira coisa que me veio a mente, foi persistir os dados do request, uma vez que todo o processamento será feito de forma assíncrona.

Sobre mongodb, Apache Camel e Spring Batch infelizmente não será possível nesse momento, uma vez que novas ferramentas/tecnologias/recursos devem ser homologados por outra área aqui na empresa para que possamos sair usando.

Mas só pra entender melhor, você disse que o JMS não seria uma opção para este caso ?

E o que acha de processar esta lista (gigantesca) utilizando Threads ?

solução!

Oi Gustavo,

Sobre o banco: falei do mongo pois vc já recebe um json e seus dados não são relacionais, mas importante mesmo é persistir os dados antes de processar. O JMS substituiria o banco nesse cenário e existem opções no broker para persistir tbm a mensagem. Como vc já deve ter um banco para logar e guardar o request (ou não?) achava que não vale a pena usar.

Sobre o processamento: a vantagem de usar o Camel seria que ele já é um framework robusto multi-threaded para processar as informações e encadear as regras, exatamente o que vc precisa. Como vc não pode usá-lo, avalie threads + streams do java 8.

Tudo bem?

abs

Sim, já tenho um banco, para armazenar o request, porém é um banco relacional.

Estou utilizando Java 8, vou partir para esta linha, mas antes vou concluir o curso de Threads 2 para relembrar alguns conceitos.

Teria mais algum outro curso que você recomendaria, que poderia me ajudar neste contexto ?

Mas perfeito Nico. Você disse o que eu precisava ouvir. Obrigado pela atenção. Abraço.