mirror of
https://github.com/denoland/deno.git
synced 2025-09-25 03:42:30 +00:00
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:
parent
9dbcd025d6
commit
da1bf978f0
8 changed files with 49 additions and 15 deletions
12
cli/tsc/dts/lib.deno.ns.d.ts
vendored
12
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -5157,6 +5157,18 @@ declare namespace Deno {
|
|||
|
||||
/** Sets `SO_REUSEPORT` on POSIX systems. */
|
||||
reusePort?: boolean;
|
||||
|
||||
/** Maximum number of pending connections in the listen queue.
|
||||
*
|
||||
* This parameter controls how many incoming connections can be queued by the
|
||||
* operating system while waiting for the application to accept them. If more
|
||||
* connections arrive when the queue is full, they will be refused.
|
||||
*
|
||||
* The kernel may adjust this value (e.g., rounding up to the next power of 2
|
||||
* plus 1). Different operating systems have different maximum limits.
|
||||
*
|
||||
* @default {511} */
|
||||
tcpBacklog?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
12
cli/tsc/dts/lib.deno_net.d.ts
vendored
12
cli/tsc/dts/lib.deno_net.d.ts
vendored
|
@ -191,6 +191,18 @@ declare namespace Deno {
|
|||
*
|
||||
* @default {"0.0.0.0"} */
|
||||
hostname?: string;
|
||||
|
||||
/** Maximum number of pending connections in the listen queue.
|
||||
*
|
||||
* This parameter controls how many incoming connections can be queued by the
|
||||
* operating system while waiting for the application to accept them. If more
|
||||
* connections arrive when the queue is full, they will be refused.
|
||||
*
|
||||
* The kernel may adjust this value (e.g., rounding up to the next power of 2
|
||||
* plus 1). Different operating systems have different maximum limits.
|
||||
*
|
||||
* @default {511} */
|
||||
tcpBacklog?: number;
|
||||
}
|
||||
|
||||
/** @category Network */
|
||||
|
|
|
@ -936,6 +936,7 @@ function serveInner(options, handler) {
|
|||
port: options.port ?? 8000,
|
||||
reusePort: options.reusePort ?? false,
|
||||
loadBalanced: options[kLoadBalanced] ?? false,
|
||||
backlog: options.backlog,
|
||||
};
|
||||
|
||||
if (options.certFile || options.keyFile) {
|
||||
|
|
|
@ -598,6 +598,7 @@ function listen(args) {
|
|||
},
|
||||
args.reusePort,
|
||||
args.loadBalanced ?? false,
|
||||
args.tcpBacklog ?? 511,
|
||||
);
|
||||
addr.transport = "tcp";
|
||||
return new Listener(rid, addr, "tcp");
|
||||
|
|
|
@ -162,6 +162,7 @@ function listenTls({
|
|||
transport = "tcp",
|
||||
alpnProtocols = undefined,
|
||||
reusePort = false,
|
||||
tcpBacklog = 511,
|
||||
}) {
|
||||
if (transport !== "tcp") {
|
||||
throw new TypeError(`Unsupported transport: '${transport}'`);
|
||||
|
@ -176,7 +177,7 @@ function listenTls({
|
|||
const keyPair = loadTlsKeyPair("Deno.listenTls", arguments[0]);
|
||||
const { 0: rid, 1: localAddr } = op_net_listen_tls(
|
||||
{ hostname, port },
|
||||
{ alpnProtocols, reusePort },
|
||||
{ alpnProtocols, reusePort, tcpBacklog },
|
||||
keyPair,
|
||||
);
|
||||
return new TlsListener(rid, localAddr);
|
||||
|
|
|
@ -574,6 +574,7 @@ pub fn op_net_listen_tcp<NP>(
|
|||
#[serde] addr: IpAddr,
|
||||
reuse_port: bool,
|
||||
load_balanced: bool,
|
||||
tcp_backlog: i32,
|
||||
) -> Result<(ResourceId, IpAddr), NetError>
|
||||
where
|
||||
NP: NetPermissions + 'static,
|
||||
|
@ -589,9 +590,9 @@ where
|
|||
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
||||
|
||||
let listener = if load_balanced {
|
||||
TcpListener::bind_load_balanced(addr)
|
||||
TcpListener::bind_load_balanced(addr, tcp_backlog)
|
||||
} else {
|
||||
TcpListener::bind_direct(addr, reuse_port)
|
||||
TcpListener::bind_direct(addr, reuse_port, tcp_backlog)
|
||||
}?;
|
||||
let local_addr = listener.local_addr()?;
|
||||
let listener_resource = NetworkListenerResource::new(listener);
|
||||
|
@ -1483,7 +1484,7 @@ mod tests {
|
|||
let sockets = Arc::new(Mutex::new(vec![]));
|
||||
let clone_addr = addr.clone();
|
||||
let addr = addr.to_socket_addrs().unwrap().next().unwrap();
|
||||
let listener = TcpListener::bind_direct(addr, false).unwrap();
|
||||
let listener = TcpListener::bind_direct(addr, false, 511).unwrap();
|
||||
let accept_fut = listener.accept().boxed_local();
|
||||
let store_fut = async move {
|
||||
let socket = accept_fut.await.unwrap();
|
||||
|
|
|
@ -514,6 +514,7 @@ pub struct ListenTlsArgs {
|
|||
reuse_port: bool,
|
||||
#[serde(default)]
|
||||
load_balanced: bool,
|
||||
tcp_backlog: i32,
|
||||
}
|
||||
|
||||
#[op2(stack_trace)]
|
||||
|
@ -543,9 +544,9 @@ where
|
|||
.ok_or(NetError::NoResolvedAddress)?;
|
||||
|
||||
let tcp_listener = if args.load_balanced {
|
||||
TcpListener::bind_load_balanced(bind_addr)
|
||||
TcpListener::bind_load_balanced(bind_addr, args.tcp_backlog)
|
||||
} else {
|
||||
TcpListener::bind_direct(bind_addr, args.reuse_port)
|
||||
TcpListener::bind_direct(bind_addr, args.reuse_port, args.tcp_backlog)
|
||||
}?;
|
||||
let local_addr = tcp_listener.local_addr()?;
|
||||
let alpn = args
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue