6 ms·
> RPC is often accused of committing many of the fallacies of distributed computing. > But this reputation is outdated. When RPC was first invented some 40 yea
by divan 1y ago
> RPC is often accused of committing many of the fallacies of distributed computing.
> But this reputation is outdated. When RPC was first invented some 40 years ago, async programming barely existed. We did not have Promises, much less async and await.
I'm confused. How is this a "protocol" if its core premises rely on very specific implementation of concurrency in a very specific language?
- kentonv 1y agoWhat do you mean? Async programming exists in tons of languages. Just off the top of my head, I've used async/await in JavaScript, C++, Python, Rust, C#, ... Anyway, the point here is that early RPC systems worked by blocking the calling thread while performing the network request, which was obviously a terrible idea.
- chao- 1y agoReminds me of the old "MongoDB is Web Scale" series of comedy videos: https://youtu.be/bzkRVzciAZg https://youtu.be/bzkRVzciAZg Some friends and I still jokingly troll each other in the vein of these, interjecting with "When async programming was discovered in 2008...", or "When memory safe compiled languages were invented in 2012..." and so forth.
- afiori 1y agoAsync/await became ergonomic and widespread only recently, I am sure there were async systems in the '80 but for example nodejs focus on non blocking I/O changed how a lot of people thought about servers and concurrency (whether node was first is almost irrelevant) Often when something is discovered or invented is far less influential[1] than when it jumps on and hype train. [1] the discovery is very important for historical and epistemological reasons of course, rewriting the past is bad
- frollogaston 1y agoIt's not a programming paradigm shift, more of a change to how runtimes work. We want to avoid the overhead of kernel threads in servers, and async/await on top of an event loop is a convenient way to do that, like in JS, Rust, and now Python. Meanwhile Go doesn't have async/await and never will because it doesn't need it; it does greenthreading instead. Java has that too now. Either way, your code waits on IO like before and does other work while it waits. But instead of the kernel doing the context switching, your runtime does something analogous at a higher layer.
- kentonv 1y agoI disagree that async/await is purely about avoiding overhead of kernel threads. Kernel threads are actually not that expensive these days. You can have a server with 10,000 threads, no problem. The problem is synchronization becomes extremely hard to reason about. With event loop concurrency, each continuation (callback) becomes effectively a transaction, in which you don't need to worry about anything else modifying your state out from under you. That legitimately makes a lot of things easier. The Cloudflare Workers runtime actually does both: There's a separate thread for each connection, but within each thread there's an event loop to handle all the concurrent stuff relating to that one connection. This works well because connections rarely need to interact with each other's state, but they need to mess with their own state constantly. (Actually we have now gone further and stacked a custom green-threading implementation on top of this, but that's really a separate story and only a small incremental optimization.)
- frollogaston 1y agoIt's true that JS await is kinda like releasing a lock, but otherwise, you'd just use a mutex whenever you access shared state. Which is rare as you said, and also easy to enforce in various langs nowadays.
- kentonv 1y agoI said that shared state between connections is rare, but shared state within a connection is extremely common. And there are still multiple concurrent things going on within that connection context, requiring some concurrency mechanism. Locking mutexes everywhere sounds like a nightmare to me.
- deleted 1y ago[deleted]
- closeparen 1y ago"RPC" originally referred to a programming paradigm where remote calls looked just like any other method calls, and it might not even be any of the programmer's business whether they're implemented in-process or on another machine. This obviously required wire protocols, client and server libraries, etc. to implement. There's been a renaissance in the tools, but now we mainly use them like "REST" endpoints with the type signatures of functions. Programming language features like Future and Optional make it easier to clearly delineate properties like "this might take a while" or "this might fail" whereas earlier in RPC, these properties were kind of hidden.
- kiitos 1y agomm, i think you're describing corba, not rpc in general
- deleted 1y ago[deleted]
- closeparen 1y agoCORBA is trippier than that. A client’s request could include elements not normally serializable, like callbacks. A server could provide an object in response to your query and then continue mutating it, with the mutations reflected (effectively) in your address space, without your knowledge or participation.
- kentonv 1y agoThat's exactly what Cap'n Web does...
- kiitos 1y agoI am not really sure what you're talking about RPC is "remote procedure call", emphasis on "remote", meaning you always necessarily gonna be serializing/deserializing the information over some kind of wire, between discrete/different nodes, with discrete/distinct address spaces a client request by definition can't include anything that can't be serialized, serialization is the ground truth requirement for any kind of RPC... a server doesn't provide "an object" in response to a query, it provides "a response payload", which is at most a snapshot of some state it had at the time of the request, it's not as if there is any expectation that this serialized state is gonna be consistent between nodes