5.three Remote Procedure Call¶

A mutual blueprint of communication used by application programs structured as a customer/server pair is the request/reply message transaction: A client sends a request message to a server, and the server responds with a reply bulletin, with the client blocking (suspending execution) to wait for the reply. Figure 137 illustrates the basic interaction between the customer and server in such an exchange.

../_images/f05-13-9780123850591.png

Figure 137. Timeline for RPC.

A send protocol that supports the request/reply paradigm is much more than a UDP message going in one management followed past a UDP bulletin going in the other direction. It needs to bargain with correctly identifying processes on remote hosts and correlating requests with responses. It may too need to overcome some or all of the limitations of the underlying network outlined in the problem statement at the get-go of this chapter. While TCP overcomes these limitations by providing a reliable byte-stream service, it doesn't perfectly lucifer the request/reply paradigm either. This section describes a third category of transport protocol, called Remote Process Call (RPC), that more than closely matches the needs of an application involved in a request/reply message exchange.

5.three.1 RPC Fundamentals¶

RPC is not technically a protocol—it is better thought of as a full general machinery for structuring distributed systems. RPC is popular considering it is based on the semantics of a local process telephone call—the application program makes a call into a procedure without regard for whether information technology is local or remote and blocks until the call returns. An awarding developer can exist largely unaware of whether the process is local or remote, simplifying his task considerably. When the procedures being chosen are actually methods of remote objects in an object-oriented language, RPC is known as remote method invocation (RMI). While the RPC concept is uncomplicated, at that place are ii main bug that go far more complicated than local procedure calls:

  • The network betwixt the calling process and the called procedure has much more circuitous properties than the backplane of a computer. For instance, information technology is likely to limit message sizes and has a tendency to lose and reorder letters.
  • The computers on which the calling and chosen processes run may have significantly different architectures and data representation formats.

Thus, a consummate RPC mechanism really involves two major components:

  1. A protocol that manages the letters sent betwixt the customer and the server processes and that deals with the potentially undesirable properties of the underlying network.
  2. Programming language and compiler support to package the arguments into a request bulletin on the client automobile so to interpret this message back into the arguments on the server machine, and as well with the return value (this piece of the RPC machinery is usually called a stub compiler).

Figure 138 schematically depicts what happens when a client invokes a remote process. First, the client calls a local stub for the process, passing it the arguments required past the procedure. This stub hides the fact that the procedure is remote by translating the arguments into a asking message and and so invoking an RPC protocol to send the request bulletin to the server machine. At the server, the RPC protocol delivers the request bulletin to the server stub, which translates it into the arguments to the procedure and then calls the local procedure. After the server procedure completes, it returns in a reply message that it easily off to the RPC protocol for transmission back to the customer. The RPC protocol on the customer passes this message upward to the client stub, which translates it into a render value that it returns to the client program.

../_images/f05-14-9780123850591.png

Effigy 138. Complete RPC machinery.

This section considers just the protocol-related aspects of an RPC mechanism. That is, information technology ignores the stubs and focuses instead on the RPC protocol, sometimes referred to equally a asking/answer protocol, that transmits messages between client and server. The transformation of arguments into messages and vice versa is covered elsewhere. It is besides important to keep in listen that the client and server programs are written in some programming language, significant that a given RPC machinery might support Python stubs, Java stubs, GoLang stubs, and then on, each of which includes language-specific idioms for how procedures are invoked.

The term RPC refers to a type of protocol rather than a specific standard like TCP, so specific RPC protocols vary in the functions they perform. And, different TCP, which is the dominant reliable byte-stream protocol, there is no i ascendant RPC protocol. Thus, in this section we will talk more than about alternative blueprint choices than previously.

Identifiers in RPC¶

Two functions that must be performed by whatever RPC protocol are:

  • Provide a name space for uniquely identifying the procedure to be called.
  • Match each respond message to the corresponding request message.

The first trouble has some similarities to the problem of identifying nodes in a network (something IP addresses do, for case). One of the blueprint choices when identifying things is whether to brand this name space flat or hierarchical. A flat proper name space would simply assign a unique, unstructured identifier (eastward.g., an integer) to each process, and this number would be carried in a single field in an RPC request message. This would require some kind of central coordination to avoid assigning the same process number to two unlike procedures. Alternatively, the protocol could implement a hierarchical name space, analogous to that used for file pathnames, which requires only that a file's "basename" be unique within its directory. This arroyo potentially simplifies the job of ensuring uniqueness of procedure names. A hierarchical name space for RPC could be implemented by defining a fix of fields in the asking message format, one for each level of naming in, say, a 2- or three-level hierarchical name space.

The key to matching a reply message to the corresponding asking is to uniquely place request-replies pairs using a message ID field. A reply bulletin had its bulletin ID field set to the same value as the request message. When the client RPC module receives the reply, it uses the message ID to search for the corresponding outstanding asking. To brand the RPC transaction appear like a local procedure call to the caller, the caller is blocked until the reply message is received. When the answer is received, the blocked caller is identified based on the request number in the reply, the remote process's render value is obtained from the reply, and the caller is unblocked and so that it can return with that return value.

One of the recurrent challenges in RPC is dealing with unexpected responses, and we see this with bulletin IDs. For example, consider the following pathological (only realistic) situation. A client machine sends a request message with a bulletin ID of 0, so crashes and reboots, and then sends an unrelated asking message, also with a message ID of 0. The server may not have been aware that the client crashed and rebooted and, upon seeing a asking message with a bulletin ID of 0, acknowledges it and discards it as a duplicate. The client never gets a response to the request.

One way to eliminate this problem is to use a boot ID. A machine'due south boot ID is a number that is incremented each time the machine reboots; this number is read from nonvolatile storage (due east.g., a disk or flash drive), incremented, and written dorsum to the storage device during the auto'southward outset-upward procedure. This number is then put in every message sent by that host. If a message is received with an sometime message ID but a new kicking ID, information technology is recognized as a new message. In effect, the message ID and kicking ID combine to form a unique ID for each transaction.

Overcoming Network Limitations¶

RPC protocols often perform additional functions to deal with the fact that networks are not perfect channels. 2 such functions are:

  • Provide reliable message delivery
  • Support big message sizes through fragmentation and reassembly

An RPC protocol might "ascertain this problem away" past choosing to run on top of a reliable protocol like TCP, but in many cases, the RCP protocol implements its own reliable message delivery layer on top of an unreliable substrate (e.g., UDP/IP). Such an RPC protocol would likely implement reliability using acknowledgments and timeouts, similarly to TCP.

The basic algorithm is straightforward, as illustrated by the timeline given in Figure 139. The customer sends a request message and the server acknowledges it. Then, subsequently executing the procedure, the server sends a respond message and the client acknowledges the reply.

../_images/f05-15-9780123850591.png

Figure 139. Simple timeline for a reliable RPC protocol.

Either a message carrying data (a asking message or a reply message) or the ACK sent to acknowledge that message may be lost in the network. To account for this possibility, both client and server save a re-create of each message they transport until an ACK for it has arrived. Each side also sets a RETRANSMIT timer and resends the message should this timer expire. Both sides reset this timer and try again some agreed-upon number of times earlier giving upwards and freeing the bulletin.

If an RPC client receives a respond message, clearly the corresponding asking message must have been received by the server. Hence, the respond bulletin itself is an implicit acknowledgment, and any additional acknowledgment from the server is not logically necessary. Similarly, a request message could implicitly admit the preceding reply message—assuming the protocol makes request-respond transactions sequential, so that 1 transaction must complete before the next begins. Unfortunately, this sequentiality would severely limit RPC performance.

A way out of this predicament is for the RPC protocol to implement a channel brainchild. Within a given aqueduct, asking/respond transactions are sequential—at that place can exist but one transaction agile on a given aqueduct at any given time—simply there can be multiple channels. Or said another way, the channel abstraction makes it possible to multiplex multiple RPC request/answer transactions between a client/server pair.

Each message includes a aqueduct ID field to indicate which channel the message belongs to. A request message in a given channel would implicitly acknowledge the previous reply in that aqueduct, if it hadn't already been acknowledged. An application program can open up multiple channels to a server if it wants to accept more than 1 request/reply transaction between them at the aforementioned time (the awarding would need multiple threads). As illustrated in Effigy 140, the respond message serves to acknowledge the request bulletin, and a subsequent request acknowledges the preceding reply. Notation that we saw a very like approach—called concurrent logical channels—in an earlier section as a style to improve on the performance of a stop-and-wait reliability mechanism.

../_images/f05-16-9780123850591.png

Figure 140. Timeline for a reliable RPC protocol using implicit acquittance.

Another complication that RPC must accost is that the server may accept an arbitrarily long time to produce the outcome, and, worse yet, it may crash before generating the reply. Go on in heed that we are talking about the catamenia of fourth dimension later on the server has acknowledged the request but before it has sent the respond. To help the client distinguish between a slow server and a expressionless server, the RPC's client side tin can periodically send an "Are you live?" bulletin to the server, and the server side responds with an ACK. Alternatively, the server could transport "I am all the same alive" messages to the client without the customer having first solicited them. The arroyo is more scalable because it puts more of the per-client burden (managing the timeout timer) on the clients.

RPC reliability may include the property known as at-almost-once semantics. This ways that for every request message that the customer sends, at most one re-create of that message is delivered to the server. Each fourth dimension the client calls a remote process, that procedure is invoked at most one time on the server car. We say "at about once" rather than "exactly once" because it is always possible that either the network or the server motorcar has failed, making it impossible to deliver fifty-fifty ane copy of the request message.

To implement at-most-once semantics, RPC on the server side must recognize duplicate requests (and ignore them), even if it has already successfully replied to the original request. Hence, information technology must maintain some state information that identifies past requests. One approach is to place requests using sequence numbers, so a server need but remember the most contempo sequence number. Unfortunately, this would limit an RPC to 1 outstanding request (to a given server) at a time, since ane request must be completed before the asking with the side by side sequence number tin can be transmitted. One time once more, channels provide a solution. The server could recognize indistinguishable requests by remembering the current sequence number for each channel, without limiting the client to ane request at a time.

As obvious as at-virtually-one time sounds, not all RPC protocols support this behavior. Some back up a semantics that is facetiously chosen zippo-or-more than semantics; that is, each invocation on a customer results in the remote procedure being invoked zero or more times. Information technology is non difficult to sympathize how this would cause problems for a remote process that changed some local state variable (e.g., incremented a counter) or that had some externally visible side effect (e.one thousand., launched a missile) each fourth dimension it was invoked. On the other hand, if the remote procedure being invoked is idempotent—multiple invocations accept the aforementioned issue as just one—then the RPC mechanism need not back up at-nearly-once semantics; a simpler (possibly faster) implementation volition suffice.

As was the case with reliability, the two reasons why an RPC protocol might implement message fragmentation and reassembly are that it is non provided by the underlying protocol stack or that it can be implemented more efficiently by the RPC protocol. Consider the case where RPC is implemented on top of UDP/IP and relies on IP for fragmentation and reassembly. If fifty-fifty ane fragment of a message fails to arrive within a certain amount of time, IP discards the fragments that did arrive and the bulletin is effectively lost. Eventually, the RPC protocol (assuming it implements reliability) would time out and retransmit the message. In contrast, consider an RPC protocol that implements its own fragmentation and reassembly and aggressively ACKs or NACKs (negatively acknowledges) individual fragments. Lost fragments would be more apace detected and retransmitted, and only the lost fragments would exist retransmitted, not the whole bulletin.

Synchronous versus Asynchronous Protocols¶

One way to characterize a protocol is by whether it is synchronous or asynchronous. The precise meaning of these terms depends on where in the protocol bureaucracy you utilise them. At the transport layer, it is most authentic to think of them as defining the extremes of a spectrum rather than as two mutually exclusive alternatives. The key attribute of any point forth the spectrum is how much the sending process knows after the performance to send a message returns. In other words, if we assume that an application programme invokes a send operation on a transport protocol, and then exactly what does the application know about the success of the operation when the ship operation returns?

At the asynchronous cease of the spectrum, the application knows absolutely zero when send returns. Not only does it not know if the message was received by its peer, only information technology doesn't fifty-fifty know for sure that the bulletin has successfully left the local motorcar. At the synchronous end of the spectrum, the ship operation typically returns a reply message. That is, the awarding not only knows that the bulletin it sent was received by its peer, only it also knows that the peer has returned an answer. Thus, synchronous protocols implement the request/reply brainchild, while asynchronous protocols are used if the sender wants to be able to transmit many messages without having to wait for a response. Using this definition, RPC protocols are usually synchronous protocols.

Although we take not discussed them in this chapter, at that place are interesting points betwixt these two extremes. For instance, the send protocol might implement transport so that it blocks (does not render) until the message has been successfully received at the remote car, but returns before the sender's peer on that machine has actually candy and responded to information technology. This is sometimes called a reliable datagram protocol.

v.3.2 RPC Implementations (SunRPC, DCE, gRPC)¶

We now turn our give-and-take to some example implementations of RPC protocols. These will serve to highlight some of the different blueprint decisions that protocol designers accept made. Our first example is SunRPC, a widely used RPC protocol also known as Open up Network Computing RPC (ONC RPC). Our second instance, which we volition refer to every bit DCE-RPC, is part of the Distributed Computing Environment (DCE). DCE is a set of standards and software for building distributed systems that was defined past the Open Software Foundation (OSF), a consortium of estimator companies that originally included IBM, Digital Equipment Corporation, and Hewlett-Packard; today, OSF goes by the name The Open up Group. Our third example is gRPC, a popular RPC mechanism that Google has open sourced, based on an RPC mechanism that they have been using internally to implement cloud services in their datacenters.

These three examples represent interesting alternative design choices in the RPC solution space, but lest you retrieve they are the just options, nosotros describe 3 other RPC-like mechanisms (WSDL, Soap, and REST) in the context of spider web services in Affiliate 9.

SunRPC¶

SunRPC became a de facto standard thank you to its wide distribution with Sun workstations and the central function it plays in Sun's popular Network File System (NFS). The IETF subsequently adopted information technology equally a standard Internet protocol under the proper name ONC RPC.

SunRPC can be implemented over several different transport protocols. Figure 141 illustrates the protocol graph when SunRPC is implemented on UDP. As we noted before in this section, a strict layerist might frown on the idea of running a send protocol over a transport protocol, or debate that RPC must exist something other than a send protocol since it appears "higher up" the send layer. Pragmatically, the design decision to run RPC over an existing ship layer makes quite a lot of sense, as will be apparent in the post-obit discussion.

../_images/f05-17-9780123850591.png

Effigy 141. Protocol graph for SunRPC on elevation of UDP.

SunRPC uses two-tier identifiers to identify remote procedures: a 32-bit program number and a 32-flake procedure number. (There is also a 32-bit version number, but nosotros ignore that in the following discussion.) For example, the NFS server has been assigned program number x00100003 , and within this programme getattr is procedure 1 , setattr is procedure 2 , read is procedure half-dozen , write is process viii , and so on. The plan number and procedure number are transmitted in the SunRPC request message's header, whose fields are shown in Figure 142. The server—which may support several plan numbers—is responsible for calling the specified procedure of the specified program. A SunRPC asking really represents a request to call the specified program and procedure on the item motorcar to which the asking was sent, fifty-fifty though the same program number may be implemented on other machines in the same network. Thus, the address of the server'due south machine (due east.g., an IP address) is an implicit tertiary tier of the RPC address.

../_images/f05-18-9780123850591.png

Effigy 142. SunRPC header formats: (a) request; (b) respond.

Different program numbers may belong to different servers on the same auto. These different servers accept unlike ship layer demux keys (e.g., UDP ports), most of which are not well-known numbers but instead are assigned dynamically. These demux keys are chosen transport selectors. How can a SunRPC client that wants to talk to a particular program determine which transport selector to use to attain the corresponding server? The solution is to assign a well-known address to only ane programme on the remote machine and permit that program handle the job of telling clients which transport selector to use to reach any other program on the machine. The original version of this SunRPC program is called the Port Mapper, and information technology supports simply UDP and TCP as underlying protocols. Its program number is x00100000 , and its well-known port is 111 . RPCBIND, which evolved from the Port Mapper, supports capricious underlying transport protocols. Equally each SunRPC server starts, it calls an RPCBIND registration procedure, on the server's own home automobile, to register its transport selector and the plan numbers that it supports. A remote client can then call an RPCBIND lookup procedure to look upward the transport selector for a particular programme number.

To make this more physical, consider an example using the Port Mapper with UDP. To send a request bulletin to NFS'due south read procedure, a customer start sends a request message to the Port Mapper at well-known UDP port 111 , request that procedure 3 be invoked to map plan number x00100003 to the UDP port where the NFS program currently resides. The client then sends a SunRPC request message with program number x00100003 and procedure number half dozen to this UDP port, and the SunRPC module listening at that port calls the NFS read process. The client also caches the plan-to-port number mapping and then that it need not become back to the Port Mapper each time it wants to talk to the NFS plan.[ane]

[1] In exercise, NFS is such an important program that it has been given its ain well-known UDP port, but for the purposes of analogy we're pretending that's not the case.

To friction match upward a reply message with the corresponding request, then that the result of the RPC can be returned to the correct caller, both request and reply message headers include a XID (transaction ID) field, as in Figure 142. A XID is a unique transaction ID used only by one request and the corresponding reply. After the server has successfully replied to a given asking, it does not remember the XID . Because of this, SunRPC cannot guarantee at-most-one time semantics.

The details of SunRPC's semantics depend on the underlying transport protocol. Information technology does not implement its own reliability, and so it is merely reliable if the underlying transport is reliable. (Of course, any application that runs over SunRPC may likewise cull to implement its own reliability mechanisms above the level of SunRPC.) The power to send asking and reply letters that are larger than the network MTU is also dependent on the underlying transport. In other words, SunRPC does not make whatever attempt to ameliorate on the underlying transport when it comes to reliability and message size. Since SunRPC tin run over many dissimilar send protocols, this gives it considerable flexibility without complicating the design of the RPC protocol itself.

Returning to the SunRPC header format of Effigy 142, the request bulletin contains variable-length Credentials and Verifier fields, both of which are used by the client to authenticate itself to the server—that is, to give bear witness that the client has the correct to invoke the server. How a client authenticates itself to a server is a full general issue that must be addressed by any protocol that wants to provide a reasonable level of security. This topic is discussed in more than particular in another affiliate.

DCE-RPC¶

DCE-RPC is the RPC protocol at the core of the DCE system and was the basis of the RPC mechanism underlying Microsoft'southward DCOM and ActiveX. Information technology can exist used with the Network Information Representation (NDR) stub compiler described in another chapter, but it also serves as the underlying RPC protocol for the Common Object Request Banker Architecture (CORBA), which is an manufacture-wide standard for building distributed, object-oriented systems.

DCE-RPC, like SunRPC, can be implemented on top of several ship protocols including UDP and TCP. It is likewise similar to SunRPC in that it defines a two-level addressing scheme: the transport protocol demultiplexes to the right server, DCE-RPC dispatches to a particular procedure exported by that server, and clients consult an "endpoint mapping service" (similar to SunRPC's Port Mapper) to acquire how to attain a particular server. Different SunRPC, notwithstanding, DCE-RPC implements at-most-once call semantics. (In truth, DCE-RPC supports multiple telephone call semantics, including an idempotent semantics like to SunRPC's, but at-most-one time is the default beliefs.) There are some other differences between the two approaches, which we volition highlight in the following paragraphs.

../_images/f05-19-9780123850591.png

Figure 143. Typical DCE-RPC message exchange.

Effigy 143 gives a timeline for the typical commutation of messages, where each bulletin is labeled by its DCE-RPC type. The client sends a Request message, the server eventually replies with a Response bulletin, and the customer acknowledges ( Ack ) the response. Instead of the server acknowledging the asking messages, however, the client periodically sends a Ping message to the server, which responds with a Working message to bespeak that the remote procedure is all the same in progress. If the server's reply is received reasonably speedily, no Ping s are sent. Although not shown in the figure, other message types are also supported. For case, the customer tin send a Quit message to the server, request it to abort an earlier telephone call that is still in progress; the server responds with a Quack (quit acknowledgment) message. As well, the server can answer to a Request message with a Reject message (indicating that a call has been rejected), and it can respond to a Ping message with a Nocall message (indicating that the server has never heard of the caller).

Each request/reply transaction in DCE-RPC takes identify in the context of an activity. An activity is a logical request/reply channel between a pair of participants. At whatsoever given fourth dimension, there tin can exist only one message transaction active on a given channel. Similar the concurrent logical channel approach described above, the application programs have to open multiple channels if they desire to have more than 1 request/answer transaction betwixt them at the same time. The activeness to which a message belongs is identified by the bulletin's ActivityId field. A SequenceNum field then distinguishes between calls made as part of the same action; it serves the same purpose as SunRPC'southward XID (transaction id) field. Dissimilar SunRPC, DCE-RPC keeps track of the last sequence number used every bit part of a particular activity, so as to ensure at-virtually-once semantics. To distinguish between replies sent earlier and afterward a server machine reboots, DCE-RPC uses a ServerBoot field to hold the machine's kicking ID.

Another blueprint choice made in DCE-RPC that differs from SunRPC is the back up of fragmentation and reassembly in the RPC protocol. Equally noted higher up, fifty-fifty if an underlying protocol such as IP provides fragmentation/reassembly, a more than sophisticated algorithm implemented as role of RPC can result in quicker recovery and reduced bandwidth consumption when fragments are lost. The FragmentNum field uniquely identifies each fragment that makes upwardly a given request or reply message. Each DCE-RPC fragment is assigned a unique fragment number (0, 1, ii, 3, and then on). Both the client and server implement a selective acknowledgment mechanism, which works as follows. (Nosotros draw the mechanism in terms of a client sending a fragmented request message to the server; the aforementioned machinery applies when a server sends a fragment response to the client.)

First, each fragment that makes upward the request message contains both a unique FragmentNum and a flag indicating whether this packet is a fragment of a call ( frag ) or the concluding fragment of a call (); request messages that fit in a single packet carry a flag. The server knows information technology has received the consummate request message when it has the packet and at that place are no gaps in the fragment numbers. Second, in response to each arriving fragment, the server sends a Fack (fragment acknowledgment) message to the client. This acknowledgment identifies the highest fragment number that the server has successfully received. In other words, the acknowledgment is cumulative, much like in TCP. In add-on, nonetheless, the server selectively acknowledges whatever higher fragment numbers it has received out of order. It does so with a scrap vector that identifies these out-of-club fragments relative to the highest in-order fragment it has received. Finally, the client responds past retransmitting the missing fragments.

Effigy 144 illustrates how this all works. Suppose the server has successfully received fragments up through number 20, plus fragments 23, 25, and 26. The server responds with a Fack that identifies fragment 20 as the highest in-order fragment, plus a chip-vector ( SelAck ) with the third (23=xx+iii), 5th (25=20+five), and sixth (26=20+half-dozen) $.25 turned on. So every bit to back up an (almost) arbitrarily long bit vector, the size of the vector (measured in 32-chip words) is given in the SelAckLen field.

../_images/f05-20-9780123850591.png

Figure 144. Fragmentation with selective acknowledgments.

Given DCE-RPC's back up for very big messages—the FragmentNum field is 16 bits long, meaning information technology can back up 64K fragments—it is not appropriate for the protocol to boom all the fragments that brand up a message as fast as it tin can since doing and so might overrun the receiver. Instead, DCE-RPC implements a flow-control algorithm that is very similar to TCP's. Specifically, each Fack bulletin not merely acknowledges received fragments but besides informs the sender of how many fragments it may at present send. This is the purpose of the WindowSize field in Effigy 144, which serves exactly the aforementioned purpose every bit TCP'due south AdvertisedWindow field except it counts fragments rather than bytes. DCE-RPC as well implements a congestion-command mechanism that is similar to TCP's. Given the complexity of congestion control, it is mayhap not surprising that some RPC protocols avoid it by avoiding fragmentation.

In summary, designers have quite a range of options open to them when designing an RPC protocol. SunRPC takes the more minimalist approach and adds relatively little to the underlying send beyond the essentials of locating the right process and identifying messages. DCE-RPC adds more functionality, with the possibility of improved operation in some environments at the cost of greater complexity.

gRPC¶

Despite its origins in Google, gRPC does non stand for Google RPC. The "grand" stands for something different in each release. For version one.10 it stood for "glamorous" and for 1.18 it stood for "goose". Googlers are wild and crazy people. Nonetheless, gRPC is pop because it makes available to everyone—as open up source—a decade'south worth of experience inside Google using RPC to build scalable cloud services.

Before getting into the details, there are some major differences between gRPC and the other ii examples we've simply covered. The biggest is that gRPC is designed for cloud services rather than the simpler client/server epitome that preceded it. The difference is essentially an actress level of indirection. In the client/server world, the customer invokes a method on a specific server process running on a specific server machine. One server process is presumed to be enough to serve calls from all the customer processes that might telephone call it.

With cloud services, the client invokes a method on a service, which in gild to back up calls from arbitrarily many clients at the same time, is implemented by a scalable number of server processes, each potentially running on a different server car. This is where the cloud comes into play: datacenters make a seemingly infinite number of server machines available to calibration up cloud services. When we employ the term "scalable" we mean that the number of identical server processes yous elect to create depends on the workload (i.eastward., the number of clients that want service at any given time) and that number can be adjusted dynamically over fourth dimension. One other particular is that cloud services don't typically create a new process, per se, merely rather, they launch a new container, which is essentially a process encapsulated inside an isolated surround that includes all the software packages the process needs to run. Docker is today's canonical example of a container platform.

../_images/Slide13.png

Effigy 145. Using RPC to invoke a scalable cloud service.

Back to the merits that a service is essentially an actress level of indirection layered on top of a server, all this ways is that the caller identifies the service information technology wants to invoke, and a load balancer directs that invocation to 1 of the many available server processes (containers) that implement that service, as shown in Figure 145. The load balancer tin can exist implemented in dissimilar means, including a hardware device, but information technology is typically implemented by a proxy procedure that runs in a virtual machine (as well hosted in the deject) rather than every bit a physical appliance.

There is a set of best practices for implementing the actual server code that eventually responds to that asking, and some additional cloud machinery to create/destroy containers and load remainder requests beyond those containers. Kubernetes is today'southward canonical case of such a container management organisation, and the micro-services architecture is what nosotros call the best practices in edifice services in this deject native manner. Both are interesting topics, just beyond the scope of this book.

What we are interested in here is send protocol at the core of gRPC. Hither again, there is a major divergence from the two previous instance protocols, not in terms of fundamental bug that need to be addressed, merely in terms of gRPC's approach to addressing them. In short, gRPC "outsources" many of the problems to other protocols, leaving gRPC to essentially bundle those capabilities in an easy-to-use form. Let'due south expect at the details.

Commencement, gRPC runs on superlative of TCP instead of UDP, which means it outsources the problems of connection direction and reliably transmitting request and answer messages of arbitrary size. Second, gRPC actually runs on top of a secured version of TCP called Transport Layer Security (TLS)—a thin layer that sits to a higher place TCP in the protocol stack—which means information technology outsources responsibility for securing the advice channel so adversaries can't eavesdrop or hijack the bulletin commutation. 3rd, gRPC actually, actually runs on top of HTTP/2 (which is itself layered on top of TCP and TLS), meaning gRPC outsources yet two other problems: (i) efficiently encoding/compressing binary information into a bulletin, (2) multiplexing multiple remote procedure calls onto a single TCP connection. In other words, gRPC encodes the identifier for the remote method equally a URI, the request parameters to the remote method equally content in the HTTP message, and the return value from the remote method in the HTTP response. The full gRPC stack is depicted in Effigy 146, which besides includes the linguistic communication-specific elements. (1 forcefulness of gRPC is the wide set of programming languages information technology supports, with merely a pocket-size subset shown in Figure 146.)

../_images/Slide21.png

Figure 146. gRPC core stacked on summit of HTTP, TLS, and TCP and supporting a drove of languages.

We hash out TLS in Chapter eight (in the context of a wide range of security topics) and HTTP in Chapter 9 (in the context of what are traditionally viewed as application level protocols). But nosotros find ourselves in an interesting dependency loop: RPC is a flavour of ship protocol used to implement distributed applications, HTTP is an example of an awarding-level protocol, and withal gRPC runs on acme of HTTP rather than the other way around.

The brusque caption is that layering provides a convenient way for humans to wrap their heads around circuitous systems, only what we're really trying to do is solve a set of problem (e.g., reliably transfer messages of arbitrary size, identify senders and recipients, match requests messages with respond letters, and so on) and the way these solutions get bundled into protocols, and those protocols then layered on elevation of each other, is the consequence of incremental changes over fourth dimension. Yous could argue it's an historical blow. Had the Net started with an RPC mechanism as ubiquitous as TCP, HTTP might have been implemented on superlative of it (as might have well-nigh all of the other application-level protocols described in Chapter 9) and Google would accept spent their time improving that protocol rather than inventing one of their ain (every bit they and others have been doing with TCP). What happened instead is that the web became the Net'southward killer app, which meant that its application protocol (HTTP) became universally supported by the rest of the Cyberspace's infrastructure: Firewalls, Load Balancers, Encryption, Authentication, Compression, and and then on. Because all of these network elements have been designed to work well with HTTP, HTTP has effectively become the Cyberspace'southward universal request/reply transport protocol.

Returning to the unique characteristics of gRPC, the biggest value it brings to the table is to contain streaming into the RPC mechanism, which is to say, gRPC supports four different asking/answer patterns:

  1. Elementary RPC: The client sends a single request bulletin and the server responds with a single reply message.
  2. Server Streaming RPC: The client sends a single asking bulletin and the server responds with a stream of respond messages. The client completes one time it has all the server's responses.
  3. Client Streaming RPC: The client sends a stream of requests to the server, and the server sends back a unmarried response, typically (but non necessarily) afterwards it has received all the customer's requests.
  4. Bidirectional Streaming RPC: The telephone call is initiated past the customer, but afterward that, the client and server tin can read and write requests and responses in any guild; the streams are completely independent.

This extra freedom in how the client and server interact means the gRPC send protocol needs to transport additional metadata and control messages—in addition to the actual request and reply letters—between the two peers. Examples include Error and Status codes (to indicate success or why something failed), Timeouts (to betoken how long a customer is willing to look for a response), PING (a go on-alive notice to indicate that i side or the other is yet running), EOS (cease-of-stream observe to indicate that there are no more requests or responses), and GOAWAY (a find from servers to clients to signal that they will no longer accept any new streams). Unlike many other protocols in this volume, where nosotros show the protocol's header format, the mode this control data gets passed between the two sides is largely dictated by the underlying transport protocol, in this case HTTP/two. For example, every bit we'll see in Affiliate 9, HTTP already includes a set of header fields and respond codes that gRPC takes advantage of.

You may want to peruse the HTTP discussion in Chapter ix before continuing, but the following is fairly straightforward. A simple RPC asking (with no streaming) might include the following HTTP message from the client to the server:

                    HEADERS (flags = END_HEADERS) :method = Postal service :scheme = http :path = /google.pubsub.v2.PublisherService/CreateTopic :authority = pubsub.googleapis.com grpc-timeout = 1S content-type = awarding/grpc+proto grpc-encoding = gzip authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v Data (flags = END_STREAM)                    <                    Length-Prefixed                    Message                    >                  

leading to the post-obit response message from the server back to the customer:

                    HEADERS (flags = END_HEADERS) :status = 200 grpc-encoding = gzip content-type = awarding/grpc+proto Information                    <                    Length-Prefixed                    Message                    >                    HEADERS (flags = END_STREAM, END_HEADERS) grpc-status = 0 # OK trace-proto-bin = jher831yy13JHy3hc                  

In this example, HEADERS and DATA are ii standard HTTP control messages, which finer delineate between "the message'south header" and "the message's payload." Specifically, each line following HEADERS (simply before DATA ) is an attribute = value pair that makes upwards the header (think of each line as analogous to a header field); those pairs that start with colon (e.g., :status = 200 ) are part of the HTTP standard (e.thousand., status 200 indicates success); and those pairs that practise not starting time with a colon are gRPC-specific customizations (east.k., grpc-encoding = gzip indicates that the data in the message that follows has been compressed using gzip , and grpc-timeout = 1S indicates that the client has set a 1 2d timeout).

There is one terminal slice to explain. The header line

                    content-type = awarding/grpc+proto                  

indicates that the message body (as demarcated by the DATA line) is meaningful only to the application programme (i.e., the server method) that this client is requesting service from. More specifically, the +proto cord specifies that the recipient volition be able to interpret the bits in the bulletin according to a Protocol Buffer (abbreviated proto ) interface specification. Protocol Buffers are gRPC's way of specifying how the parameters existence passed to the server are encoded into a message, which is in turn used to generate the stubs that sit between the underlying RPC mechanism and the actual functions existence called (see Figure 138). This is a topic nosotros'll take up in Affiliate 7.

Key Takeaway

The bottom line is that complex mechanisms like RPC, once packaged as a monolithic parcel of software (as with SunRPC and DCE-RPC), is nowadays congenital by assembling an assortment of smaller pieces, each of which solves a narrow problem. gRPC is both an example of that arroyo, and a tool that enables further adoption of the approach. The micro-services compages mentioned earlier in this subsection applies the "built from pocket-size parts" strategy to unabridged cloud applications (eastward.g., Uber, Lyft, Netflix, Yelp, Spotify), where gRPC is oftentimes the communication mechanism used by those small pieces to commutation letters with each other. [Next]