Transcript os-rpc

Remote Procedure Call
Andrew Whitaker
CSE451
Remote Procedure Call
RPC exposes a programming interface
across machines:
interface PriceService {
Price getPrice(ASIN uniqueID);
}
Caller
PriceImpl
RPC
System
RPC
System
Client
Server
getPrice
461 in two slides
Network software is
arranged in layers
Higher layers offer
more convenient
programming
abstractions
TCP provides in-order,
reliable delivery of a byte
stream
Application (HTTP, FTP)
Transport (TCP, UDP)
Network (IP)
Link (Ethernet, 802.11)
What TCP Does (Not) Provide
 TCP allows one machine to send a reliable byte
stream to another machine:
Socket.send(byte[] byteBuffer);
 TCP does not provide:
Mapping to/from programming language types
 Called “marshalling”
Thread management
Intelligent failure semantics
Discovery
 RCP packages build on TCP (or sometimes
UDP) to provide these services
What Uses RPC?
Service-oriented architectures
Web services allow arbitrary clients and servers
to communicate using XML-based exchange
formats
Distributed file systems
e.g., NFS (network file system)
Multiplayer network games
Many other distributed systems
RPC at 10,000 feet
The key to an RPC system is its Interface
Definition Language (IDL)
An interface provides the contract between
clients and servers
Given an interface, an RPC compiler
generates RPC “stubs”
Which abstract away the network
RPC Visualized
interface PriceService {
Price getPrice(ASIN uniqueID);
}
RPC
Compiler
Caller
PriceImpl
Client
Stub
Server
Stub
Client
Server
RPC stubs
 The client program thinks it’s invoking the server
But, it’s really calling the client-side stub
 The server program thinks it’s called by the
client
But it’s really called by the server-side stub
 The stubs send messages to each other to make
the RPC happen transparently
RPC Example: An Add() Service
Client Program:
Server Program:
…
sum = server->Add(3,4);
…
int Add(int x, int y) {
return x + y;
}
client-side stub:
server-side stub:
int Add(int x, int y) {
alloc message buffer;
mark as “add” call;
store x,y in buffer;
send message;
receive response;
unpack response;
return response;
}
RPC runtime system:
send message to server;
receive response;
Message Add_Stub(Message m) {
remove x,y from m;
r = Add(x,y);
allocate response buffer;
store r in response;
return response;
}
RPC runtime system:
receive message m;
response = Add_Stub(m);
send response to client;
IDL Example #1: Java RMI
Interface definition language is Java itself
interface PriceServices extends Remote {
Price getPrice(ASIN uniqueID) throws RemoteException;
}
IDL Example #2: CORBA IDL
module BankSimple{
struct CustomerDetails {
string name;
short age;
};
Note: compound types
must be explicitly defined
interface Bank {
CustomerDetails getCustomerDetails (in string name);
};
};
IDL Example #3: WSDL
????
<?xml version="1.0"?>
<!-- root element wsdl:definitions defines set of related services -->
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns=http://example.com/stockquote.wsdl
xmlns:xsd1=http://example.com/stockquote.xsd
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<!-- wsdl:types encapsulates schema definitions of communication types; here using xsd -->
<wsdl:types>
<!-- all type declarations are in a chunk of xsd -->
<xsd:schema targetNamespace=http://example.com/stockquote.xsd
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
<!-- xsd definition: TradePriceRequest [... tickerSymbol string ...] -->
<xsd:element name="TradePriceRequest">
<xsd:complexType>
<xsd:all>
<xsd:element name="tickerSymbol" type="string"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<!-- xsd definition: TradePrice [... price float ...] -->
<xsd:element name="TradePri
xsd:<complexType>
<xsd:all>
<xsd:element name="price" type="floa
</xsd:all>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<!-- request GetLastTradePriceInput is of type TradePriceRequest -->
<wsdl:message name="GetLastTradePriceInput">
<wsdl:part name="body" element="xsd1:TradePriceRequest"/>
</wsdl:message>
<!-- request GetLastTradePriceOutput is of type TradePrice -->
<wsdl:message name="GetLastTradePriceOutput">
<wsdl:part name="body" element="xsd1:TradePrice"/>
Design Issues in RPC
Transparency: to be or not to be?
Marshalling and unmarshalling
Converting types to byte streams
Discovery and naming
Versioning
Transparency
 General distributed systems issue: does a
remote service look identical to a local service
 Transparency allows programmers to ignore the
network
 But, transparency can impose poor performance
and complexity
 In practice
File systems try for transparency
RPC systems do not
A Java RMI Example
interface FileStream extends Remote {
// read from a (possibly) remote file into a buffer
int read (byte[] buffer, int offset, int howManyBytes)
throws RemoteException;
}
This doesn’t work! Java RMI is call-by-value
Revised Java RMI Example
interface FileStream extends Remote {
// read from a (possibly) remote file into a buffer
byte[] read (int howManyBytes)
throws RemoteException;
}
Data Marshalling
Marshalling is the task of converting
programming language types into a byte
stream
Unmarshalling is the reverse
This is boring, but potentially complex
How many bits are in an integer?
How are floating point numbers represented?
Is the architecture big-endian or little-endian?
Complex Types
Object-oriented languages allow
programmer-defined types
Two basic strategies:
Push the type definition into the IDL (CORBA)
Add implicit support to the language
Java Serialization
Java Serialization
Instances of Serializable can automatically
converted into a byte stream
Thus, RMI allows serializable arguments
public class Person implements Serializable {
private int age;
private String name;
private float salary;
private transient boolean gender;
}
transient turns off serialization
Discovery and Lookup
Clients must locate a remote object or
service