190 likes | 273 Views
Chamada Remota de Procedimentos. Remote Procedure Call. O fluxo de informações em uma implementação de clientes e servidores por passagem de mensagem requer a programação de duas trocas explícitas de mensagens em dois canais diferentes de comunicação
E N D
Remote Procedure Call • O fluxo de informações em uma implementação de clientes e servidores por passagem de mensagem requer a programação de duas trocas explícitas de mensagens em dois canais diferentes de comunicação • Cada cliente precisa de um canal de comunicação que leva a um grande número de canais • RPC serve especialmente para programar interações cliente/servidor • Combina aspectos de monitores e passagem de mensagem síncrona
Remote Procedure Call • Como em monitores, um processo ou módulo exporta operações que são invocadas através da instrução call • Como em um processo síncrono de envio de mensagens, a execução do call atrasa o invocador da chamada • Uma operação é um canal de comunicação dupla do chamador para o processo que serve a chamada e de volta para o chamador • O chamador espera até que a operação invocada seja executada e os resultados sejam retornados • Um procedimento é declarado para cada operação e um processo novo é criado para tratar cada chamada
Remote Procedure Call • Um procedimento é declarado para cada operação e um processo novo é criado para tratar cada chamada • O chamador e o corpo do procedimento podem estar em máquinas diferentes • Um módulo contém processos e procedimentos • Módulos podem residir em espaços de endereçamento diferentes • Processos dentro do módulo podem compartilhar variáveis e chamar procedimentos declarados dentro do módulo
Modelo de um módulo • Um processo em um módulo só pode se comunicar com processos em outro módulo através da chamada de procedimentos exportados por esse módulo • Forma de um módulo módulo mnome indicações das operações exportadas corpo declarações de variáveis inicialização do código procedimentos das operações exportadas procedimentos locais e processos fim mnome
Modelo de um módulo • Declaração de uma operação exportada • op opnome(formais) [returns resultado] • Operação implementada por uma proc • proc opnome(identificadores formais) returns identificador do resultado declarações de variáveis locais instruções fim • Um processo chama um procedimento em outro módulo executando call mnome.opnome(argumentos)
Implementação da chamada entre módulos Call Processo chamador (chama procedimento opnome) Processo servidor ( executa procedimento opnome)
Sincronização dentro dos módulos • Sincronização entre chamador e servidor implícita • Processos dentro de um módulo, incluindo servidores e processos locais, necessitam ser sincronizados entre eles e obter acesso mutuamente exclusivo a variáveis compartilhadas • Duas abordagens utilizadas: • processos executam com exclusão mútua, ou seja, um de cada vez está ativo • processos executam concorrentemente e mecanismos de exclusão mútua tem que ser utilizados
Um servidor de tempo • Implementação de um módulo que provê serviços de tempo para clientes em outros módulos • Duas operações visíveis: • get_time, para um cliente obter a hora do dia • delay, para bloquear o processo do cliente por interval unidades de tempo • O servidor possui um processo interno que inicia continuamente um timer de hardware, que incrementa a hora do dia quando ocorre uma interrupção
Um servidor de tempo Module TimeServer op get_time() returns int; op delay (int interval); body int tod=0; # hora do dia sem m =1; # semáforo para exclusão mútua sem d[n]=([n] 0); # semáforos privados para delay queue of (int waketime, int process_id) napQ; ## quando m==1, tod < waketime para os processos atrasados proc get_time() returns time { time = tod; } proc delay (interval) { # assume interval > 0 int waketime = tod + interval; P(m); insere (waketime, myid) no lugar apropriado em napQ; V(m); P(d[myid]); # espera para ser acordado }
Um servidor de tempo process Clock { inicia o timer de hardware; while (true) { espera por interrupção, então reinicia timer; tod = tod + 1; P(m); while (tod >= menor waketime em napQ) { remove (waketime, id) de napQ; V(d[id]); # acorda processo id } V(m); } } fim TimeServer
Java RMI (Remote Method Invocation) • Suporte de Java a RPC • Operações em objetos Java são chamados métodos, daí o nome RMI • Três componentes: • uma interface que declara os headers para os métodos remotos • uma classe servidora que implementa a interface • um ou mais clientes que chamam os métodos remotos
Programação emRMI • Escreva uma interface Java que estende Remote com métodos que declaram o lance de exceções remotas • Escreva uma classe servidora que estende UnicastRemoteObject e implementa os métodos da interface • Escreva código que cria uma instância do servidor e registre seu nome em um servidor de nomes denominado registry service • Escreva uma classe cliente que interage com o servidor • O cliente deve criar um gerenciador de segurança para não carregar código errado pela rede e deve obter um objeto servidor do registry service. Após esse procedimento, o cliente pode chamar os métodos remotos do servidor.
Mecanismo de funcionamento • O programa do cliente invoca os métodos do servidor como se fossem locais • Quando os métodos são remotos, a interação entre cliente e servidor é gerenciada por um stub e skeleton • Após a compilação do programa, o stub e skeleton são criados pelo comando rmic
Mecanismo de funcionamento • Quando um cliente invoca um método remoto, ele, na verdade, invoca um método no stub • O stub organiza os argumentos da chamada remota e os envia em uma única mensagem para o skeleton • O skeleton recebe a mensagem com os argumentos, gera uma invocação local do método para o servidor, espera o resultado e o retorna para o stub • O stub retorna o resultado para o código do cliente
Detalhes para execução • Cliente e servidor são programas separados que executam em hosts separados • Necessita-se de utilizar um identificador o servidor que deve ser único, pois podem existir mais de um servidor executando ao mesmo tempo • Formato dos nomes de servidores • rmi://hostname:port/pathname, onde hostname é o nome do host na Internet, port é uma porta escolhida pelo usuário e pathname é um nome do diretório escolhido pelo usuário no servidor • O registry service é um programa que mantém uma lista de nomes registrados de servidores em um host
Detalhes para execução • O registry service é um programa que mantém uma lista de nomes registrados de servidores em um host • Inicia-se o programa em background na máquina servidora através do comando “rmiregistry port &” • A interface para esse serviço é fornecida por um objeto Naming com dois métodos: bind, para registrador um nome e lookup para obter o nome de um servidor • Os programas cliente e servidor são iniciados através do interpretador java • O servidor deve ser iniciado em uma máquina e os clientes em máquinas conectadas as servidor
import java.rmi.*; import java.rmi.server.*; public interface RemoteDatabase extends Remote { public int read() throws RemoteException; public void write(int value) throws RemoteException; } class Client { public static void main(String[] args) { try { System.setSecurityManager(new RMISecurityManager()); String name ="rmi://neuman:9999/database"; RemoteDatabase db = (RemoteDatabase) Naming.lookup(name); int value, rounds = Integer.parseInt(args[0]); for (int i = 0; i , rounds; i==) { value = db.read(); System.out.println("read: "+ value); db.write(value+1); } } catch (Exception e) { System.err.println(e); } } }
class RemoteDatabaseServer extends UnicastRemoteObject implements RemoteDatabase { protected int data = 0; public int read() throws RemoteException { return data; } public void write (int value) throws RemoteException { data = value; System.out.println(”new value is : “ + data); } public RemoteDatabaseServer() throws RemoteException { super (); } public static void main(String[] args) { try { RemoteDatabaseServer server = new RemoteDatabaseServer(); String name ="rmi://neuman:9999/database"; Naming.bind(name, server); System.out.println(name + “is running”); } catch (Exception e ) { System.err.println(e); } } }