java -indonésia -real -c roda

Propaganda
JAVA RMI
RECIFE-PE
2011
2
Alberto de Lima Medeiros
Paulo Marcio Fernandes Xavier
Tulio José Ferreira dos Santos
JAVA RMI
Trabalho apresentado ao professor Flavio
Gonçalves da Rocha, da disciplina de
Sistemas distribuídos, da turma 2008.1
do turno da Noite, do curso: Ciência da
Computação.
RECIFE-PE
2010
SUMÁRIO
3
1
INTRODUÇÃO..........................................................
4
2
OBJETIVO..............................................................
4
3
4
5
6
7
5
Arquitetura Java RMI.....................................................
Interfaces: O coração do RMI.............................................
Arquitetura de Camadas do RMI.........................
Usando o RMI.....................................................
Interfaces.......................................................
Implementação..............................................
4
4
5
7
8
6
4
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.
Arquitetura Java RMI
A arquitetura RMI estende a segurança e robustez da arquitetura Java
para o mundo da computação distribuída.
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
5
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
Proxy e então ao programa cliente.
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).
6
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>
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.
7
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.
8
Segue ilustração dos paços acima.
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?
1. javac Mensageiro.java
javac Mensageiro.java
Implementação
Agora, você deverá escrever a implementação para o serviço remoto, ou seja,
o código a ser executado no ambiente remoto. Nomeia o arquivo como:
MensageiroImpl.java.
view plainprint?
1. import java.rmi.RemoteException;
2. import java.rmi.server.UnicastRemoteObject;
3.
4. public class MensageiroImpl extends UnicastRemoteObject implements Mensageiro {
5.
6. public MensageiroImpl() throws RemoteException {
7.
super();
8. }
9
Salve este arquivo (MensageiroImpl.java) no seu diretório e compile, com a
seguinte linha de comando:
view plainprint?
1. javac MensageiroImpl.java
javac MensageiroImpl.java
Observe que a classe se utiliza (estende) da classe
UnicastRemoteObject para linkar com o sistema RMI. Neste exemplo a classe
estende a classe UnicastRemoteObject diretamente. Isto não é realmente
necessário, mas essa discusão fica para uma próxima etapa. Quando uma
classe estende a classe UnicastRemoteObject, ele deve prover um construtor
que declare que ele pode lançar uma exceção RemoteException, pois quando
o método super( ) é chamado, ele ativa o código em UnicastRemoteObject, que
executa o link RMI e a iniciação do objeto remoto.
Stubs e Skeletons
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.
view plainprint?
1. rmic MensageiroImpl
rmic MensageiroImpl
Após a execução deste comando, você deveria ver no seu diretório os
arquivos Mensageiro_Stub.class, Mensageiro_Skeleton.class. Servidor O
serviço remoto RMI deve ser hospedado em um processo servidor. A classe
MensageiroServer é um servidor bem simples, que provê serviços essenciais.
Salve o arquivo como: MensageiroServer.java.
view plainprint?
1. import java.rmi.Naming;
10
2.
3. public class MensageiroServer {
4.
5. public MensageiroServer() {
6.
try {
7.
Mensageiro m = new MensageiroImpl();
8.
Naming.rebind("rmi://localhost:1099/MensageiroService", m);
9.
}
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
Cliente
O código fonte para o cliente é o seguinte. Salve o arquivo como:
MensageiroClient.java.
view plainprint?
1. import java.rmi.Naming;
2. import java.rmi.RemoteException;
3. import java.rmi.NotBoundException;
4. import java.net.MalformedURLException;
5.
6. public class MensageiroClient {
7.
8. public static void main( String args[] ) {
9.
try {
10.
Mensageiro m = (Mensageiro) Naming.lookup(
"rmi://localhost/MensageiroService" );
11.
System.out.println( m.lerMensagem() );
12.
m.enviarMensagem( "Hello World!" );
13.
}
14.
15.
16.
catch( MalformedURLException e ) {
System.out.println();
System.out.println( "MalformedURLException: " + e.toString() );
11
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30. }
31. }
}
catch( RemoteException e ) {
System.out.println();
System.out.println( "RemoteException: " + e.toString() );
}
catch( NotBoundException e ) {
System.out.println();
System.out.println( "NotBoundException: " + e.toString() );
}
catch( Exception e ) {
System.out.println();
System.out.println( "Exception: " + e.toString() );
}
Salve este arquivo (MensageiroClient.java) no seu diretório e compile, com a
seguinte linha de comando:
view plainprint?
1. javac MensageiroClient.java
javac MensageiroClient.java
Rodando o sistema RMI
Agora que todos os arquivos do projeto de exemplo foram criados e
devidamente compilados, estamos prontos para rodar o sistema! Você
precisará abrir três diferentes consoles do MS-DOS no seu Windows, ou outro,
caso utilize um diferente sistema operacional. Em um dos consoles vai rodar o
programa servidor, no outro o cliente e no terceiro o RMI Registry. Inicie com o
RMI Registry. Você deve estar no mesmo diretório em que estão gravados
seus arquivos para rodar o aplicativo. Execute a seguinte linha de comando:
view plainprint?
1. rmiregistry
rmiregistry
Isso irá iniciar o RMI Registry e rodá-lo. No segundo console vamos
executar o programa servidor. Você deve estar no mesmo diretório em que
estão gravados seus arquivos para rodar o aplicativo. Execute o seguinte
comando:
view plainprint?
1. java MensageiroServer
java MensageiroServer
Isso 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 diretório em que estão gravados seus arquivos para rodar o
aplicativo. Excute o comando:
view plainprint?
12
1. java MensageiroClient
java MensageiroClient
Se tudo correr bem, que é o que esperamos e o que deveria acontecer,
a seguinte saída será gerada nos consoles 2 (servidor) e 3 (cliente). No
console 2 (servidor):
view plainprint?
1. Hellow World!
Hellow World!
No console 3 (cliente):
view plainprint?
1. This is not a Hello World! message
This is not a Hello World! Message
Referências
Site
WikiPédia - PT.wikipedia.org
Livro
Use a cabeça Java 2ª edição
Download