RMI - JAVA Introdução Introdução á Computação Distribuída com RMI A tecnologia RMI - Remote Method Invocation (Invocação de Métodos Remotos) foi primeiramente introduzida no Java, no JDK versão 1.1, elevando a programação para redes em um patamar mais elevado. Apesar do RMI ser relativamente fácil, ele põe o desenvolvedor Java frente à um novo paradigma, o mundo da computação de objetos distribuídos. Onde o desenvolvedor ou equipe de desenvolvimento terá a necessidade de criar um paradigma de distribuição dos métodos e uma boa abordagem dos mesmos. Objetivo O principal objetivo para os criadores do RMI, é que programadores desenvolvam seus sistemas do mesmo modo que desenvolviam antes porem sendo possível utilizá-los como sistemas distribuídos. Para que isso ocorresse ele tiveram que mapear cuidadosamente as classes e objetos do Java em JVM(Java Virtual Machine), afim que os mesmos sejam implementados em sistemas distribuídos como múltiplas JVMS. Os criadores tiveram o trabalho de simular que essas classes e objetos trabalhassem separadamente mas de que pra os processos fossem localmente, ou seja uma classe e seus métodos estariam em outra maquina diferente da que estou porem isso seria indiferente para meu processo pois para o mesmo tudo estaria loca. Interfaces: O coração do RMI A arquitetura RMI é baseada em um importante princípio: a definição do comportamento e a implementação do comportamento são conceitos separados. RMI permite que o código que define o comportamento e o código que implementa o comportamento permanecerem separados e rodarem em JVMs separadas. Em RMI, a definição do serviço remoto é codificada usando uma interface Java. A implementação do serviço remoto é codificada em uma classe. Logo, a chave para se entender o RMI é lembrar que as interfaces definem o comportamento e as classes definem a implementação. A classe que implementa o comportamento roda do lado do servidor RMI. A classe que roda no cliente atua como um Proxy para o serviço remoto. Veja o seguinte diagrama: O programa cliente faz chamadas de métodos pelo objeto Proxy, o RMI envia a requisição para a JVM remota e redireciona para a implementação. Qualquer valor retornado pela implementação é devolvido ao Arquitetura de Camadas do RMI Com o entendimento da arquitetura RMI num alto nível, vamos dar uma breve olhada na sua implementação. A implementação do RMI é essencialmente feita de três camadas de abstração. 1º A camada Stub e Skeleton está abaixo dos olhos do desenvolvedor. Esta camada intercepta as chamadas de métodos feitas pelo cliente para que a variável de referência da interface redirecione essas chamadas para o serviço RMI remoto. 2º A próxima camada é a Remote Reference Layer. Esta camada sabe como interpretar e gerencias referências feitas dos clientes para os objetos do serviço remoto. A conexão do cliente ao servidor é Unicast (uma-para-um). 3º A camada de transporte é baseada nas conexões TCP/IP entre as maquinas em uma rede. Usando essa arquitetura de camadas, cada uma das camadas poderia ser facilmente melhorada ou substituída sem afetar o resto do sistema. Por exemplo, a camada de transporte poderia ser substituída por uma camada que implemente conexões UDP/IP, sem afetar as camadas superiores. Neste exemplo mostro melhor como Funciona. Nomeando Objetos Remotos Como um cliente acha o serviço remoto RMI? Os clientes acham os serviços remotos usando o serviço de nomeação ou diretório (naming or directory). Isso parece um pouco redundante, mas o serviço de nomeação ou diretório roda como um endereço bem formado (host:port). O RMI pode usar diferentes tipos de serviços de diretório, incluindo o JNDI. O próprio RMI inclue um simples serviço, chamado de RMI Registry. O RMI Registry roda em cada maquina que hospeda o serviço remoto, por definição na porta 1099. Numa máquina host, um programa servidor cria um serviço remoto, primeiramente criando o objeto que implemente aquele serviço. Em seguida ele exporta aquele objeto para o RMI. Quando o objeto é exportado o RMI cria um serviço que aguarda as conexões do cliente. O servidor registra o objeto no RMI Registry, com um nome público. No lado do cliente o RMI Registry é acessado através da classe estática Naming. Ela provém o método lookup( ), que o cliente usa para requisitar o registro. Esse método aceita a URL que especifica o nome do servidor e o nome do serviço desejado. O método retorna uma referência remota para o objeto do serviço. A URL é formada como seguinte: view plainprint? rmi://<host_name>[:port_number]/<service_name> rmi://<host_name>[:port_number]/<service_name> Elementos do RMI Arquitetura de Camadas do RMI Cliente. Qualquer programa JAVA pode ser um potencial cliente, contanto que ele possua acesso as classes e objetos mínimos necessários e obtenha a referencia do objeto registrado. Stub. Este é o responsável por qualquer comunicação com o objeto distuibuido através do skeleton. O stub transforma as chamadas locais do cliente em chamadas no objeto remoto, e também é responsável por traduzir a chamada remota para o formato esperado pela chamada local. Sendo assim o mesmo se assemelha ao Maximo a programação usual. Skeleton. O skeleton tem o papel semelhante a o stub, porem no lado do servidor. O mesmo é responsável por receber as requisições do cliente e traduzi-las para o servidor de forma análoga e devolve-la para o stub posteriormente. Camadas de referência. Responsável pela criação e gerenciamento de referencias aos objetos remotos. Ele basicamente converte as solicitações RMI para a camada de transporte que esta sendo utilizada. Camadas de transporte. Prove a comunicação em rede entre as jvms, usa os sokets default (tcp) ou outro tipo pode ser utilizado. Usando o RMI Criando um aplicativo simples, cliente e servidor, que executa métodos do objeto remoto. Para tanto não necessitamos de duas máquinas distintas ou com IP distintos. O exemplo pode ser rodado na mesma máquina, pois o RMI sabe como trabalhar com isso, mesmo que o host e o cliente sejam na mesma localidade. Um sistema RMI é composto de várias partes: Definição das interfaces para os serviços remotos Mostrarei como criar um sistema que implemente o RMI, utilizando-se de um programa cliente e um programa servidor. Não utilizaremos um servidor FTP ou HTTP, no entanto utilizaremos os programas na mesma máquina e uma mesma estrutura de diretórios. Os passos a serem seguidos agora são: Escrever e compilar o código Java da interface 1º - Escrever e compilar o código Java das implementações das classes 2º - Gerar as classes Stub e Skeleton das classes de implementação Crie um diretório para salvar todos os seus arquivos de projeto. Você pode fazer o download do código fonte usado nesse tutorial. 3º - Escrever e compilar o código Java das implementações das classes 4º - Gerar as classes Stub e Skeleton das classes de implementação Crie um diretório para salvar todos os seus arquivos de projeto. Você pode fazer o download do código fonte usado nesse tutorial. Interfaces O primeiro passo, como dito, será criar a interface e compilá-la. A interface define todas as funcionalidades remotas oferecidas pelo serviço. Nomeio o arquivo como: Mensageiro.java. view plainprint? 1. import java.rmi.Remote; 2. import java.rmi.RemoteException; 3. 4. public interface Mensageiro extends Remote { 5. 6. public void enviarMensagem( String msg ) throws RemoteException; 7. public String lerMensagem() throws RemoteException; 8. } Perceba que esta interface estende a classe Remote, e cada assinatura de método declara as funcionalidades do serviço, e que podem gerar uma exceção RemoteException. Salve este arquivo (Mensageiro.java) no seu diretório e compile, com a seguinte linha de comando: view plainprint? Implementação