Uma questão de Escalabilidade

Olá a todos, tenho um problema sério aqui, e queria a opinião da galera aqui. Normalmente as pessoas dão ótimas opiniões, e decisões de arquitetura tem sérias conseqüências no projeto, então; desde já agradeço a ajuda. :slight_smile:

Tenho o seguinte cenário:

Minha aplicação possui duas entidades principais: uma Central de Processamentos de Dados (CPD) e um Produtor de Dados (PD).
As duas são aplicações distintas estão a grosso modo em Java (porque o produtor de dados possui boa parte implementada em C).

Bem, a questão principal é a seguinte:

A aplicação CPD, possui um ou mais Sockets que colhem dados da PD; onde esses dados podem ser dados propriamente ditos, vídeos e audios. O x da questão é: eu preciso de uma solução tal que na CPD, eu possa, aumentando o número de máquinas, conseguir aumentar o números de PD’s que podem aumentar consideravelmente de forma, digamos, inesperada.

Imaginem que eu posso ter 3 PD’sem um determinado momento, e em um outro possuir 20 PD’s. Com esse aumento de dispositivos, a quantidade de informações que vou receber na minha CPD é muito grande, ela poderá não suportar, e vai chegar num ponto onde uma máquina apenas não conseguirá processar a quantidade elevada de informações; solução: dividir em mais máquinas. Só que estou meio sem rumos sobre a como fazer isso no Java.

Desde já agradeço a ajuda de vocês,
até :slight_smile:

Olá

Precisa ser usando sockets a comunicação? Chegará um momento em que não escalará a menos que aumente recursos.

Sistemas que se comunicam por sockets são fáceis de fazer enquanto as soluções são triviais. Quando o negócio cresce pode ficar complicado. Não sei o que está usando. Grizzly? Mina?

Se ao invés de sockets síncronos usar menssageria asíncrona (message beans ou JMS), pode escalar mais facilmente porque com o aumento de carga o pior que pode acontecer é aumento no tempo de resposta ao invés de saturação no sistema.

Há outras alternativas. Mas precisaria saber mais detalhes. Por enquanto foi apenas um pitaco.

[]s
Luca

E ae Luca, :slight_smile:

Seguinte:

Eu tenho as entidades que produzem dados, em campo, colhendo dados constantemente (24h/dia) e enviando esses dados para uma central.
Esses dados podem ser imagens/vídeo/áudio.

Na central que recebe esses dados, temos um Socket (1 socket mesmo); essa central recebe esses dados, persiste em banco, processa, envia alertas, etc.
Problema é que vai chegar um ponto, que 1 socket (ou a largura de banda) não vai dar vazão a quantidade de informação, ou a capacidade de processamento dessa central não vai ser suficiente (por mais que você coloque uma máquina super potente, vai chegar uma hora que não vai mais poder aumentar sua capacidade).

Pensei nas seguintes soluções:

O servidor de banco é fácil de colocar em uma máquina isolada, uma carga grande a menos.
Criar uma máquina que simplesmente enfileira os recebimentos de informações e vai passando para outras máquinas processarem - o problema dessa abordagem, é que a se a máquina de faixada cair, o sistema todo cai.

Bem só que a aplicação dessa central em sí que cria o socket, é em Java, então:
Como dividí-la em mais máquinas?
Socket me empede de fazer isso?

Obs.: Todas as informações são enviadas utilizando o sistema de Envelope Digital (Criptografia simétrica com criptografia Assimétrica), e as mensagens estão em XML, e frisando: a quantidade de informações é muito grande.

Quanto ao Grizzly e Mina, desculpe minha ignorância, mas não sei o que é.

Ao invés de ter 1 máquina com socket, uma opção é ter uma farm com 2 ou 3 máquinas respondendo HTTP (REST, SOAP, POX). Conforme a necessidade você coloca mais máquinas

Se você adorat a idéia que coloquei acima, esse problema vai ser minimizado no ponto de entrada. O Servidor de mensageria também não deveria funcionar com somente uma instância, pra evitar justamente o que você falou. Nesse ponto, você vai ter consumidores dessa mensagens e pode dosar esse processamento como convir para evitar a saturação do sistema, e trabalhar em cima do tempo de resposta, como o Luca já havia explicado.

Olá

[quote=xdraculax]
Quanto ao Grizzly e Mina, desculpe minha ignorância, mas não sei o que é.[/quote]

Ambos são APIs de sockets adequadas para grandes volumes. O Mina é mais fácil de usar. O Grizzly é usado pelo glassfish.

Mas como disse, existem outras alternativas além de sockets. Usar o socket do Java pura e simplesmente é só para casos em que as cargas máximas estão perfeitamente definidas e a infra-estrutura dimensionada adequadamente.

[]s
Luca

A aplicação tem outros requisitos de Segurança e Performance; onde a performance afeta diretamente essa comunicação feita entre os equipamentos em campo e a central. Acredito que REST e SOAP não são boas opções para uma performance alta. Outra questão que não deve ser fácil com relação a SOAP e REST é Segurança.
Como eu disse tudo é criptografado e SOAP não se adequaria bem a esse requisito.

[quote=Emerson Macedo]
Se você adorat a idéia que coloquei acima, esse problema vai ser minimizado no ponto de entrada. O Servidor de mensageria também não deveria funcionar com somente uma instância, pra evitar justamente o que você falou. Nesse ponto, você vai ter consumidores dessa mensagens e pode dosar esse processamento como convir para evitar a saturação do sistema, e trabalhar em cima do tempo de resposta, como o Luca já havia explicado.[/quote]

Tudo bem, entendi. Mas imaginemos o seguinte (um exemplo bem bobo, mas é só pra ter certeza que estamos compreendendo a mesma coisa):

Você tem sua fábrica de carros com
1 linha de produção e
1 porta pequena (meu socket - coisa estranha, “meu socket”), que recebe uma pequena quantidade de peças.

De repente sua demanda aumenta 200%, e você coloca mais 2 linhas de produção, mas sua porta continua a mesma; ou seja, você possui o mesmo ponto de entrada limitado, que em nosso caso é o socket. E agora você tem capacidade de produção mas sua porta não dá vazão a essa quantidade de peças que chegam.

Meu problema é exatamente essa porta. Eu quero uma forma de tornar essa porta mais escalar, segura e rápida (quer nada ein ^^).

Eu estou dando uma lida sobre a Mina da Apache. Não entendi o conceito ainda a ponto de saber se resolve o meu problema.

A aplicação tem outros requisitos de Segurança e Performance; onde a performance afeta diretamente essa comunicação feita entre os equipamentos em campo e a central. Acredito que REST e SOAP não são boas opções para uma performance alta. Outra questão que não deve ser fácil com relação a SOAP e REST é Segurança.
Como eu disse tudo é criptografado e SOAP não se adequaria bem a esse requisito.
[/quote]
Quais seriam esses requisitos de segurança e performance para que possamos ajudar e ver se realmente alternativas webservices seriam tão ruins?

[quote=xdraculax]

Eu não sei se entendi seu problema, mas pelo que você está dizendo ta me parecendo largura de banda, é isso? Caso contrário, poderia explicar melhor?

[quote=xdraculax]
Meu problema é exatamente essa porta. Eu quero uma forma de tornar essa porta mais escalar, segura e rápida (quer nada ein ^^).[/quote]
Mais uma vez, seria interessante você colocar aqui esses requisitos de segurança e performance para que possamos ajudar e ver se realmente alternativas webservices seriam tão ruins.

Ok:

Segurança:

Todos os dados devem ser enviados para a central criptografados. Usando uma chave de tamanho variável (ou seja, para alguns contratos posso utilizar uma chave de 128 bits, e em outro uma de 1024 bits).

Performance

Alguns contratos possuem restrições de tempo de envio. Por exemplo, a mensagem deve sair do equipamento para a central de 2 seg. Se você imaginar isso isoladamente, é perfeitamente possível usar SOAP, mas no momento de enviar essa mensagem eu posso estar enviando um arquivo de 300MB, e mais n mensagens com outras finalidades. Como, com SOAP isso seria tratado?

Escalabilidade

Novamente a variação por contrato. Em alguns eu posso ter 30 equipamentos em campo, e em outro eu posso ter 500. Uma central para suportar os 500 equipamentos, certamente não será uma máquina só.

Olá

Meu pitaco:

Com requisitos destes, a menos que tenha um Jean-Francois Arcand na equipe, não poderá usar soluções caseiras.

O fato de ser criptografado só reforça esta necessidade de buscar socorro. Escolha entre o Mina ou o Grizzly. Mas não descarte o uso de soluções assíncronas.

[]s
Luca

Eu voto com o luca para algo baseado em messaging se possível. Alguns fornecedores mantém em suas ferramentas critérios de preferência para envio e recebimento de mensagens, segurança integrada, por exemplo… Conforme forem aumentando suas requisições vc vai aumentando os consumidores, paralelizando o processo.

[quote=xdraculax]Ok:

Segurança:

Todos os dados devem ser enviados para a central criptografados. Usando uma chave de tamanho variável (ou seja, para alguns contratos posso utilizar uma chave de 128 bits, e em outro uma de 1024 bits).
[/quote]
Entendi. No caso aqui o protocolo de transporte não invalida o uso da criptografia. Usando HTTP ou Simplesmente sockets TCP você pode implementar a criptografia conforme você precisar.

Aqui está o ponto mais problemático. Se você tem um SLA específico, precisará analisar com cuidado e principalmente fazer testes pra ver o que está atrapalhando . Como você diz que envia arquivos de 300MB, acho que antes da preocupação com o protocolo de transferênia você vai ter que se preocupar com a largura de banda, pois caso contrário não vai adiantar nada você trocar HTTP por TCP puro.

Quanto a como isso seria tratado com SOAP, REST ou qualquer outra coisa isso depende apenas da modelagem dos Serviços/Recursos.

O fato de ter N servidores vai fazer com que você tenha que ter um balanceador na frente para direcionar a requisição (HTTP ou TCP puro) para o servidor que estiver mais “folgado” no momento.

Uma coisa importante que o Luca falou vou reforçar aqui: Não desconsidere a possibilidade de fazer o processamento assíncrono. Esse seu servidor que vai receber essas mensagens poderia fazer um trabalho bem leve, jogando essas mensagens numa fila para não gerar um Load muito alto em momentos de pico. Quanto mais leve esse ponto de entrada for, melhor.

[]s

Olá

Só mais umas considerações para encaminhar seu estudo:

  1. O Apache Mina foi feito pelo coreano Trustin Lee (90% do código baseado em um antigo projeto chamado netty).

  2. Há quase 2 anos o Trustin Lee brigou com outros commiters do Mina e pulou fora.

  3. Hoje o Trustin Lee trabalha para a RedHat/JBoss e coordena o Netty Project http://www.jboss.org/netty (The Netty project is an effort to provide an asynchronous event-driven network application framework and tools for rapid development of maintainable high performance & high scalability protocol servers & clients.)

  4. O Jean-Francois Arcand, criador do ótimo projeto com péssima ou quase nenhuma documentação Grizzly, que é o motor de IO/NIO do Glassfish, é mais um ex-Sun que não ficou na Oracle. Hoje trabalha no NING.

Considerando os itens 1 a 4, se eu fosse estudar alguma API para servidor de IO/NIO, começaria pelo JBoss Netty.

Quanto a criptografia tentaria usar algum protocolo relacionado com transmissão ao invës de simplesmente criptografar de um lado e descriptografar do outro com os 2 lados sabendo abertamente as chaves. Eu estaria tranquilo com TSL ou mesmo com SSL.

Seu projeto parece bem interessante. Espero que esteja no início e que possa resolver calmamente e a contento estas partes da infra-estrutura que simplesmente podem viabilizar ou não todo o resto do esforço. É aqui que o SLA pode machucar.

[]s
Luca

Olá

E sobre mensageria, acho que vale a pena olhar o novo projeto do JBoss Messaging que agora se chama HorneQ (justamente substituiu o Apache Mina pelo JBoss Netty como motor de IO/NIO).

Fiquei bem impressionado com o que li dele. Deu até vontade de brincar com ele. Vem aí o fim de semana e é um bom divertimento para você.

E quanto ao tamanho de mensagens o único limite é seu espaço em disco para armazenar as mensagens. Eles já testaram até com mensagens de 8 Gb (o default é 100Kb, precisa alterar no arquivo de configuração). Para melhorar o desempenho não recomendam armazenar as mensagens no mesmo volume físico do journal ou do diretório de paginação.

Veja:
http://jboss.org/hornetq/

http://community.jboss.org/wiki/hornetq

http://jboss.org/hornetq/downloads.html

[]s
Luca

Olá pessoal, primeiramente, Obrigado pela ajuda, a todos :slight_smile:

Vocês falaram algo interessante: “Não desconsidere a possibilidade de fazer o processamento assíncrono.”

Não teria problema nenhum em fazer isso na Central, inclusive era uma alternativa que imaginei: separar o que tem que ser processado de quem processa, assim eu consigo ter uma maior flexibilidade no número de máquinas, pois enquanto o servidor responsável por receber os dados apenas funcionaria como uma fila, os outros processariam as informações desta fila.

O que o Luca falou sobre o Apache Mina e o Grizzly é muito importante, dá mais critérios para eu selecionar um dos dois. E como ficou a primeira vista que os dois são muitos bons, acho que vou me dedicar a estudar o Mina pela documentação mais disponível.

Quanto ao que o Luca falou da criptografia, essa forma de utilização é uma restrição de projeto, até meio esquisita por sinal: porque se eu tenho que manter a chave-pública nos dois lados, pra que usar criptografia assimétrica + simétrica? Eu poderia usar somente simétrica e arcar com os custos de distribuição de chaves; um custo que já existe pela restrição esquisita.

Quanto ao projeto estar no inicio, hehe, não está não, já está bem avançado. Hoje, temos 1 socket na central para receber as montanhas de dados que serão enviados pelos equipamentos em campo. Só que: esse sistema vai entrar em produção em algum tempo (em torno de 2 meses) e identificamos esta questão que, sabemos, vai dar problema.

Olá

[quote=xdraculax] “Não desconsidere a possibilidade de fazer o processamento assíncrono.”

Não teria problema nenhum em fazer isso na Central, inclusive era uma alternativa que imaginei: separar o que tem que ser processado de quem processa, assim eu consigo ter uma maior flexibilidade no número de máquinas, pois enquanto o servidor responsável por receber os dados apenas funcionaria como uma fila, os outros processariam as informações desta fila.[/quote]

Acho que não foi isto que pensei. Para fazer algo assíncrono, a descrição de como ficariam as coisas vai além disto. Passa por mudança total na arquitetura e jogar seus sockets no lixo. Eu usaria o que disse em http://www.guj.com.br/posts/list/203392.java#1030610

De jeito algum. Muito pelo contrário. Acho que não me fiz entender. Recomendei o JBoss Netty. Veja http://www.guj.com.br/posts/list/203392.java#1030604

Pena, jamais começaria um projeto deste com sockets caseiros sabendo que existe coisa muito melhor pronta e disponível.

[]s
Luca

Pois é cara, já haviam começado, e só agora perceberam esse problema. Eu estava em outro projeto. O problema é que estão com a seguinte filosofia:

“Vamos ver se dá certo”. E esse ver se dá certo, é em produção!

Outra pessoa e eu é que queremos arranjar uma solução pra isso logo, porque sabemos que vai dar problema.
De qualquer forma eu estou estudando Apache Mina, e vou olhar as outras opções também.