Practical ASP.NET

What Are gRPC Web Services and When Should I Use Them?

ASP.NET Core allows you to create Web Services based on gRPC ... which raises two questions: "What is gRPC?" and "Does it ever make sense to use it?" Here are Peter's answers.

If you're working with ASP.NET Core then you now have two options for creating Web Services: the current default style that leverages the HTTP protocol (what I think of as a "RESTful services") and the new kid on the block, gRPC services.

In some ways, it's worthwhile to think of gRPC Web Services as a throwback to the original Web Service technologies, SOAP and WSDL. Unlike REST, gRPC isn't an architectural style that comes with a lot of design principles or guidelines on how you should structure your services. Instead, like WSDL/SOAP services, gRPC is a technical specification that lets you call methods over the Internet without worrying about what platform the service or the client is running on (well, mostly: see below). That distinction is the point of the technology's name: RPC is short for Remote Procedure Call.

So, unlike a REST service, you can't assume as much about a gRPC service as you can with a service that's been built following REST principles. That means, in turn, that documentation is more critical with gRPC services than it is with REST if you're creating a service to be called by business partners (though gRPC does natively help to compensate for that necessary documentation, as I'll discuss below).

What that definition of gRPC misses is the point of the technology, which is performance and functionality.

Performance
To begin with, a default gRPC service will be more efficient (run faster) than a default RESTful service. The primary driver for that improved efficiency is the way gRPC handles the content of your messages (the payload).

gRPC requires that you convert your messages to something compatible with Protobuf, which is a binary standard. Protobuf provides for a more compact (and datatyped!) payload than the pure text format that's the default for RESTful services. The good news here is that, in ASP.NET Core, writing out and reading in messages delivered in Protobuf isn't more difficult than handling messages in a RESTful service. So, on the face of it, you're getting more speed for the same work.

But that doesn't mean that you get that improved performance for free. Using Protobug means you're also giving up interoperability: Your gRPC service can only communicate with gRPC clients.

The Protobuf standard does provide something that I miss in RESTful services, though: automatic and machine-readable payload documentation. A gRPC service comes with metadata that describes the service. Client-side developers can use that metadata to generate a client guaranteed to work with the service. It also works with services. System designers create a contract, pass it to the service developers and those developers can use the contract to generate the skeleton of the service. If this reminds you of WSDL ... well, it should.

Personally, I like these kinds of contract-based approaches (as I've shown with earlier columns on JSON schema and Swagger/OpenAPI, along with its implementation in NSwag). This is the feature that helps to compensate for the additional documentation that gRPC services require.

Protocol
On the protocol side, gRPC requires HTTP/2 because HTTP/2 provides direct support for the binary payloads that Protobuf implements. HTTP/2 also, however, addresses a number of limitations in HTTP 1.1, resulting in improved performance.

This has two implications. First, it means that you'll need to make sure that your servers support HTTP/2 (they probably do) and, because HTTP/2 requires Secure Sockets Layer (SSL), you'll need to make sure that you have the necessary certificates in place for HTTPS. Second, some interoperability is lost because your clients must also support HTTP/2. But, of course, if your client doesn't support gRPC, HTTP/2 is a moo point.

I wouldn't, however, focus on the difference in protocol as a differentiator between RESTful and gRPC services from the point of view of performance. There's no reason, for example, why REST services can't run over HTTP/2 and pick up most of those performance gains.

The real difference around HTTP/2 is the second benefit that gRPC delivers in addition to better performance: functionality. For example (and thanks to HTTP/2), gRPC gives you bi-directional services out of the box that allow the server to send messages to the client without first getting a request from the client. I suspect that RESTful services won't be able to take advantage of the features that can be built on top of HTTP/2 without some tweaking.

That creates another potential issue with gRPC, though -- there's a real danger that gRPC will lead back to one of the problems that characterized WSDL/SOAP services: complex implementations. One of the benefits of RESTful services is that, compared to WSDL/SOAP services, they "just work."

When gRPC?
For me, where gRPC currently makes the most sense is in intra-application communication. The most obvious case is where you're building an application as a collection of cooperating microsevices. Assuming applications are calling microservices (and microservices are calling one another) directly rather than writing to a queue or using some event-driven manager, gRPC seems like the ideal solution for reducing inter-process latency. In event-driven systems, gRPC may the preferred choice for communicating with the event manager and not just for performance's sake. The ability to notify a microservice about an event that has occurred in the system is a critical part of an event-driven system so bidirectionality is a real benefit.

And, when thinking of intra-application communication, you shouldn't just think of server-to-server communication. If your application consists of a dedicated client and a set of services then, it seems to me, gRPC makes just as much sense for communicating between your clients and its services. And, since there are gRPC implementations for most platforms (including a JavaScript library), it doesn't matter if your client is a Web browser, a desktop application, or a smartphone.

I'll go one step further: At an architectural level, I'm willing to make the case that it makes sense for a client that's tightly bound to a set of dedicated services to be designed in terms of method calls (that is, to use RPC). After all, that's what you do when you call a method inside your application (well, except for the "remote" part). It may be that a REST approach is best suited for public APIs and not for private ones.

And, as a side note, with internal teams, documentation is less of an issue than if you're supporting a potentially infinite number of external clients. Though, again, being able to deliver a contract to your business partners to support creating external clients doesn't sound like the worst idea ever.

I don't like expanding my toolkit any more than the next guy. But I think there's room in my toolbox for gRPC. So, in an upcoming column, I'll walk through the mechanics of creating and calling gRPC services in ASP.NET Core.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

Subscribe on YouTube