|
|
Subscribe / Log in / New account

Building HTTP/2 services with gRPC

By Nathan Willis
March 11, 2015
Google recently released a new remote procedure call (RPC) framework that is designed to supplant traditional representational state transfer (REST) in the development of web applications. Called gRPC (which the FAQ defines as "gRPC Remote Procedure Calls"), the new framework takes advantage of several features in the recently approved HTTP/2 standard that the project claims will result in better performance and greater flexibility than REST APIs. Implementations are available—for both client- and server-side code—in a variety of programming languages.

The basic idea behind gRPC is quite similar to that used by the RESTful services that make up so many web applications today. The methods of the server application are accessible to clients through a well-defined set of HTTP requests. The server answers each of these calls with an HTTP response (or, if necessary, an error code). But gRPC dispenses with HTTP 1.1, relying strictly on HTTP/2—and thus, the project claims, gaining considerable performance.

gRPC was announced in a February 26 blog post. The post described gRPC as enabling "highly performant, scalable APIs and microservices" and said that Google is starting to expose gRPC endpoints to its own services. It also said that other companies have been involved in the creation of gRPC, naming mobile-payment processor Square as one example. Square posted an account of its own that explains some of the background. Both of the posts highlight a few key features that are enabled by building on top of HTTP/2—namely, bidirectional streaming, multiplexed connections, flow control, and HTTP header compression.

Those improvements, of course, would be available to any RPC framework using HTTP/2. As for gRPC itself, it is built on top of Google's protocol buffers, which was updated to version 3.0 (a.k.a. "proto3") in conjunction with the gRPC release. Proto3 is largely a stripped-down version of proto2: multiple fields have been removed, including several that were required in proto2 or that had required default values, and the extension mechanism has been replaced with a simple Any standard type that can hold. Proto3 also adds standard types for times and dates and for dynamic data, plus bindings for Ruby and JavaNano (an Android-centric Java library optimized for low-resource systems).

gRPC uses protocol buffers to serialize and deserialize its over-the-wire messages. Employing that technique leverages HTTP/2's binary wire format, allowing for more efficient RPC traffic than HTTP 1.1's ASCII encoding. But gRPC also uses proto3's interface definition language (IDL) to specify the structure and the content that a web service's RPC messages will take.

To get started, the application developer writes a schema for the new web service, defining each of the requests and the possible responses that the service will use. The protocol buffers compiler (protoc) can then be used to generate classes and stub code (for client and server) from the schema, in any of the supported languages. At launch time, the available languages were Python, C++, C#, Objective-C, PHP, Ruby, Go, Java (both in generic and Android flavors), and JavaScript tailored to use with Node.js.

Quick-start guides are available for most of the languages (C#, Objective-C, and PHP guides are absent at the moment). Each of these tutorials begins with the same basic service definition:

    syntax = "proto2";

    // The greeting service definition.
    service Greeter {
      // Sends a greeting
      rpc SayHello (HelloRequest) returns (HelloReply) {}
    }

    // The request message containing the user's name.
    message HelloRequest {
      string name = 1;
    }

    // The response message containing the greetings
    message HelloReply {
      string message = 1;
    }

One side point is worth noting: for reasons that are not explained, the project's Python tutorial does, indeed, specify proto2 syntax rather than proto3. For the simple "Hello World" example used, proto2 and proto3 syntax are identical (which is visible when comparing it with the Java and Go tutorials), but the generated code does leave some artifacts behind, in the _pb2 portion of the module name.

The output language of protoc compiler is specified with a command-line switch. Using --python_out, for example, generates a helloworld_pb2 module, a stub function called SayHello() for the client, and a Greeter class for the server that includes a stub function to respond to the SayHello() message as well as a simple serve() function that waits for incoming messages.

By using an abstract IDL, the argument goes, developers can quickly generate client code for a variety of different platforms, both desktop- and mobile-oriented. gRPC also makes it easy to include a version number in each message-format definition, so that clients and servers can support interoperability across versions.

The project has a detailed description of how gRPC's messages are sent in HTTP/2 frames. This is where some of HTTP/2's other advantages over HTTP 1.1 come into play.

For example, whenever an endpoint (client or server) sends a message, it can choose to keep the stream open, so that it can be used for bi-directional communication for the remainder of the session. gRPC uses HTTP/2's stream IDs as its internal identifiers for RPC calls, so the mapping between the RPC call and its associated stream comes for free. Multiplexing several open streams over one connection is another way that HTTP/2 enables more efficient use of the available bandwidth; it is up to the developer to determine how many active streams make sense for the service.

gRPC also piggybacks on HTTP/2 for its error codes. That allows the application to pick up on HTTP/2 error conditions (such as one endpoint of the stream throttling the connection) with little additional effort. Finally, gRPC is designed to support pluggable authentication methods; TLS 1.2 (or greater) and OAuth 2.0 are supported so far.

Where gRPC heads from here, naturally, remains to be seen. It is certainly a straightforward enough framework to warrant closer examination, and there will, no doubt, be many developers interested in seeing how they can take advantage of HTTP/2's promised improvements over HTTP 1.1.

That said, HTTP/2 is still in its infancy—one should expect to see a wide array of new frameworks announced in the next few years, all claiming to leverage the new protocol for a range of enhanced features. gRPC may be one of the first, but only time will tell how many developers outside of Google and its partners find it a good fit.


to post comments

Building HTTP/2 services with gRPC

Posted Mar 12, 2015 15:41 UTC (Thu) by adamgundy (subscriber, #5418) [Link] (8 responses)

thanks for the article.. but to me it sounds like CORBA and/or DCOM all over again. fine grained RPCs don't work well over the WAN. that's why REST APIs tend to be much more 'bulk data' oriented.

Building HTTP/2 services with gRPC

Posted Mar 12, 2015 15:59 UTC (Thu) by osma (subscriber, #6912) [Link] (7 responses)

My thoughts too. I'm not sure we need another RPC protocol. This sounds an awful lot like SOAP, which almost nobody liked.

REST is nice in so many ways. It is easy to start working with even just from a browser: an API is just URLs and (typically) JSON data. Most methods work with GET requests so you can use standard HTTP caching. And it's completely implementation language agnostic, no need for bindings of any kind.

Obviously gRPC may perform better than REST due to the compression, binary protocol etc. but I think HTTP/2 techniques could be used with standard REST as well so you could get most of the benefits without the downsides of an RPC paradigm. A binary protocol should be opt-in with something saner (probably JSON) as the default.

Building HTTP/2 services with gRPC

Posted Mar 12, 2015 16:44 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link] (6 responses)

REST is horrible. It's a quick-and-dirty way to write a simple RPC (and let's not kid ourselves, that's what REST is used for 99% of time) but once you want to do something complex - you're on your own.

For example, there's no standard way to specify idempotency tokens so each service reinvents the wheel. If the authors even remember to think about it.

Dealing with errors is also abysmal. Apart from a misuse of the transport-level error code - you're on your own.

Then there's a question of streaming (there is none) and of timeouts (ditto).

So personally I prefer a good RPC implementation to a morass of pseudo-REST ad-hoc APIs. CORBA and DCOM were bad but not because REST is somehow more 'bulk-oriented' or more 'web-scale'.

Building HTTP/2 services with gRPC

Posted Mar 12, 2015 20:12 UTC (Thu) by osma (subscriber, #6912) [Link] (5 responses)

We seem to disagree on the usefulness of the RPC paradigm. For me, REST is not about RPC. It's about data-oriented services. If you use REST for RPC, you're doing it wrong - or at least stretching it in a direction where it's likely not the best tool for the job.

I agree that REST is not perfect. There are issues like error codes you mention. There is best practice which may help somewhat but not everyone follows it.

Building HTTP/2 services with gRPC

Posted Mar 12, 2015 23:59 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link] (4 responses)

REST is most certainly about RPC in the real-world practice.

It might make a lot of noises about how it's used to access complicated objects using path-like structures, but in reality it's almost always used for classic synchronous RPC calls.

For example, http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API... - and this is called REST API for some reason.

In most APIs about the only nod to REST-fullness is a syntax to get individual objects out of collections: "some/blah/objects" and "some/blah/objects/<id>".

Building HTTP/2 services with gRPC

Posted Mar 13, 2015 8:42 UTC (Fri) by osma (subscriber, #6912) [Link] (3 responses)

> For example, http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API... - and this is called REST API for some reason.

Ouch. That's certainly not following 90% of REST best practice. Starting from the fact that they use GET requests for things that obviously change the server state.

Though I don't see AWS calling it a REST API anywhere (searched the documentation). The closest that I found was this:

> The Amazon EC2 Query API provides HTTP or HTTPS requests that use the HTTP verb GET or POST and a Query parameter named Action.

-- http://docs.aws.amazon.com/AWSEC2/latest/APIReference/mak...

It appears that AWS has migrated their earlier SOAP API to work directly with simple HTTP requests, without the SOAP overhead and complexity. That's not REST, that's just a form of ad-hoc RPC over HTTP. So maybe there's a niche for gRPC after all, it could provide a standard framework for things like this. Though I'd like to see a genuinely RESTful version of the AWS API, but who am I to tell Amazon what API technologies they should use...

Building HTTP/2 services with gRPC

Posted Mar 13, 2015 9:26 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link] (2 responses)

> Ouch. That's certainly not following 90% of REST best practice. Starting from the fact that they use GET requests for things that obviously change the server state.
It's actually a POST. With parameters in the URL, no less.

> Though I don't see AWS calling it a REST API anywhere (searched the documentation).
They gave up. Basically, the only remaining REST API is S3. It's not that much better: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObject... or http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObject...

> It appears that AWS has migrated their earlier SOAP API to work directly with simple HTTP requests, without the SOAP overhead and complexity. That's not REST, that's just a form of ad-hoc RPC over HTTP.
Yes, sure. And I work with similar shit APIs all the time. I have yet to see a textbook clean REST API - in ALL cases it breaks down at some point.

By this point I'm actually convinced that CORBA _is_ _better_ than the morass of shitty REST APIs, most of them designed by crack-smoking monkeys. Hell, even SOAP is better, and that says something!

At least with CORBA/SOAP you have cleanly defined interfaces. With REST you have to pray that the API provider deigned to describe it in some kind of a documentation. Because of course there's no standard service and schema discovery method.

But that's not all. The HTTP/1.1 interface itself is limited to request-response. If you want to do streaming then you have to use hacks like websockets and/or simply ignore the HTTP spec and stream content continuously. Bidirectional streaming? Hah! Next you'd want standardized machine-readable error messages!

Then there's a question of security. Amazon had to implement special signing algorithm because of impossibility to securely use HTTP[S] without exposing raw credentials on the wire all the time.

And finally, I don't see the _point_ of REST. It's literally a one-trick pony - it has an intuitive method for navigation of simple collections of entities. But I hesitate to name any other advantage.

What I like? Cap'n Proto implements lots of sane ideas: https://capnproto.org/rpc.html - API pipelining, sane security model, static service description with explicit versioning, bidirectional streaming support.

Building HTTP/2 services with gRPC

Posted Mar 13, 2015 17:58 UTC (Fri) by cesarb (subscriber, #6266) [Link] (1 responses)

> And finally, I don't see the _point_ of REST. It's literally a one-trick pony - it has an intuitive method for navigation of simple collections of entities. But I hesitate to name any other advantage.

Entity naming. Your comment, for instance, is identified by the URL https://lwn.net/Articles/636622/. It's a permanent, global, hierarchical name for the object which represents your comment in LWN's database.

REST is supposed to build on that; a GET to the object's URL returns the object, a PUT or POST to the object's URL modifies it. Of course, since that's a very limited API, people extend it in many different (and mutually incompatible) ways. But REST's core idea (each object has a name which is a URL, access that URL to operate on the object) is sound.

Building HTTP/2 services with gRPC

Posted Mar 13, 2015 18:23 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

> Entity naming. Your comment, for instance, is identified by the URL https://lwn.net/Articles/636622/. It's a permanent, global, hierarchical name for the object which represents your comment in LWN's database.
Actually, it's not hierarchical. A hierarchical system would mean something like: http://lwn.net/article/636129/comments/636618/636622/ or maybe http://lwn.net/article/636129/comments/636622/

And we're not talking about the web-ui. It makes little sense to use the full URL ("http://lwn.net/article/636129/comments/636622/") in place of a single ID in an RPC API.

> REST is supposed to build on that; a GET to the object's URL returns the object, a PUT or POST to the object's URL modifies it.
That naturally limits the API. Severely. For example, how do I modify several objects at once?

> But REST's core idea (each object has a name which is a URL, access that URL to operate on the object) is sound.
Not really. It sounds nice in theory but is almost always done poorly and pointlessly in practice.


Copyright © 2015, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds