Hacker News new | past | comments | ask | show | jobs | submit login
GRPC: A high performance, open source, general RPC framework (grpc.io)
223 points by chuhnk on Feb 26, 2015 | hide | past | favorite | 62 comments



It's a bit buried in the announcement, but this is also using a new version of protobuf [0] (3.0) which fixes a number of long-standing complaints about the format:

    * No more required fields
    * Now supports maps (a huge pain point)
    * A canonical json encoding
    * Wider official language support
[0] https://github.com/google/protobuf/releases


The changes around defaults and field presence are a great improvement for Go integration (and according to the release notes, also Android Java and Objective C).

proto2 integration in Go is fairly unpleasant and involves getters and lots of pointers everywhere (see proto.Int, proto.String).


Personally, I'm very disappointed that we've lost immutability, along with support for nullable fields (e.g. Protobuf3 now assumes that 0 == null).


Immutability is still there. You get to choose whether you want it or not.

For when you actually want a nullable field, I think the idea is that it is easy to have a wrapper message (just like boxing in languages). Such wrappers could even be made standard and provided by protobuf.


> Such wrappers could even be made standard and provided by protobuf.

They will be: https://github.com/google/protobuf/issues/159#issuecomment-7...


This is what I've been looking for! Generated code on a production quality server (Netty), with no faffing around with JSON, etc. It would be sweet to see that Java server ported to scala though (or some docs to show me how to plug scala into the Java server), and also front-end javascript clients (I saw that was a work-in-progress).

If this would work with juniversal[0], and if that's actually any good, then this might actually give a quick way of churning out cross-platform apps.

[0]http://juniversal.org/


+1. I'd been looking for a while for a production quality RPC solution, especially one with Scala bindings.

Regarding the gRPC release, I've looked at the examples in the repo and only found this: https://github.com/grpc/grpc-java/tree/master/integration-te.... While it's a great showcase for the power of gRPC, having a "hello world" example with, hopefully, not a whole lot of boilerplate, would help a lot selling this to my team.


The Java examples are in the examples folder: https://github.com/grpc/grpc-java/tree/master/examples/src/m...

The examples folder references a tutorial at https://github.com/grpc/grpc-common/blob/master/java/javatut...


Thrift has been production quality for some time now, so if you've been looking for something like this you may also want to check out https://thrift.apache.org/



What HTTP/2 features make it desirable for general RPC (no browser involved)?

In the past I've found HTTP (1.1) to be okay, but not great for server->server RPC. The semantics are fine (but overkill) and the overhead sort of sucks. With HTTP/2 I guess the performance should be a lot better (with a binary protocol); I'm still unsure about the HTTP semantics in a general RPC context. Anyone with deeper knowledge of HTTP/2 care to enlighten me?

(Following up on a twitter conversation I had with @bradfitz: https://twitter.com/calebspare/status/571049339541270529)


gRPC uses the following features from HTTP/2: Framing (needed to multiplex different RPCs on the same TCP connection), Flow Control (both intra-stream and connection-wide), HPAC (for compressing metadata that tends to be common across requests), and GoAway (to gracefully drain backends).


Thanks! This is a good list.


Streaming RPCs in both directions (client to server, and server to client) is one big feature. It's not really possible to do client-side streaming with HTTP/1.1, especially if you have proxies in the way. Independently framed messages make it a lot more feasible to implement other important RPC features like flow control too.


Yeah, it's certainly more compelling than trying to build on HTTP 1.1. The alternative I had in mind was not using HTTP, though (for instance building some custom framed protocol on TCP, or open-sourcing some version of whatever Google uses internally for protobuf RPC.)

a11r pointed out several interesting features of HTTP/2 that are put to good use in gRPC, though.


gRPC is based on the internal Stubby RPC system, and that works over HTTP/1.1 based on CONNECT and switching to raw TCP. That works well enough, but the HTTP/2 goodies are too good to pass up.


And using HTTP/2 directly allows using HTTP/2-based load balancers and reverse proxies, which is a huge bonus.


Great context, thanks. I'm excited to start using it :)


Curious how this compares to Capn'Proto? Speed differences? Any functionality that's in one that's not in the other?


This is an interesting an complex topic.

Kenton does a pretty good job discussing this here https://capnproto.org/news/2014-06-17-capnproto-flatbuffers-...

and rightly mostly focuses on the message-encoding aspects. Performance will vary by use-case & platform and should be traded off against the suitability for the given use-case (platform support, schema evolution, fidelity of representation, maturity vs bleeding edge)

Cap'N'Proto has some interesting RPC features (promise-pipelining, pass-by-reference) that may be valuable to some.

FYI it would be perfectly reasonable to use Cap'N'Proto messages with GRPC as the transport layer to get HTTP2 support. GRPC was explicitly designed to allow for this.

Protobuf has better platform coverage than FlatBuffers and it's schema is easier to evolve but neither of these may matter for your use-case. As in all things it depends.


GRPC looks a lot like Google's internal Stubby, which is the main thing I am thinking of when I say "traditional RPC system" on this page:

https://capnproto.org/rpc.html


Same here but i'm also curious how the new version of Protocol Buffers compares to Flat Buffers that Google released a few months ago. The flat buffers documentation explains fairly well why i should use that but why should i use protocol buffers instead of either Capn'Proto or Flat Buffers?


    Automatically generate idiomatic client and server
    stubs for your service in a variety of languages.

    gRPC has libraries in ... C# [0]
Aweso-

    This gRPC C# implementation is work-in-
    progress and is not expected to work yet.
[0] https://github.com/grpc/grpc/tree/master/src/csharp



Awesome, now they can get to work on making the security portions of QUIC the basis for SSL 2.0 with PFS, EC and SSH like fingerprinting with user agent pinning, as well as multi-tiered CA (so a CA can only sign certs for a certain domain) and something resembling DANE but without the mandatory DNSSEC dependency.


There seems to be a semantic overlap between streaming data with HTTP/2 vs streaming websocket frames back and forth.

Does this have a distinct advantage over websockets, does it supersede it or is completely different?

To put it another way, could gRPC have worked via websockets (or maybe some long-polling fallback mode).


HTTP2 is superior to WebSocket at the transport layer because it adds explicit framing support and other things. Websocket-over-HTTP2 is coming, but it's not here now.

While HTTP/1.1 was a poor transport for high-perf RPC there are many parts of it that make sense semantically (headers, trailers, mime-types, virtual-hosting, content-encoding specification etc). HTTP2 lets you continue to use those in a form everyone is familiar with, with Websocket you would have to invent them again.


Does HTTP2 have guarantees that the connection is really reused for multiple requests or could a user agent (or HTTP library) silently use multiple connections for different requests?

I think this makes a major difference for RPC applications, because with a single connection you have a guarantee that all messages will be retrieved in the same order that they were sent.

E.g. with a persistent websocket connection I have the guarantee that all messages will be in order. With mulitple HTTP/1.1 requests I don't have it. Don't know about HTTP/2.

And of course the requirements about such a thing depend on how you design your RPC API (stateless or not).


HTTP/2 has the concept of streams. Each stream is independent, but within a stream data and headers are ordered. Each HTTP request would be on a new stream.

gRPC maps calls to streams so calls can proceed at different rates, but you still receive the information on a particular call in order. So conceptually each call is completely separate, but we can use a single HTTP/2 connection for all the calls to a particular destination.


Presuming you've done the research here: will Websocket-over-HTTP2 make websockets cheaper, to the point that e.g. it'd be performant to use individual websockets for each channel of a pub-sub system, rather than multiplexing them all over a single channel that is statefully subscribed on the server?

Or, now that I think of it, would the modern recommendation for this lean more toward opening multiple parallel Server-Sent-Events streams, with each channel being its own HTTP resource? That seems more idiomatic, at least.


That is certainly a goal for Websocket-over-HTTP2, though in truth it would be no cheaper than long-poll-over-HTTP2 and more expensive if you invented your own metadata mechanism rather than using HTTP2 headers. And as you say, less idiomatic.

Using separately addressable resources and having HTTP2 do the connection multiplexing for you seems like a good pattern to me.


> WebSocket at the transport layer because it adds explicit framing support and other things.

Websockets also have frames, binary or text.


Websocket does framing at the application layer, not the transport layer. Its probably more accurate to say that websocket lets you send binary or text messages.

More specifically this means that multiple WebSockets are not multiplexed over a single TCP/IP socket. One physical connection per-Websocket is a real scalability issue for servers and proxies.

WebSocket-over-HTTP would address that. See the options being discussed here http://tools.ietf.org/html/draft-hirano-httpbis-websocket-ov...


I don't think you would lose much in real world applications with the way websockets work:

You want to multiplex websockets (for RPC) with normal HTTP requests -> Works through different URLs.

If you want to multiplex different websocket RPC services on a single websocket endpoint it's easy to do this on application level with some kind of service identifiers. You will probably want those anyway for some purposes - even if your transport layer also provides multiplexing.

Want to multiplex different websocket connections -> Works through different URLs. Yes, each will require a seperate IP connection. However I don't see a lot of applications that will go and utilize this scenario. They will either use gRpc OR WAMP OR SignalR OR etc, because that will make the maintainability much better then with a very mixed technology stack.


Multiplexing RPCs onto a single WebSocket has some serious downsides. For one you now have an entirely custom protocol that standard proxies will not understand and cannot route. GRPC is very careful to be valid HTTP/2 for this reason.

One of the major reasons for the existence of WebSocket is to support duplex streaming. HTTP/2 explicitly states

"A server can send a complete response prior to the client sending an entire request if the response does not depend on any portion of the request that has not been sent and received"

With better HTTP APIs (particularly in the browser) you would get full-duplex and the need for WebSocket would diminsh.


HTTP/2 gives you more than just a stream of frames (matching of requests to responses, some structure around headers and bodies, flow control, etc). gRPC could have been built on websockets but it would have been more work (almost as much work as building on plain TCP sockets - websockets add very little except the ability to work from a browser)


You are correct in assuming that, technically, gRPC could be built on top of WebSockets. Building directly over HTTP/2 allows for a leaner protocol stack.


I like to think of it the other way 'round: WebSockets can now be thought of as merely a weird polyfill for when you want to use HTTP streaming to emulate a stateful protocol. For anything else, just use plain HTTP/2.


It's a little hard for me to understand what if anything this presents. At first I thought perhaps Protocol Buffers didn't have an RPC layer, and that this was bringing Protocol Buffers up to a comparable level of competitors like Thrift. Checking the Protocol Buffers docs though, I see they do already have services.

Is this simply a consistent, cross-language looking interface for authoring/consuming Protocol Buffers services? What makes this different from other Protocol Buffer implementations?


Just to add to a11r's comment:

- this is not a new Protocol Buffer implementation. It uses the existing Protocol Buffers implementation for serialization/deserialization.

- this is actual implementation for the service declarations you could write in .proto files already (previously Protocol Buffers could only generate interface stubs, without implementation).


Protocol Buffers didn't really have an RPC engine - the services feature was limited to generating some interfaces. gRPC provides an actual RPC engine with required network functionality.


What are the benefits of using HTTP rather than TCP directly? I guess one of them is easy to pass firewalls. Anything else makes HTTP better than raw TCP for RPC?


HTTP/2 is quite featureful and provides most of the advanced needs that gRPC has; HTTP/2 is pretty similar to what we would make ourselves if gRPC used TCP directly.

Using HTTP/2 though also allows fitting into the wider web ecosystem of proxies, reverse proxies, load balancers/TLS terminators, and developer familiarity.


There wouldn't be much benefit to using HTTP/1.1, but HTTP/2 makes it easy to pipeline and multiplex requests over a single TCP connection.


Not having to worry about calculating the length of the message before transferring it?


gRPC actually still has to calculate the length of a message before transferring it.


This is great, but the asymmetry here is not. Specifically, if you are a company and you use this and contribute to it, you have to sign this license: https://cla.developers.google.com/clas/new?kind=KIND_CORPORA...

Which has these clauses:

Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to Google and to recipients of software distributed by Google a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.

Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to Google and to recipients of software distributed by Google a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.

But Google doesn't grant you the same perpetual right to use and patent licenses back to you if you use gRPC. So I worry that if I start using this code, and Google decides to pull it, they can, even if some of it came from work that I did on it.

Now before someone says "But Chuck, they wouldn't do that ..." I want to remind you that licenses and contracts are not written to cover the 'good' time where everyone likes everyone, they are written to cover the 'bad' time when for one reason or another (often entirely unrelated to a particular API) that people stop liking each other so much.

The fix is simple however, Google could put in their license just a bit of additional text, which replaces

"Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:"

With

"Redistribution, use, and sub-licensing for this code in source or binary form, with or without modification, is granted, without cost, non-exclusively, and in perpetuity, provided the following conditions are met:"

Is there someone from the project reading this that can get that wording updated?


1. These clauses are actually not ones we wrote, they are from the Apache CCLA, widely used across the industry :)

2. "But Google doesn't grant you the same perpetual right to use and patent licenses back to you if you use gRPC"

Sorry, this was actually just human error.

They forgot to add the file I gave them.

I'll get it added to the repository post-haste.

(The patent grant is identical to the Go one)


We've just added the Patent Grant to all the repos. Thanks for pointing this out.


Additional IP Rights Grant now added to the repo: https://github.com/grpc/grpc/blob/master/PATENTS


Awesome sauce!


I'm not even allowed to read the page you linked without pretending to accept Google's universal tracking agreement. Nevermind.


that's definitely a bug that you can't read the agreement text without logging in. We'll see about getting it fixed.


How does performance compare to XDR and ONC/RPC?


Can anyone find benchmarks? I can't spend much time looking at it unless they back up their claims.



How is concurrency handled in this RPC server for blocking operations?


It varies based on language: some languages use async callbacks, some use futures/promises, some block and require threads, and some support multiple forms. The intent is that programmers in that language would handle concurrency however they would normally handle concurrency.


exicting


> A High performance

> Define your service using Protocol Buffers,

Erm...


If you are advertising it as a high performance RPC, you shouldn't be using protobufs.

Cap'n proto and flatbuffers are much faster.


When people might be comparing it to REST with JSON, it is fast.

gRPC can be used with flatbuffers and similar. The experience has been targeting protobufs, but at its core it just expects a serialized message. Other formats can be made to work with relatively low effort. So if protobuf is the issue, try swapping to your favorite marshaller.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: