RPC: Remote Procedure Calls

Anuncio
RPC: Remote Procedure Calls
LSUB
GSYC
13 de abril de 2016
(cc) 2015 Laboratorio de Sistemas,
Algunos derechos reservados. Este trabajo se entrega bajo la licencia Creative Commons Reconocimiento NoComercial - SinObraDerivada (by-nc-nd). Para obtener la licencia completa, véase
http://creativecommons.org/licenses/. También puede solicitarse a Creative Commons, 559 Nathan Abbott Way,
Stanford, California 94305, USA.
Las imágenes de terceros conservan su licencia original.
RPC
I
Llamada a un procedimiento que ejecuta en otro espacio de
direcciones.
I
Objetivo: enmascarar un llamada remota como una llamada a
un procedimiento local.
I
Sigue el modelo cliente/servidor, petición-respuesta.
I
Pueden ser sı́ncronas o ası́ncronas.
I
Middleware: capa de software que permite realizar RPCs
ocultando los detalles de la comunicación y de la distribución:
transparencia de acceso y de distribución.
ecución
RPC de una RPC
PC involucra una serie de etapas que se ejecutan tanto en la máquina que realiza
omo en la máquina que ejecuta el procedimiento remoto (servidor).
Figura 2: Pasos en la ejecución de una RPC
RPC: fallos
¿Y si el servidor falla mientras se está haciendo? Hay distintas
semánticas:
I
At most once: la operación se ejecuta como mucho una vez,
pero puede que ninguna. Si se retorna error, no se puede saber
si se ha realizado la operación o no.
I
At least once: la operacion se ejecuta al menos una vez, puede
que varias. Si la operación es idempotente no hay problema.
I
Exactly once: la operación se realiza exactamente una vez. En
general, es muy complicado (mecanismos de tolerancia a
fallos).
RPC: Nombrado
I
Necesitamos nombrar los recursos para poder acceder a ellos
(p. ej. hacer una RPC sobre un recurso concreto).
I
Transparencia de localización: permite encontrar los recursos
con independencia de su localización fı́sica.
I
El servicio puede ser centralizado o distribuido.
I
El esquema de nombrado puede ser plano o estructurado.
Ejemplo de resolución de nombres: DHT
I
Una tabla hash distribuida es un servicio de nombres planos.
Como en una tabla hash, a una clave le pertenece un valor
asociado.
I
La tabla hash puede estar distribuida en una red P2P (lo
veremos más adelante).
Nombres estructurados
I
Los nombres estructurados forman un espacio de nombres
(name space)
I
Generalmente se representan como un grafo dirigido con
nodos contenedores y nodos hoja,
I
Los objetos se pueden nombrar con nombres absolutos o
relativos.
I
La resolución puede ser iterativa o recursiva.
Ejemplo de resolución de nombres: DNS
I
El DNS es un servicio distribuido de nombres estructurados
para traducir nombres a direcciones IP.
I
Ya habéis estudiado en profundidad DNS.
(cc) George Shuklin
Resolución de nombres iterativa
(c) A. Tanenbaum
Resolución de nombres recursiva
I
Reduce los mensajes en el cliente (puede afectar a la latencia
en gran medida) y facilita el caching.
(c) A. Tanenbaum
RPC: Serialización
Serialización o aplanado:
I
Necesitamos transmitir los datos por la red con un formato
dado.
I
Datos binarios (enteros, floats, etc.), texto, colecciones,
referencias a otros objetos...
I
¿Interoperabilidad?
Serialización en Java
I
Cliente y servidor (ambos en Java) se pueden despreocupar
del formato de los datos. Problema: ambos deben ser
programas en Java1 .
I
Una clase que cumpla con la interfaz Serializable se puede
serializar. Esa interfaz no tiene ningún método.
I
Aplana el objeto y todos los objetos referenciados (web of
objects).
I
Todas las clases involucradas tienen que implementar
Serializable.
1
o el componente ejecutando en otra plataforma debe usar una biblioteca de
compatibilidad con Java.
Serialización en Java
I
Hay que poner una constante serialVersionUID a la clase.
Esta constante sirve para verificar en el desaplanado que las
clases que tiene el receptor son compatibles con las clases que
tiene el emisor. Debemos cambiarla si modificamos la
estructura de la clase.
I
Si un miembro es transient no forma parte del estado
persistente del objeto y no se serializa.
I
Tampoco se serializan los miembros de clase (static).
I
Si un objeto no se puede serializar, se levanta la excepción
NotSerializableException.
Código
F i g u r e s = new S q u a r e ( p1 , p2 ) ;
ObjectOutputStream os =
new O b j e c t O u t p u t S t r e a m ( s o c k . g e t O u t p u t S t r e a m ( ) ) ;
os . w r i t e O b j e c t ( s ) ;
Serialización en Java
Las clases que necesitan personalizar la serialización deben
redefinir ciertos métodos como:
p r i v a t e void w r i t e O b j e c t ( j a v a . i o . ObjectOutputStream out )
throws IOException
private void readObject ( java . io . ObjectInputStream in )
throws IOException , ClassNotFoundException ;
Serialización
I
Pero las máquinas del sistema distribuido pueden ser
heterogéneas (hardware y software).
I
En este caso, tiene que haber una representación canónica
para los datos.
I
Cada extremo debe convertir los datos de su formato local al
formato canónico y viceversa: serialización (marshalling o
aplanado).
I
Podemos definir nuestra propia serialización o usar uno de los
múltiples estándars: XDR (Sun rpc), JSON, ASN.1,
XML-RPC, etc.
Ejemplo de serialización: XML
I
Es un formato de texto.
I
Bastante enrevesado.
<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=”UTF−8” s t a n d a l o n e=” no ” ?>
<SOAP−E N V: En ve lo pe
SOAP−E N V : e n c o d i n g S t y l e=” h t t p : // schemas . x m l s o a p . o r g / s o a p / e n c o d i n g / ”
xmlns:SOAP−ENV=” h t t p : // schemas . x m l s o a p . o r g / s o a p / e n v e l o p e / ”
xmlns:SOAP−ENC=” h t t p : // schemas . x m l s o a p . o r g / s o a p / e n c o d i n g / ”
x m l n s : x s i=” h t t p : //www . w3 . o r g /1999/XMLSchema−i n s t a n c e ”
x m l n s : x s d=” h t t p : //www . w3 . o r g /1999/XMLSchema”>
<SOAP−ENV:Body>
<n s 1 : d o u b l e A n I n t e g e r
x m l n s : n s 1=” u r n : M y S o a p S e r v i c e s ”>
<param1 x s i : t y p e =” x s d : i n t ”>123</ param1>
</ n s 1 : d o u b l e A n I n t e g e r>
</SOAP−ENV:Body>
</SOAP−EN V :En ve lo pe>
Ejemplo de serialización: JSON
I
Es un formato de texto.
I
En general, más sencillo que XML.
Permite aplanar:
I
I
I
Una colección de pares atributo/valor con el que se pueden
serializar objetos, records, diccionarios, etc.
Lista de valores con el que se pueden aplanar arrays, listas,
conjuntos, etc.
Ejemplo de serialización: JSON
Objeto:
{
” rectangulo ” : {
” v i s i b l e ” : true ,
” color ” : ” verde ” ,
” supIzq ” : {
”x” : 34 ,
” y ” : 30
},
” infDer ” : {
”x” : 43 ,
” y ” : 10
}
}
}
Ejemplo de serialización: JSON
Lista:
{
”listaCoor”: [
{”x” : 0 , ”y” : 0} ,
{”x” : 2 , ”y” : 1} ,
{”x” : 4 , ”y” : 5} ,
{”x” : 0 , ”y” : 1} ,
{ ” x ” : −1 , ” y ” : 23}
]
}
Serialización
Para realizar nuestra propia serialización tenemos dos alternativas:
I
Texto. Factores a tener en cuenta:
I
I
I
Codificación (p. ej. UTF-8).
Terminación de las cadenas.
Binario. Factores a tener en cuenta:
I
I
I
Longitud de los datos.
Endianess.
Formato (p. ej: coma flotante IEEE 754, IEEE 754-2008, etc.).
Serialización: endianess
c
imagen OOO
Program Verification Systems
Serialización: texto vs binario
Ejemplo: serializar un array de 3 enteros : 1, -2, 3.
I
Texto (UTF-8):
"[[1], [-2], [3]]"
I
Binario (little endian, 4 bytes por entero, complemento a 2):
0x03 0x00 0x00 0x00
0x01 0x00 0x00 0x00
0xfe 0xff 0xff 0xff
0x03 0x00 0x00 0x00
Ejemplo de serialización: aplanar un Integer positivo
Formato de red: little-endian, 32-bit.
private
final
static
int
INTSIZE = 4 ;
p u b l i c s t a t i c byte [ ] m a r s h a l l ( i n t
b y t e r [ ] = new b y t e [ INTSIZE ] ;
r [ 3 ] = ( b y t e ) ( i >>24 & 0 x f f ) ;
r [ 2 ] = ( b y t e ) ( i >>16 & 0 x f f ) ;
r [ 1 ] = ( b y t e ) ( i >>8 & 0 x f f ) ;
r [ 0 ] = ( byte ) ( i & 0 x f f ) ;
return r ;
}
i ) throws Exception {
Ejemplo de serialización: desaplanar un Integer
Formato de red: little-endian, 32-bit.
private
final
static
int
INTSIZE = 4 ;
p u b l i c s t a t i c i n t g e t I n t ( B y t e B u f f e r b ) throws Exception {
int n;
i f ( b . c a p a c i t y ( ) < INTSIZE )
throw new E x c e p t i o n ( ”Bad a r r a y l e n g t h : must ” +
” be g r e a t e r o r e q u a l t o ” + INTSIZE ) ;
b . o r d e r ( B y t e O r d e r . LITTLE ENDIAN ) ;
n = b. getInt ();
return n ;
}
Ejemplo de serialización: aplanar un String
Formato de red: UTF-8, tamaño + null-terminated.
public
byte
int
byte
static
[] b =
size =
[] r =
byte [ ] m a r s h a l l ( S t r i n g s ) throws Exception {
s . g e t B y t e s ( ”UTF−8” ) ;
b . length + 1;
new b y t e [ s i z e+INTSIZE ] ;
// a p l a n a m o s e l tamano como a r r a y de b y t e s y
// l o c o p i a m o s a l a r r a y de b y t e s de d e s t i n o .
System . a r r a y c o p y ( m a r s h a l l ( s i z e ) , 0 , r , 0 , INTSIZE ) ;
// c o p i a m o s l o s b y t e s de l a s t r i n g a l a r r a y de d e s t i n o
// a p a r t i r de donde n o s quedamos ( INTSIZE ) .
System . a r r a y c o p y ( b , 0 , r , INTSIZE , s i z e −1);
r [ INTSIZE+s i z e −1] = ( b y t e ) 0 ;
return r ;
}
Ejemplo de serialización: desaplanar un String
Formato de red: UTF-8, tamaño + null-terminated.
p u b l i c s t a t i c S t r i n g g e t S t r ( B y t e B u f f e r b ) throws Exception {
int sz = b . getInt ( ) ;
b y t e b u f [ ] = new b y t e [ s z − 1 ] ; /∗ i g n o r e t h e n u l l c h a r ∗/
b . get ( buf ) ;
b . g e t ( ) ; /∗ s k i p t h e n u l l c h a r ∗/
r e t u r n new S t r i n g ( buf , ”UTF−8” ) ;
}
Ejemplo de serialización: aplanar un array de Integer
p u b l i c s t a t i c byte [ ] m a r s h a l l ( i n t [ ] a r r ) throws Exception {
b y t e r [ ] = new b y t e [ INTSIZE + INTSIZE ∗ a r r . l e n g t h ] ;
i n t pos = 0 ;
// s i m i l a r a l a p l a n a d o de l a s t r i n g a n t e r i o r
System . a r r a y c o p y ( m a r s h a l l ( a r r . l e n g t h ) , 0 , r , pos , INTSIZE ) ;
p o s += INTSIZE ;
f o r ( i n t i : a r r ){
System . a r r a y c o p y ( m a r s h a l l ( i ) , 0 , r , pos , INTSIZE ) ;
p o s += INTSIZE ;
}
return r ;
}
Ejemplo de serialización: desaplanar un array de Integer
public s t a t i c Integer [ ] getIntArr ( ByteBuffer b)
throws Exception {
I n t e g e r n el em = g e t I n t ( b ) ;
i f ( ne le m < 0 )
throw new E x c e p t i o n ( ”Bad a r r a y l e n , n e g a t i v e ” ) ;
I n t e g e r [ ] a r r = new I n t e g e r [ n el em ] ;
f o r ( i n t i = 0 ; i < n el em ; i ++)
arr [ i ] = getInt (b );
return arr ;
}
Descargar