Um problema complexo! Troca de mensagens entre Threads

Pessoal, este é o meu primeiro tópico, mas já acompanho este fórum há bastante tempo. Estou desenvolvendo um sistema que é um pouco complexo. Vou relatar como ele funciona e após informo qual o problema.

Há um servidor de frente (frontserver) que receberá as conexões de todos os clientes que desejam se conectar aos backservers e ter acesso aos seus dados. Além disso, ele controla quantas instâncias daquela conta estão conectadas. Por exemplo, uma conta pode ter 5 instâncias, outra, apenas uma. Então o frontserver mantém um Map com um objeto login, que contem o login, a quantidade máxima de instâncias e quantidade de conexões atuais (esses valores sao informados pelo backserver, apos o cliente firmar conexao com ele). Nenhum cliente poderá se conectar diretamente ao backserver, sem antes ter passado pelo frontserver. O frontserver tem várias threads. Um grupo de threads é referente ao controle das conexoes com os backservers, e o outro grupo de threads é referente ao controle das conexoes com o aplicativo cliente.

Os backservers são os servidores que tem acesso a base de dados, não significando que essa base estará local. Ela ficará em outro local. O sistema pode ter um ou mais backservers. É necessário que o sistema seja escalável. No início serão dois servidores, após, mais. Os backservers se comunicam tanto com o frontserver como tambem com os outros backservers. Exemplo de comunicação entre os backservers.

Backserver A: -“Há novos dados postados e esses dados são referentes ao cliente X. Nao estou fazendo o cache desse cliente e você Backserver B?”
Backserver B: -“Estou fazendo o cache, então sou eu quem deve fazer o cache. Vou fazer atualizar cache agora!”

O backserver ao se conectar ao frontserver tem que passar uma mensagem indicando qual a chave de autenticacao do servidor, além de outras, como seu ip, porta de escuta das conexões do cliente, seu limite de conexões, uma lista com a relacao dos clientes(logins) que ele fez cache. (Essa lista é atualizada sempre. Sempre que um cache for criado ele informa ao frontserver, atualizando a lista). Se a chave de autenticacao bater, a conexão permanece ininterruptamente, caso contrário cai.

Os backservers terão um cache com os dados binários enviados pelos clientes através dos sites. Isso pra ganhar performance. Caso não existisse, o backserver teria que ir buscar esses dados multimídia na base de dados quando o cliente requisitasse, depois serializar e enviar via socket. Esse processo pode ser bastante demoroso. Então estou desenvolvendo um mecanismo para que quando o usuário poste qualquer conteúdo multimídia pelo site, o sistema envia mensagem para todos os backservers do sistema indicando que há novos dados e o servidor que estiver responsável por fazer cache daquele cliente vai lá, puxa os dados, serializa e atualiza o índice do cache. Quando o cliente se conecta ao backserver ele envia quais sao as campanhas que possuem e o sistema verifica se aqueles dados estao atualizados ou se ha dados que nao foram enviados, efetuando a sincronizacao.

Quando o usuário se conecta ao frontserver e informa o login e a senha, este deve verificar em um Map qual o servidor que mantem cache daquele cliente, verifica se a quantidade maxima de conexoes para aquele servidor nao estourou e manda uma mensagem para aquele servidor indicando que o usuario X deseja se conectar a ele. O backserver entao gera uma chave, insere em um Map o login e a chave gerada e manda a chave para o frontserver. Este por sua vez deve pegar esse valor e mandar para o cliente, a chave, o ip do servidor, e a porta. Automaticamente o frontserver fecha a conexao e o aplicativo cliente de posse desses dados cria a conexao ao backserver com os dados de ip e porta indicados e informa a chave. Quando o backserver recebe a conexao do cliente ele primeiramente pega o login e a chave e compara la no Map, se bater, ele consulta a base de dados e verifica se os dados de login e senha estao corretos. Se sim a conexao se mantem, caso contrário a conexao fecha.

Pelo que voces podem constatar, nenhum cliente consegue manter conexao ao backserver sem passar pelo frontserver. Quem gera o pedido da chave é o frontserver e manda para o cliente. Isso é um requisito de seguranca muito importante que não pode faltar.

[color=red]PROBLEMA[/color]

Se eu tenho dois grupos de threads, um referente as conexao dos clientes e outro as conexoes dos backservers.

VISUALIZAÇÃO

CONEXAO CLIENTE
THREADC1 (carlos@ig.com.br)
THREADC2 (jose@ig.com.br)
THREADC3 (marcos@ig.com.br)
THREADC4 (maria@flflf.com)

CONEXAO BACKSERVER
THREADBS1 (Esse servidor tem cache de marcos e de maria)
THREADBS2 (Esse servidor tem cache de jose e carlos)

A conta carlos@ig.com.br se conectou ao frontserver e deseja acessar seus dados multimidia pelo aplicativo cliente. O sistema pegou o id e verificou que o servidor1 mantem cache dele. Como essa thread poderá sinalizar para a thread que controla conexao do servidor1 (threadbs1) que mande o servidor gerar uma chave para o usuario carlos@ig.com.br, esperando a resposta do servidor e apos, enviar ao cliente?

Um dos cenarios que pode ocorrer, por exemplo, eh que dezenas de conexoes(threads) podem requisitar a thread de controle de conexao do backserver que gere a chave para os logins.

1…N threads requisita dados para apenas 1 thread.

Obs: Toda essa infraestrutura esta sendo desenvolvida apenas com socket.

Valeu!!!

Ainda não consegui chegar a uma resolução para este problema. Alguém possui alguma idéia? Qualquer idéia é bem-vinda.

Obrigado!

eh meio complexo mesmo… mas se eu entendi direito, nao poderia vc criar uma thread que mantém o controle sobre as threads do cliente ( chamaremos de thread A ) e outra que mantem controle sobre as threads do backserver ( thread B )?

vc nao consegue comunicar de forma eficiente uma thread especifica mas o acesso aos dados do backserver vai ser feito pela thread do cliente (A) então ele pode notificar um conjunto de variaveis que a thread que mantem os controles do backserver (B) pode ficar verificando constantemente e ser assim ser sinalizada como vc queria…

Putz digao.br

Eu juro que li tudo que você escreveu. Não sou tããão bom assim, mas deixa eu tentar entender: você escreveu um Listener na mão? Não tem nada no mercado que possa ficar escutando o seu servidor sem ter que utilizar N threads?

De qualquer forma, o seu problema é que N threads vão chamar a thread de controle. Mas isso vai acarretar em quê? A thread de controle vai se perder? Vai sobrecarregá-la?

Edit: Você já pensou em utilizar AOP pra agir como um interceptor e matar algumas threads?

Valeu

oi digão,

acho que talvez você precise utilizar os executor do Java5, veja se o tópico abaixo te ajuda

http://javafree.uol.com.br/topic-851714-Problemas-com-Socket-+-Thread.html

Nem li seu post, mas por acaso, se isso for redutivel ao problema “vários consumidores, vários produtores”, pode-se usar uma BlockingQueue. Leia o seguinte post no StackOverflow:

digao.br,

Vou tentar te ajudar com um problema que tive semestre passado.
Desenvolvi um trabalho onde havia várias Threads. Em alguns casos Threads deveriam conversar com Threads, fazendo requisições para fazer alguma coisa. Mas Nesses casos utilizei classes chamadas RequisicoesXPTO (que guardava uma lista de requisições), essas classes utilizavam a classe java.util.concurrent.locks.Lock(Para controlar as secões críticas) e a classe java.util.concurrent.locks.Condition(utilizada para controle quando chegava uma requisição).
No Caso Eu tinha uma classe chamada ControleXPTO que guardava uma instancia de RequisicoesXPTO.
Em fim tinha outras classes que faziam requisições para RequisicoesXPTO. As requisições(objeto Requisição por exemplo) guardava quem estava requisitando. Quando ControleXPTO ia buscar requisicoes pegava da lista(se a lista estivesse fazia ia esperar chegar pelo Condition), e saberia para quem devolver.

Não sei se fui bem claro mas é isso.
Talvez te ajude.

Vlw Abraço.

Use filas de mensagens.

O java tem classes prontas para isso, como a LinkedBlockingQueue.
Se dezenas de threads requisitarem ao mesmo tempo, o máximo que elas irão fazer é gerar um monte de mensagens na fila, que serão atendidas na medida do possível.