• Nenhum resultado encontrado

Chamadas Remotas de Procedimentos (RPC)

N/A
N/A
Protected

Academic year: 2021

Share "Chamadas Remotas de Procedimentos (RPC)"

Copied!
21
0
0

Texto

(1)

Chamadas Remotas de

Procedimentos (RPC)

• Chamada Remota de Procedimento (RPC)

ou Chamada de Função ou Chamada de

Subrotina

• Método de transferência de controle de

parte de um processo para outra parte

• Procedimentos => permite a divisão do

programas em vários pedaços

Motivação para RPC

• Desvantagens do Socket:

– Abordagem orientada a Comunicação

– A aplicação não recebe atenção exclusiva

• Chamadas de Procedimentos Convencionais

podem representar send e receive

(2)

O Conceito de Procedimentos

main

proc1

proc5

proc2

proc3

proc4

proc6

proc7

proc8

- Um programa convencional consiste de um ou mais procedimentos, geralmente

organi-zados em uma hierarquia de chamadas.

- Uma seta de um procedimento n para um procedimento m significa uma chamada de n

para m

RPC: Programa Distribuído

- A divisão ocorre entre o programa principal e o procedimento 4.

- Um protocolo de comunicação é necessário para implementar a chamada remota.

main

proc1

proc5

proc2

proc3

proc4

proc6

proc7

proc8

(3)

RPC: Modelo de Execução

P ro grama P rin cip al P ro ced imen to A

n a máq u ina 1 n a máqu in a 2

(cliente) (servido r)

ch amad a remota

p roc. A

S aída

R espo sta

• O processo cliente fica bloqueado durante a

execução do procedimento remoto!

RPC

Objetivo: Tornar mais fácil a implementação de Aplicações Distribuídas

Esconde o código de chamadas a rede em procedimentos chamados

stubs

– Stubs -> procedimentos que contêm o código de chamadas a rede.

– Com stubs o RPC protege os programas de aplicação (cliente e

servidor) de preocupações com detalhes como sockets.

– O RPC inclui uma especificação para formato padrão dos dados

(visando interoperabilidade), e nos stubs é que acontece a conversão

dos dados

• No RPC da Sun o padrão para a representação dos dados é o

XDR (eXternal Data Representation Standard)

– Os stubs são gerados automaticamente por algum compilador.

Exemplo: O RPCGen da Sun

(4)

Passos de uma Chamada Remota

de Procedimentos

transporte de mensagens via rede

Cliente

Empacota

Parâmetros

Desempacota

Resultado

Máquina do Cliente

Stub do Cliente

KERNEL

Servidor

Empacota

Resultados

Desempacota

Parâmetros

Máquina do Servidor

Stub do Servidor

KERNEL

transporte de mensagens via rede

Chamadas Remotas de

Procedimentos (RPC)

• Idéia do modelo é estender o conceito de chamada de

procedimento convencional para ambientes distribuídos.

– a ênfase é em distribuição e não em concorrência!

– objetivo é simplificar a programação distribuída,

tornando-a semelhante à programação convencional!

• Remote Procedure Call (RPC): subrotina chamada pode

ser função ou procedimento

• Procedimentos => permitem a divisão do programas em

vários pedaços que podem executar em máquinas

arbitrárias.

(5)

RPC - Implementação

• O código das chamadas a rede é escondido em

procedimentos chamados stubs

– Stubs

-> procedimentos que contêm o código de

chamadas a rede.

– Com stubs o RPC protege os programas de aplicação

(cliente e servidor) de preocupações com detalhes como

sockets.

• Cabe aos stubs a passagem de parâmetros entre

procedimentos.

– Máquinas diferentes podem usar representações

diferentes de dados como inteiros, caracteres, etc.

– O que fazer com dados complexos, como listas, etc?

Um exemplo de RPC: Sun-RPC

• Sistema originalmente criado para máquinas Sun.

– oferecido atualmente em diversos sistemas operacionais!

• A arquitetura definida inclui:

– uma linguagem para definição das interfaces (cabeçalhos de

procedimentos, etc);

– a ferramenta RPCGEN, que gera os stubs cliente e servidor

automaticamente;

– uma biblioteca RPC, que pode ser usada diretamente na

construção de programas que não usem o PRCGEN;

– o protocolo de comunicação entre os stubs.

(6)

Sun-RPC - Tradução de dados

• Tradução entre formatos de dados:

utilização de uma representação padrão,

XDR (eXternal Data Representation

Standard).

• A conversão é especificada para um

conjunto pré-definido de tipos de dados.

formato

origem

formato

padrão

formato

destino

RPC - Mapeamento Dinâmico de

Portas (Portmapper)

• Mapeia serviços a Portas

• Em geral está na porta 111

Programa RPC

(servidor)

RPC

port mapper

Registra (programa,porta)

Socket usado

atualmente por

este programa

Socket em porta

bem conhecida

usada

(7)

RPC - Mapeamento Dinâmico de

Portas

Portmapper

daemon

svc_register

clnt_create

(1) registro

(2)

(3)

(4)

Sistema

Remoto

Sistema

Local

Passos envolvidos em uma chamada RPC

rpcgen - Funcionamento

prog.x

rpcgen

biblioteca

RPC

cc

cc

rprog.c

prog_proc.c

prog_clnt.c

prog.h

prog_svc.c

rprog

prog_svc

procedimentos servidores

cliente

especificação RPC

stub servidor

stub cliente

programa servidor

programa cliente

(8)

rpcgen

• Exemplo de arquivo de especificação:

/* date.x

especificação de serviços remotos de data e hora */

program DATE_PROG{

version DATE_VERS{

long BIN_DATE(void) = 1;

string STR_DATE(long) = 2;

} = 1;

} = 0x31234567;

Passo 1: Construir uma Aplicaçao Convencional

main

(9)

Passo 2: Dividir o programa em duas partes

insere

remove

busca

inicializar

main

proxima

Banco

de

Dados

Chamadas a

Procedimentos Remotos

Cliente

Programa Remoto

Passo 3: Criar uma Especificação Rpcgen

/* rbd.x

especificação rpc para um programa de banco de dados

que oferece os procedimentos INSERE, REMOVE e BUSCA

*/

struct example {

/* estrutura não usada, declarada para ilustrar como rpcgen */

int exfield1;

/* constrói rotinas XDR para converter estruturas */

char exfield2;

};

program RBDPROG{

/* nome do programa remoto */

version RDBVERS{

/* declaração da versão */

int INICIALIZAR(void) = 1;

/* primeiro procedimento deste programa */

int INSERE(string) = 2;

/* segundo procedimento deste programa */

int REMOVE(string) = 3;

/* terceiro procedimento deste programa */

int BUSCA(string) = 4;

/* quarto procedimento deste programa */

} = 1;

/* definição da versão do programa */

(10)

Passo 4: Rodar o Rpcgen

• rpcgen rbd.x

rpcgen

rdb_clnt.c

rdb.h

rdb_svc.c

rdb_xdr.c

Rpcgen

Arquivo .h

/* rbd.h */

struct example {

int exfield1;

char exfield2;

};

typedef sruct example example;

bool_t xdr_example();

#define RBDPROG (u_long) 0x30090949)

#define RDBVERS ((u_long) 1)

#define INICIALIZAR ((u_long) 1)

extern int *inicializar_1();

#define INSERE ((u_long) 2)

extern int *insere_1();

#define REMOVE ((u_long) 3)

extern int *remove_1();

#define BUSCA ((u_long) 4)

extern int *busca_1();

(11)

Rpcgen

Arquivo de Conversão XDR

/* rbd_xdr.c */

#include <rpc/rpc.h>

#include “rbd.h”

bool_t

xdr_example(xdrs, objp)

XDR *xdrs;

example *objp;

{

if (!xdr_int(xdrs, &objp->exfield1)) {

return(FALSE);

}

if (!xdr_char(xdrs, &objp->exfield2) {

return(FALSE);

}

return(TRUE);

}

Rpcgen

Stub do Cliente

/* rbd_clnt.c */ #include <rpc/rpc.h> #include “rbd.h” int * inicializar_1(argp, clnt) void *argp; CLIENT *clnt; {

static int res;

bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, INICIALIZAR, xdr_void, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res); } int *insere_1(argp, clnt) char **argp; CLIENT *clnt; {

static int res;

bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, INSERE, xdr_wrapstring, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res); } int * remove_1(argp, clnt) char **argp; CLIENT *clnt; {

static int res;

bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, REMOVE, xdr_wrapstring, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res); } int *busca_1(argp, clnt) char **argp; CLIENT *clnt; {

static int res;

bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, BUSCA, xdr_wrapstring, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res); }

(12)

Rpcgen

Stub do Servidor

/* rbd_svc.c */

#include <rpc/rpc.h> #include “rbd.h”

static void rbdprog_1();

main() { SVCXPRT *transp; (void)pmap_unset(RBDPROG, RBDVERS); transp = svcudp_create(RPC_ANYSOCK); if (transp == NULL) {

(void) fprintf(“Não pode criar serviço udp\n”); exit(1);

}

if (!svc_register(transp, RBCPROG, RBDVERS, rbdprog_1, IPPROTO_UDP)) {

(void) fprintf(“Não pode registrar tal prog.\n”); exit(1);

}

transp = svctcp_create(RPC_ANYSOCK, 0, 0); if (transp == NULL) {

(void) fprintf(“Não pode criar serviço TCP\n”); exit(1);

}

if (!svc_register(transp, RBCPROG, RBDVERS, rbdprog_1, IPPROTO_TCP)) {

(void) fprintf(“Não pode registrar tal prog.\n”); exit(1); } svc_run(); (void)fprintf(“SVC_RUn retornado \n”); exit(1); }

static void rbdprog_1(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp; { union { char *insere_1_arg; char *remove_1_arg; char *busca_1_arg; } argument; char *result;

bool_t (*xdr_argument) (), (*xdr_result)(); char *(*local)();

switch (rqstp->rq_proc) { case NULLPROC:

( void)svc_sendreply(transp, xdr_void,(char *) NULL); return;

case INICIALIZAR: xdr_argument = xdr_void; xdr_result = xdr_int;

local = (char *(*)())inicializar_1; break;

case INSERE:

xdr_argument = xdr_wrapstring; xdr_result = xdr_int; local = (char *(*)()) insere_1; break;

Rpcgen

Continuação Stub do Servidor

case REMOVE:

xdr_argument = xdr_wrapstring; xdr_result = xdr_int; local = (char *(*)())remove_1; break;

case BUSCA:

xdr_argument = xdr_wrapstring; xdr_result = xdr_int; local = (char *(*)()) busca_1; break; default: svcerr_noproc(transp); return; } bzero((char*)&argument, sizeof(argument)); if (!svc_getargs(transp, xdr_argument, &argument)) {

svcerr_decode(transp); return;

}

result = (*local)(&argument, rqstp); if (result != NULL && !svc_sendreply(transp,

xdr_result, result )) { svcerr_systemerr(transp); }

if (!svc_freeargs(transp, xdr_argument, &argument)) { (void)fprintf(“Problema nos argumentos\n”); exit(1);

} }

(13)

Passo 5: Escrever procedimentos de Interface com o Stub

/* rbd_cif.c - inicializar, insere, remove, busca */

#include <rpc/rpc.h>

#include “rbd.h”

extern CLIENT *handle; /* handle para procedimento

remoto */

int inicializar()

{

return *inicializar_1(handle);

}

int insere(item)

char *item;

{

char **arg;

arg = &item;

return *insere_1(arg, handle);

}

• Rotinas de Interface do Cliente

int remove(item)

char *item;

{

char **arg;

arg = &item;

return *remove_1(arg, handle);

}

int busca(item)

char *item;

{

char **arg;

arg = &item;

return *busca_1(arg, handle);

}

Rotinas de Interface do Servidor

/* rbd_sif.c - inicializar_1, insere_1, remove_1, busca_1

*/

#include <rpc/rpc.h>

#include “rbd.h”

static int retcode;

int *inicializar_1()

{

retcode = inicializar();

return &retcode;

}

int *insere_1(i)

char **i;

{

retcode = insere(*i);

return &retcode;

}

int *remove_1(i)

char **i;

{

retcode = remove(*i);

return &retcode;

}

int *busca_1(i)

char **i;

{

retcode = busca(*i);

return &retcode;

}

(14)

Passo 6: Compilar e Linkar o Programa Cliente

• cc -c rbd_cif.c ---> rbd_cif.o

• cc -c rbd.c ---> rdb.o

• cc -o rbd rbd.o rbd_clnt.o rbd_xdr.o

rbd_cif.o

/* rbd.c - main, proxima*/ #include <rpc/rpc.h> #include “rbd.h”

#define RMACHINE “localhost” /* nome da máquina remota */ CLIENT *handle; /* handle para um procedimento remoto */ int main(argc, argv)

int argc; char *argv[]; {

char palavra[MAXWORD+1]; char cmd;

int plvlen; /* tamanho da palavra */

/* Seta a conexão para uma chamada remota de procedimento */ handle = clnt_create(RMACHINE, RBDPROG, RBDVERS, “tcp”); if (handle == 0) {

printf(“Não pode conectar programa remoto/n”); exit(1);

} while (1) {

plvlen = proxima(&cmd, palavra); if (plvlen < 0)

exit(0);

switch (cmd) { case ‘I’: /*inicialize */

inicializar(); printf(“BD inicializado \n”); break;

case ‘i’: /*insere */ insere(palavra);

printf(“%s Inserida \n”, palavra); break;

case ‘b’: /*busca */ if (busca(palavra))

printf(“%s foi encontrada \n”, palavra); else printf(“%s não existe \n”, palavra); break;

case ‘r’: /*remove */ if (remove(palavra))

printf(“%s removida \n”, palavra); else

printf(“%s não encontrada”\n”, palavra); break;

case ‘q’: /*quit */

printf(“programa encerrado \n”); exit(0);

default: /* entrada ilegal */ printf(“Comando inválido \n”); break; } } }

Programa Cliente

(15)

int proxima(cmd, palavra) char *cmd, *palavra; { int i, ch; ch = getc(stdin); while (ch == ‘ ‘) ch = getc(stdin); if (ch == EOF) return -1; *cmd = (char) ch; ch = getc(stdin); while (ch = ‘ ‘) ch = getc(stdin); if (ch == EOF) return -1; if (ch == ‘\n’) return 0; i = 0; while ((ch != ‘ ‘) && (ch != ‘\n’)) { if (++i > MAXWORD) {

printf(“Erro, palavra muito longa \n”); exit(1); } *palavra++ = ch; ch = getc(stdin); } return i; }

Continuação Programa Cliente

Passo 7: Compilar e Linkar o Programa Servidor

• cc -c rbd_sif.c ---> rbd_sif.o

• cc -c rbd_srp.c --->

rdb_srp.o

• cc -o rbddaemon rbd_svc.o rbd_xdr.o

rbd_sif.o rbd_srp.o

(16)

/* rbd_srp.c - inicializar, insere, remove, busca*/ #include <rpc/rpc.h>

#include “rbd.h”

/* Procedimentos remotos do servidor e dados globais */

char bd[BDSIZE][MAXWORD+1] /* armazena o dicionário de palavras */ int npalavras = 0; /* número de palavras no dicionário */ int inicializar() { npalavras = 0; return 1; } int insere(palavra) char *palavra; { strcpy(bd[npalavras], palavra); npalavras++; return npalavras; } int remove(palavra) char *palavra; { int i;

for (i=0; i<npalavras; i++)

if (strcmp(palavra, bd[i]) == 0) { npalavras--; strcpy(bd[i], bd[npalavras]); return 1; } return 0; } int busca(palavra) char *palavra; { int i;

for (i=0; i<npalavras; i++)

if (strcmp(palavra, bd[i]) == 0 ) return 1;

return 0; }

Programa Servidor

Passo 8: Iniciar o Servidor e Executar o Cliente

• Iniciar o servidor em background:

rbddaemon&

(17)

Possíveis Falhas em Sistemas

Baseados em RPC

• Cliente não consegue localizar o servidor

• Perda das mensagens de solicitação

• Perda das mensagens de resposta

• Queda do Servidor

• Queda do Cliente

RPC - Cliente não consegue

localizar o servidor

• Causas:

– Servidor está fora do Ar

– Cliente está usando versão antiga do servidor

• Soluções:

– Variáveis com código de retorno indicando erro

– Exceções (em linguagem que dão suporte a

(18)

RPC - Perda das mensagens de

solicitação

• Causa:

– problemas na rede

• Soluções:

– temporização para chegada da resposta ou

mensagem de reconhecimento

– tempo expira -> retransmissão da mensagem

RPC - Perda das mensagens de

resposta

• Causas:

– perda da solicitação

– perda da resposta

– servidor

• Soluções:

– Fácil de tratar quando a operação é

idempotente: reenvio da solicitação

(19)

Semântica de Chamadas Remotas

• Ao contrário do que acontece em chamadas convencionais,

uma das máquinas envolvidas pode falhar e a outra

permanecer ativa...

• Sistema pode garantir que a execução da rotina chamada

ocorre:

– exatamente uma vez

• difícil!!

– no mínimo uma vez

• operações devem ser idempotentes!

– no máximo uma vez

• Sistema deve retornar indicações no caso de máquina

servidora falhar!

RPC - Queda do Servidor

• Soluções:

– não pode ser resolvida com números sequenciais

– retransmissão da mensagem -> problema recai na

semântica da execução

Servidor

Recepção

Execução

Queda

Requisição

Sem resposta

Servidor

Recepção

Queda

Requisição

Sem resposta

(20)

RPC - Queda do Cliente

• Processamento órfão

– consomem tempo de processamento

– no caso do cliente se recuperar, a resposta deste

processamento pode chegar até ele

• Soluções:

– Consistem em estratégias para eliminação dos

órfãos. Exemplo:

• Reencarnação: ao se recuperar, o cliente envia uma

mensagem em broadcast para todas as máquinas da

rede, declarando um novo início. Os processamentos

anteriores são eliminados

RPC Assíncrona

• Chamadas de Procedimentos que não

bloqueiam ou não recebem respostas são

ditas Assíncronas.

• A chamada é enviada para o servidor e o

controle é retornado imediatamente para o

cliente (não há bloqueio do cliente)

(21)

Necessidade de RPC Assíncrona

• Quando a resposta não é necessária, o

cliente pode enviar a solicitação e não

bloquear. Ex.: print

• Quando a resposta é necessária, o cliente

pode se beneficiar em fazer a chamada e

não aguardar a resposta

RPC Síncrona X Assíncrona

send 1

receive 1

execute 1

send 1

receive 1

receive 2

cliente

servidor

send

receive

execute

send

receive

processa

send

receive

execute

send

receive

cliente

servidor

tempo

send 2

receive 2

execute 2

send 2

Síncrona

Assíncrona

Referências

Documentos relacionados

Médico Anestesiologista Plantonista 03 Município de Mata de São João 00 Nível Superior em Medicina Diploma de conclusão de Curso de graduação de Nível Superior de

Em relação ao luto, indica a não direção sobre o analisante: ao contrário, o analista deve tornar-se paciente.. Gostaria ainda de comentar sobre a metáfora de que Lacan se

Com exceção dos animais submetidos aos banhos com verde malaquita, os peixes dos demais tratamen- tos apresentaram infecção progressiva pelo ictio de acordo com as lesões

4.1 Antes de efetuar a inscrição, o candidato deverá conhecer o Edital e certificar- se de que preenche todos os requisitos exigidos. 4.3 É de responsabilidade exclusiva do

Dito isso, seguem abaixo as descrições resumidas para cada carta, alertando ainda que é apenas um resumo para facilitar ao estudante fixar (não decorar) ou

Não há dúvida que o resgate da inteligência insular matriarcal é indispensável na Antropologia e na Psicologia para operar lado a lado com a inteligência polarizada

Anticorpos antiparasitários inespecíficos de alto peso molecular no soro sanguíneo ocorrem com frequências semelhantes em pacientes com esclerose múltipla quando

Luciano Elias Bruxel (Instituto Cultural São Francisco de Assis - CPCA) – Eu acho 620. que