jgaskins / grpc

Pure-Crystal implementation of gRPC
MIT License
76 stars 12 forks source link

Add Support for Unix Domain Sockets as Transport Method #9

Open stellarpower opened 3 years ago

stellarpower commented 3 years ago

I have a small application where I need to communicate over a socket on the filesystem rather than via an exposed port. It would be a great addition to be able to start a server on a Unix domain socket as an alternative to using an HTTP/2 server. I believe the core gRPC library has had this support for a while, but it hasn't filtered through to several of the other supported languages - e.g., I see no way to do this in Ruby either.

Thanks!

jgaskins commented 3 years ago

I think at this point I've had feature requests for Unix domain sockets on most of my libraries that talk over a network. 🙂 I find this fascinating because I've somehow never had to use them in a production app.

I think this could probably be done, tbh, since it's the HTTP/2 server that listens. Maybe we could either add an override for that method or a HTTP2::UnixServer subclass that listens on a Unix socket.

Same goes for the client. The upside is that the type of the @socket instance variable is just IO (I was trying to leave room for OpenSSL::SSL::Socket) so it could, in theory, be a Unix socket. We would just need to construct it as one. I think the challenge there would be that a UNIXSocket is probably pretty reliable but the Connection class also has to be able to reconstruct a TCPSocket because it's not. I'm not sure what a good interface for that would be.

stellarpower commented 3 years ago

Haha, must get annoying after a while! The actual use case is podman containers - when there are many of them, opening ports for each becomes unwieldy. I'm currently just using named pipes and want to get rid of that and upgrade. Ended up writing something in Dart and then Go and certainly regret it already, but unfortunately in this case I think being able to listen to an object on the filesystem will be almost essential. And a shame, as I keep meaning to learn Crystal properly, but find every time I go to start a project, I have to fall back to a different language as I'm missing some shard that doesn't yet exist, or there's one critical feature that just hasn't been supported yet. If I get the time to learn properly then I could try and have a look - it looked like this shard is reasonably coupled to the HTTP2 for now so didn't look much further. As you say, if as much could be delegated to the standard library, since it's a while since I looked but it seems to be a good one as languages go, and if we could just use a generic connection or at least a socket, then that would be pretty ideal. In fact, perhaps if this can't be done so easily it would be worth recommending upstream(?). If version 1.x is still quite recent there may be some scope for abstracting some of this I guess. I find other languages have a standard library that goes some way, and then you have to fall back to a package that is a relatively thin wrapper on top of Unix libraries. It would be lovely if the Crystal stdlib could just take a URI like "unix:///path" or "tcp://localhost:1234" and return a listener of some sort. Cover all bases inherently.

Anyway, thanks for the detailed feedback, and the project - it's a language I really, really want to be able to spend more time in, and without much documentation I can find, every shard someone publishes means it's more likely whenever I just need to get the job done™️ that I will be able to do so with less pain in Crystal than the next best option, so thanks.