From: Remi Gacogne Date: Mon, 8 Feb 2021 15:01:07 +0000 (+0100) Subject: dnsdist: Add an option to set the size of the TCP internal pipe's buffer X-Git-Tag: dnsdist-1.6.0-alpha2~11^2~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4ce513a4cb7f698a99e736f8e4ff17f2ce293e01;p=thirdparty%2Fpdns.git dnsdist: Add an option to set the size of the TCP internal pipe's buffer --- diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index 88e2de511e..55fdc7a6ca 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -615,6 +615,7 @@ const std::vector g_consoleKeywords{ { "setStaleCacheEntriesTTL", true, "n", "allows using cache entries expired for at most n seconds when there is no backend available to answer for a query" }, { "setSyslogFacility", true, "facility", "set the syslog logging facility to 'facility'. Defaults to LOG_DAEMON" }, { "setTCPDownstreamCleanupInterval", true, "interval", "minimum interval in seconds between two cleanups of the idle TCP downstream connections" }, + { "setTCPInternalPipeBufferSize", true, "size", "Set the size in bytes of the internal buffer of the pipes used internally to distribute connections to TCP (and DoT) workers threads" }, { "setTCPUseSinglePipe", true, "bool", "whether the incoming TCP connections should be put into a single queue instead of using per-thread queues. Defaults to false" }, { "setTCPRecvTimeout", true, "n", "set the read timeout on TCP connections from the client, in seconds" }, { "setTCPSendTimeout", true, "n", "set the write timeout on TCP connections from the client, in seconds" }, diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 7535c66ced..77f12140d5 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -1817,6 +1817,8 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) g_useTCPSinglePipe = flag; }); + luaCtx.writeFunction("setTCPInternalPipeBufferSize", [](size_t size) { g_tcpInternalPipeBufferSize = size; }); + luaCtx.writeFunction("snmpAgent", [client,configCheck](bool enableTraps, boost::optional daemonSocket) { if(client || configCheck) return; diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index e4840fc9e1..e2f1aab0c6 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -62,6 +62,7 @@ uint64_t g_maxTCPQueuedConnections{1000}; size_t g_maxTCPQueriesPerConn{0}; size_t g_maxTCPConnectionDuration{0}; size_t g_maxTCPConnectionsPerClient{0}; +size_t g_tcpInternalPipeBufferSize{0}; uint16_t g_downstreamTCPCleanupInterval{60}; bool g_useTCPSinglePipe{false}; @@ -212,7 +213,9 @@ TCPClientCollection::TCPClientCollection(size_t maxThreads, bool useSinglePipe): throw std::runtime_error("Error setting the TCP single communication pipe non-blocking: " + stringerror(err)); } - setPipeBufferSize(d_singlePipe[0], 1048576); + if (g_tcpInternalPipeBufferSize > 0 && getPipeBufferSize(d_singlePipe[0]) < g_tcpInternalPipeBufferSize) { + setPipeBufferSize(d_singlePipe[0], g_tcpInternalPipeBufferSize); + } } } @@ -247,6 +250,10 @@ void TCPClientCollection::addTCPClientThread() errlog("Error setting the TCP thread communication pipe non-blocking: %s", stringerror(err)); return; } + + if (g_tcpInternalPipeBufferSize > 0 && getPipeBufferSize(pipefds[0]) < g_tcpInternalPipeBufferSize) { + setPipeBufferSize(pipefds[0], g_tcpInternalPipeBufferSize); + } } { diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 81b1b3af52..9e7634fc74 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -1183,6 +1183,7 @@ extern uint64_t g_maxTCPQueuedConnections; extern size_t g_maxTCPQueriesPerConn; extern size_t g_maxTCPConnectionDuration; extern size_t g_maxTCPConnectionsPerClient; +extern size_t g_tcpInternalPipeBufferSize; extern pdns::stat16_t g_cacheCleaningDelay; extern pdns::stat16_t g_cacheCleaningPercentage; extern uint32_t g_staleCacheEntriesTTL; diff --git a/pdns/dnsdistdist/docs/advanced/tuning.rst b/pdns/dnsdistdist/docs/advanced/tuning.rst index 692f14979d..72454ad9e2 100644 --- a/pdns/dnsdistdist/docs/advanced/tuning.rst +++ b/pdns/dnsdistdist/docs/advanced/tuning.rst @@ -21,7 +21,7 @@ If all the TCP threads are busy, new TCP connections are queued while they wait Before 1.4.0, a TCP thread could only handle a single incoming connection at a time. Starting with 1.4.0 the handling of TCP connections is now event-based, so a single TCP worker can handle a large number of TCP incoming connections simultaneously. Note that before 1.6.0 the TCP worker threads were created at runtime, adding a new thread when the existing ones seemed to struggle with the load, until the maximum number of threads had been reached. Starting with 1.6.0 the configured number of worker threads are immediately created at startup. -The maximum number of queued connections can be configured with :func:`setMaxTCPQueuedConnections` and defaults to 1000. +The maximum number of queued connections can be configured with :func:`setMaxTCPQueuedConnections` and defaults to 1000. Note that the size of the internal pipe used to distribute queries might need to be increased as well, using :func:`setTCPInternalPipeBufferSize`. Any value larger than 0 will cause new connections to be dropped if there are already too many queued. By default, every TCP worker thread has its own queue, and the incoming TCP connections are dispatched to TCP workers on a round-robin basis. This might cause issues if some connections are taking a very long time, since incoming ones will be waiting until the TCP worker they have been assigned to has finished handling its current query, while other TCP workers might be available. diff --git a/pdns/dnsdistdist/docs/reference/tuning.rst b/pdns/dnsdistdist/docs/reference/tuning.rst index 015e37e00d..4ceaef264b 100644 --- a/pdns/dnsdistdist/docs/reference/tuning.rst +++ b/pdns/dnsdistdist/docs/reference/tuning.rst @@ -63,6 +63,14 @@ Tuning related functions :param int num: +.. function:: setTCPInternalPipeBufferSize(size) + + .. versionadded:: 1.6.0 + + Set the size in bytes of the internal buffer of the pipes used internally to distribute connections to TCP (and DoT) workers threads. Requires support for ``F_SETPIPE_SZ`` which is present in Linux since 2.6.35. The actual size might be rounded up to a multiple of a page size. 0 means that the OS default size is used. + + :param int size: The size in bytes. + .. function:: setTCPUseSinglePipe(val) Whether the incoming TCP connections should be put into a single queue instead of using per-thread queues. Defaults to false