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