changeset 3137:5a3b961e9524

New configuration option: 'TcpNoDelay' to disable Nagle's algorithm in HTTP server
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 17 Jan 2019 18:24:23 +0100
parents f948deef53d9
children ab46e537f92e
files Core/HttpServer/MongooseServer.cpp Core/HttpServer/MongooseServer.h NEWS OrthancServer/main.cpp Resources/Configuration.json
diffstat 5 files changed, 57 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/MongooseServer.cpp	Thu Jan 17 16:26:44 2019 +0100
+++ b/Core/HttpServer/MongooseServer.cpp	Thu Jan 17 18:24:23 2019 +0100
@@ -934,6 +934,7 @@
     exceptionFormatter_ = NULL;
     realm_ = ORTHANC_REALM;
     threadsCount_ = 50;  // Default value in mongoose
+    tcpNoDelay_ = true;
 
 #if ORTHANC_ENABLE_SSL == 1
     // Check for the Heartbleed exploit
@@ -994,8 +995,10 @@
 
 #if ORTHANC_ENABLE_CIVETWEB == 1
         // Disable TCP Nagle's algorithm to maximize speed (this
-        // option is not available in Mongoose)
-        "tcp_nodelay", "1",
+        // option is not available in Mongoose).
+        // https://groups.google.com/d/topic/civetweb/35HBR9seFjU/discussion
+        // https://eklitzke.org/the-caveats-of-tcp-nodelay
+        "tcp_nodelay", (tcpNoDelay_ ? "1" : "0"),
 #endif
 
         // Set the number of threads
@@ -1086,6 +1089,13 @@
     Stop();
     keepAlive_ = enabled;
     LOG(INFO) << "HTTP keep alive is " << (enabled ? "enabled" : "disabled");
+
+#if ORTHANC_ENABLE_MONGOOSE == 1
+    if (enabled)
+    {
+      LOG(WARNING) << "You should disable HTTP keep alive, as you are using Mongoose";
+    }
+#endif
   }
 
 
@@ -1162,4 +1172,13 @@
     Stop();
     threadsCount_ = threads;
   }
+
+
+  void MongooseServer::SetTcpNoDelay(bool tcpNoDelay)
+  {
+    Stop();
+    tcpNoDelay_ = tcpNoDelay;
+    LOG(INFO) << "TCP_NODELAY for the HTTP sockets is set to "
+              << (tcpNoDelay ? "true" : "false");
+  }
 }
--- a/Core/HttpServer/MongooseServer.h	Thu Jan 17 16:26:44 2019 +0100
+++ b/Core/HttpServer/MongooseServer.h	Thu Jan 17 18:24:23 2019 +0100
@@ -97,6 +97,7 @@
     IHttpExceptionFormatter* exceptionFormatter_;
     std::string realm_;
     unsigned int threadsCount_;
+    bool tcpNoDelay_;
   
     bool IsRunning() const;
 
@@ -206,5 +207,13 @@
     {
       return threadsCount_;
     }
+
+    // New in Orthanc 1.5.2, not available for Mongoose
+    void SetTcpNoDelay(bool tcpNoDelay);
+
+    bool IsTcpNoDelay() const
+    {
+      return tcpNoDelay_;
+    }
   };
 }
--- a/NEWS	Thu Jan 17 16:26:44 2019 +0100
+++ b/NEWS	Thu Jan 17 18:24:23 2019 +0100
@@ -1,6 +1,11 @@
 Pending changes in the mainline
 ===============================
 
+General
+-------
+
+* New configuration option: "TcpNoDelay" to disable Nagle's algorithm in HTTP server
+
 Maintenance
 -----------
 
--- a/OrthancServer/main.cpp	Thu Jan 17 16:26:44 2019 +0100
+++ b/OrthancServer/main.cpp	Thu Jan 17 18:24:23 2019 +0100
@@ -800,6 +800,14 @@
     MongooseServer httpServer;
     bool httpDescribeErrors;
 
+#if ORTHANC_ENABLE_MONGOOSE == 1
+    const bool defaultKeepAlive = false;
+#elif ORTHANC_ENABLE_CIVETWEB == 1
+    const bool defaultKeepAlive = true;
+#else
+#  error "Either Mongoose or Civetweb must be enabled to compile this file"
+#endif
+  
     {
       OrthancConfiguration::ReaderLock lock;
       
@@ -809,9 +817,10 @@
       //httpServer.SetThreadsCount(50);
       httpServer.SetPortNumber(lock.GetConfiguration().GetUnsignedIntegerParameter("HttpPort", 8042));
       httpServer.SetRemoteAccessAllowed(lock.GetConfiguration().GetBooleanParameter("RemoteAccessAllowed", false));
-      httpServer.SetKeepAliveEnabled(lock.GetConfiguration().GetBooleanParameter("KeepAlive", true));
+      httpServer.SetKeepAliveEnabled(lock.GetConfiguration().GetBooleanParameter("KeepAlive", defaultKeepAlive));
       httpServer.SetHttpCompressionEnabled(lock.GetConfiguration().GetBooleanParameter("HttpCompressionEnabled", true));
       httpServer.SetAuthenticationEnabled(lock.GetConfiguration().GetBooleanParameter("AuthenticationEnabled", false));
+      httpServer.SetTcpNoDelay(lock.GetConfiguration().GetBooleanParameter("TcpNoDelay", true));
 
       lock.GetConfiguration().SetupRegisteredUsers(httpServer);
 
--- a/Resources/Configuration.json	Thu Jan 17 16:26:44 2019 +0100
+++ b/Resources/Configuration.json	Thu Jan 17 18:24:23 2019 +0100
@@ -349,11 +349,20 @@
   // Enable or disable HTTP Keep-Alive (persistent HTTP
   // connections). Setting this option to "true" prevents Orthanc
   // issue #32 ("HttpServer does not support multiple HTTP requests in
-  // the same TCP stream"), but can slow down HTTP clients that do not
-  // support persistent connections. The default behavior used to be
-  // "false" in Orthanc <= 1.5.1.
+  // the same TCP stream"), but can possibly slow down HTTP clients
+  // that do not support persistent connections. The default behavior
+  // used to be "false" in Orthanc <= 1.5.1. Setting this option to
+  // "false" is also recommended if Orthanc is compiled against
+  // Mongoose.
   "KeepAlive" : true,
 
+  // Enable or disable Nagle's algorithm. Only taken into
+  // consideration if Orthanc is compiled to use CivetWeb. Experiments
+  // show that best performance can be obtained by setting both
+  // "KeepAlive" and "TcpNoDelay" to "true". Beware however of
+  // caveats: https://eklitzke.org/the-caveats-of-tcp-nodelay
+  "TcpNoDelay" : true,
+
   // If this option is set to "false", Orthanc will run in index-only
   // mode. The DICOM files will not be stored on the drive. Note that
   // this option might prevent the upgrade to newer versions of Orthanc.