public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Robert Obkircher <r.obkircher@proxmox.com>
To: Christian Ebner <c.ebner@proxmox.com>
Cc: pbs-devel@lists.proxmox.com
Subject: Re: [PATCH proxmox-backup v3 2/3] api: add heartbeat endpoint for backup reader/writer http/2 clients
Date: Thu, 23 Jul 2026 16:15:44 +0200	[thread overview]
Message-ID: <178481614425.204362.18056299450161646361.b4-review@b4> (raw)
In-Reply-To: <20260721114806.505047-3-c.ebner@proxmox.com>

> Backup readers and writers can potentially have long periods of idle
> connections, e.g. a reader if a backup snapshot has been mounted and
> all relevant chunks are locally cached, a backup session with
> previous metadata archive not needing to fetch new contents while the
> backup is ongoing or a backup writer to a datastore with slow backend
> storage.
> 
> Proxies like e.g. HAProxy might however close idle connections for
> better resource handling [0,1], even multiplexed HTTP/2 connections as
> are being used for the Proxmox Backup Sever backup reader/writer
> protocol.
> 
> Therefore, perform heartbeat traffic in the HTTP/2 client when no
> other requests are being send, tracked by an internal timeout,
> being rest before sending a request.
nit: typo: "rest"
> 
> Since older servers do not provide the new API path, ignore errors
> as the response is not strictly necessary for the connection to
> remain established.
> 
> The heartbeat is currently only being performed if the timeout value
> in seconds is given via the PBS_READER_HEARTBEAT_TIMEOUT for readers
> and PBS_WRITER_HEARTBEAT_TIMEOUT for writers.
> 
> Testing was performed using HAProxy with the Proxmox Backup Server
> as backend using the following 5 second connection idle timeouts
> as configuration parameters in haproxy.cfg:
> ```
> ...
> defaults
>     ...
>     timeout connect 5000
>     timeout client  5000
>     timeout server  5000
>     ..
> 
> frontend http-in
>     bind *:8007
>     mode tcp
>     default_backend pbs
> 
> backend pbs
>     mode tcp
>     http-reuse always
>     server pbs <PBS-IP>:8007 verify none
> ```
> 
> As command invocation:
> ```
> PBS_READER_HEARTBEAT_TIMEOUT=1 proxmox-backup-client mount <snapshot> <archive> \
> <mountpoint> --repository <user-and-realm>@<PROXY-IP>:<datastore> --verbose
> ```
> 
> [0] https://www.haproxy.com/documentation/haproxy-configuration-manual/latest/#4-timeout%20client
> [1] https://www.haproxy.com/documentation/haproxy-configuration-manual/latest/#4.2-timeout%20http-keep-alive
> 
> Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=6373
> Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
>
> diff --git a/pbs-client/src/backup_reader.rs b/pbs-client/src/backup_reader.rs
> index 139659479..cd9071310 100644
> --- a/pbs-client/src/backup_reader.rs
> +++ b/pbs-client/src/backup_reader.rs
> @@ -5,6 +5,7 @@ use std::sync::Arc;
>  
>  use futures::future::AbortHandle;
>  use serde_json::{Value, json};
> +use tokio::sync::mpsc;
>  
>  use pbs_api_types::{BackupArchiveName, BackupDir, BackupNamespace, MANIFEST_BLOB_NAME};
>  use pbs_datastore::data_blob::DataBlob;
> @@ -16,28 +17,61 @@ use pbs_datastore::{BackupManifest, PROXMOX_BACKUP_READER_PROTOCOL_ID_V1};
>  use pbs_tools::crypt_config::CryptConfig;
>  use pbs_tools::sha::sha256;
>  
> -use super::{H2Client, HttpClient};
> +use super::{H2Client, HeartBeatMsg, HttpClient, parse_optional_heartbeat_env};
>  
>  /// Backup Reader
>  pub struct BackupReader {
>      h2: H2Client,
>      abort: AbortHandle,
>      crypt_config: Option<Arc<CryptConfig>>,
> +    heartbeat: Option<mpsc::Sender<HeartBeatMsg>>,
>  }
>  
>  impl Drop for BackupReader {
>      fn drop(&mut self) {
> +        self.send_msg_heartbeat(HeartBeatMsg::Abort);
>          self.abort.abort();
>      }
>  }
>  
>  impl BackupReader {
> -    fn new(h2: H2Client, abort: AbortHandle, crypt_config: Option<Arc<CryptConfig>>) -> Arc<Self> {
> -        Arc::new(Self {
> -            h2,
> -            abort,
> -            crypt_config,
> -        })
> +    fn new(
> +        h2: H2Client,
> +        abort: AbortHandle,
> +        crypt_config: Option<Arc<CryptConfig>>,
> +    ) -> Result<Arc<Self>, Error> {
> +        if let Some(timeout) = parse_optional_heartbeat_env("PBS_READER_HEARTBEAT_TIMEOUT")? {
> +            let (send, mut recv) = mpsc::channel(1);
> +            let backup_reader = Arc::new(Self {
> +                h2,
> +                abort,
> +                crypt_config,
> +                heartbeat: Some(send),
> +            });
> +            let reader_cloned = Arc::clone(&backup_reader);
> +
> +            tokio::spawn(async move {
> +                loop {
> +                    match tokio::time::timeout(timeout, recv.recv()).await {
> +                        Ok(Some(HeartBeatMsg::Reset)) => (),
> +                        Ok(Some(HeartBeatMsg::Abort)) | Ok(None) => break,
> +                        Err(_elapsed) => {
> +                            // connection idle timeout reached, send heatbeat
> +                            let _ = reader_cloned.h2.get("heartbeat", None).await;
> +                        }
> +                    }
Wouldn't this spam the server if someone sets timeout to 0?

-- 
Robert Obkircher <r.obkircher@proxmox.com>




  reply	other threads:[~2026-07-23 14:16 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-21 11:48 [PATCH proxmox{,-backup} v3 0/3] fix #6373: HTTP level keepalive for http2 backup reader/writer connection Christian Ebner
2026-07-21 11:48 ` [PATCH proxmox v3 1/3] rest-server: add request logfilter by method and path in h2 service Christian Ebner
2026-07-23 14:17   ` Robert Obkircher
2026-07-21 11:48 ` [PATCH proxmox-backup v3 2/3] api: add heartbeat endpoint for backup reader/writer http/2 clients Christian Ebner
2026-07-23 14:15   ` Robert Obkircher [this message]
2026-07-21 11:48 ` [PATCH proxmox-backup v3 3/3] fix #6373: HTTP level client heartbeat for proxy connection keepalive Christian Ebner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178481614425.204362.18056299450161646361.b4-review@b4 \
    --to=r.obkircher@proxmox.com \
    --cc=c.ebner@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal