nghttpx: Use BlockAllocator per DownstreamConfig

This commit is contained in:
Tatsuhiro Tsujikawa 2016-10-02 17:44:45 +09:00
parent f5285d1f5a
commit 272cfa320e
5 changed files with 129 additions and 42 deletions

View File

@ -804,7 +804,7 @@ namespace {
// as catch-all. We also parse protocol specified in |src_proto|. // as catch-all. We also parse protocol specified in |src_proto|.
// //
// This function returns 0 if it succeeds, or -1. // This function returns 0 if it succeeds, or -1.
int parse_mapping(Config *config, DownstreamAddrConfig addr, int parse_mapping(Config *config, DownstreamAddrConfig &addr,
const StringRef &src_pattern, const StringRef &src_params) { const StringRef &src_pattern, const StringRef &src_params) {
// This returns at least 1 element (it could be empty string). We // This returns at least 1 element (it could be empty string). We
// will append '/' to all patterns, so it becomes catch-all pattern. // will append '/' to all patterns, so it becomes catch-all pattern.
@ -824,7 +824,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
addr.rise = params.rise; addr.rise = params.rise;
addr.proto = params.proto; addr.proto = params.proto;
addr.tls = params.tls; addr.tls = params.tls;
addr.sni = ImmutableString{std::begin(params.sni), std::end(params.sni)}; addr.sni = make_string_ref(downstreamconf.balloc, params.sni);
auto &routerconf = downstreamconf.router; auto &routerconf = downstreamconf.router;
auto &router = routerconf.router; auto &router = routerconf.router;
@ -833,18 +833,31 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
for (const auto &raw_pattern : mapping) { for (const auto &raw_pattern : mapping) {
auto done = false; auto done = false;
std::string pattern; StringRef pattern;
auto slash = std::find(std::begin(raw_pattern), std::end(raw_pattern), '/'); auto slash = std::find(std::begin(raw_pattern), std::end(raw_pattern), '/');
if (slash == std::end(raw_pattern)) { if (slash == std::end(raw_pattern)) {
// This effectively makes empty pattern to "/". // This effectively makes empty pattern to "/". 2 for '/' and
pattern.assign(std::begin(raw_pattern), std::end(raw_pattern)); // terminal NULL character.
util::inp_strlower(pattern); auto iov = make_byte_ref(downstreamconf.balloc, raw_pattern.size() + 2);
pattern += '/'; auto p = iov.base;
p = std::copy(std::begin(raw_pattern), std::end(raw_pattern), p);
util::inp_strlower(iov.base, p);
*p++ = '/';
*p = '\0';
pattern = StringRef{iov.base, p};
} else { } else {
pattern.assign(std::begin(raw_pattern), slash); auto path = http2::normalize_path(downstreamconf.balloc,
util::inp_strlower(pattern); StringRef{slash, std::end(raw_pattern)},
pattern += http2::normalize_path(StringRef{slash, std::end(raw_pattern)}, StringRef{});
StringRef{}); auto iov = make_byte_ref(downstreamconf.balloc,
std::distance(std::begin(raw_pattern), slash) +
path.size() + 1);
auto p = iov.base;
p = std::copy(std::begin(raw_pattern), slash, p);
util::inp_strlower(iov.base, p);
p = std::copy(std::begin(path), std::end(path), p);
*p = '\0';
pattern = StringRef{iov.base, p};
} }
for (auto &g : addr_groups) { for (auto &g : addr_groups) {
if (g.pattern == pattern) { if (g.pattern == pattern) {
@ -863,7 +876,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
} }
auto idx = addr_groups.size(); auto idx = addr_groups.size();
addr_groups.emplace_back(StringRef{pattern}); addr_groups.emplace_back(pattern);
auto &g = addr_groups.back(); auto &g = addr_groups.back();
g.addrs.push_back(addr); g.addrs.push_back(addr);
g.affinity = params.affinity; g.affinity = params.affinity;
@ -886,10 +899,13 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
auto &router = wildcard_patterns.back().router; auto &router = wildcard_patterns.back().router;
router.add_route(path, idx); router.add_route(path, idx);
auto rev_host = host.str(); auto iov = make_byte_ref(downstreamconf.balloc, host.size() + 1);
std::reverse(std::begin(rev_host), std::end(rev_host)); auto p = iov.base;
p = std::reverse_copy(std::begin(host), std::end(host), p);
*p = '\0';
auto rev_host = StringRef{iov.base, p};
rw_router.add_route(StringRef{rev_host}, wildcard_patterns.size() - 1); rw_router.add_route(rev_host, wildcard_patterns.size() - 1);
} else { } else {
(*it).router.add_route(path, idx); (*it).router.add_route(path, idx);
} }
@ -897,7 +913,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
continue; continue;
} }
router.add_route(StringRef{g.pattern}, idx); router.add_route(g.pattern, idx);
} }
return 0; return 0;
} }
@ -1804,12 +1820,14 @@ int parse_config(Config *config, int optid, const StringRef &opt,
switch (optid) { switch (optid) {
case SHRPX_OPTID_BACKEND: { case SHRPX_OPTID_BACKEND: {
auto &downstreamconf = *config->conn.downstream;
auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';'); auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
DownstreamAddrConfig addr{}; DownstreamAddrConfig addr{};
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size(); auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size();
addr.host = ImmutableString(path, addr_end); addr.host =
make_string_ref(downstreamconf.balloc, StringRef{path, addr_end});
addr.host_unix = true; addr.host_unix = true;
} else { } else {
if (split_host_port(host, sizeof(host), &port, if (split_host_port(host, sizeof(host), &port,
@ -1817,7 +1835,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return -1; return -1;
} }
addr.host = ImmutableString(host); addr.host = make_string_ref(downstreamconf.balloc, StringRef{host});
addr.port = port; addr.port = port;
} }
@ -3071,13 +3089,13 @@ int configure_downstream_group(Config *config, bool http2_proxy,
if (addr_groups.empty()) { if (addr_groups.empty()) {
DownstreamAddrConfig addr{}; DownstreamAddrConfig addr{};
addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST); addr.host = StringRef::from_lit(DEFAULT_DOWNSTREAM_HOST);
addr.port = DEFAULT_DOWNSTREAM_PORT; addr.port = DEFAULT_DOWNSTREAM_PORT;
addr.proto = PROTO_HTTP1; addr.proto = PROTO_HTTP1;
DownstreamAddrGroupConfig g(StringRef::from_lit("/")); DownstreamAddrGroupConfig g(StringRef::from_lit("/"));
g.addrs.push_back(std::move(addr)); g.addrs.push_back(std::move(addr));
router.add_route(StringRef{g.pattern}, addr_groups.size()); router.add_route(g.pattern, addr_groups.size());
addr_groups.push_back(std::move(g)); addr_groups.push_back(std::move(g));
} else if (http2_proxy) { } else if (http2_proxy) {
// We don't support host mapping in these cases. Move all // We don't support host mapping in these cases. Move all
@ -3090,7 +3108,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
std::vector<DownstreamAddrGroupConfig>().swap(addr_groups); std::vector<DownstreamAddrGroupConfig>().swap(addr_groups);
// maybe not necessary? // maybe not necessary?
routerconf = RouterConfig{}; routerconf = RouterConfig{};
router.add_route(StringRef{catch_all.pattern}, addr_groups.size()); router.add_route(catch_all.pattern, addr_groups.size());
addr_groups.push_back(std::move(catch_all)); addr_groups.push_back(std::move(catch_all));
} }
@ -3100,7 +3118,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
auto &sni = tlsconf.backend_sni_name; auto &sni = tlsconf.backend_sni_name;
for (auto &addr_group : addr_groups) { for (auto &addr_group : addr_groups) {
for (auto &addr : addr_group.addrs) { for (auto &addr : addr_group.addrs) {
addr.sni = ImmutableString{sni}; addr.sni = StringRef{sni};
} }
} }
} }
@ -3147,7 +3165,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
// for AF_UNIX socket, we use "localhost" as host for backend // for AF_UNIX socket, we use "localhost" as host for backend
// hostport. This is used as Host header field to backend and // hostport. This is used as Host header field to backend and
// not going to be passed to any syscalls. // not going to be passed to any syscalls.
addr.hostport = ImmutableString::from_lit("localhost"); addr.hostport = StringRef::from_lit("localhost");
auto path = addr.host.c_str(); auto path = addr.host.c_str();
auto pathlen = addr.host.size(); auto pathlen = addr.host.size();
@ -3171,10 +3189,11 @@ int configure_downstream_group(Config *config, bool http2_proxy,
continue; continue;
} }
addr.hostport = ImmutableString( addr.hostport =
util::make_http_hostport(StringRef(addr.host), addr.port)); util::make_http_hostport(downstreamconf.balloc, addr.host, addr.port);
auto hostport = util::make_hostport(StringRef{addr.host}, addr.port); auto hostport =
util::make_hostport(downstreamconf.balloc, addr.host, addr.port);
if (resolve_hostname(&addr.addr, addr.host.c_str(), addr.port, if (resolve_hostname(&addr.addr, addr.host.c_str(), addr.port,
downstreamconf.family, resolve_flags) == -1) { downstreamconf.family, resolve_flags) == -1) {

View File

@ -54,6 +54,7 @@
#include "template.h" #include "template.h"
#include "http2.h" #include "http2.h"
#include "network.h" #include "network.h"
#include "allocator.h"
using namespace nghttp2; using namespace nghttp2;
@ -375,13 +376,13 @@ struct UpstreamAddr {
struct DownstreamAddrConfig { struct DownstreamAddrConfig {
Address addr; Address addr;
// backend address. If |host_unix| is true, this is UNIX domain // backend address. If |host_unix| is true, this is UNIX domain
// socket path. // socket path. This must be NULL terminated string.
ImmutableString host; StringRef host;
// <HOST>:<PORT>. This does not treat 80 and 443 specially. If // <HOST>:<PORT>. This does not treat 80 and 443 specially. If
// |host_unix| is true, this is "localhost". // |host_unix| is true, this is "localhost".
ImmutableString hostport; StringRef hostport;
// hostname sent as SNI field // hostname sent as SNI field
ImmutableString sni; StringRef sni;
size_t fall; size_t fall;
size_t rise; size_t rise;
// Application protocol used in this group // Application protocol used in this group
@ -404,9 +405,9 @@ struct AffinityHash {
struct DownstreamAddrGroupConfig { struct DownstreamAddrGroupConfig {
DownstreamAddrGroupConfig(const StringRef &pattern) DownstreamAddrGroupConfig(const StringRef &pattern)
: pattern(pattern.c_str(), pattern.size()), affinity(AFFINITY_NONE) {} : pattern(pattern), affinity(AFFINITY_NONE) {}
ImmutableString pattern; StringRef pattern;
std::vector<DownstreamAddrConfig> addrs; std::vector<DownstreamAddrConfig> addrs;
// Bunch of session affinity hash. Only used if affinity == // Bunch of session affinity hash. Only used if affinity ==
// AFFINITY_IP. // AFFINITY_IP.
@ -655,10 +656,11 @@ struct RateLimitConfig {
// field. router includes all path patterns sharing the same wildcard // field. router includes all path patterns sharing the same wildcard
// host. // host.
struct WildcardPattern { struct WildcardPattern {
WildcardPattern(const StringRef &host) WildcardPattern(const StringRef &host) : host(host) {}
: host(std::begin(host), std::end(host)) {}
ImmutableString host; // This may not be NULL terminated. Currently it is only used for
// comparison.
StringRef host;
Router router; Router router;
}; };
@ -676,7 +678,8 @@ struct RouterConfig {
struct DownstreamConfig { struct DownstreamConfig {
DownstreamConfig() DownstreamConfig()
: timeout{}, : balloc(1024, 1024),
timeout{},
addr_group_catch_all{0}, addr_group_catch_all{0},
connections_per_host{0}, connections_per_host{0},
connections_per_frontend{0}, connections_per_frontend{0},
@ -684,6 +687,12 @@ struct DownstreamConfig {
response_buffer_size{0}, response_buffer_size{0},
family{0} {} family{0} {}
DownstreamConfig(const DownstreamConfig &) = delete;
DownstreamConfig(DownstreamConfig &&) = delete;
DownstreamConfig &operator=(const DownstreamConfig &) = delete;
DownstreamConfig &operator=(DownstreamConfig &&) = delete;
BlockAllocator balloc;
struct { struct {
ev_tstamp read; ev_tstamp read;
ev_tstamp write; ev_tstamp write;

View File

@ -182,7 +182,8 @@ void Worker::replace_downstream_config(
auto &dst = downstream_addr_groups_[i]; auto &dst = downstream_addr_groups_[i];
dst = std::make_shared<DownstreamAddrGroup>(); dst = std::make_shared<DownstreamAddrGroup>();
dst->pattern = src.pattern; dst->pattern =
ImmutableString{std::begin(src.pattern), std::end(src.pattern)};
auto shared_addr = std::make_shared<SharedDownstreamAddr>(); auto shared_addr = std::make_shared<SharedDownstreamAddr>();
@ -198,16 +199,14 @@ void Worker::replace_downstream_config(
auto &dst_addr = shared_addr->addrs[j]; auto &dst_addr = shared_addr->addrs[j];
dst_addr.addr = src_addr.addr; dst_addr.addr = src_addr.addr;
dst_addr.host = dst_addr.host = make_string_ref(shared_addr->balloc, src_addr.host);
make_string_ref(shared_addr->balloc, StringRef{src_addr.host});
dst_addr.hostport = dst_addr.hostport =
make_string_ref(shared_addr->balloc, StringRef{src_addr.hostport}); make_string_ref(shared_addr->balloc, src_addr.hostport);
dst_addr.port = src_addr.port; dst_addr.port = src_addr.port;
dst_addr.host_unix = src_addr.host_unix; dst_addr.host_unix = src_addr.host_unix;
dst_addr.proto = src_addr.proto; dst_addr.proto = src_addr.proto;
dst_addr.tls = src_addr.tls; dst_addr.tls = src_addr.tls;
dst_addr.sni = dst_addr.sni = make_string_ref(shared_addr->balloc, src_addr.sni);
make_string_ref(shared_addr->balloc, StringRef{src_addr.sni});
dst_addr.fall = src_addr.fall; dst_addr.fall = src_addr.fall;
dst_addr.rise = src_addr.rise; dst_addr.rise = src_addr.rise;

View File

@ -1172,6 +1172,32 @@ std::string make_http_hostport(const StringRef &host, uint16_t port) {
return hostport; return hostport;
} }
StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port) {
if (port != 80 && port != 443) {
return make_hostport(balloc, host, port);
}
auto ipv6 = ipv6_numeric_addr(host.c_str());
auto iov = make_byte_ref(balloc, host.size() + (ipv6 ? 2 : 0) + 1);
auto p = iov.base;
if (ipv6) {
*p++ = '[';
}
p = std::copy(std::begin(host), std::end(host), p);
if (ipv6) {
*p++ = ']';
}
*p = '\0';
return StringRef{iov.base, p};
}
std::string make_hostport(const StringRef &host, uint16_t port) { std::string make_hostport(const StringRef &host, uint16_t port) {
auto ipv6 = ipv6_numeric_addr(host.c_str()); auto ipv6 = ipv6_numeric_addr(host.c_str());
auto serv = utos(port); auto serv = utos(port);
@ -1197,6 +1223,34 @@ std::string make_hostport(const StringRef &host, uint16_t port) {
return hostport; return hostport;
} }
StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port) {
auto ipv6 = ipv6_numeric_addr(host.c_str());
auto serv = utos(port);
auto iov =
make_byte_ref(balloc, host.size() + (ipv6 ? 2 : 0) + 1 + serv.size());
auto p = iov.base;
if (ipv6) {
*p++ = '[';
}
p = std::copy(std::begin(host), std::end(host), p);
if (ipv6) {
*p++ = ']';
}
*p++ = ':';
std::copy(std::begin(serv), std::end(serv), p);
*p = '\0';
return StringRef{iov.base, p};
}
namespace { namespace {
void hexdump8(FILE *out, const uint8_t *first, const uint8_t *last) { void hexdump8(FILE *out, const uint8_t *first, const uint8_t *last) {
auto stop = std::min(first + 8, last); auto stop = std::min(first + 8, last);

View File

@ -635,10 +635,16 @@ std::string format_duration(double t);
// and "]". If |port| is 80 or 443, port part is omitted. // and "]". If |port| is 80 or 443, port part is omitted.
std::string make_http_hostport(const StringRef &host, uint16_t port); std::string make_http_hostport(const StringRef &host, uint16_t port);
StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port);
// Just like make_http_hostport(), but doesn't treat 80 and 443 // Just like make_http_hostport(), but doesn't treat 80 and 443
// specially. // specially.
std::string make_hostport(const StringRef &host, uint16_t port); std::string make_hostport(const StringRef &host, uint16_t port);
StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port);
// Dumps |src| of length |len| in the format similar to `hexdump -C`. // Dumps |src| of length |len| in the format similar to `hexdump -C`.
void hexdump(FILE *out, const uint8_t *src, size_t len); void hexdump(FILE *out, const uint8_t *src, size_t len);