4 ms·
Ask HN: What do you use for microservice RPC?
First, some background:
In our distributed microservice-based stack, we currently use JSON-over-RESTful-HTTP exclusively for the internal APIs exposed by our microservices. Apps, including browser front ends, talk to each other using HTTP.
In particular, we've come to realize is that it's really a poor man's RPC, and that REST has no practical utility in internal APIs, which benefit from a service/verb perspective, but not from a resource-oriented one.
Some current issues we want to solve:
- Performance. HTTP/1.1 is not suited for tiny RPC payloads where you want seamless pipelining. HTTP/2 is starting to look good as a much more performant transport, however.
- Wire formats. JSON is increasingly an expensive format to shuffle data around in.
- "Service discovery". A client wants simply to communicate with a bunch of services (preferably using the same connection) — it shouldn't concern itself with where those services run or how.
- Fault tolerance. Clients should be resilient against failing services and networking blips.
- Latency. Right now every HTTP request goes through HAProxy. Adds complexity, adds latency. We'd like microservices to talk to directly.
We could solve these issues for ourselves in a proprietary way. But we're not in the business of reinventing wheels, nor are we in the business of creating libraries. Developing the required glue from scratch in all the languages we use (Go, Node.js and Ruby currently) would consume resources we'd like to devote to app code.
What do devs on HN use?
- lobster_johnson 11y agoHere's some tech we are thinking about: * gRPC. Good attempt at solving cross-language RPC. Downsides: Alpha quality; Protobuf requires build steps on the client side (codegen, schema versioning); Doesn't yet solve discovery or fault tolerance; 3.0 beta is required if you want to ship free-form blobs of data around. * Protobuf: Similar to gRPC. * NATS. Fast in-memory messaging broker which seems suitable for RPC. In particular, this solves the discoverability issue, since services are simply topics. Downsides: Something of a single point of failure. Also, we still need to add an HTTP compatibility layer for browser clients, and we'd still need to write bindings for each language we use so that services can declare endpoints, and clients can talk to them, without using the NATS library directly. Fault tolerance also needs to built into this glue. Not saying it wouldn't be a nice open source project, though. * Thrift. Similar to gRPC/Protobuf. Requires schemas. We've talked to people who use this in production, and they're not too happy. Seems rather biased towards the Java universe.
- rdli 11y agoprotobuf and Thrift are serialization formats and an alternative to JSON, not RPC.
- lobster_johnson 11y agoI know, I should have said "Protobuf + custom connection handling". Thrift does come with RPC client/server code. You can choose between different transports. Example [1]. [1] https://github.com/apache/thrift/blob/master/lib/nodejs/examples/client.js https://github.com/apache/thrift/blob/master/lib/nodejs/exam...
- rdli 11y agoHere's what I've seen: 1. HTTP/JSON, with resiliency semantics layered on via SmartStack, Hystrix, or DIY library. 2. GRPC/protobuf. Haven't seen anyone other than Google run this in production, and Google doesn't really use gRPC (they use Stubby). 3. Finagle/Thrift. Twitter and some other folks use this. 4. Async message bus. Not as popular because it's not point-to-point, but it works. It's technically not RPC so it requires a different architectural approach that lots of people aren't willing to adopt. 5. Super fancy custom RPC protocol. Uber does this, for example. As does Google. You need lots of engineering to do this well, though. <plug> We've seen these design patterns over and over again, which is why we're building Quark (github.com/datawire/quark) which is a language for you to build your own custom RPC protocol (case #5 or to a lesser extent #1). We're also building Datawire Connect on top of Quark which gives you resilient RPC semantics in a way that's compatible with your existing tech stack. </plug>
- lobster_johnson 11y agoQuark looks quite interesting, if odd — it's an entire language, with classes and generics and everything? Just for implementing protocol glue? I think it's something I'd like to revisit once it's matured, as your set of languages is quite small at the moment, and I think it's overkill for us at the moment. In particular, I'm much more concerned about connection and discovery semantics than about things like wire protocol and how to express the "schema".
- meddlepal 11y agoDisclosure: Datawire employee Quark is a protocol implementation language. If you think of a protocol as being defined by something like an RFC (or RFC equivalent) then RFC's are fairly complex because of English and ambiguity. Quark is trying to help you define protocol's by encoding them in a language more familiar to programmers and computers and at the same time generate language-native bindings.
- rdli 11y agoIf you're more worried about connection and discovery semantics, you'd want to use Datawire Connect which is built on top of Quark. Quark is being used by companies that for one reason or another need/want to build their own protocol. This is admittedly overkill for most people. Datawire Connect integrates discovery as well as connection semantics (next week we'll have a release that supports full Hystrix semantics, e.g., circuit breakers and timeouts and load balancing).