-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Bun.serve({fd})
and Bun.listen({fd})
for socket-activated deployments
#2852
Conversation
…ed deployments Make use of new functionality in uWebSockets and uSockets, which allow servers to attach to sockets that have already been bound and listened, rather than themselves binding and listening to a port.
Aside: this is probably the safest way to deploy with good multicore performance. The key is SO_REUSEPORT, which Bun uses by default. But there are downsides to making each Bun worker handle its own socket binding:
With |
Hey, this PR is great and really appreciate the work you put in and I
intend to merge it. Trying to ship the bundler so I haven’t had a chance to
review in depth yet but @cirospaciari can you take a look?
…On Fri, May 12, 2023 at 10:08 AM Shiva Kaul ***@***.***> wrote:
Aside: this is probably the safest way to deploy with good multicore
performance. The key is SO_REUSEPORT, which Bun uses by default. But there
are downsides to making each Bun worker handle its own socket binding:
- security: each worker is unprivileged, and has to keep the port open
for additional workers. But then any user process can interfere in the pool.
- usability: #1443 <#1443>
With fd, the privileged monitor gets sockets and passes them to only
legitimate workers. With multiple workers, a monitor process is anyways
necessary, since crashed workers need to be detected and restarted.
—
Reply to this email directly, view it on GitHub
<#2852 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFNGSYSHLJHMDZF5DY6NEDXFZVAZANCNFSM6AAAAAAX6NLHO4>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Probably we will need an abstraction here when Windows support for Runtime release.
The most common use case should be
This API diverged slightly from the current C API of WebSockets because the C API itself was not done yet when Bun started to use it, and Bun required some changes to achieve some features (like sendfile) and add fixes. So
I'm working on Windows support, this can be added later.
I take a look at LGTM, thanks @shivak |
This PR touches some critical codepaths (creating any kind of server) and the underlying libs, so it is a good candidate to merge before a stable release. In the next few days, I'll resolve the conflicts that have arisen. |
@Jarred-Sumner Is the plan for this to be merged still? I'm hoping to migrate my Node.js web services to Bun, but using systemd sockets is how I architect things for zero-downtime deployments. Alternatively I can look into SO_REUSEPORT which I know works with uWS, which on modern Linux kernels might also be part of a solution for zero-downtime setup, but before I look into it was curious on when might get fd support. |
I would also like to express my interest in this feature. In Node.js this isn't an issue. |
I would like for us to do this, but I think it'll need a new PR due to bitrot |
Overview. This PR implements
Bun.serve({fd})
andBun.listen({fd})
, which runs the HTTP (or TCP) server on a socket that has are already been bound and listened. The overall idea is to have a separate processbind()
andlisten()
to a socket, and pass it to the Bun process. This is used in production deployments for:This feature is available in Go, Node, etc but not Deno (denoland/deno#6529). Here, it's mildly tricky to implement, since it involves changes to two layers of low-level platform bindings - see the companion PRs at the bottom.
Usage. Typical users (on Linux/systemd) would call
Bun.serve({fd: process.env.LISTEN_FDS})
. On Mac/launchd, the fd is obtained from launch_activate_socket. On Windows, it could ostensibly be transferred by WSADuplicateSocket.Workaround. socat or systemd-socket-proxyd. These aren't ideal for efficiency, security, or reliability.
Notes.
The Zig and C++ code correctly handle the socket type, which is usually just an fd, but isn't on Windows. The Javascript API is simple and oblivious, expecting positive ints to be passed.
This introduces an asymmetry between
listen()
andconnect()
, since now you canlisten()
to an fd, but you cannotconnect()
to one. Hence the somewhat awkwardFdOrUnixOrHost
type, which I don't think is worth fretting over.Testing requires some Zig code to perform the
bind()
andlisten()
typically done out-of-process.I copied the library changes to
_libusockets.h
andlibuwsockets.cpp
. These seem to differ in minor (unnecessary?) ways from the underlying libraries, for reasons I don't currently understand.I haven't tried running this on Windows. Also, as @Jarred-Sumner mentioned, some sanitization of fd might be useful. Also, I've never actually written any Zig code, so maybe double-check things.
Building. For politeness, I didn't redirect any submodules. Wait for the following PRs to be merged, or use my feature branches.