- Author(s): murgatroid99
- Approver: wenbozhu
- Status: In Review
- Implemented in: Node.js
- Last updated: 2023-10-18
- Discussion at: https://groups.google.com/g/grpc-io/c/0R8lD87XDo8
Add a new method unbind
to the Server
class to unbind a port previously bound by bindAsync
.
gRFC A36: xDS-Enabled Servers specifies that ports must be in the "serving" or "not serving" state. In Node.js, we have decided that the best way to represent this is with the bound state of the port. Since an xDS-enabled server may receive a configuration update that causes it to transition from the "serving" to "not serving" state, it needs to be able to unbind a previously-bound port.
A single method unbind(port: string): void
will be added to the Server
class. When called, if the port
argument matches the port argument to a previous call to bindAsync
, any ports bound by that bindAsync
call will be unbound, and a GOAWAY will be sent to any active connections that were established using that port. Those connections will still be tracked for shutdown methods, meaning that tryShutdown
will wait for them to finish, and forceShutdown
will close them.
If a previous call to bindAsync
is still pending, the unbind
call will cancel it if possible, or close the ports after they have been opened otherwise. If cancelled, the bindAsync
callback will be called with an error referencing the cancellation. If unbind
is called while bindAsync
is pending, and then bindAsync
is called again with the same port
and identical credentials
while the previous bindAsync
call is still pending, the previous attempt will be un-cancelled if possible, and the callbacks for both bindAsync
calls will be called when binding is complete. If instead bindAsync
is called again with different credentials, it will start a new separate bind attempt.
Ephemeral ports (port 0) are handled differently as a special case. A call to unbind
with a port number of 0 will throw an error. After a call to bindAsync
with a port number of 0 succeeds, and the specific bound port number is provided in the callback, unbind
can be called with the original port
string with the bound port number substituted for port 0 to unbind that port.
As an alternative to unbinding ports in an existing server, the xDS server could use a separate server object under the hood for each port it wants to bind. The upside of this option is that it does not require any API changes. However, there are a few downsides:
- The xDS server would need its own tracking for registered services, and possibly other things in the future such as server interceptors, in order to pass each of those things along to each underlying server it creates.
- Channelz statistics would be fragmented between the different server objects.
I (murgatroid99) will implement this initially as _unbind
, which is considered non-public because of the underscore prefix. If/when this proposal is accepted, I will also add the non-underscore-prefixed method.