]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: config: properly adjust maxconn with nbproc when memmax is forced
authorWilly Tarreau <w@1wt.eu>
Mon, 14 Dec 2015 11:46:07 +0000 (12:46 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 14 Dec 2015 12:03:09 +0000 (13:03 +0100)
When memmax is forced using "-m", the per-process memory limit is enforced
using setrlimit(), but this value is not used to compute the automatic
maxconn limit. In addition, the per-process memory limit didn't consider
the fact that the shared SSL cache only needs to be accounted once.

The doc was also fixed to clearly state that "-m" is global and not per
process. It makes sense because people who use -m want to protect the
system's resources regardless of whatever appears in the configuration.

doc/management.txt
include/types/global.h
src/haproxy.c

index a53a953a3cde9a895b05d3d54fbdfd44f47ced26..e770b794c27e119b3d2e7c7ef2e7a981fb30a29f 100644 (file)
@@ -223,11 +223,13 @@ list of options is :
     generally be the "select" poller, which cannot be disabled and is limited
     to 1024 file descriptors.
 
-  -m <limit> : limit the total allocatable memory to <limit> megabytes per
-    process. This may cause some connection refusals or some slowdowns
+  -m <limit> : limit the total allocatable memory to <limit> megabytes across
+    all processes. This may cause some connection refusals or some slowdowns
     depending on the amount of memory needed for normal operations. This is
-    mostly used to force the process to work in a constrained resource usage
-    scenario.
+    mostly used to force the processes to work in a constrained resource usage
+    scenario. It is important to note that the memory is not shared between
+    processes, so in a multi-process scenario, this value is first divided by
+    global.nbproc before forking.
 
   -n <limit> : limits the per-process connection limit to <limit>. This is
     equivalent to the global section's keyword "maxconn". It has precedence
index ca96193df4523a93b3d888011c41816a89014b60..61f039167608410c650201b38210039e6d8150cd 100644 (file)
@@ -115,7 +115,8 @@ struct global {
        int maxpipes;           /* max # of pipes */
        int maxsock;            /* max # of sockets */
        int rlimit_nofile;      /* default ulimit-n value : 0=unset */
-       int rlimit_memmax;      /* default ulimit-d in megs value : 0=unset */
+       int rlimit_memmax_all;  /* default all-process memory limit in megs ; 0=unset */
+       int rlimit_memmax;      /* default per-process memory limit in megs ; 0=unset */
        long maxzlibmem;        /* max RAM for zlib in bytes */
        int mode;
        unsigned int req_count; /* request counter (HTTP or TCP session) for logs and unique_id */
index 5cd337998b2f27ac4f72d018a80773c70cb8b174..21a5e1286de8c4b1ebbca71c7f9f5c814c85f054 100644 (file)
@@ -581,7 +581,7 @@ void init(int argc, char **argv)
     
 
 #ifdef HAPROXY_MEMMAX
-       global.rlimit_memmax = HAPROXY_MEMMAX;
+       global.rlimit_memmax_all = HAPROXY_MEMMAX;
 #endif
 
        tv_update_date(-1,-1);
@@ -729,7 +729,7 @@ void init(int argc, char **argv)
                                switch (*flag) {
                                case 'C' : change_dir = *argv; break;
                                case 'n' : cfg_maxconn = atol(*argv); break;
-                               case 'm' : global.rlimit_memmax = atol(*argv); break;
+                               case 'm' : global.rlimit_memmax_all = atol(*argv); break;
                                case 'N' : cfg_maxpconn = atol(*argv); break;
                                case 'L' : strncpy(localpeer, *argv, sizeof(localpeer) - 1); break;
                                case 'f' :
@@ -794,6 +794,22 @@ void init(int argc, char **argv)
                exit(1);
        }
 
+       /* recompute the amount of per-process memory depending on nbproc and
+        * the shared SSL cache size (allowed to exist in all processes).
+        */
+       if (global.rlimit_memmax_all) {
+#if defined (USE_OPENSSL) && !defined(USE_PRIVATE_CACHE)
+               int64_t ssl_cache_bytes = global.tune.sslcachesize * 200LL;
+
+               global.rlimit_memmax =
+                       ((((int64_t)global.rlimit_memmax_all * 1048576LL) -
+                         ssl_cache_bytes) / global.nbproc +
+                        ssl_cache_bytes + 1048575LL) / 1048576LL;
+#else
+               global.rlimit_memmax = global.rlimit_memmax_all / global.nbproc;
+#endif
+       }
+
 #ifdef CONFIG_HAP_NS
         err_code |= netns_init();
         if (err_code & (ERR_ABORT|ERR_FATAL)) {
@@ -1645,7 +1661,7 @@ int main(int argc, char **argv)
 
        if (global.rlimit_memmax) {
                limit.rlim_cur = limit.rlim_max =
-                       global.rlimit_memmax * 1048576ULL / global.nbproc;
+                       global.rlimit_memmax * 1048576ULL;
 #ifdef RLIMIT_AS
                if (setrlimit(RLIMIT_AS, &limit) == -1) {
                        Warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",