Múltiplos Sockets Conectados + de 1000 simultaneamente

Pessoal,

Preciso desenvolver uma aplicação Web que seja um servidor, onde múltiplos equipamentos eletrônicos irão se conectar, no mínimo 1000 simultaneamente!!!
Há clientes que tem projeto de usar mais 4000 equipamentos !

Esse equipamentos conectam-se via internet e tem que ficar conectados 24 horas por dia, enviando uma mensagem de Keep Alive a cada 5 minutos ±

O servidor deve receber esses dados, muitas vezes eventos de arme e desarme de um alarme eletrônico e guardar em um banco de dados (Esses eventos são coletados posteriormente por outro software).

Ou seja, o sistema tem que ser escalável, de alta disponibilidade e com balanceamento de carga.

Desenvolvi um sistema assim, mas não com a mesma dimensão e nem em Java.

Gostaria de migrar e peço orientação sobre quais tecnologias e ferramentas devo estudar e usar e como montar essa aplicação.

Alguém me ajudaria ?

Obrigado !!!

Você precisa manter os equipamentos conectados? Ou um KEEP ALIVE baseado em UDP serve?

Os equipamentos externos se conectariam via socket? é isso?

Voce gostaria de implementar este sistema em j2ee ? ou web seria apenas algumas telas de configurações ou monitoramento?

Olá. Sim, os equipamentos conectam-se via módulo celular GPRS e acessam o computador onde está o software de recepção de eventos.
Sinceramente, ainda não sei que tecnologia usar, mas gostaria que fosse Java e se possível com interface web, permitindo ao usuário acessar o sistema remotamente.

[quote=douglaspaulino]Os equipamentos externos se conectariam via socket? é isso?

Voce gostaria de implementar este sistema em j2ee ? ou web seria apenas algumas telas de configurações ou monitoramento?[/quote]

[quote=aloisiop1]Olá. Sim, os equipamentos conectam-se via módulo celular GPRS e acessam o computador onde está o software de recepção de eventos.
Sinceramente, ainda não sei que tecnologia usar, mas gostaria que fosse Java e se possível com interface web, permitindo ao usuário acessar o sistema remotamente.

[quote=douglaspaulino]Os equipamentos externos se conectariam via socket? é isso?

Voce gostaria de implementar este sistema em j2ee ? ou web seria apenas algumas telas de configurações ou monitoramento?[/quote]

[/quote]
Ual, tenho a impressão que vou aprender bastante nesse tópico :stuck_out_tongue:

A solução que tenho hoje usa TCP, os módulos conectam-se por GPRS e mantem-se conectados, pois o consumo de dados é menor mantendo-os conectados e enviando um keep alive de tempos em tempos, também recebo eventos como arme e desarme do painel.
Ao receber esses eventos, respondo ao equipamento confirmando que recebi, gravo em banco de dados e envio para um software de monitoramento especializado(de terceiros) onde um usuário visualizará e tratará o evento.

Olá

Não sei se entendi direito

Vem tudo via Internet? Protocolo HTTP? A solução mais rápida é montar um servidor HTTP com node.js (em javascript, não se assuste, é MUITO bom). A solução mais demorada e tenho dúvidas se seria melhor é usar o Netty (ou o Mina)

Se o protocolo não for HTTP ou você pecisar coisas como UDP então acho que precisará mesmo do Netty (ou do Mina). Veja comparação em http://stackoverflow.com/questions/1637752/netty-vs-apache-mina

Quanto a ser escalável e ao mesmo tempo ter alta disponibilidade e fazer balanceamento de carga… acho que precisara repensar sua solução. O banco de dados é sempre um potencial gargalo quando entra a palavra escalabilidade no assunto. Já pensou em armazenar os dados em um NoSQL do tipo HBase no Hadoop? Muito maiores as chances de escalar. A passagem para o banco de dados do outro software poderia ser feito via batch.

Quanto a alta disponibilidade e balanceamento de carga aí é impossível falar sem conhecer toda a arquitetura de rede incluindo o que será usado no hardware.

[]s
Luca

Trabalhar com socket é sempre um pouco complicado, ainda mais quando temos que prover um serviço desse tipo. Por esse motivo que perguntei se seria j2ee, o que tornaria ainda mais dificil e prover um serviço desse tipo, pois teria que utilizar threads para manter/gerenciar as conexões e bla bla bla, sem esquecer que numa arquitetura j2ee não é aconselhavel utilizar-se de thread muito menos em um cenário desse que voce citou :shock: … olhe uma explicação para isso http://stackoverflow.com/questions/533783/why-spawning-threads-in-j2ee-container-is-discouraged

O luca citou muito bem a possibilidade do uso do Mina, para prover o serviço e gerenciar concorrencias, mas mesmo assim não fugiria do uso de threads, mas pelo menos com o netty ou mina voce minimizaria alguns esforços de implementação.

Uma saida para gerenciar essas conexões seria implementar um JCA(Java EE Connector Architecture) inbound para “startar” um socket,o que te livraria do problema do uso de thread numa arquitetura j2ee, porém é um porre implementar isso (experiencia própria) de uma olhada num post de um amigo http://itdevworld.wordpress.com/2008/12/24/inbound-jca-connectors-introduction/

Sobre o banco de dados o luca mandou muito bem outra vez(tem até um texto meu falando um pouco disso http://computacaoanotada.wordpress.com/2010/07/14/desenvolvendo-aplicacoes-de-alto-desempenho-em-java/)… uma solução NoSQL ou datagrid, na minha opinião, é sempre bem vinda para poder ter desempenho e alta disponibilidade… alguns teria mesmo que desenvolver batch para passar com pro BD, mas se não me engano utlizando o infinispan da jboss não teria essa necessidade.

Talvez alguem possa não concordar com tudo oque eu disse(JCA, socket em j2ee) mas é foi essa minha linha de pensamento por enquanto(posso mudar neh! :stuck_out_tongue: )…rsrsrs

até mais!

Olá

Tudo que você escreveu faz sentido e está no parágrafo abaixo. A pretensão dele de escrever um servidor eliminaria o que o JEE tem contra as threads. Poderia eventualmente usar o Hibernate, JMX e outras coisicas mas nada que impeça de usar threads. Só que…

Todos sabemos o trabalho que dá escrever um servidor que funcione tão bem como aqueles prontos e testados há muitos anos. Concordo contigo que usar servlets pode ser a solução do problema. Nesta caso esqueceria Netty, Mina e threads. Caso seja possível, usar servlets deixando a encrenca para o Jetty pode ser a melhor maneira de ter algo pronto e funcionando em pouco tempo (sem precisar mexer com JCA).

Outra coisa: para mim o Netty é um Mina melhorado. O autor do Mina é o mesmo autor do antigo Netty que virou depois Mina. Agora ele reescreveu o Mina voltando a usar o nome Netty. Se fosse partir para uma solução de servidor caseiro, usaria a API do Netty.

Chamo a atenção que o Node.js é um negocinho pra lá de bom. Mesmo que não se aplique neste caso por algum motivo vale a pena conhecer.

[color=red]Editado: [/color]

Chamo a atenção que servlets se aplicariam caso seja possível arquitetar a solução usando HTTP para receber as mensagens. Neste caso os tais keep alive precisariam de algo do tipo Continuations, Comet (o Jetty suporta), websockets ou similar. Para falar com o outro software que consome os eventos se poderia usar threads normalmente mesmo dentro de um servlet.

Nada impede também de partir para outras alternativas como Erlang, Scala/Lift e Clojure. Coisa mais para programador Indiana Jones do que para o Chuck Norris.

[]s
Luca

Eu já trabalhei com esses equipamentos. Posso dar uma ideia…

As sugestões citadas são boas. Recomendo Apache Mina. Existem soluções como Node.js para Javascript e EventMachine para Ruby, mas minha sugestão é não usá-las por enquanto, porque existe muito poucas bibliotecas em volta desses sistemas, vai ser difícil achar drivers pra bancos, por exemplo. (A maioria das Gems do Ruby são otimizadas para o framework Rails, não para o EventMachine.) Mas talvez daqui a uns dois anos, a coisa mude de figura. Sim, eu fiz testes com eles.

Há uma opção de usar C, com poll(), epoll() ou kqueue(), mas isso é pedir pra fritar seu cérebro.

O gargalo na otimização será o banco. Não venham com essa de que o Oracle é “parrudo”, pois se tiver muitos equipamentos conectados, vai pedir água. A razão é o seguinte:

:arrow: Se você tenta obter leituras rápidas, você coloca índices, que gargala escritas;
:arrow: Se você tenta obter escritas rápidas, você remove qualquer índice existente, que gargala leituras.

Ou seja, pesquise por bancos NoSQL.

Opa… só pelo link que vc havia passado ja relata que o Netty no mínimo é mais rápido…rsrsrsrs, nunca utilizei o Netty mas ja utilizei o Mina e não sabia que era da mesma autoria, só sei que é um negócio de doido…rsrsrs ele pode ter nelhorado o esquema de bloqueio no netty em relação ao mina… mas enfim!

Não conheço o funcionamento do Node.js, irei analisar sim! valeu!

espero não termos embaralhado mais a idéia do aloisiop1 :stuck_out_tongue:

até mais!

Olá

Só para registrar: editei minha mensagem anterior restringindo a hipótese de usar servlets ao caso de troca de mensagens HTTP.

Se for na raça tipo Chuck Norris, aí o negócio é partir para o Netty e acender umas 3 velas para Nossa Senhora do Debug de servidores.

[]s
Luca

[quote=Luca]Olá

Só para registrar: editei minha mensagem anterior restringindo a hipótese de usar servlets ao caso de troca de mensagens HTTP.

Se for na raça tipo Chuck Norris, aí o negócio é partir para o Netty e acender umas 3 velas para Nossa Senhora do Debug de servidores.

[]s
Luca [/quote]

ok muito boa a “editada”…

hahahahahaha… e põe raça nisso, sem contar que “Debugar” o Netty deve ser facil facil acompanhar :twisted:

até!

Ola

Ja desenvolvi um sistema parecido, porém ele não tinha essa necessidade de abrir e manter todas estas conexões simultaneas.

Foi usando Perl + Net::Server::PreFork, aguentava muitas conexões porém preferi usar um protocolo mais simples do que HTTP, com um tempo de resposta tão baixo que o balanceador de carga não conseguia distribuir direito usando a metrica least-conn – precisei forçar um round-robin.

Acho que qualquer tecnologia pode fazer isso, basta vc ter como testar uma situação de stress. Talvez a aplicação possa ser simplificada ao ponto de poder ter uma arquitetura shared-nothing, com pouco ou nenhum gargalo de I/O. Analise load e consumo de memória de toda a infra e prepare suas maquinas para operar com alguma folga para o numero de requisições que vc espera com apenas metade das maquinas (no caso de um switch ou quadro de força cair). O ideal é nunca passar de 40% de CPU. Se vc tem um balanceador de carga use direito o max-conn e configure algo para evitar RAJADAS, pois uma quantidade grande de conexões em curto periodo de tempo pode derrubar um servidor.

Se vc precisa usar HTTP veja se vc pode cachear alguma coisa, de repente usando ETAG ou Modified-Since e ai coloque um cache na frente, como um Varnish ou NGinX.

Veja se vc precisa fazer todo o processamento sincrono. Esta pode ser a chave. Vc pode ter um servidor bem simples que sempre retorne 200 OK – pode servir um estático, um gif de 1 pixel, pode ser um PHP, qualquer coisa. O processamento pode ser feito depois, analisando o log do servidor por exemplo, ou troca de mensagens assincronas via um barramento de eventos, pode ser q vc crie um arquivo vazio em um filesystem, etc. Processando as informações em separado vc pode ter uma FARM de Front-End que atenda estas 1000 conexões e uma de Back-End que, se não atender a demanda pode ser tão simples adicionar maquinas e em caso de pane o Front-End pode seguir de pé e vc só analisa o resto da informação depois do desastre.

Um bom exemplo: vc pode ter um PHP que escreva em uma tabela no mysql as informações que vem do seus 1000 dispositivos. O Mysql pode usar a engine Black-Hole, ou seja não grava nada (por isso o nome ‘buraco negro’) mas gera log das transações. Paralelo a isto vc tem um map-reduce dos logs - pode usar o hadoop ou algo semelhante - e grava no que vc quiser. De repente até o Nagios pode ser adaptado ao que vc quer.

Acho que existem muitas soluções, inclusive com Java. Eu usaria a coisa mais simples possivel, um Jetty de repente, uma servletzinha ou nem isso, eu pensaria em poucas linhas, muita eficiencia, algum profilling da aplicação e conceitos como mensageria, processamento assincrono, caching, etc. Talvez uma combinação de tecnologias resolva o seu problema.

Edit: lembrei de outro sistema q trabalhei e este tenho alguma paixão ainda.

Era um PHP - mas podias ser qq coisa - que escrevia o request HTTP inteiro no filesystem. O request tinha dados de um formulario e um arquivo de video que alguem havia feito o upload. Um sistema assincrono movia o arquivo para outras pastas e ia fatiando de acordo com certas especialidades. Um processo inseria dados no banco, outro validava se era um video, outro gerava um preview pequeno do video para um editor poder aprovar ou não, etc. Acho que vc pode fazer algo parecido mas talvez só com o log de acesso possa ser suficiente.

Boas opiniões, parabens a todas.

Gostaria de dar a minha opinião.

Bom, posso esta sendo ingênuo, porém não acredito que voce tenha que pensar em escalabilidade exageradamente agora, nesse momento, até por que são muitos fatores que influenciam esse aspecto, decisões de arquitetura,design de aplicações em rede,hardware´s e software´s adjacentes, uma boa maneira de começar na minha opinião é escrever o aplicativo concorrente, começe atendendo múltiplos clientes, escreva o teste para isso se for o caso, essa ja vai ser uma tarefa bem trabalhosa, porem vejo que ja tem alguns frameworks que vão facilitar sua vida como o citados acima se for trabalhar com java.

Existe diversas abordagens cada uma com seu próprio custo, grau de complexidade e logicamente vantagens e desvantagens.

Em java ainda acho simples de se fazer, porém trabalhar com socket´s (multiplexado, assíncrono e não bloqueantes) e threads em C seria um ótimo desafio e tem boas literaturas a respeito, Unix Network Programming[Richard Stevens] e caso precise de comunicação entre processos do mesmo autor temos “Interprocess Comunication”.
Programação concorrente e de redes tem muito conteúdo e exige muita experiência e muito conhecimento não somente de algoritmos conhecidos, mas também do sistema adjacente(Hardware e Software).

Aconselho você desenhar sua solução no estilo arquitetural de aplicações em rede REST, pois você somente usará o HTTP que é bastante comum e largamente utilizado no mundo todo e tem suporte a conexões keep-alive e várias questões de escalabilidade também já conhecidas e divulgadas em palestras inclusive aqui no brasil usando esse esquema você já pouparia tempo de não ter que pensar sobre escalabidade pois é bem subjetivo. :slight_smile:

Você ganharia a interoperabilidade com vários outros sistemas, sejam móveis ou corporativos.

Acredito friamente, pois não sou especialista no assunto, que não seja tão complexo manter uma lista de conexões ativas e que você possa desenhar uma solução em java que atenda múltiplos clientes simultaneamente, no caso 1000 e criar um temporizador em java para iterar na sua lista de conexões ver o tempo de inatividade e responder a elas, claro seguindo a RFC 2616 para conexões persistentes. Você também terá que pensar em variáveis que possam quantificar e qualificar quando uma conexão esta inativa, criar esse conceito na sua aplicação.

Java possui um número grande de frameworks para trabalhar com programação concorrente e que atenda múltiplos clientes através da rede. voce pode dar uma olhada neles e começar a partir deles. "se conselho fosse bom não dava, vendia! " hehe.

Outro palpite, se tiver frameworks que te ajudem a desenhar a aplicação utilize, pois aplicações como esta estão sujeitas, por falta de experiência, voce criar muitos bugs de segurança o que pode a vir comprometer o seu sistema, por exemplo, disponibilidade.

Bom é isso, se eu puder ajudar pode me contactar.

bruno.taboada@gmail.com

Abraço.

Precisa ser em Java?

Tente o YAWS

http://yaws.hyber.org/

E use-o com JInterface se precisar integrar com Java

ah! E não esqueça de dimensionar corretamente o seu hardware para esse tipo de demanda :wink:

T+

Ressucitando o tópico.

Qual foi o rumo tomado nesse projeto boblast? Estou pensando num sistema “mais ou menos” com as mesmas peculiaridade, porém não precisarei manter a conexão, pois os dispositivos ficarão dando um “ping” no servidor de tempos em tempos (aproximadamente a cada 5s). Tomei essa decisão por se tratar de uma conexão feita via GPRS. Cada pacote de dados será relativamente pequeno (em torno de 150 bytes) sem contar os bytes utilizado pelo TCP/IP. Criei um protocolo que minimizou bastante o tamanho dos pacotes. Também usei GZIP para diminuir ainda mais o tamanho destes pacotes.

Enfim, se alguém tiver algum pronunciamento, experiência, dica… Ficarei agradecido!

Abraço.