Remote Procedure Call (RPC)
In this lesson, we look at a programming language abstraction, RPC, to provide the basis for building distributed systems.
We'll cover the following...
While OS abstractions turned out to be a poor choice for building distributed systems, programming language (PL) abstractions make much more sense. The most dominant abstraction is based on the idea of a
Remote procedure call packages all have a simple goal: to make the process of executing code on a remote machine as simple and straightforward as calling a local function. Thus, to a client, a procedure call is made, and sometime later, the results are returned. The server simply defines some routines that it wishes to export. The rest of the magic is handled by the RPC system, which in general has two pieces: a stub generator (sometimes called a protocol compiler), and the run-time library. We’ll now take a look at each of these pieces in more detail.
Stub generator
The stub generator’s job is simple: to remove some of the pain of packing function arguments and results in messages by automating it. Numerous benefits arise: one avoids, by design, the simple mistakes that occur in writing such code by hand. Further, a stub compiler can perhaps optimize such code and thus improve performance.
The input to such a compiler is simply the set of calls a server wishes to export to clients. Conceptually, it could be something as simple as this:
interface {int func1(int arg1);int func2(int arg1, int arg2);};
The stub generator takes an interface like this and generates a few different pieces of code. For the client, a client stub is generated, which contains each of the functions specified in the interface; a client program wishing to use this RPC service would link with this client stub and call into it in order to make RPCs.
Internally, each of these functions in the client stub does all of the work needed to perform the remote procedure call. To the client, the code just appears as a function call (e.g., the client calls func1(x)
); internally, the code in the client stub for func1()
does this:
-
Create a message buffer. A message buffer is usually just a contiguous array of bytes of some size.
-
Pack the needed information into the message buffer. This information includes some kind of identifier for the function to be called, as well as all of the arguments that the function needs (e.g., in our example above, one integer for
func1
). The process of putting all of this information into a single contiguous buffer is sometimes referred to as the marshaling of arguments or the serialization of the message. -
Send the ...