Skip to content

Commit f2d7aa8

Browse files
committed
BUG/MEDIUM: peers: also limit the number of incoming updates
There's a configurable limit to the number of messages sent to a peer (tune.peers.max-updates-at-once), but this one is not applied to the receive side. While it can usually be OK with default settings, setups involving a large tune.bufsize (1MB and above) regularly experience high latencies and even watchdogs during reloads because the full learning process sends a lot of data that manages to fill the entire buffer, and due to the compactness of the protocol, 1MB of buffer can contain more than 100k updates, meaning taking locks etc during this time, which is not workable. Let's make sure the receiving side also respects the max-updates-at-once setting. For this it counts incoming updates, and refrains from continuing once the limit is reached. It's a bit tricky to do because after receiving updates we still have to send ours (and possibly some ACKs) so we cannot just leave the loop. This issue was reported on 3.1 but it should progressively be backported to all versions having the max-updates-at-once option available.
1 parent 098a5e5 commit f2d7aa8

File tree

1 file changed

+20
-0
lines changed

1 file changed

+20
-0
lines changed

src/peers.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2905,6 +2905,7 @@ static void peer_io_handler(struct appctx *appctx)
29052905
int repl = 0;
29062906
unsigned int maj_ver, min_ver;
29072907
int prev_state;
2908+
int msg_done = 0;
29082909

29092910
if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR)))) {
29102911
co_skip(sc_oc(sc), co_data(sc_oc(sc)));
@@ -3107,6 +3108,19 @@ static void peer_io_handler(struct appctx *appctx)
31073108
applet_wont_consume(appctx);
31083109
goto out;
31093110
}
3111+
3112+
/* check if we've already hit the rx limit (i.e. we've
3113+
* already gone through send_msgs and we don't want to
3114+
* process input messages again). We must absolutely
3115+
* leave via send_msgs otherwise we can leave the
3116+
* connection in a stuck state if acks are missing for
3117+
* example.
3118+
*/
3119+
if (msg_done >= peers_max_updates_at_once) {
3120+
applet_have_more_data(appctx); // make sure to come back here
3121+
goto send_msgs;
3122+
}
3123+
31103124
applet_will_consume(appctx);
31113125

31123126
/* local peer is assigned of a lesson, start it */
@@ -3128,6 +3142,12 @@ static void peer_io_handler(struct appctx *appctx)
31283142

31293143
/* skip consumed message */
31303144
co_skip(sc_oc(sc), totl);
3145+
3146+
/* make sure we don't process too many at once */
3147+
if (msg_done >= peers_max_updates_at_once)
3148+
goto send_msgs;
3149+
msg_done++;
3150+
31313151
/* loop on that state to peek next message */
31323152
goto switchstate;
31333153

0 commit comments

Comments
 (0)