4 ms·
As someone who has worked at a few of the FAANGs, having thrift/grpc is a godsend for internal service routing, but a lot of the complexity is managed by teams
by toprerules 2y ago
As someone who has worked at a few of the FAANGs, having thrift/grpc is a godsend for internal service routing, but a lot of the complexity is managed by teams building the libraries, creating the service discovery layers, doing the routing etc. But using an RPC protocol enables those things to happen on a much greater scale and speed than you could ever do with your typical JSON/REST service. I've also never seen a REST API that didn't leak verbs. If I need to build a backend service mesh or wire two local services together via an networked stream, I will always reach for grpc.
That said, I absolutely would not use grpc for anything customer or web facing. RPC is powerful because it locks you into a lot of decisions and gives you "the one way". REST is far superior when you have many different clients with different technology stacks trying to use your service.
- jitl 2y agoFor a public API I wouldn’t do this, but for private APIs we just do POST /api/doThingy with a JSON body, easy peasy RPC anyone can participate in with the most basic HTTP client. Works great on every OS and in every browser, no fucking around with “what goes in the URL path” vs “what goes in query params” vs “what goes in the body”. You can even do this with gRPC if you’re using Buf or Connect - one of the server thingies that try not to suck; they will accept JSON via HTTP happily.
- pandemic_region 2y agoThis. The amount of time lost debating correct rest semantics for a use case is staggering.
- spelunker 2y agoArguing the Right Way To Do REST was a favorite passtime amongst people at one of my previous jobs. Huge waste of time.
- porridgeraisin 2y agoYeah, when it matters in close to 0% of cases. Everyone reads the docs for everything anyways, any shared knowledge granting implicit meaning to things is very close to useless in practice with REST APIs.
- ryathal 2y agoI'd argue just making everything POST is the correct way to do a public Api too. REST tricks you into endpoints no one really wants, or you break it anyway to support functionality needed. SOAP was heavy with it's request/respone, but it was absolutely correct that just sending everything as POST across the wire is easier to work with.
- porridgeraisin 2y agoYeah, I like doing this as well. And all the data goes in the request body. No query parameters. Especially when the primary intended client is an SPA, where the URL shown is decoupled with the API URL. Little bit of a memory jolt: I once built a (not for prod) backend in python as follows: write a list of functions, one for each RPC, in a file `functions.py` then write this generic function for flask: import server.functions as functions @server.post("/<method>") def api(method: str): data: Any = request.json if request.is_json else {} fn = lookup(functions, method) if fn is None: return {"error": "Method not found."} return fn(data) And `lookup()` looks like: def lookup(module: ModuleType, method: str): md = module.__dict__ mn = module.__name__ is_present = method in md is_not_imported = md[method].__module__ == mn is_a_function = inspect.isfunction(md[method]) if is_present and is_not_imported and is_a_function: return md[method] return None So writing a new RPC is just writing a new function, and it all gets automatically wired up to `/api/function_name`. Quite nice. The other nice feature there was automatic "docs" generation, from the python docstring of the function. You see, in python you can dynamically read the docstring of an object. So, I wrote this: def get_docs(module: ModuleType): md = module.__dict__ mn = module.__name__ docs = "" for name in md: if not inspect.isfunction(md[name]) or md[name].__module__ != mn: continue docs += md[name].__doc__ + "\n<br>\n" return docs[:-6] Gives a simple text documentation which I served at an endpoint. Of course you could also write the docstring in openapi yaml format and serve it that way too. Quite cursed overall, but hey, its python. One of the worst footguns here is that you could accidentally expose helper functions, so you have to be sure to not write those in the functions file :P
- jitl 2y ago
- rfw300 2y agoWhat do you mean by “leak verbs”?
- jon_richards 2y agoNot OP, but https://cloud.google.com/blog/products/api-management/restful-api-design-nouns-are-good-verbs-are-bad https://cloud.google.com/blog/products/api-management/restfu... The problem is that clients generally have a bunch of verbs they need to do. You have to design your objects and permissions just right such that clients can do all their verbs without an attacker being able to PATCH "payment_status" from "Requires Payment" to "Payment Confirmed". RPC uses verbs, so that could just be the SubmitPayment RPC's job. In REST, the correct design would be to give permission to POST a "Payment" object and base "payment_status" on whether that has been done.
- robertlagrant 2y agoThis is the most painful bit of REST for sure.
- Cthulhu_ 2y agoWhat about non-web client/server applications though? I'm thinking online games / MMOs that require much more realtime communications than REST does. I have no idea what is used now, socket connections with something on the line I suppose.
- kyrra 2y agoFor a game, I would maybe use Protobuf and grpc. There is serialization and deserializarion required. Something like flatbuffers or capnproto where the wireformat matches language data layout makes for extremely efficient parsing (though it may not be as network efficient). Really depends on how you structure your data.
- crabbone 2y ago> thrift/grpc is a godsend for internal service routing Compared to what? What else did you try?