mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
BUG/MINOR: sink: add tempo between 2 connection attempts for sft servers
When the connection for sink_forward_{oc}_applet fails or a previous one is destroyed, the sft->appctx is instantly released. However process_sink_forward_task(), which may run at any time, iterates over all known sfts and tries to create sessions for orphan ones. It means that instantly after sft->appctx is destroyed, a new one will be created, thus a new connection attempt will be made. It can be an issue with tcp log-servers or sink servers, because if the server is unavailable, process_sink_forward() will keep looping without any temporisation until the applet survives (ie: connection succeeds), which results in unexpected CPU usage on the threads responsible for that task. Instead, we add a tempo logic so that a delay of 1second is applied between two retries. Of course the initial attempt is not delayed. This could be backported to all stable versions.
This commit is contained in:
parent
c9d4192726
commit
9561b9fb69
@ -40,6 +40,7 @@ enum sink_type {
|
|||||||
struct sink_forward_target {
|
struct sink_forward_target {
|
||||||
struct server *srv; // used server
|
struct server *srv; // used server
|
||||||
struct appctx *appctx; // appctx of current session
|
struct appctx *appctx; // appctx of current session
|
||||||
|
uint last_conn; // copy of now_ms for last session establishment attempt
|
||||||
size_t ofs; // ring buffer reader offset
|
size_t ofs; // ring buffer reader offset
|
||||||
size_t e_processed; // processed events
|
size_t e_processed; // processed events
|
||||||
struct sink *sink; // the associated sink
|
struct sink *sink; // the associated sink
|
||||||
|
16
src/sink.c
16
src/sink.c
@ -654,6 +654,7 @@ static struct appctx *sink_forward_session_create(struct sink *sink, struct sink
|
|||||||
goto out_close;
|
goto out_close;
|
||||||
appctx->svcctx = (void *)sft;
|
appctx->svcctx = (void *)sft;
|
||||||
appctx_wakeup(appctx);
|
appctx_wakeup(appctx);
|
||||||
|
sft->last_conn = now_ms;
|
||||||
return appctx;
|
return appctx;
|
||||||
|
|
||||||
/* Error unrolling */
|
/* Error unrolling */
|
||||||
@ -678,9 +679,20 @@ static struct task *process_sink_forward(struct task * task, void *context, unsi
|
|||||||
* assigment right away since the applet is not supposed to change
|
* assigment right away since the applet is not supposed to change
|
||||||
* during the session lifetime. By doing the assignment now we
|
* during the session lifetime. By doing the assignment now we
|
||||||
* make sure to start the session exactly once.
|
* make sure to start the session exactly once.
|
||||||
|
*
|
||||||
|
* We enforce a tempo to ensure we don't perform more than 1 session
|
||||||
|
* establishment attempt per second.
|
||||||
*/
|
*/
|
||||||
if (!sft->appctx)
|
if (!sft->appctx) {
|
||||||
sft->appctx = sink_forward_session_create(sink, sft);
|
uint tempo = sft->last_conn + MS_TO_TICKS(1000);
|
||||||
|
|
||||||
|
if (sft->last_conn == TICK_ETERNITY || tick_is_expired(tempo, now_ms))
|
||||||
|
sft->appctx = sink_forward_session_create(sink, sft);
|
||||||
|
else if (task->expire == TICK_ETERNITY)
|
||||||
|
task->expire = tempo;
|
||||||
|
else
|
||||||
|
task->expire = tick_first(task->expire, tempo);
|
||||||
|
}
|
||||||
HA_SPIN_UNLOCK(SFT_LOCK, &sft->lock);
|
HA_SPIN_UNLOCK(SFT_LOCK, &sft->lock);
|
||||||
sft = sft->next;
|
sft = sft->next;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user