]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: servers: Use server_full to detect if a server is full 20260302-oho-server-optims
authorOlivier Houchard <ohouchard@haproxy.com>
Mon, 9 Feb 2026 10:20:40 +0000 (11:20 +0100)
committerOlivier Houchard <cognet@ci0.org>
Mon, 2 Mar 2026 12:46:17 +0000 (13:46 +0100)
Instead of checking the value of served to know if the server is full,
make use of the newly introduced server_full where relevant, so that we
have less access to served.

include/haproxy/queue.h
include/haproxy/server-t.h
src/backend.c
src/server.c

index 1b02e1aca72d4b99f34d0bc94e3a8dde6c71b540..2b1d0f38475f727de777dba0a84c4ba8fc418e5c 100644 (file)
@@ -78,7 +78,8 @@ static inline void pendconn_free(struct stream *s)
 
 /* Returns 0 if all slots are full on a server, or 1 if there are slots available. */
 static inline int server_has_room(const struct server *s) {
-       return !s->maxconn || s->served < srv_dynamic_maxconn(s);
+       return ((s->server_max_static && !s->server_full) ||
+               (!s->server_max_static && (!s->maxconn || s->served < srv_dynamic_maxconn(s))));
 }
 
 /* returns 0 if nothing has to be done for server <s> regarding queued connections,
@@ -86,8 +87,8 @@ static inline int server_has_room(const struct server *s) {
  * for and if/else usage.
  */
 static inline int may_dequeue_tasks(const struct server *s, const struct proxy *p) {
-       return (s && (s->queues_not_empty || (p->queues_not_empty && srv_currently_usable(s))) &&
-               (!s->maxconn || s->served < srv_dynamic_maxconn(s)));
+       return (s && server_has_room(s) &&
+               (s->queues_not_empty || (p->queues_not_empty && srv_currently_usable(s))));
 }
 
 static inline int queue_limit_class(int class)
index b08a7a8076c9d815545b3a34072118fb58bf4e5f..300b0e74d0bdf2329ebd9513ed39bd457bfb1649 100644 (file)
@@ -555,6 +555,7 @@ struct server {
        __decl_thread(HA_SPINLOCK_T state_lock);/* protect the following state fields */
        uint8_t queues_not_empty;               /* Are the request queues not empty ? Only changed when the queues go from non-empty to empty, and vice-versa. Protected by the state_lock lock when changed */
        uint8_t server_full;                    /* we reached maxconn, and can no longer process more requests, protected by the state_lock */
+       uint8_t server_max_static;              /* the number of max requests for the server is static, and thus server_full can reliably be used */
 };
 
 /* data provided to EVENT_HDL_SUB_SERVER handlers through event_hdl facility */
index 5ff2732727f51a671476d1e18944a3fcbff153d5..444667de59d54bf540cc279278ca69b243a7949f 100644 (file)
@@ -597,7 +597,7 @@ struct server *get_server_rnd(struct stream *s, const struct server *avoid)
         * the backend's queue instead.
         */
        if (curr &&
-           (curr->queues_not_empty || (curr->maxconn && curr->served >= srv_dynamic_maxconn(curr))))
+           (curr->queues_not_empty || !server_has_room(curr)))
                curr = NULL;
 
        return curr;
index d888988f4b3471f5d552295d7f6665ac2eab783f..551c152cf5a82d80c9b0ba24eca4a6c7f2ec999e 100644 (file)
@@ -3603,6 +3603,8 @@ int srv_postinit(struct server *srv)
                        goto out;
                }
        }
+       if (!srv->slowstart && srv->minconn == srv->maxconn)
+               srv->server_max_static = 1;
 
  out:
        return err_code;
@@ -5948,12 +5950,19 @@ static struct task *server_warmup(struct task *t, void *context, unsigned int st
        /* probably that we can refill this server with a bit more connections */
        process_srv_queue(s, &full);
 
+       if (s->maxconn) {
+               HA_SPIN_LOCK(SERVER_LOCK, &s->state_lock);
+               s->server_full = (s->served >= s->maxconn);
+               HA_SPIN_UNLOCK(SERVER_LOCK, &s->state_lock);
+       }
 
        /* get back there in 1 second or 1/20th of the slowstart interval,
         * whichever is greater, resulting in small 5% steps.
         */
        if (s->next_state == SRV_ST_STARTING)
                t->expire = tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)));
+       else if (s->minconn == s->maxconn)
+               s->server_max_static = 1;
        return t;
 }
 
@@ -6786,6 +6795,11 @@ static int _srv_update_status_op(struct server *s, enum srv_op_st_chg_cause caus
                 */
                xferred = process_srv_queue(s, &full);
 
+               if (s->maxconn) {
+                       HA_SPIN_LOCK(SERVER_LOCK, &s->state_lock);
+                       s->server_full = (s->served >= s->maxconn);
+                       HA_SPIN_UNLOCK(SERVER_LOCK, &s->state_lock);
+               }
                tmptrash = alloc_trash_chunk();
                if (tmptrash) {
                        chunk_printf(tmptrash,
@@ -6985,6 +6999,11 @@ static int _srv_update_status_adm(struct server *s, enum srv_adm_st_chg_cause ca
                 * We will take as many as we can handle.
                 */
                xferred = process_srv_queue(s, &full);
+               if (s->maxconn) {
+                       HA_SPIN_LOCK(SERVER_LOCK, &s->state_lock);
+                       s->server_full = (s->served >= s->maxconn);
+                       HA_SPIN_UNLOCK(SERVER_LOCK, &s->state_lock);
+               }
        }
        else if (s->next_admin & SRV_ADMF_MAINT) {
                /* remaining in maintenance mode, let's inform precisely about the