From 5d2390deba1fb5439b610d6ce51889beb402a4d1 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 17 Aug 2014 16:17:10 +0900 Subject: [PATCH] nghttpx: Bring per-connection rate limit back --read-burst=0 still does not work. But specifying n > 0 workarounds this. --- src/shrpx.cc | 55 +++++++++++++++++++++++++++++++++++++ src/shrpx_client_handler.cc | 5 ++++ src/shrpx_config.cc | 38 +++++++++++++++++++++++++ src/shrpx_config.h | 6 ++++ 4 files changed, 104 insertions(+) diff --git a/src/shrpx.cc b/src/shrpx.cc index 9d81f4e1..fed74457 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -770,6 +770,11 @@ void fill_default_config() mod_config()->downstream_http_proxy_host = nullptr; mod_config()->downstream_http_proxy_port = 0; mod_config()->downstream_http_proxy_addrlen = 0; + mod_config()->rate_limit_cfg = nullptr; + mod_config()->read_rate = 0; + mod_config()->read_burst = 1 << 30; + mod_config()->write_rate = 0; + mod_config()->write_burst = 0; mod_config()->worker_read_rate = 0; mod_config()->worker_read_burst = 0; mod_config()->worker_write_rate = 0; @@ -864,6 +869,29 @@ Performance: Set the number of worker threads. Default: )" << get_config()->num_worker << R"( + --read-rate= + Set maximum average read rate on frontend + connection. Setting 0 to this option means read + rate is unlimited. + Default: )" + << get_config()->read_rate << R"( + --read-burst= + Set maximum read burst size on frontend + connection. Setting 0 does not work. + Default: )" + << get_config()->read_burst << R"( + --write-rate= + Set maximum average write rate on frontend + connection. Setting 0 to this option means write + rate is unlimited. + Default: )" + << get_config()->write_rate << R"( + --write-burst= + Set maximum write burst size on frontend + connection. Setting 0 to this option means write + burst size is unlimited. + Default: )" + << get_config()->write_burst << R"( --worker-read-rate= Set maximum average read rate on frontend connection per worker. Setting 0 to this option @@ -1229,6 +1257,10 @@ int main(int argc, char **argv) {"frontend-no-tls", no_argument, &flag, 29}, {"backend-tls-sni-field", required_argument, &flag, 31}, {"dh-param-file", required_argument, &flag, 33}, + {"read-rate", required_argument, &flag, 34}, + {"read-burst", required_argument, &flag, 35}, + {"write-rate", required_argument, &flag, 36}, + {"write-burst", required_argument, &flag, 37}, {"npn-list", required_argument, &flag, 38}, {"verify-client", no_argument, &flag, 39}, {"verify-client-cacert", required_argument, &flag, 40}, @@ -1423,6 +1455,22 @@ int main(int argc, char **argv) // --dh-param-file cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, optarg); break; + case 34: + // --read-rate + cmdcfgs.emplace_back(SHRPX_OPT_READ_RATE, optarg); + break; + case 35: + // --read-burst + cmdcfgs.emplace_back(SHRPX_OPT_READ_BURST, optarg); + break; + case 36: + // --write-rate + cmdcfgs.emplace_back(SHRPX_OPT_WRITE_RATE, optarg); + break; + case 37: + // --write-burst + cmdcfgs.emplace_back(SHRPX_OPT_WRITE_BURST, optarg); + break; case 38: // --npn-list cmdcfgs.emplace_back(SHRPX_OPT_NPN_LIST, optarg); @@ -1771,6 +1819,13 @@ int main(int argc, char **argv) } } + mod_config()->rate_limit_cfg = ev_token_bucket_cfg_new + (get_rate_limit(get_config()->read_rate), + get_rate_limit(get_config()->read_burst), + get_rate_limit(get_config()->write_rate), + get_rate_limit(get_config()->write_burst), + nullptr); + mod_config()->worker_rate_limit_cfg = ev_token_bucket_cfg_new (get_rate_limit(get_config()->worker_read_rate), get_rate_limit(get_config()->worker_read_burst), diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 6c041647..97c59fff 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -238,6 +238,11 @@ ClientHandler::ClientHandler(bufferevent *bev, ++worker_stat->num_connections; + rv = bufferevent_set_rate_limit(bev_, get_config()->rate_limit_cfg); + if(rv == -1) { + CLOG(FATAL, this) << "bufferevent_set_rate_limit() failed"; + } + rv = bufferevent_add_to_rate_limit_group(bev_, rate_limit_group); if(rv == -1) { CLOG(FATAL, this) << "bufferevent_add_to_rate_limit_group() failed"; diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 622dd1ae..d1e71379 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -103,6 +103,10 @@ const char SHRPX_OPT_CACERT[] = "cacert"; const char SHRPX_OPT_BACKEND_IPV4[] = "backend-ipv4"; const char SHRPX_OPT_BACKEND_IPV6[] = "backend-ipv6"; const char SHRPX_OPT_BACKEND_HTTP_PROXY_URI[] = "backend-http-proxy-uri"; +const char SHRPX_OPT_READ_RATE[] = "read-rate"; +const char SHRPX_OPT_READ_BURST[] = "read-burst"; +const char SHRPX_OPT_WRITE_RATE[] = "write-rate"; +const char SHRPX_OPT_WRITE_BURST[] = "write-burst"; const char SHRPX_OPT_WORKER_READ_RATE[] = "worker-read-rate"; const char SHRPX_OPT_WORKER_READ_BURST[] = "worker-read-burst"; const char SHRPX_OPT_WORKER_WRITE_RATE[] = "worker-write-rate"; @@ -670,6 +674,40 @@ int parse_config(const char *opt, const char *optarg) return 0; } + if(util::strieq(opt, SHRPX_OPT_READ_RATE)) { + mod_config()->read_rate = strtoul(optarg, nullptr, 10); + + return 0; + } + + if(util::strieq(opt, SHRPX_OPT_READ_BURST)) { + errno = 0; + auto n = strtoul(optarg, nullptr, 10); + + if(errno != 0 || n == 0) { + LOG(ERROR) << SHRPX_OPT_READ_BURST + << ": specify integer strictly larger than 0"; + + return -1; + } + + mod_config()->read_burst = n; + + return 0; + } + + if(util::strieq(opt, SHRPX_OPT_WRITE_RATE)) { + mod_config()->write_rate = strtoul(optarg, nullptr, 10); + + return 0; + } + + if(util::strieq(opt, SHRPX_OPT_WRITE_BURST)) { + mod_config()->write_burst = strtoul(optarg, nullptr, 10); + + return 0; + } + if(util::strieq(opt, SHRPX_OPT_WORKER_READ_RATE)) { mod_config()->worker_read_rate = strtoul(optarg, nullptr, 10); diff --git a/src/shrpx_config.h b/src/shrpx_config.h index e6711ec9..a74597e8 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -96,6 +96,10 @@ extern const char SHRPX_OPT_BACKEND_IPV4[]; extern const char SHRPX_OPT_BACKEND_IPV6[]; extern const char SHRPX_OPT_BACKEND_HTTP_PROXY_URI[]; extern const char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[]; +extern const char SHRPX_OPT_READ_RATE[]; +extern const char SHRPX_OPT_READ_BURST[]; +extern const char SHRPX_OPT_WRITE_RATE[]; +extern const char SHRPX_OPT_WRITE_BURST[]; extern const char SHRPX_OPT_WORKER_READ_RATE[]; extern const char SHRPX_OPT_WORKER_READ_BURST[]; extern const char SHRPX_OPT_WORKER_WRITE_RATE[]; @@ -190,6 +194,8 @@ struct Config { std::unique_ptr downstream_http_proxy_host; std::unique_ptr http2_upstream_dump_request_header_file; std::unique_ptr http2_upstream_dump_response_header_file; + // Rate limit configuration per connection + ev_token_bucket_cfg *rate_limit_cfg; // Rate limit configuration per worker (thread) ev_token_bucket_cfg *worker_rate_limit_cfg; // list of supported NPN/ALPN protocol strings in the order of