ServiceLocator para sistemas distribuídos

31 respostas
danieldestro

Aos que trabalham com sistemas realmente distribuídos em diferentes instâncias (Seja física ou logicamente).

Como vocês trabalham com o ServiceLocator, ou mesmo com um sistema de configuração dos contextos remotos?

Explico. Imagine um grande sistema com duas ou mais instâncias de um container rodando. Cada uma dessas instâncias contém serviços EJBs que se conversam entre si, remotamente.

Uma das abordagens é configurar no JAR um jndi.properties, que o InitContext dá conta de ler e usar as configurações.

Mas imagine o caso de diferentes EJBs em diferentes instâncias. Como vocês resolvem isso?

Tenho pensado em um ServiceLocator que lê as configurações de cada serviço de um repositório de configurações, e ele se incube de achar os serviços EJB distribuídos.

Para acessar um EJB eu faria:

MeuEJB ejb = (MeuEJ) ServiceLocator.getInstance("CADASTRO").getEjb("nomeJNDI"); UmRelatorioEJB relEjb = (UmRelatorioEJB) ServiceLocator.getInstance("RELATORIO").getEjb("outroNomeJNDI");

E em um diretório teria:

CADASTRO-jndi.properties
RELATORIO-jndi.properties

O que acham? Sugestões? Experiências passadas?

ps: Usando EBJ 3.0… pena que injection, neste caso, não se aplica.

31 Respostas

A

Que tal pensar que seus EJBs oferecem SERVIÇOS e que os serviços estão catalogados em um REPOSITÓRIO de SERVIÇOS!? A boa-e-velha Arquitetura Orientada a Serviços…

danieldestro

Pode até ser que eu use o conceito de UDDI, implementado, por exemplo, no meu ServiceLocator.
Porém eu NÃO vou usar Web Services.

E outra, eu não terei meia dúzia de serviços (EJBs). Terei uma centena deles. E será inviável ficar registrando cada um deles em um repositório.

fabeen

Olá Daniel,

Certa vez passei por uma situação parecida com a sua. Para solucionar esse empasse de várias possíveis instâncias e vários EJB podendo estar se comunicando entre si, criamos um repositório(Base de dados) de componentes contendo algumas informações sobre eles, tipo algo simples mesmo, contendo informações sobre qual o sistema, a interface do componente, para que ele era aplicado, etc.

Com certeza terá um esforço significativo no início, mas creio que seja o mais coerente a se fazer.

[]s

A

Eu falei para vc usar Web Services? :?

danieldestro

Estou pensando na possibilidade de criar uma anotação especialista, para o meu caso. Até achei o projeto Apache Beehive, que parece ser uma solução para mim. Vou estudá-lo.

Rafael_Nunes

E como você usaria UDDI sem ser com Web Services? Ao menos todas implementações que eu vi de servidores(jUDDI, UDDI4j) só trabalhavam com/para Web Services.

rodrigoallemand

Vc não conseguiria centralizar toda a configuração dos diversos “caminhos” dos diversos EJBs em um unico lugar, como a solução em banco de dados dada pelo amigo acima?

Com isso o ServiceLocator iria ler esta configuração e disponibilizaria o JNDI correto!

Acho que essa seria a melhor solução pra vc…

Outras soluções:

  • Fazer com que o seu ServiceLocator leia todas as suas instancias?!? Feio!
  • Fazer com que todo o serviço seja replicado nas instancias e que o ServiceLocator seja inteligente a ponto de fazer um controle de carga?!? Bonito e trabalhoso!!!
  • Fazer “hardecodeado” a instancia para cada EJB, fazendo o ServiceLocator, num primeiro estagio, trabalhar como uma AbstractFactory?!? Feio!

É Daniel… acho que num tempo razoavel, com uma arqutetura razoavel, seria colocar todas as configurações em um lugar conhecido e fazer com que o ServiceLocator leia essas informações e lhe retorne o Bean EJB correto!

danieldestro
rodrigoallemand:
É Daniel... acho que num tempo razoavel, com uma arqutetura razoavel, seria colocar todas as configurações em um lugar conhecido e fazer com que o ServiceLocator leia essas informações e lhe retorne o Bean EJB correto!

Bom, esta já é a solução que eu propus. Pena que ela não fica tão transparente, pois tenho EJBs que se comunicam com EJBs que podem estar na mesma instância e/ou em outras. E usar a anotação @EJB, neste caso, não se aplica. Então eu teria de ficar usando o ServiceLocator para fazer lookups em todos os pontos. É trabalhoso.

Exemplo:

MeuEJB (instância A)
@Stateless(name="MeuEJB")
public class MeuEJBBean implements MeuEJB {
  private OutroEJB oejb;
  private AqueleEJB aejb;

  public MeuEJBBean() {
    oejb = ServiceLocator.getInstance("OUTROS").getEjb("OutroEJB");
    aejb = ServiceLocator.getInstance("AQUELES").getEjb("AqueleEJB");
  }

  public void executar( parâmetros ) {
    double val = oejb.calcular( cod );
    aejb.processar( user, val );
  }
}
OutroEJB (instância B)
@Stateless(name="OutroEJB")
public class OutroEJBBean implements OutroEJB {
  public double calcular( int cod ) {
    return... ;
  }
}
AqueleEJB(instância A)
@Stateless(name="AqueleEJB")
public class AqueleEJBBean implements AqueleEJB {
  public double processar( User u, double val ) {
    // processa
  }
}

E o ServiceLocator teria dois arquivos de configurações:
OUTROS-jndi.properties
AQUELES-jndi.properties

Agora imagine isso espalhado por centenas de EJBs.

rodrigoallemand

Eu seguiria pelo LoadBalance das instancias, claro, se isso for possivel no seu projeto!

Não sei se a opção de LoadBalance já existe pronta em algum lugar, mas… Caso não, tente estimar o tempo de contrução de um LoadBalance para EJBs distribuidos e leve aos donos do dinheiro…
Porque ai vc teria algo assim:

  • Um pacote com todos os EJBs
  • Cada instancia atualizada com este pacote (terá um trabalho no suporte de infra para este deploy)
  • Criar um BalanceControl para cada instancia
  • Um service Locator que fará um LoadBalance entre as instancias de BalanceControl escritas
danieldestro

Neste momento não preciso de load balance, tendo em vista que cada grupo de ejbs (ejb module) ficará em uma instância diferente.

O que eu quero, de fato, é simplificar o modo de usar os EJBs (lookup).

A

E como você usaria UDDI sem ser com Web Services? Ao menos todas implementações que eu vi de servidores(jUDDI, UDDI4j) só trabalhavam com/para Web Services.

App-serves mais “gordos” (BEA, Websphere) só trabalham com Web Services (se não estou enganado). Por isso, muitos associam UDDI/repositorio de serviços com Web Services.

Já, o pessoal do JBoss ESB, decidiu utilizar uma implementação mais light.

Ou seja, fazer um BD/cadastro de EJBs é pura reinvenção de roda. :wink:

Ops: faltou a referência (http://labs.jboss.com/wiki/Jbossesb/JAXR)

danieldestro

Vamos dizer que estou usando Oracle AS (OC4J), sem JBoss ESB.

A

Aí já virou consultoria…:wink:

danieldestro

É que o pessoal aqui no GUJ tem mania de sugerir soluções que não se aplicam no “mundo real” dos projetos (++eu).

Só disse que no meu caso (Oracle solution), suas sugestões não vão se encaixar, Taz. Por isso perguntei de casos reais (experiências aplicadas).

T

Destro, isso existe no Oracle AS tb, mas acho que é um produto a parte. O componente chama-se Oracle Service Registry. Não conheço afundo, mas acredito que não faça exatamente o que vc quer, pois até onde sei ele utiliza SEMPRE o stack SOAP para fazer o registro dos serviços.

A

danieldestro:
É que o pessoal aqui no GUJ tem mania de sugerir soluções que não se aplicam no “mundo real” dos projetos (++eu).

Isso acontece em qualquer lugar. Mas tb existem pessoas pragmáticas por aqui.

danieldestro

E também tem aquelas que têm que seguir as regras do jogo que os outros definem.

A

Hmm, é verdade. Mas vc pode seguir as regras definidas por outros e ser pragmático (sem chamar muito atenção :)). O que outros definem não tem nada a ver com o que vc pensa. Por outro lado, entendo que a politicagem atrapalha a maioria dos projetos.

Pq vcs escolheram a Oracle?

danieldestro

Cheguei no meio da história! Já estava aqui.
Tem gente/empresas que gostam de confiar em um nome.

le-silva

Também uso Oracle iAS aqui no trabalho…

Tenho o mesmo requisito de mais de um servidor provendo EJBs. Estes servidores podem mudar. Hoje a aplicação está rodando em um servidor, mas amanhã pode ser que tenha que rodar em um outro - por N motivos que não vem ao caso. Então, isso tem que ficar transparente para as aplicações.

Minha solução…

Onde quer que exista um cliente dos meus EJBs (seja outro EJB, ou web app, ou sei lá o que), há um diretório mapeado para uma variável de ambiente MINHA_APP_HOME. Neste diretório há um sub-diretório config, onde tenho meus arquivos *-jndi.properties contendo as configurações de JNDI para cada servidor.

Assim, se uma aplicação precisar acessar outro servidor para consumir os mesmos EJBs, apenas mudo a configuração em um desses arquivos que estão fora do meu EAR, e boa, tá tudo funcionando.

A resumo, a minha solução foi essa…

Acho que pode ser mais ou menos adaptada para o que você precisa.

Abraço!

danieldestro

Legal!
Bom saber que outros também tem as mesmas dificuldade que eu.
A sua solução é basicamente o que eu propus aqui. Vejo que não tem o que fazer fora isso mesmo.
Pobre de nós!

le-silva

danieldestro:
Legal!
Bom saber que outros também tem as mesmas dificuldade que eu.
A sua solução é basicamente o que eu propus aqui. Vejo que não tem o que fazer fora isso mesmo.
Pobre de nós!

Verdade!

Escrevi minha experiência mesmo pra você ver que você não é o único…

Abraço!

Paulo_Silveira

nao tem mesmo como fazer uma inversao de controle ai de jeito nenhum? se nao tiver, acho que eh a unica solucao viavel…

bem, receber o ServiceLocator via construtor em vez de usar o acesso singleton ja deixa o codigo muito mais elegante.

le-silva

Bom, no meu caso, o problema é que quem usa os meus EJBs não são somente EJBs, dai eu não poderia usar a injeção de dependência do próprio containner. Mas até ai, tudo bem, esse não é o maior problema, eu poderia facilmente fazer uma injeção via Spring, por exemplo. Mas isso não resolveria o meu requisito de poder alterar o servidor onde estão meus EJBs sem afetar os aplicativos clientes (digo: ter que alterar e redeployar), sejam eles EJBs ou não. Porque todas as vezes que eu precisasse mudar meus EJBs de servidor (isso não será sempre, claro, mas ainda que sejam pouquíssimas vezes, eu não tenho domínio sobre os aplicativos clientes), teria também que ser modificadas as propriedades JNDI usadas pelos aplicativos clientes.

Mas ainda não é tudo. Eu também não tenho acesso ao servidor de produção, então, preciso prover pro pessoal de infra que cuida do servidor de produção, uma maneira de alterar usuário e senha do app-server sem ter que gerar um novo EAR, etc.

Então, tenho o problema da remotabilidade transparente (nem sei que essa frase está semanticamente correta, but…) e o problema da falta de “poderes” no servidor de produção.

Nosso build, então, é gerado pelo nosso ambiente de integração contínua e implantado no servidor de homologação; estando tudo OK, quando dos releases, o pessoal de infra apenas pega o EAR gerado e faz deploy na produção (na verdade até pelo próprio ambiente de i.c.).

É, é mais ou menos isso…

Depois de pensar, testar, e pensar, e testar novamente, esta foi a solução que cheguei e não tive problemas até agora… graaaças a Deus! :smiley:

le-silva

Depois de fazer uns profilers, acabei optando por usar um ServiceLocator cacheado, por causa do custo de inicialização e lookup; e, quando necessário, caso modifique propriedades JNDI, basta fazer um refresh na aplicação e boa, tá tudo no ar novamente.

Bom, pelo menos até agora não houve nenhum problema. É claro que, em cluster, vou ter uma instancia de ServiceLocator em cada nó, mas isso também não será o fim.

danieldestro
@Stateless
public class MeuPehDeJacarandaBean implements MeuPehDeJacaranda {
  @EJB
  private ServiceLocator locator;

  public void alimentarMe() {
    List<Nutriente> nutris = locator.getEJB("Solo").extrairNutrientes();
    yammi( nutris );
  }
}

Hehehehehehe... um ServiceLocator & EJB.

Na versão 3.1 do EJB deverá haver EJB Singleton.

Alessandro_Lazarotti

Sei que o Rodrigo já disse sobre isso Daniel, mas eu tbm acho que a saída mais transparente é utilizar as instancias em Cluster. Não ter que se preocupar em que host esta o componente e ainda ter ganhos de fail-over e load-balance é algo a se pensar.
http://download-uk.oracle.com/docs/cd/B32110_01/web.1013/b28221/undejdev011.htm

Você tem alguma restrição quanto a isso ou o foco do problema não é este ?

danieldestro

Cluster e Load Balance não é minha necessidade.
O que preciso mesmo é ter serviços em diferentes containers.
Seja por uma questão de serviços verticais (ex: vendas, rh, financeiros), ou por demanda (volume de uso).

Alessandro_Lazarotti

Mas este é um requisito ou decisão de arquitetura sua? Se for uma decisão a ser tomada por você, vale apenas considerar um parque de máquinas trabalhando de forma colaborativa, não vale?

danieldestro

Ainda não é requisito, será uma decisão conjunta da área de arquitetura (que me incluo) e do gerente.
A princípio, não deve rodar nada em cluster, apenas load balance, mas não gerenciado pelo App Server.
É que cada serviço vertical (rh, financeiro, etc) precisa rodar em uma instância diferente, para que sua manutenção não afete diretamente uma outra. Se estiverem num mesmo container, isso prejudica.
Não é o caso de Load Balance ou Cluster.

Paulo_Silveira

service locator ser um ejb stateless ficou perfeito! e ai faz injecao. parabens daniel. enquanto nao vem o ejb singleton, deixe o mapa de objetos estatico dentro do locator!

Criado 13 de fevereiro de 2008
Ultima resposta 12 de mar. de 2008
Respostas 31
Participantes 9