feat: add tcpBacklog arg to Deno.listen{Tls} and Deno.serve (#30541)

This commit adds `tcpBacklog` argument to `Deno.listen`,
`Deno.listenTls` and `Deno.serve` APIs.

The argument specifies maximum number of pending connections in the
listen queue, and by default is set to 511. 

Users that expect huge bursts of traffic can customize this
option to a higher value.

Ref https://github.com/denoland/deno/pull/30471
Closes https://github.com/denoland/deno/issues/30388
This commit is contained in:
Bartek Iwańczuk 2025-08-28 09:43:20 +02:00 committed by GitHub
parent 9dbcd025d6
commit da1bf978f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 49 additions and 15 deletions

View file

@ -31,8 +31,8 @@ pub struct TcpConnection {
impl TcpConnection {
/// Boot a load-balanced TCP connection
pub fn start(key: SocketAddr) -> std::io::Result<Self> {
let listener = bind_socket_and_listen(key, false)?;
pub fn start(key: SocketAddr, backlog: i32) -> std::io::Result<Self> {
let listener = bind_socket_and_listen(key, false, backlog)?;
let sock = listener.into();
Ok(Self { sock, key })
@ -78,11 +78,12 @@ impl TcpListener {
pub fn bind(
socket_addr: SocketAddr,
reuse_port: bool,
backlog: i32,
) -> std::io::Result<Self> {
if REUSE_PORT_LOAD_BALANCES && reuse_port {
Self::bind_load_balanced(socket_addr)
Self::bind_load_balanced(socket_addr, backlog)
} else {
Self::bind_direct(socket_addr, reuse_port)
Self::bind_direct(socket_addr, reuse_port, backlog)
}
}
@ -91,9 +92,10 @@ impl TcpListener {
pub fn bind_direct(
socket_addr: SocketAddr,
reuse_port: bool,
backlog: i32,
) -> std::io::Result<Self> {
// We ignore `reuse_port` on platforms other than Linux to match the existing behaviour.
let listener = bind_socket_and_listen(socket_addr, reuse_port)?;
let listener = bind_socket_and_listen(socket_addr, reuse_port, backlog)?;
Ok(Self {
listener: Some(tokio::net::TcpListener::from_std(listener)?),
conn: None,
@ -101,7 +103,10 @@ impl TcpListener {
}
/// Bind to the port in a load-balanced manner.
pub fn bind_load_balanced(socket_addr: SocketAddr) -> std::io::Result<Self> {
pub fn bind_load_balanced(
socket_addr: SocketAddr,
backlog: i32,
) -> std::io::Result<Self> {
let tcp = &mut CONNS.get_or_init(Default::default).lock().unwrap().tcp;
if let Some(conn) = tcp.get(&socket_addr) {
let listener = Some(conn.listener()?);
@ -110,7 +115,7 @@ impl TcpListener {
conn: Some(conn.clone()),
});
}
let conn = Arc::new(TcpConnection::start(socket_addr)?);
let conn = Arc::new(TcpConnection::start(socket_addr, backlog)?);
let listener = Some(conn.listener()?);
tcp.insert(socket_addr, conn.clone());
Ok(Self {
@ -151,6 +156,7 @@ impl Drop for TcpListener {
fn bind_socket_and_listen(
socket_addr: SocketAddr,
reuse_port: bool,
backlog: i32,
) -> Result<std::net::TcpListener, std::io::Error> {
let socket = if socket_addr.is_ipv4() {
socket2::Socket::new(Domain::IPV4, Type::STREAM, Some(Protocol::TCP))?
@ -170,8 +176,7 @@ fn bind_socket_and_listen(
socket.set_reuse_address(true)?;
socket.set_nonblocking(true)?;
socket.bind(&socket_addr.into())?;
// Kernel will round it up to the next power of 2 + 1.
socket.listen(511)?;
socket.listen(backlog)?;
let listener = socket.into();
Ok(listener)
}