diff --git a/dbms/src/Common/ErrorCodes.cpp b/dbms/src/Common/ErrorCodes.cpp index 4e724c995c4..3bace270cac 100644 --- a/dbms/src/Common/ErrorCodes.cpp +++ b/dbms/src/Common/ErrorCodes.cpp @@ -396,6 +396,7 @@ namespace ErrorCodes extern const int MULTIPLE_ASSIGNMENTS_TO_COLUMN = 419; extern const int CANNOT_UPDATE_COLUMN = 420; extern const int CANNOT_ADD_DIFFERENT_AGGREGATE_STATES = 421; + extern const int UNKNOWN_PROTOCOL = 422; extern const int KEEPER_EXCEPTION = 999; extern const int POCO_EXCEPTION = 1000; diff --git a/dbms/src/Core/Defines.h b/dbms/src/Core/Defines.h index b17c2cd287c..570c108b2a6 100644 --- a/dbms/src/Core/Defines.h +++ b/dbms/src/Core/Defines.h @@ -62,6 +62,8 @@ #define DEFAULT_HTTP_READ_BUFFER_TIMEOUT 1800 #define DEFAULT_HTTP_READ_BUFFER_CONNECTION_TIMEOUT 1 +/// Maximum namber of http-connections between two endpoints +/// the number is unmotivated #define DEFAULT_COUNT_OF_HTTP_CONNECTIONS_PER_ENDPOINT 15 // more aliases: https://mailman.videolan.org/pipermail/x264-devel/2014-May/010660.html diff --git a/dbms/src/IO/HTTPCommon.cpp b/dbms/src/IO/HTTPCommon.cpp index d2aa0f375cd..f627a850d68 100644 --- a/dbms/src/IO/HTTPCommon.cpp +++ b/dbms/src/IO/HTTPCommon.cpp @@ -52,23 +52,24 @@ namespace #endif } - HTTPSessionPtr makeHTTPSessionImpl(const std::string & host, UInt16 port, bool https) + HTTPSessionPtr makeHTTPSessionImpl(const std::string & host, UInt16 port, bool https, bool keep_alive) { HTTPSessionPtr session; if (https) #if USE_POCO_NETSSL - session = std::make_unique(); + session = std::make_shared(); #else throw Exception("ClickHouse was built without HTTPS support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME); #endif else - session = std::make_unique(); + session = std::make_shared(); ProfileEvents::increment(ProfileEvents::CreatedHTTPConnections); session->setHost(DNSResolver::instance().resolveHost(host).toString()); session->setPort(port); + session->setKeepAlive(keep_alive); return session; } @@ -83,7 +84,7 @@ namespace ObjectPtr allocObject() override { - return makeHTTPSessionImpl(host, port, https); + return makeHTTPSessionImpl(host, port, https, true); } public: @@ -133,7 +134,9 @@ namespace std::tie(pool_ptr, std::ignore) = endpoints_pool.emplace( key, std::make_shared(host, port, https, max_connections_per_endpoint)); - auto session = pool_ptr->second->get(-1); + auto retry_timeout = timeouts.connection_timeout.totalMicroseconds(); + auto session = pool_ptr->second->get(retry_timeout); + setTimeouts(*session, timeouts); return session; } @@ -156,7 +159,7 @@ HTTPSessionPtr makeHTTPSession(const Poco::URI & uri, const ConnectionTimeouts & UInt16 port = uri.getPort(); bool https = (uri.getScheme() == "https"); - auto session = makeHTTPSessionImpl(host, port, https); + auto session = makeHTTPSessionImpl(host, port, https, false); setTimeouts(*session, timeouts); return session; } diff --git a/dbms/src/IO/HTTPCommon.h b/dbms/src/IO/HTTPCommon.h index a607e5f512c..6dc669c248e 100644 --- a/dbms/src/IO/HTTPCommon.h +++ b/dbms/src/IO/HTTPCommon.h @@ -40,7 +40,7 @@ public: SingleEndpointHTTPSessionPool(const std::string & host_, UInt16 port_, bool https_, size_t max_pool_size_); }; using PooledHTTPSessionPtr = SingleEndpointHTTPSessionPool::Entry; -using HTTPSessionPtr = std::unique_ptr; +using HTTPSessionPtr = std::shared_ptr; void setResponseDefaultHeaders(Poco::Net::HTTPServerResponse & response, unsigned keep_alive_timeout); diff --git a/dbms/src/IO/ReadWriteBufferFromHTTP.h b/dbms/src/IO/ReadWriteBufferFromHTTP.h index 433bf23effd..215aa29a3e0 100644 --- a/dbms/src/IO/ReadWriteBufferFromHTTP.h +++ b/dbms/src/IO/ReadWriteBufferFromHTTP.h @@ -50,7 +50,7 @@ namespace detail : ReadBuffer(nullptr, 0) , uri {uri} , method {!method.empty() ? method : out_stream_callback ? Poco::Net::HTTPRequest::HTTP_POST : Poco::Net::HTTPRequest::HTTP_GET} - , session {std::move(session_)} + , session {session_} { // With empty path poco will send "POST HTTP/1.1" its bug. if (uri.getPath().empty()) diff --git a/dbms/tests/integration/test_max_http_connections_for_replication/configs/log_conf.xml b/dbms/tests/integration/test_max_http_connections_for_replication/configs/log_conf.xml new file mode 100644 index 00000000000..0de2745ca4c --- /dev/null +++ b/dbms/tests/integration/test_max_http_connections_for_replication/configs/log_conf.xml @@ -0,0 +1,11 @@ + + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/dbms/tests/integration/test_max_http_connections_for_replication/test.py b/dbms/tests/integration/test_max_http_connections_for_replication/test.py index b90650337d4..5fbd7f26e9f 100644 --- a/dbms/tests/integration/test_max_http_connections_for_replication/test.py +++ b/dbms/tests/integration/test_max_http_connections_for_replication/test.py @@ -22,8 +22,8 @@ def _fill_nodes(nodes, shard, connections_count): '''.format(shard=shard, replica=node.name, connections=connections_count)) cluster = ClickHouseCluster(__file__) -node1 = cluster.add_instance('node1', config_dir="configs", main_configs=['configs/remote_servers.xml'], with_zookeeper=True) -node2 = cluster.add_instance('node2', config_dir="configs", main_configs=['configs/remote_servers.xml'], with_zookeeper=True) +node1 = cluster.add_instance('node1', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) +node2 = cluster.add_instance('node2', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) @pytest.fixture(scope="module") def start_small_cluster(): @@ -52,9 +52,9 @@ def test_single_endpoint_connections_count(start_small_cluster): assert node2.query("SELECT value FROM system.events where event='CreatedHTTPConnections'") == '1\n' -node3 = cluster.add_instance('node3', config_dir="configs", main_configs=['configs/remote_servers.xml'], with_zookeeper=True) -node4 = cluster.add_instance('node4', config_dir="configs", main_configs=['configs/remote_servers.xml'], with_zookeeper=True) -node5 = cluster.add_instance('node5', config_dir="configs", main_configs=['configs/remote_servers.xml'], with_zookeeper=True) +node3 = cluster.add_instance('node3', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) +node4 = cluster.add_instance('node4', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) +node5 = cluster.add_instance('node5', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) @pytest.fixture(scope="module") def start_big_cluster():