From: Christian Ebner <c.ebner@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [PATCH proxmox-backup v2 2/3] api: add heartbeat endpoint for backup reader/writer http/2 clients
Date: Mon, 11 May 2026 15:46:09 +0200 [thread overview]
Message-ID: <20260511134610.675164-3-c.ebner@proxmox.com> (raw)
In-Reply-To: <20260511134610.675164-1-c.ebner@proxmox.com>
Add dedicated API endpoints to send http level heartbeat requests
for the backup reader and backup writer, used to keep otherwise idle
tcp connections to be dropped by proxies.
By making heartbeats part of the H2 service, these endpoints are only
available for active sessions after the http/2 upgrade.
Heartbeat requests can happen with a frequency as high as 1/s, adding
individual lines to the task log. Therefore, use the http/2 service
filter function of the rest server to exclude these request from
being logged by matching method and path accordingly.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
src/api2/backup/mod.rs | 13 +++++++++++--
src/api2/helpers.rs | 14 +++++++++++++-
src/api2/reader/mod.rs | 13 +++++++++++--
3 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/src/api2/backup/mod.rs b/src/api2/backup/mod.rs
index 86ec49487..7fd9af6a3 100644
--- a/src/api2/backup/mod.rs
+++ b/src/api2/backup/mod.rs
@@ -240,8 +240,13 @@ fn upgrade_to_backup_protocol(
"starting new {worker_type} on datastore '{store}'{origin}: {path:?}",
));
- let service =
- H2Service::new(env.clone(), worker.clone(), &BACKUP_API_ROUTER, debug);
+ let service = H2Service::new(
+ env.clone(),
+ worker.clone(),
+ &BACKUP_API_ROUTER,
+ debug,
+ Some(crate::api2::helpers::heartbeat_request_filter),
+ );
let abort_future = worker.abort_future();
@@ -396,6 +401,10 @@ const BACKUP_API_SUBDIRS: SubdirMap = &[
.post(&API_METHOD_CREATE_FIXED_INDEX)
.put(&API_METHOD_FIXED_APPEND),
),
+ (
+ "heartbeat",
+ &Router::new().get(&crate::api2::helpers::API_METHOD_HEARTBEAT),
+ ),
(
"previous",
&Router::new().download(&API_METHOD_DOWNLOAD_PREVIOUS),
diff --git a/src/api2/helpers.rs b/src/api2/helpers.rs
index f346b0cca..4b0634515 100644
--- a/src/api2/helpers.rs
+++ b/src/api2/helpers.rs
@@ -5,7 +5,8 @@ use futures::stream::TryStreamExt;
use hyper::{header, Response, StatusCode};
use proxmox_http::Body;
-use proxmox_router::http_bail;
+use proxmox_router::{http_bail, RpcEnvironment};
+use proxmox_schema::api;
pub async fn create_download_response(path: PathBuf) -> Result<Response<Body>, Error> {
let file = match tokio::fs::File::open(path.clone()).await {
@@ -28,3 +29,14 @@ pub async fn create_download_response(path: PathBuf) -> Result<Response<Body>, E
.body(body)
.unwrap())
}
+
+#[api()]
+/// HTTP level heartbeat to avoid proxies closing long running idle backup reader/writer connections.
+pub fn heartbeat(_rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ Ok(())
+}
+
+// filter heartbeat requests from being written to task log
+pub(super) fn heartbeat_request_filter(method: &hyper::Method, path: &str) -> bool {
+ method == hyper::Method::GET && path == "/heartbeat"
+}
diff --git a/src/api2/reader/mod.rs b/src/api2/reader/mod.rs
index a814ba5f7..ab74eb1ec 100644
--- a/src/api2/reader/mod.rs
+++ b/src/api2/reader/mod.rs
@@ -173,8 +173,13 @@ fn upgrade_to_backup_reader_protocol(
"starting new backup reader datastore '{store}': {path:?}"
));
- let service =
- H2Service::new(env.clone(), worker.clone(), &READER_API_ROUTER, debug);
+ let service = H2Service::new(
+ env.clone(),
+ worker.clone(),
+ &READER_API_ROUTER,
+ debug,
+ Some(crate::api2::helpers::heartbeat_request_filter),
+ );
let mut abort_future = worker
.abort_future()
@@ -228,6 +233,10 @@ const READER_API_SUBDIRS: SubdirMap = &[
"download",
&Router::new().download(&API_METHOD_DOWNLOAD_FILE),
),
+ (
+ "heartbeat",
+ &Router::new().get(&crate::api2::helpers::API_METHOD_HEARTBEAT),
+ ),
("speedtest", &Router::new().download(&API_METHOD_SPEEDTEST)),
];
--
2.47.3
next prev parent reply other threads:[~2026-05-11 13:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-11 13:46 [PATCH proxmox{,-backup} v2 0/3] fix #6373: HTTP level keepalive for http2 backup reader/writer connection Christian Ebner
2026-05-11 13:46 ` [PATCH proxmox v2 1/3] rest-server: add request logfilter by method and path in h2 service Christian Ebner
2026-05-11 13:46 ` Christian Ebner [this message]
2026-05-11 13:46 ` [PATCH proxmox-backup v2 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=20260511134610.675164-3-c.ebner@proxmox.com \
--to=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