]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: peers: Save date of the last update to wake the peer applet
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 14 Oct 2025 12:02:05 +0000 (14:02 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 17 Oct 2025 14:38:53 +0000 (16:38 +0200)
Instead of looking for new updates in each updates lists to wake a peer
applet up, we now only detect that some updates should have been inserted by
comparing the date of the last update inserted in the list and the last
update sent to the peer.

It is not 100% accurrate of course. Some extra wakeups may be observed. But
this should not lead to any spinning loop because the operation is performed
by the sync task. This task is woken up when a timeout is fired or when an
update was inserted. However, this saves several loops on the updates lists.

include/haproxy/peers-t.h
include/haproxy/stick_table-t.h
src/peers.c
src/stick_table.c

index fd5da5f251c32c5b4778873cd1d0de249dccf441..067d711d45967cdc066f9650f56ee08bef6fb4c6 100644 (file)
@@ -164,6 +164,7 @@ struct peer {
        unsigned int heartbeat;       /* next heartbeat timer */
        unsigned int confirm;         /* confirm message counter */
        unsigned int last_hdshk;      /* Date of the last handshake. */
+       unsigned int last_update;     /* Date of last update sent */
        uint32_t rx_hbt;              /* received heartbeats counter */
        uint32_t tx_hbt;              /* transmitted heartbeats counter */
        uint32_t no_hbt;              /* no received heartbeat counter */
index 76771da461f83cfa544408b0994ba2b3134c8c8b..81427348f1836c4774e612f0a7653cb96cd85a94 100644 (file)
@@ -230,7 +230,7 @@ struct stktable {
        __decl_thread(HA_RWLOCK_T lock); /* lock related to the table */
 
        THREAD_ALIGN(64);
-
+       unsigned int   last_update; /* Date of the last update inserted in the list */
        struct mt_list updates;     /* list of sticky updates sequence */
        struct mt_list *pend_updts; /* list of updates to be added to the update sequence list, one per thread-group */
        struct tasklet *updt_task;/* tasklet responsible for pushing the pending updates into the tree */
index 3ef6052fafc28940d81db58908a4e9de6c618396..41e3585245ccf347fe13a2ad239f00f326146e8e 100644 (file)
@@ -1634,6 +1634,7 @@ int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, struct shared_tab
                p->last.id = st->update_id;
                st->update_id++;
                p->flags &= ~PEER_F_SYNCHED;
+               p->last_update = now_ms;
 
                /* identifier may not needed in next update message */
                new_pushed = 0;
@@ -3521,18 +3522,9 @@ static void __process_running_peer_sync(struct task *task, struct peers *peers,
 
                                        /* Awake session if there is data to push */
                                        for (st = peer->tables; st ; st = st->next) {
-                                               struct stksess *ts;
-                                               struct mt_list back;
-
-                                               // TODO: may be handled via an atomic flags ?
-                                               MT_LIST_FOR_EACH_ENTRY_LOCKED(ts, &st->last->upd, upd, back) {
-                                                       if (&ts->upd == &st->table->updates)
-                                                               break;
-                                                       if (&ts->upd != &st->table->updates && ts->updt_type == STKSESS_UPDT_LOCAL) {
-                                                               update_to_push = 1;
-                                                               break;
-                                                       }
-                                               }
+                                               if (tick_is_le(peer->last_update, st->table->last_update))
+                                                       update_to_push = 1;
+
                                                if (update_to_push == 1) {
                                                        /* wake up the peer handler to push local updates */
                                                        /* There is no need to send a heartbeat message
@@ -3721,17 +3713,7 @@ static void __process_stopping_peer_sync(struct task *task, struct peers *peers,
                /* current peer connection is active and established
                 * wake up all peer handlers to push remaining local updates */
                for (st = peer->tables; st ; st = st->next) {
-                       struct stksess *ts;
-                       struct mt_list back;
-                       int wakeup = 0;
-
-                       MT_LIST_FOR_EACH_ENTRY_LOCKED(ts, &st->last->upd, upd, back) {
-                               if (&ts->upd != &st->table->updates && ts->updt_type == STKSESS_UPDT_LOCAL) {
-                                       wakeup = 1;
-                                       break;
-                               }
-                       }
-                       if (wakeup) {
+                       if (tick_is_le(peer->last_update, st->table->last_update)) {
                                appctx_wakeup(peer->appctx);
                                break;
                        }
index 55a80280ddbe2a5db238514db5d5e5009fbf0220..7f197478e61e06746c3e2b101205bdc40f6b5663 100644 (file)
@@ -840,6 +840,7 @@ struct task *stktable_add_pend_updates(struct task *t, void *ctx, unsigned int s
 
        if (i > 0) {
                /* We did at least one update, let's wake the sync task */
+               table->last_update = now_ms;
                task_wakeup(table->sync_task, TASK_WOKEN_MSG);
        }
        return t;
@@ -1125,6 +1126,7 @@ int stktable_init(struct stktable *t, char **err_msg)
        for (i = 0; i < global.nbtgroups; i++)
                MT_LIST_INIT(&t->pend_updts[i]);
        t->updt_task = tasklet_new();
+       t->last_update = TICK_ETERNITY;
        if (!t->updt_task)
                goto mem_error;
        t->updt_task->context = t;