]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: listener: automatically adjust shards based on support for SO_REUSEPORT
authorWilly Tarreau <w@1wt.eu>
Sat, 22 Apr 2023 09:38:55 +0000 (11:38 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 23 Apr 2023 07:46:15 +0000 (09:46 +0200)
Now if multiple shards are explicitly requested, and the listener's
protocol doesn't support SO_REUSEPORT, sharding is disabled, which will
result in the socket being automatically duped if needed. A warning is
emitted when this happens. If "shards by-group" or "shards by-thread"
are used, these will automatically be turned down to 1 since we want
this to be possible easily using -dR on the command line without having
to djust the config. For "by-thread", a diag warning will be emitted to
help troubleshoot possible performance issues.

doc/configuration.txt
src/listener.c

index 396fc5f566a4db0d6440aa5f4a6950baf808f0bf..d337c886c6e431d428e574b689001b4d7f6dcc4f 100644 (file)
@@ -15297,6 +15297,14 @@ shards <number> | by-thread | by-group
   sockets. The load distribution will be a bit less optimal but the contention
   (especially in the system) will still be lower than with a single socket.
 
+  On operating systems that do not support multiple sockets bound to the same
+  address, "by-thread" and "by-group" will automatically fall back to a single
+  shard. For "by-group" this is done without any warning since it doesn't
+  change anything for a single group, and will result in sockets being
+  duplicated for each group anyway. However, for "by-thread", a diagnostic
+  warning will be emitted if this happens since the resulting number of
+  listeners will not be the expected one.
+
 ssl
   This setting is only available when support for OpenSSL was built in. It
   enables SSL deciphering on connections instantiated from this listener. A
index 8a3aa7caf89dca8c14b988ecba499100c4ef38b0..45595cc69e76b08c01d0d0d0c0cb5a29cd8d7916 100644 (file)
@@ -1668,15 +1668,31 @@ int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code)
                todo = thread_set_count(&bind_conf->thread_set);
 
                /* special values: -1 = "by-thread", -2 = "by-group" */
-               if (shards == -1)
-                       shards = todo;
+               if (shards == -1) {
+                       if (li->rx.proto->flags & PROTO_F_REUSEPORT_SUPPORTED)
+                               shards = todo;
+                       else {
+                               if (fe != global.cli_fe)
+                                       ha_diag_warning("[%s:%d]: Disabling per-thread sharding for listener in"
+                                                       " %s '%s' because SO_REUSEPORT is disabled\n",
+                                                       bind_conf->file, bind_conf->line, proxy_type_str(fe), fe->id);
+                               shards = 1;
+                       }
+               }
                else if (shards == -2)
-                       shards = my_popcountl(bind_conf->thread_set.grps);
+                       shards = (li->rx.proto->flags & PROTO_F_REUSEPORT_SUPPORTED) ? my_popcountl(bind_conf->thread_set.grps) : 1;
 
                /* no more shards than total threads */
                if (shards > todo)
                        shards = todo;
 
+               /* We also need to check if an explicit shards count was set and cannot be honored */
+               if (shards > 1 && !(li->rx.proto->flags & PROTO_F_REUSEPORT_SUPPORTED)) {
+                       ha_warning("[%s:%d]: Disabling sharding for listener in %s '%s' because SO_REUSEPORT is disabled\n",
+                                  bind_conf->file, bind_conf->line, proxy_type_str(fe), fe->id);
+                       shards = 1;
+               }
+
                shard = done = grp = bit = mask = 0;
                new_li = li;