Commit cf08bdfc authored by jan.koester's avatar jan.koester
Browse files

test

parent 77747035
Loading
Loading
Loading
Loading
+18 −12
Changes for src/http/HttpProxyServer.cpp: 18 added lines, 12 removed lines.
Original line number Diff line number Diff line
@@ -118,7 +118,8 @@ HttpProxyController::HttpProxyController(std::vector<netplus::socket *> serverSo
                                          tls::AcmeChallengeStore *acmeChallenges,
                                          int idleTimeoutSeconds,
                                          int upstreamTimeoutSeconds,
                                          int h2DispatchQueueMax)
                                          int h2DispatchQueueMax,
                                          int h1DispatchQueueMax)
    // H2 dispatch now runs through the same offload pool as H1 (see shouldOffloadH2Dispatch
    // below): both RequestEvent calls do real backend I/O, so both need off the shared
    // epoll/kqueue listener workers to avoid one bursty connection starving new TLS
@@ -126,15 +127,15 @@ HttpProxyController::HttpProxyController(std::vector<netplus::socket *> serverSo
    // try/catch around RequestEvent (see httpd.cpp's _dispatchH2Stream) -- without it, a
    // backend exception left the stream queued forever with no HEADERS/DATA/RST_STREAM ever
    // sent. ALPN is left at HttpEvent's own default (prefer h2, fall back to http/1.1) below;
    // H3 stays independent via QUIC/Alt-Svc regardless. h2DispatchQueueMax bounds that same
    // pool's queue (see httpd.h) so a saturated/stuck pool degrades to 503 instead of every
    // subsequent stream -- on every connection -- queuing forever with no way to notice; see
    // BootstrapConfig.h's h2DispatchQueueMax doc comment for the incident this fixes.
    // H3 stays independent via QUIC/Alt-Svc regardless. h2DispatchQueueMax/h1DispatchQueueMax
    // bound those same pools' queues (see httpd.h) so a saturated/stuck pool degrades to 503
    // instead of every subsequent stream/request -- on every connection -- queuing forever
    // with no way to notice; see BootstrapConfig.h's doc comments for the incidents this fixes.
    : libhttppp::HttpEvent(serverSockets, /*timeout=*/1000,
                            /*h2OffloadThreads=*/(std::max<size_t>)(4, std::thread::hardware_concurrency() * 2),
                            idleTimeoutSeconds,
                            /*h1OffloadThreads=*/(std::max<size_t>)(4, std::thread::hardware_concurrency() * 2),
                            h2DispatchQueueMax)
                            h2DispatchQueueMax, h1DispatchQueueMax)
    , _listenerLabel(std::move(listenerLabel))
    , _tlsActive(tlsActive)
    , _configStore(configStore)
@@ -144,7 +145,8 @@ HttpProxyController::HttpProxyController(std::vector<netplus::socket *> serverSo
    , _connectionPool(connectionPool)
    , _acmeChallenges(acmeChallenges)
    , _upstreamTimeoutSeconds(upstreamTimeoutSeconds)
    , _h2DispatchQueueMax(h2DispatchQueueMax) {
    , _h2DispatchQueueMax(h2DispatchQueueMax)
    , _h1DispatchQueueMax(h1DispatchQueueMax) {
}

bool HttpProxyController::shouldOffloadH2Dispatch(libhttppp::HttpRequest &, uint32_t) const {
@@ -670,7 +672,8 @@ HttpProxyServer::HttpProxyServer(config::ListenerConfig listener, std::string ce
                                  tls::AcmeChallengeStore *acmeChallenges,
                                  int idleTimeoutSeconds,
                                  int upstreamTimeoutSeconds,
                                  int h2DispatchQueueMax)
                                  int h2DispatchQueueMax,
                                  int h1DispatchQueueMax)
    : _listener(listener)
    , _tlsActive(!listener.tlsProfile.empty())
    , _httpd(std::make_unique<libhttppp::HttpD>(listener.address, listener.port, 512, certPath,
@@ -683,7 +686,8 @@ HttpProxyServer::HttpProxyServer(config::ListenerConfig listener, std::string ce
    , _acmeChallenges(acmeChallenges)
    , _idleTimeoutSeconds(idleTimeoutSeconds)
    , _upstreamTimeoutSeconds(upstreamTimeoutSeconds)
    , _h2DispatchQueueMax(h2DispatchQueueMax) {
    , _h2DispatchQueueMax(h2DispatchQueueMax)
    , _h1DispatchQueueMax(h1DispatchQueueMax) {
    bindAndListen();
}

@@ -695,7 +699,8 @@ HttpProxyServer::HttpProxyServer(config::ListenerConfig listener,
                                  tls::AcmeChallengeStore *acmeChallenges,
                                  int idleTimeoutSeconds,
                                  int upstreamTimeoutSeconds,
                                  int h2DispatchQueueMax)
                                  int h2DispatchQueueMax,
                                  int h1DispatchQueueMax)
    : _listener(listener)
    , _tlsActive(true)
    , _httpd(std::make_unique<libhttppp::HttpD>(listener.address, listener.port, 512, certsByHostname))
@@ -707,7 +712,8 @@ HttpProxyServer::HttpProxyServer(config::ListenerConfig listener,
    , _acmeChallenges(acmeChallenges)
    , _idleTimeoutSeconds(idleTimeoutSeconds)
    , _upstreamTimeoutSeconds(upstreamTimeoutSeconds)
    , _h2DispatchQueueMax(h2DispatchQueueMax) {
    , _h2DispatchQueueMax(h2DispatchQueueMax)
    , _h1DispatchQueueMax(h1DispatchQueueMax) {
    bindAndListen();
}

@@ -728,7 +734,7 @@ void HttpProxyServer::run() {
                                    _tlsActive, _configStore, _authService, _pluginManager,
                                    _loadBalancer, _connectionPool, _acmeChallenges,
                                    _idleTimeoutSeconds, _upstreamTimeoutSeconds,
                                    _h2DispatchQueueMax);
                                    _h2DispatchQueueMax, _h1DispatchQueueMax);
    controller.runEventloop();
}

+8 −5
Changes for src/http/HttpProxyServer.h: 8 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -124,9 +124,9 @@ private:
// from a worker thread after privileges have been dropped.
class HttpProxyServer {
public:
    // idleTimeoutSeconds/upstreamTimeoutSeconds/h2DispatchQueueMax: see HttpProxyController's
    // own doc comment above -- threaded down into the controller it constructs internally in
    // run().
    // idleTimeoutSeconds/upstreamTimeoutSeconds/h2DispatchQueueMax/h1DispatchQueueMax: see
    // HttpProxyController's own doc comment above -- threaded down into the controller it
    // constructs internally in run().
    HttpProxyServer(config::ListenerConfig listener,
                     std::string certPath,
                     std::string keyPath,
@@ -138,7 +138,8 @@ public:
                     tls::AcmeChallengeStore *acmeChallenges = nullptr,
                     int idleTimeoutSeconds = 0,
                     int upstreamTimeoutSeconds = 60,
                     int h2DispatchQueueMax = 256);
                     int h2DispatchQueueMax = 256,
                     int h1DispatchQueueMax = 256);

    // SNI virtual hosting variant: certsByHostname carries one CertificateBundle per domain
    // sharing this listener (see ListenerConfig::tlsProfiles) instead of the single cert/key
@@ -153,7 +154,8 @@ public:
                     tls::AcmeChallengeStore *acmeChallenges = nullptr,
                     int idleTimeoutSeconds = 0,
                     int upstreamTimeoutSeconds = 60,
                     int h2DispatchQueueMax = 256);
                     int h2DispatchQueueMax = 256,
                     int h1DispatchQueueMax = 256);

    void run();

@@ -184,6 +186,7 @@ private:
    int _idleTimeoutSeconds;
    int _upstreamTimeoutSeconds;
    int _h2DispatchQueueMax;
    int _h1DispatchQueueMax;
};

} // namespace proxyplus::httpproxy
+3 −2
Changes for src/main.cpp: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -356,7 +356,8 @@ int main(int argc, char **argv) {
                    httpServers.push_back(std::make_unique<proxyplus::httpproxy::HttpProxyServer>(
                        listener, sniCerts, configStore, authService, pluginManager, loadBalancer,
                        connectionPool, &acmeChallenges, cfg.idleConnectionTimeoutSeconds,
                        cfg.upstreamRequestTimeoutSeconds, cfg.h2DispatchQueueMax));
                        cfg.upstreamRequestTimeoutSeconds, cfg.h2DispatchQueueMax,
                        cfg.h1DispatchQueueMax));
                    auto *server = httpServers.back().get();
                    auto allProfiles = configStore.listTlsProfiles();
                    for (const auto &profileName : tlsProfiles) {
@@ -378,7 +379,7 @@ int main(int argc, char **argv) {
                    listener, certPathFor(cfg, profile), keyPathFor(cfg, profile), configStore,
                    authService, pluginManager, loadBalancer, connectionPool, &acmeChallenges,
                    cfg.idleConnectionTimeoutSeconds, cfg.upstreamRequestTimeoutSeconds,
                    cfg.h2DispatchQueueMax));
                    cfg.h2DispatchQueueMax, cfg.h1DispatchQueueMax));
                if (!profile.empty()) {
                    auto *server = httpServers.back().get();
                    certManager.registerReloadCallback(profile, [server, &cfg, profile] {