RPC: Remote Procedure Calls

RPC: Remote Procedure Calls
LSUB
GSYC
15 de abril de 2015
(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
• Llamada a un procedimiento que ejecuta en otro espacio de
direcciones.
• Objetivo: enmascarar un llamada remota como una llamada a
un procedimiento local.
• Sigue el modelo cliente/servidor, petición-respuesta.
• Pueden ser sı́ncronas o ası́ncronas.
• 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 de una RPC
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:
• At most once: la operación se ejecuta como mucho una vez,
pero puede que ninguna. Se retorna error al cliente, que no
puede saber si se ha realizado la operación o no.
• At least once: la operacion se ejecuta al menos una vez, puede
que varias. Si la operación es idempotente no hay problema.
• Exactly once: la operación se realiza exactamente una vez. En
general, es muy complicado (mecanismos de tolerancia a
fallos).
RPC: Nombrado
• Necesitamos nombrar los recursos para poder acceder a ellos
(p. ej. hacer una RPC sobre un recurso concreto).
• Transparencia de localización: permite encontrar los recursos
con independencia de su localización fı́sica.
• El servicio puede ser centralizado o distribuido.
• El esquema de nombrado puede ser plano o estructurado.
RPC: Serialización
Serialización o aplanado:
• Necesitamos transmitir los datos por la red con un formato
dado.
• Datos binarios (enteros, floats, etc.), texto, colecciones,
referencias a otros objetos...
• ¿Interoperabilidad?
Serialización en Java
• Cliente y servidor (ambos en Java) se pueden despreocupar
del formato de los datos. Problema: ambos deben ser
programas en Java.
• Una clase que cumpla con la interfaz Serializable se puede
serializar. Esa interfaz no tiene ningún método.
• Aplana el objeto y todos los objetos referenciados (web of
objects).
• Todas las clases involucradas tienen que implementar
Serializable.
Serialización en Java
• 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.
• Si un miembro es transient no forma parte del estado
persistente del objeto y no se serializa.
• Tampoco se serializan los miembros de clase (static).
• 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
• Pero las máquinas del sistema distribuido pueden ser
heterogéneas (hardware y software).
• En este caso, tiene que haber una representación canónica
para los datos.
• Cada extremo debe convertir los datos de su formato local al
formato canónico y viceversa: serialización (marshalling o
aplanado).
• 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: JSON
• Es un formato de texto.
• Es independiente del lenguaje.
• Permite aplanar:
• 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: JSON
Objeto:
{
” rectangulo ” : {
” v i s i b l e ” : true ,
” color ” : ” verde ” ,
” supIzq ” : {
”x” : 34 ,
” y ” : 30
},
” infDer ” : {
”x” : 43 ,
” y ” : 10
}
}
}
Ejemplo: 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:
• Texto. Factores a tener en cuenta:
• Codificación (p. ej. UTF-8).
• Terminación de las cadenas.
• Binario. Factores a tener en cuenta:
• Longitud de los datos.
• Endianess.
• Formato (p. ej: coma flotante IEEE 754, IEEE 754-2008, etc.).
RPC
c
imagen OOO
Program Verification Systems
Serialización
Ejemplo: serializar un array de 3 enteros : 1, -2, 3.
• Texto (UTF-8):
"[[1], [-2], [3]]"
• Binario (little endian, 4 bytes por entero, complemento a 2):
0x03
0x01
0xfe
0x03
0x00
0x00
0xff
0x00
0x00
0x00
0xff
0x00
0x00
0x00
0xff
0x00
Ejemplo: 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: 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: 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 ] ;
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 ) ;
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: 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: 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 ;
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: 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 ;
}