Computacao distribuida com rmi
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Computacao distribuida com rmi

on

  • 979 views

 

Statistics

Views

Total Views
979
Views on SlideShare
979
Embed Views
0

Actions

Likes
0
Downloads
24
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Computacao distribuida com rmi Document Transcript

  • 1. Introdução á Computação Distribuída com RMIA tecnologia RMI - Remote Method Invocation (Invocação de Métodos Remotos), foiprimeiramente introduzida no Java, no JDK versão 1.1, elevando a programação pararedes em um patamar mais elevado. Apesar do RMI ser relativamente fácil, ele põe odesenvolvedor Java frente à um novo paradigma, o mundo da computação de objectosdistribuídos.Este guia prático vai lhe introduzir à esta tecnologia versátil, que melhorou muito desdesua primeira versão.O principal objectivo para os criadores (designers) do RMI era permitir osprogramadores a desenvolverem programas distribuídos em Java com a mesma sintaxee semântica usada em programas não-distribuídos. Para isso, eles tiveram que mapearcuidadosamente como classes Java e objectos trabalham em uma única Java VirtualMachine (JVM) para um novo modelo de como as classes e objectos trabalhariam numambiente distribuído de computação (múltiplas JVMs). Os arquitectos do RMI tentaramfazer com que o uso dos objectos distribuídos em Java fosse similar ao uso de objectosJava locais.Esta secção introduz a arquitectura RMI da perspectiva dos objectos Java remotosdistribuídos, e explora as diferenças de comportamento com objectos locais. Aarquitectura RMI define como os objectos se comportam, como e quando excepçõespodem ocorrer, como a memória é gerida e como os parâmetros são passados eretornados de métodos remotos.A arquitectura RMI estende a segurança e robustez da arquitectura Java para o mundoda computação distribuída.A arquitectura RMI é baseada em um importante princípio: a definição docomportamento e a implementação do comportamento são conceitos separados. RMIpermite que o código que define o comportamento e o código que implementa ocomportamento permanecerem separados e rodarem em JVMs separadas.Em RMI, a definição do serviço remoto é codificada usando uma interface Java. A Página 1 de 11
  • 2. implementação do serviço remoto é codificada em uma classe. Logo, a chave para seentender o RMI é lembrar que as interfaces definem o comportamento e as classesdefinem a implementação.A classe que implementa o comportamento roda do lado do servidor RMI. A classe queroda no cliente actua como um Proxy para o serviço remoto. Veja o seguinte diagrama:O programa cliente faz chamadas de métodos pelo objecto Proxy, o RMI envia arequisição para a JVM remota e redirecciona para a implementação. Qualquer valorretornado pela implementação é devolvido ao Proxy e então ao programa cliente.Com o entendimento da arquitectura RMI num alto nível, vamos dar uma breve olhadana sua implementação.A implementação do RMI é essencialmente feita de três camadas de abstracção. Acamada Stub e Skeleton está abaixo dos olhos do desenvolvedor. Esta camadaintercepta as chamadas de métodos feitas pelo cliente para que a variável de referênciada interface redirecione essas chamadas para o serviço RMI remoto.A próxima camada é a Remote Reference Layer. Esta camada sabe como interpretar egerir referências feitas dos clientes para os objectos do serviço remoto. A conexão docliente ao servidor é Unicast (uma-para-um).A camada de transporte é baseada nas conexões TCP/IP entre as maquinas em umarede.Usando essa arquitectura de camadas, cada uma das camadas poderia ser facilmente Página 2 de 11
  • 3. melhorada ou substituída sem afectar o resto do sistema. Por exemplo, a camada detransporte poderia ser substituída por uma camada que implemente conexões UDP/IP,sem afectar as camadas superiores.Como um cliente acha o serviço remoto RMI?Os clientes acham os serviços remotos usando o serviço de nomeação ou directório(naming or directory). Isso parece um pouco redundante, mas o serviço de nomeaçãoou directório roda como um endereço bem formado (host:port).O RMI pode usar diferentes tipos de serviços de directório, incluindo o JNDI. O próprioRMI inclue um simples serviço, chamado de RMI Registry. O RMI Registry roda em cadamaquina que hospeda o serviço remoto, por definição na porta 1099.Numa máquina host, um programa servidor cria um serviço remoto, primeiramentecriando o objecto que implemente aquele serviço. Em seguida ele exporta aqueleobjecto para o RMI. Quando o objecto é exportado o RMI cria um serviço que aguardaas conexões do cliente. O servidor registra o objecto no RMI Registry, com um nomepúblico.No lado do cliente o RMI Registry é acedido através da classe estática Naming. Elaprovém o método lookup( ), que o cliente usa para requisitar o registro. Esse métodoaceita a URL que especifica o nome do servidor e o nome do serviço desejado. Ométodo retorna uma referência remota para o objecto do serviço. A URL é formadacomo seguinte:rmi://<host_name>[:port_number]/<service_name> Página 3 de 11
  • 4. Agora vamos trabalhar com um sistema que realmente implementa um sistema comRMI. Vamos criar um aplicativo simples, cliente e servidor, que executa métodos doobjecto remoto.Para tanto não necessitamos de duas máquinas distintas ou com IP distintos. O exemplopode ser rodado na mesma máquina, pois o RMI sabe como trabalhar com isso, mesmoque 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• Implementações dos serviços remotos• Arquivos de Stub e Skeletons• Um servidor para hospedar os serviços remotos• Um serviço de RMI Naming que permite o cliente achar os serviços remotos• Um provedor de arquivos de classes (servidor http ou ftp)• Um programa cliente que necessita os serviços remotosAgora iremos, de fato, criar um sistema que implemente o RMI, utilizando-se de umprograma 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 dedirectórios.Os passos a serem seguidos agora são:• Escrever e compilar o código Java da interface• Escrever e compilar o código Java das implementações das classes• Gerar as classes Stub e Skeleton das classes de implementaçãoCrie um directório para salvar todos os seus arquivos de projecto.Você pode fazer o download do código fonte usado nesse tutorial.O primeiro passo, como dito, será criar a interface e compilá-la. A interface define todasas funcionalidades remotas oferecidas pelo serviço. Nomeio o arquivo como:Mensageiro.java. Página 4 de 11
  • 5. 1 import java.rmi.Remote;2 import java.rmi.RemoteException;34 public interface Mensageiro extends Remote {56 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étododeclara as funcionalidades do serviço, e que podem gerar uma excepçãoRemoteException.Salve este arquivo (Mensageiro.java) no seu directório e compile, com a seguinte linhade comando:javac Mensageiro.javaAgora, você deverá escrever a implementação para o serviço remoto, ou seja, o códigoa ser executado no ambiente remoto. Nomeia o arquivo como: MensageiroImpl.java.01 import java.rmi.RemoteException;02 import java.rmi.server.UnicastRemoteObject;0304 public class MensageiroImpl extends UnicastRemoteObject implements Mensageiro {0506 public MensageiroImpl() throws RemoteException {07 super();08 }0910 public void enviarMensagem( String msg ) throws RemoteException {11 System.out.println( msg );12 }1314 public String lerMensagem() throws RemoteException {15 return "This is not a Hello World! message";16 }17 }Salve este arquivo (MensageiroImpl.java) no seu directório e compile, com a seguintelinha de comando: Página 5 de 11
  • 6. javac MensageiroImpl.javaObserve que a classe se utiliza (estende) da classe UnicastRemoteObject para ligar como sistema RMI. Neste exemplo a classe estende a classe UnicastRemoteObjectdirectamente. Isto não é realmente necessário, mas essa discussão fica para umapróxima etapa.Quando uma classe estende a classe UnicastRemoteObject, ele deve prover umconstrutor que declare que ele pode lançar uma exceção RemoteException, pois quandoo método super( ) é chamado, ele activa o código em UnicastRemoteObject, queexecuta a ligação RMI e a iniciação do objecto remoto.Gere os arquivos Stubs e Skeletons da classe de implementação que roda no servidor.Para tanto, execute o comando rmic, compilador RMI do JDK.rmic MensageiroImplApós a execução deste comando, você deveria ver no seu diretório os arquivosMensageiro_Stub.class, Mensageiro_Skeleton.class.ServidorO serviço remoto RMI deve ser hospedado em um processo servidor. A classeMensageiroServer é um servidor bem simples, que provê serviços essenciais. Salve oarquivo como: MensageiroServer.java.01 import java.rmi.Naming;0203 public class MensageiroServer {0405 public MensageiroServer() {06 try {07 Mensageiro m = new MensageiroImpl();08 Naming.rebind("rmi://localhost:1099/MensageiroService", m); Página 6 de 11
  • 7. 09 } 10 catch( Exception e ) { 11 System.out.println( "Trouble: " + e ); 12 } 13 } 14 15 public static void main(String[] args) { 16 new MensageiroServer(); 17 } 18 } Salve este arquivo (MensageiroServer.java) no seu diretório e compile, com a seguinte linha de comando: > javac MensageiroServer.java O código fonte para o cliente é o seguinte. Salve o arquivo como: MensageiroClient.java.01 import java.rmi.Naming;02 import java.rmi.RemoteException;03 import java.rmi.NotBoundException;04 import java.net.MalformedURLException;0506 public class MensageiroClient {0708 public static void main( String args[] ) {09 try {10 Mensageiro m = (Mensageiro) Naming.lookup( "rmi://localhost/MensageiroService" );11 System.out.println( m.lerMensagem() );12 m.enviarMensagem( "Hello World!" );13 }14 catch( MalformedURLException e ) {15 System.out.println();16 System.out.println( "MalformedURLException: " + e.toString() );17 }18 catch( RemoteException e ) {19 System.out.println();20 System.out.println( "RemoteException: " + e.toString() );21 }22 catch( NotBoundException e ) {23 System.out.println();24 System.out.println( "NotBoundException: " + e.toString() );25 }26 catch( Exception e ) {27 System.out.println();28 System.out.println( "Exception: " + e.toString() );29 }30 }31 } Página 7 de 11
  • 8. Salve este arquivo (MensageiroClient.java) no seu diretório e compile, com a seguintelinha de comando:javac MensageiroClient.javaAgora que todos os arquivos do projeto de exemplo foram criados e devidamentecompilados, estamos prontos para rodar o sistema! Você precisará abrir três diferentesconsoles do MS-DOS no seu Windows, ou outro, caso utilize um diferente sistemaoperacional.Em um dos consoles vai rodar o programa servidor, no outro o cliente e no terceiro oRMI Registry.Inicie com o RMI Registry. Você deve estar no mesmo diretório em que estão gravadosseus arquivos para rodar o aplicativo. Execute a seguinte linha de comando:rmiregistryIsso irá iniciar o RMI Registry e rodá-lo.No segundo console vamos executar o programa servidor. Você deve estar no mesmodirectório em que estão gravados seus arquivos para rodar o aplicativo. Execute oseguinte comando:java MensageiroServerIsso irá iniciar, carregar a implementação na memória e esperar pela conexão cliente.No último console, rode o programa cliente. Você deve estar no mesmo directório emque estão gravados seus arquivos para rodar o aplicativo. Execute o comando:java MensageiroClient Página 8 de 11
  • 9. Se tudo correr bem, que é o que esperamos e o que deveria acontecer, a seguinte saídaserá gerada nos consoles 2 (servidor) e 3 (cliente).No console 2 (servidor):Hellow World!No console 3 (cliente):This is not a Hello World! messageÉ isso aí. Você acabou de criar um sistema utilizando a tecnologia RMI. Apesar de vocêter rodado os programas na mesma máquina, o RMI usa a pilha de rede TCP/IP para secomunicar entre as três diferentes instâncias da JVM.Exercício: 1. Defina a Interface Remota import java.rmi.Remote; import java.rmi.RemoteException; import java.math.BigInteger; public interface Operator extends Remote { BigInteger add(BigInteger b1, BigInteger b2) throws RemoteException; BigInteger subtract(BigInteger b1, BigInteger b2) throws RemoteException; BigInteger divide(BigInteger b1, BigInteger b2) throws RemoteException; BigInteger multiply(BigInteger b1, BigInteger b2) throws RemoteException; } 2. Compile a Interface Javac Operator.java 3. Implementer a Interface Remota import java.rmi.RemoteException; import java.math.BigInteger; import java.rmi.server.UnicastRemoteObject; import java.rmi.Naming; public class OperatorServer extends UnicastRemoteObject implements Operator { public OperatorServer() throws RemoteException { } public BigInteger add(BigInteger b1, BigInteger b2) throws RemoteException { return b1.add(b2); } Página 9 de 11
  • 10. public BigInteger subtract(BigInteger b1, BigInteger b2) throws RemoteException { return b1.subtract(b2); } public BigInteger divide(BigInteger b1, BigInteger b2) throws RemoteException { return b1.divide(b2); } public BigInteger multiply(BigInteger b1, BigInteger b2) throws RemoteException { return b1.multiply(b2); } public static void main(String []args) { String name = "//localhost/OperatorServer"; try { OperatorServer os = new OperatorServer(); Naming.rebind(name,os); System.out.println(name + " bound"); } catch (Exception e) { System.err.println("OperatorServer exception: " + e.getMessage()); e.printStackTrace(); } } }4. Compile a classe servidor javac OperatorServer.java5. Crie o Stub e o Skeleton rmic OperatorServer6. Verifique se as seguintes classes estão criadas OperatorServer.class OperatorServer.java OperatorServer_Skel.class OperatorServer_Stub.class7. Crie a classe cliente import java.rmi.Naming; import java.math.BigInteger; public class OperatorClient { public static void main(String args[]) { String name = "//localhost/OperatorServer"; try { Operator o = (Operator)Naming.lookup (name); BigInteger b1 = new BigInteger("1234567"); BigInteger b2 = new BigInteger("1"); BigInteger b3 = o.add(b1, b2); System.out.println("b3: " + b3); } catch( Exception e) { System.out.println(e); e.printStackTrace(); } Página 10 de 11
  • 11. } }8. Compile a classe cliente Javac OperatorClient.java9. Abra um consola do MS DOS rmiregistry10. Abra a 2ª consola do MS DOS – execução da aplicação servidor java OperatorServer Vais mostrar: //localhost/OperatorServerbound11. Abra a 3ª consola do MS DOS – execução da aplicação cliente java OperatorClient Vais mostrar: 1234568 Página 11 de 11