Implementing Remote Procedure Calls =================================== Andrew Birrell and Bruce Nelson, ACM TOCS, 1984. Big picture: Title says all. ----------- A very well written paper (reminds me of the LFS paper for clarity). Goals of RPC facility --------------------- - Make distributed computation easy: Provide a communication abstraction that eases development of dist. apps. Developers should not be encumbered by details pertaining to communication. - Clean+simple yet powerful semantics: To the end user, it should appear as if it's a local procedure call. The network should be "hidden". However, RPC semantics should be general enough to support a wide class of apps. - Efficiency. Details ------- - Stubs: When making a remote call, five components are involved: User program, user-stub, RPC-Runtime, server-stub, server program. To make a remote procedure call, user programs invokes a local procedure which actually is a stub. The stub is responsible for "marshalling" arguments, packaging them, creating packets and asking RPC-Runtime to transmit them reliably to the server. On receipt of these packets, RPC-Runtime on server m/c unpacks them and invokes an appropriate server procedure. The calling process is suspended. When the server procedure returns, it invokes the server RPC-Runtime to return results in a similar fashion. Stubs are automatically created by a program called "Lupine". Stub generation is straightforward. Lupine just requires an interface definition file to create a stub library which a user program can link to. - RPC-Runtime is responsible for retransmissions, acks, routing, encryption, name lookup and binding. RPC-Runtime takes care of the tricky communication related code. This makes a programmer's job very easy. All she needs to do is to create the interface definition files and then write the client/server code. - Naming, Location and Binding: A server who wishes to export an interface, publishes its service name at a (replicated) directory server (called Grapevine). The service name is usually a simple string (e.g., "mail server"). RPC or the directory server does not recognize any semantics associated with such strings. Not everybody can become a server. Grapevine provides access controls. Servers can be replicated. For each service name, the directory server (Grapevine) maintains a list of transport-layer end-points (e.g., ip+port for UDP) which export that service. After the RPC-Runtime at an interface-exporter (server) has registered itself with Grapevine, it records this export at a local table which contains the interface-name, the dispatcher procedure call and a 32-bit value that serves as a permanently unique (machine-relative) id of the export. [The 32-bit value plays a role: server crashes]. When an interface-importer (client) invokes a remote procedure, the RPC-Runtime firts queries Grapevine to locate one/several servers. It then contacts the server(s) who return the unique id and the local table index associated with this interface. The client thereafter remembers the exporter's address, unique id and table index for future calls. Transport Layer Protocol Details -------------------------------- - RPC comes with its own transport-layer protocol. This is because traditional protocols are geared towards byte-streams for large file transfer (TCP style). RPC communication style is "request-response". - Goal: Minimize the elapsed real-time between call invokation and return. Semantics: If the call returns to the user, then the procedure has been invoked precisely once. If an exception is reported, the procedure has been invoked once or none at all: there is no way to distinguish between a server-crash and a communication-failure. - To make a call, the caller sends a call-packet. The server responds with the results. Both packets contain a "call id" which uniquely identifies this call. Retransmissions: The caller retransmits to compensate for lost packets. However, the result of a call is an ack for the previous call pkt. And a call pkt is an ack for the previous result. However, a retransmission warrants an explicit acknowledgement. This happens if there's a lost packet, or if the call is very long at the server. - Issues: Any client has at most one outstanding RPC. The server RPC-Runtime maintains a table which records the last "call id" for each client. This allows it to ignore duplicates. The "call id" is monotonically increasing. However, this "state" for a client is not maintained for a long time at the server. It is discarded when an ack is received for the last result sent. Only one buffer per client is required at the server as only one outstanding call per client is allowed. Receipt of a call pkt from a previously unknown client is sufficient to create a connection implicitly. There is no three-way TCP-style handshake for connection establishment. Similarly, lack of a new call pkt is assumed to terminate a connection. Teardown is cheap. - Long arguments: Sent in multiple packets, each of which requires an explicit ack. This results in a very inefficient protocol if the arguments are really big. A TCP-style protocol with flow-control and buffering might help. - Exception handling: The server can send an 'exception' packet in place of a result packet in case the server routine experiences an exception. The client RPC-Runtime then checks to see if there's an appropriate catch phrase and raises an exception. This mechanism is supported by their programming language Mesa. - Optimization: For efficienty, the network layers were bypassed to communicate directly with Ethernet NIC. Broadcast could be used in LAN's for discovering servers (instead of RPC to communicate with Grapevine). - Security: The paper refers to another paper that talks about their security architecture. Discussion: - Pg 292 says "There are certain circumstances in which RPC seems to be the wrong communication paradigm". These correspond to situations where multicasting/broadcasting seems more natural. What are multicasting abstractions? Cornell's Horus comes to mind. I dont know much abt it. What's "group communication"? - Were RPC-style-small-request-response and TCP-style-large-data-transfer integrated in later protocols? Isn't passing large parameters still an issue in CORBA?