Criar ou utilizar um servidor de mensagens em Java

Opa galera,

Estou com uma dúvida aqui e queria me aproveitar um pouco da experiência e conhecimentos alheios pra solucionar ela.

Atualmente, trabalho com servidores de aplicações financeiras que fazem trocas de mensagens via socket puro. Esses servidores são acessados por vários clientes diferentes, desde POS (aquelas máquinas onde você passa o seu cartão de crétido) a PCs comuns com o sistema rodando lá.

Além desses casos dos clientes que se conectam diretamente eu também posso ter o que nós chamamos de “concentradores”, que é uma segunda aplicação servidora que recebe as conexões de outros clientes e a partir de uma única conexão socket repassa todas essas mensagens pro meu servidor.

Todas essas mensagens contam com a identificação do real cliente (o POS ou o PC lá do outro lado), mesmo que ela tenha passado por um concentrador, então seu sempre sei exatamente de quem ela veio.

Através dessas informações, eu crio contexos para que essas mensagens possam ser processadas, pois a maioria delas funciona em um modo de “envio-resposta-confirmação”, então eu tenho sempre que manter o estado no qual cada uma das transações parou para que seja possível receber uma mensagem de confirmação na transação correta. No caso, eu tenho uma multiplexação lógica de uma única conexão socket, já que o que me interessa não é quem está conectado e sim as mensagens que estão chegando.

Bem, explicado o cenário, eu gostaria de saber se alguém aí que mexe com servidores de mensagens baseados em JMS, como o AtiveMQ, suportariam um cenário como esse, principalmente quando os formados das mensagens são diversos. Em alguns momentos, eu tenho um mesmo servidor trantando mensagens em formato CSV, XML e ISO 8583, logicamente as mensagens tem as mesmas informações e chegam sempre pelo socket, mas o formato que elas chegam é completamente diferente.

Essas ferramentas de mensageria são realmente flexíveis o bastante pra resolver o meu problema ou eu realmente tenho um problema específico demais e vou ter que desenvolver tudo “na raça” mesmo?

Ah, outra coisa, comprei o “Java Messaging” que o Luca sempre indica, acho que ele deve tratar sobre isso lá pra frente (ainda estou nos primeiros capítulos), mas se alguém já puder esclarecer essas coisas agora já vai ser uma maravilha :stuck_out_tongue:

Oi Mauricio,

minha experiência com JMS foi baseada em WebLogic e isso já faz alguns bons anos.

De qualquer forma, meu entendimento é que num serviço de mensagens, você vai enviar/receber mensagens que no final das contas contém objetos.

Se o que está dentro desse objeto é CSV, XML ou qualquer outra coisa, acredito que não faça diferença, desde que você conheça as regras de formação específicas de cada um.

Acho que o problema deve ser bem mais complicado que isso e eu não entendi alguma coisa na sua mensagem! :slight_smile:

Nesse seu cenário, quem enviaria as mensagens JMS? Os clientes de verdade (ex.: POS) ou você teria um proxy no meio do caminho que recebe mensagens socket puro e coloca numa fila JMS?

Abraços,
Marco Campêlo

Eu pelo menos não vi problema algum que te impediria de usar um serviço JMS, sugiro que faça uns testes aí e veja se encontra algum problema, mas acho que é tranquilo.

Opa Marco,

É o seguinte, a minha dúvida toda é manter as transações das mensagens, entende?

Cada mensagem tem a sua identificação de cliente e de transação e independente de por qual porta essa mensagem veio eu tenho que entregar pra transação correta.

Mas essas mensagens não são enviadas por clientes JMS, os clientes que se conectam não sabem nem o que é JMS, eles falam os seus próprios formatos e a única coisa padronizada é que eles sempre se conectam via sockets.

O que eu preciso é abstrair o modo como eles estão se conectando e trabalhar sempre apenas com as mensagens.

Olá

Maurício, eu trabalhei em um ambiente igualzinho. Lidava com CSV, XML e ISO 8583 (Redecard) recebendo de sockets e de X25. E também com protocolo de 3 pernas, desfazimento (transações compensadas), etc. Como estou desempregado (se alguém souber de algo, tô precisando) e adoro esta área, deu até saudades,

Quanto ao formato das mensagens a explicação do Campelo foi perfeita. E ele também chamou a atenção sobre a questão do Proxy. No nosso caso o POS não falava diretamente com o servidor e sim com uma aplicação nossa na máquina cliente que mandava a transação para o servidor. Para discar para o servidor a gente usava o JDun que faz pré dial.

Um pouco de história. No início a gente usava um servidor pra lá de simples feito em C com uma performance espetacular (mais de 200 tps). Depois para o projeto do Banco Postal, a equipe de desenvolvimento fez outro servidor em Java, recebendo HTTP/HTTPS por um servlet, com performance menos espetacular. Era pequeno e bonitinho, tudo com reflection, as mensagens eram tratadas todas genericamente. Mais tarde a equipe de desenvolvimento “evoluiu” para outro usando EJBs e tudo o mais e a logicamente a performance ficou uma merda e ele custou até conseguir passar dos 10 tps.

Então, como viu, não foi usado JMS. Porque? Porque o meu papel no projeto não era o de definir arquitetura porque se fosse eu teria pelo menos avaliado o uso de um provedor de mensageria.

O que eu faria hoje:

  1. Avaliaria a inclusão de um provedor de mensagens.
    Ganho imediato para o projeto em condições normais de temperatura e pressão: nenhum a menos que já esteja engargalado.
    Ganho futuro: escalabilidade e resiliência.

  2. Outra alternativa caso o servidor esteja com problemas de aumento de carga seria avaliar a troca dele por outro baseado no Apache Mina (ou no Grizly do Glassfish que o autor jura que é melhor do que o Mina).

  3. Mais radical ainda seria fazer um outro servidor usando erlang que é COP, isto é, concurrent oriented programming. Rodei um exemplo com um servidor feito em erlang para servir mensagens com o protocolo AMQP e achei muito promissor apesar de ainda em alpha.

Você usa ou já experimentou o JPos?

Como todos aqui sabem, eu sou absolutamente fã de trocas de mensagens assíncronas. Mais ainda agora que estou estudando CEP. Eu acho que sempre que um projeto envolver trocas de mensagens deve avaliar a possibilidade de usar JMS, SOAP por JMS, ISO8583 por JMS, Fx por JMS, etc… Troca de mensagens é coisa comum porque quase todas as empresas fazem algum tipo de EAI.

[]s
Luca (Depois passo no caixa pelo tamanho da resposta. Espero que sirva)

[quote=Maurício Linhares]
Cada mensagem tem a sua identificação de cliente e de transação e independente de por qual porta essa mensagem veio eu tenho que entregar pra transação correta. [/quote]

Oi Maurício,

se cada mensagem tem identificação de cliente e transação, você não vai ter problemas para entregar a resposta para a transação correta, pois assim que você consumir a mensagem, você terá acesso ao ID da transação.

Não é isso?

Abraços,
Marco Campêlo

Maurício,

Quando vc. se refere a “cenário”, fiquei em dúvida em relação a aonde vc. pretende colocar o JMS. Como vc. tem vários tipos de clientes que se conectam a seu processador de mensagens, suponho que qualquer alteração no sentido de se usar o JMS teria como pré-req manter a interface externa, ou seja, um cliente que se conecta via socket enviando mensagens CSV continuaria enviando e recebendo as mensagens como se nada tivesse acontecido.

O JMS neste caso seria utilizado para a troca de mensagens entre seus diversos “front-ends” e um ou mais “back-ends” com as regras de negócio do processamento.

Tambem pelo que entendi, vc. deve ter em cada canal uma tabela de transações em andamento para implementar a lógica de três pernas típica de ISO-8583.

Uma possível vantagem de se utilizar o JMS neste caso seria a possibilidade de se tirar esta lógica dos componentes de front-end, que ficariam apenas com lógica de formatação e validação sintática de mensagens. Como estamos em modo assíncrono, o estado tem que ir para algum lugar, e este lugar seria um “blob” de estado do front end, que teria que ser rebatido na mensagem de retorno.

Talvez não seja o caso, mas vc. chegou a dar uma olhada no mule (www.mulesource.com) ?

Quanto ao formato e ao ID da transação, acho que o campelo deu boas informações já. ObjectMessage do JMS pode transportar qualquer objeto (Serializable)

Eu fiquei um pouco na dúdiva de onde você imagina que o JMS entraria.

Se todos os clientes (pc ou POS) passarem por concentradores(ou proxys como o campelo falou), você poderia colocar JMS entre os concentradores e o servidor que processa mensagens. Dessa forma, seu servidor socket poderia ser trocado para um AppServer com MessageDrivenBeans que consumiriam as mensagens da fila (ou filas) JMS.

Nesse caso, a conversa seria de IDA e VOLTA, entao o concentrador teria que ter uma forma de receber as respostas dos MDBs (JMS talvez) e manter as rotas para responder o cliente correto.

A vantagen seria a abstração dos sockets e escalabilidade vertical com cluster de JMS e Servidores de aplicação (JBoss por exemplo)

Vale lembrar também que JMS tem transações, ACK, MessageSelector e outras features que você deveria dar uma olhadinha pra ver se atende seu cenário.

[quote=Luca]O que eu faria hoje:

  1. Avaliaria a inclusão de um provedor de mensagens.
    Ganho imediato para o projeto em condições normais de temperatura e pressão: nenhum a menos que já esteja engargalado.
    Ganho futuro: escalabilidade e resiliência. [/quote]

Essa é a minha preocupação, possibilidade de clusterizar tudo e não ter que ficar esquentando a cabeça em fazer load balancing dessas coisas no meu código de aplicação, que do jeito que está, é o que vai acontecer.

O caso não é nem a carga ser grande demais, é a dificuldade que seria ter os dois atributos do outro ponto escrevendo uma solução na mão.

Conseguir trabalhar com Java já está difícil, se eu disser que poderíamos fazer em Erlang vão me chutar daqui :stuck_out_tongue:

Infelizmente nós não temos acesso aos clientes, é um sistema de integração então nós temos que manter todos os protocolos que rodam atualmente lá :frowning:

[quote=mcampelo]Oi Maurício,

se cada mensagem tem identificação de cliente e transação, você não vai ter problemas para entregar a resposta para a transação correta, pois assim que você consumir a mensagem, você terá acesso ao ID da transação.

Não é isso?
[/quote]

Opa Marco,

Olha, o que eu não queria é ter que escrever esse código que vai pegar a mensagem e jogar ela pra a transação correta, queria saber se o JMS já tem alguma coisa que faça esse trabalho sozinho, porque senão do JMS eu vou terminar não usando nem o transporte, porque até a formatação eu vou ter que escrever toda.

[quote=psevestre]
Maurício,

Quando vc. se refere a “cenário”, fiquei em dúvida em relação a aonde vc. pretende colocar o JMS. Como vc. tem vários tipos de clientes que se conectam a seu processador de mensagens, suponho que qualquer alteração no sentido de se usar o JMS teria como pré-req manter a interface externa, ou seja, um cliente que se conecta via socket enviando mensagens CSV continuaria enviando e recebendo as mensagens como se nada tivesse acontecido.[/quote]

Opa, é exatamente isso, os clientes tem que continuar se conectando ao sistema e enviando as mensagens da mesma forma, neles eu não posso alterar nem uma linha de código :stuck_out_tongue:

Mais ou menos, a idéia é que o servidor de mensagens pudesse também receber as mensagens dos clientes que enviam CSV, ISO 8583 e coisas do gênero e entregassem elas pra objetos que pudessem operar com essas mensagens dentro de suas transações.

Pois é, porque eu posso ter o proxy (ou um concentrador) pendurado em um canal repassando mensagens de vários clientes.

Pois então, eu não poderia utilizar diretamente as transações do JMS pra fazer isso não? Ele que iria manter e clusterisar esses estados pra mim?

Vou avaliar também esse :smiley:

[quote=felipec]Quanto ao formato e ao ID da transação, acho que o campelo deu boas informações já. ObjectMessage do JMS pode transportar qualquer objeto (Serializable)

Eu fiquei um pouco na dúdiva de onde você imagina que o JMS entraria.[/quote]

Eu queria que o meu servidor de mensagens que recebe as conexões e as mensagens dos clientes fosse um servidor JMS.

[quote=felipec]Se todos os clientes (pc ou POS) passarem por concentradores(ou proxys como o campelo falou), você poderia colocar JMS entre os concentradores e o servidor que processa mensagens. Dessa forma, seu servidor socket poderia ser trocado para um AppServer com MessageDrivenBeans que consumiriam as mensagens da fila (ou filas) JMS.

Nesse caso, a conversa seria de IDA e VOLTA, entao o concentrador teria que ter uma forma de receber as respostas dos MDBs (JMS talvez) e manter as rotas para responder o cliente correto.[/quote]

Então, a idéia é exatamente essa, os MDBs receberiam as mensagens e responderiam a elas e essa resposta seria transformada na resposta lá no formato específico que iria pro cliente, seja ele ISO 8583, CSV, XML ou SeiLáOQue :stuck_out_tongue:

[quote=felipec]A vantagen seria a abstração dos sockets e escalabilidade vertical com cluster de JMS e Servidores de aplicação (JBoss por exemplo)

Vale lembrar também que JMS tem transações, ACK, MessageSelector e outras features que você deveria dar uma olhadinha pra ver se atende seu cenário.[/quote]

Pois é, por isso que eu estou com essa preocupação, se eu escrever esse troço no braço, eu mesmo vou ter que implementar todos esses requisitos não funcionais nele e se eu for implementar isso tudo, não vou terminar de implementar o servidor nunca.

Olá

Fazer o controle transacional com transações compensatórias que o povo da área financeira chama de desfazimento não é nenhum bicho de 7 cabeças e você domina todo o processo.

Na parte do sistema que usa JMS o livro do Eric Bruno fala nas págs. 145-149 sobre transações. Mas seu sistema como um todo precisa garantir a atomicidade da transação financeira. Então você não escapa de ter que fazer alguma coisa com as próprias mãos.

E sobre o JPos: é não é um POS como você pensou. É um servidor que já tem pronto tratamento de ISO, XML, CSV, etc. Mas precisa comprar as documentações porque sem ela é difícil entender (eu não comprei e sofri muito antes de desistir). Há uma empresa no Rio que usa.

[]s
Luca

Acho que é uma solução interessante e que não vai exigir muito código, o que facilita os testes.

O mais importente seria você fazer testes de carga mesmo.

Engraçado que quando eu vi os desfazimentos pela primeira vez achei estranho, mas os problemas com impressão de comprovante, rede e essas coisas do POS realmente são um problema, então façamos uma gambiarra pra resolver o problema :stuck_out_tongue:

E pra quem acha que programar aquelas malditas maquininhas de passar cartão é “simples”, imaginem que muitos daqueles troços não tem nem o TCP-IP implementados. Agora imagine programar um troço desses quando tudo o que ele faz depende de conexões de rede.

Hehehehehe, sendo pouco, não mata não, o problema é ter que escrever tudo.

Pois então, vi o site dos caras e é muito interessante mesmo, acho que agente vai ter que pegar a documentação sim.

[quote=felipec]Acho que é uma solução interessante e que não vai exigir muito código, o que facilita os testes.

O mais importente seria você fazer testes de carga mesmo.

[/quote]

Meu amigo, qualquer coisa que facilite os testes disso já vai ser uma maravilha \o/

Pessoal, obrigado a todos pelas respostas, vou me informar melhor sobre os message brokers e sobre ESB pra ver qual realmente é o nosso problema e como ele pode ser resolvido. Assim que eu tiver alguma idéia do que vai ser feito eu posto aqui pra ficar no histórico.

Valeu! :smiley:

Só um detalhe: se vc. quiser pode usar apenas os “packers” ISO e ignorar o resto do servidor que existe no pacote. Mesmo sem documentação o uso é nível psicotécnico. A dificuldade, caso vc. pretenda usá-lo para troca de mensagens com sistemas já existentes, é identificar qual das n variantes de ISO utilizar.

Olá

Certo, já andei fuçando os fontes e percebi que dava para fazer isto adaptando de acordo com o modo comum que usamos o ISO aqui no Brasil.

Na verdade quase comprei a documentação pois 500 dólares não é tanto assim. Só não fiz porque sai do projeto que enviava transações para um servidor semelhante e que nos Estados Unidos pensava em adotar o JPos.

[]s
Luca

Opa,

Desculpem estar ressuscitando este tópico, mas é que atualmente estou com o mesmo problema que o Maurício enfrentou. Hoje o que tenho é uma solução implementada no braço mesmo, usando o Apache MINA, mas me preocupo principalmente com a escalabilidade e com a flexibilidade, já que a tendência é ter ainda mais clientes com protocolos distintos para executar as mesmas operações.

Como o tópico ficou sem fechamento gostaria de saber do Mauricio se usou JMS ou algum outro MQ e se a solução teve sucesso.

Valeu!