Skip to content

Commit 999e379

Browse files
committed
Support opaque extension field in Backend
Sometimes service dicovery can carry arbitrary information, such as SNI and request path to instrument how to connect to backend servers. Backend now support to carry this type of information.
1 parent a518740 commit 999e379

File tree

5 files changed

+57
-2
lines changed

5 files changed

+57
-2
lines changed

.bleep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9fdf48d67b78675c989f51ec18829a81fe6976ef
1+
9b88d76089e0f81c67cb502422148d4d26d4977e

pingora-load-balancing/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ rand = "0"
2929
tokio = { workspace = true }
3030
futures = "0"
3131
log = { workspace = true }
32+
http = { workspace = true }
33+
derivative = "2.2.0"
3234

3335
[dev-dependencies]
3436

pingora-load-balancing/src/discovery.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
use arc_swap::ArcSwap;
1818
use async_trait::async_trait;
19+
use http::Extensions;
1920
use pingora_core::protocols::l4::socket::SocketAddr;
2021
use pingora_error::Result;
2122
use std::io::Result as IoResult;
@@ -62,6 +63,7 @@ impl Static {
6263
let addrs = addrs.to_socket_addrs()?.map(|addr| Backend {
6364
addr: SocketAddr::Inet(addr),
6465
weight: 1,
66+
ext: Extensions::new(),
6567
});
6668
upstreams.extend(addrs);
6769
}

pingora-load-balancing/src/health_check.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ impl Health {
315315
mod test {
316316
use super::*;
317317
use crate::SocketAddr;
318+
use http::Extensions;
318319

319320
#[tokio::test]
320321
async fn test_tcp_check() {
@@ -323,13 +324,15 @@ mod test {
323324
let backend = Backend {
324325
addr: SocketAddr::Inet("1.1.1.1:80".parse().unwrap()),
325326
weight: 1,
327+
ext: Extensions::new(),
326328
};
327329

328330
assert!(tcp_check.check(&backend).await.is_ok());
329331

330332
let backend = Backend {
331333
addr: SocketAddr::Inet("1.1.1.1:79".parse().unwrap()),
332334
weight: 1,
335+
ext: Extensions::new(),
333336
};
334337

335338
assert!(tcp_check.check(&backend).await.is_err());
@@ -341,6 +344,7 @@ mod test {
341344
let backend = Backend {
342345
addr: SocketAddr::Inet("1.1.1.1:443".parse().unwrap()),
343346
weight: 1,
347+
ext: Extensions::new(),
344348
};
345349

346350
assert!(tls_check.check(&backend).await.is_ok());
@@ -353,6 +357,7 @@ mod test {
353357
let backend = Backend {
354358
addr: SocketAddr::Inet("1.1.1.1:443".parse().unwrap()),
355359
weight: 1,
360+
ext: Extensions::new(),
356361
};
357362

358363
assert!(https_check.check(&backend).await.is_ok());
@@ -375,6 +380,7 @@ mod test {
375380
let backend = Backend {
376381
addr: SocketAddr::Inet("1.1.1.1:80".parse().unwrap()),
377382
weight: 1,
383+
ext: Extensions::new(),
378384
};
379385

380386
http_check.check(&backend).await.unwrap();

pingora-load-balancing/src/lib.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@
1616
//! This crate provides common service discovery, health check and load balancing
1717
//! algorithms for proxies to use.
1818
19+
// https://github.com/mcarton/rust-derivative/issues/112
20+
// False positive for macro generated code
21+
#![allow(clippy::non_canonical_partial_ord_impl)]
22+
1923
use arc_swap::ArcSwap;
24+
use derivative::Derivative;
2025
use futures::FutureExt;
26+
pub use http::Extensions;
2127
use pingora_core::protocols::l4::socket::SocketAddr;
2228
use pingora_error::{ErrorType, OrErr, Result};
2329
use std::collections::hash_map::DefaultHasher;
@@ -45,13 +51,26 @@ pub mod prelude {
4551
}
4652

4753
/// [Backend] represents a server to proxy or connect to.
48-
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
54+
#[derive(Derivative)]
55+
#[derivative(Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Debug)]
4956
pub struct Backend {
5057
/// The address to the backend server.
5158
pub addr: SocketAddr,
5259
/// The relative weight of the server. Load balancing algorithms will
5360
/// proportionally distributed traffic according to this value.
5461
pub weight: usize,
62+
63+
/// The extension field to put arbitrary data to annotate the Backend.
64+
/// The data added here is opaque to this crate hence the data is ignored by
65+
/// functionalities of this crate. For example, two backends with the same
66+
/// [SocketAddr] and the same weight but different `ext` data are considered
67+
/// identical.
68+
/// See [Extensions] for how to add and read the data.
69+
#[derivative(PartialEq = "ignore")]
70+
#[derivative(PartialOrd = "ignore")]
71+
#[derivative(Hash = "ignore")]
72+
#[derivative(Ord = "ignore")]
73+
pub ext: Extensions,
5574
}
5675

5776
impl Backend {
@@ -64,6 +83,7 @@ impl Backend {
6483
Ok(Backend {
6584
addr: SocketAddr::Inet(addr),
6685
weight: 1,
86+
ext: Extensions::new(),
6787
})
6888
// TODO: UDS
6989
}
@@ -449,6 +469,31 @@ mod test {
449469
assert!(backends.ready(&good2));
450470
assert!(!backends.ready(&bad));
451471
}
472+
#[tokio::test]
473+
async fn test_backends_with_ext() {
474+
let discovery = discovery::Static::default();
475+
let mut b1 = Backend::new("1.1.1.1:80").unwrap();
476+
b1.ext.insert(true);
477+
let mut b2 = Backend::new("1.0.0.1:80").unwrap();
478+
b2.ext.insert(1u8);
479+
discovery.add(b1.clone());
480+
discovery.add(b2.clone());
481+
482+
let backends = Backends::new(Box::new(discovery));
483+
484+
// fill in the backends
485+
backends.update().await.unwrap();
486+
487+
let backend = backends.get_backend();
488+
assert!(backend.contains(&b1));
489+
assert!(backend.contains(&b2));
490+
491+
let b2 = backend.first().unwrap();
492+
assert_eq!(b2.ext.get::<u8>(), Some(&1));
493+
494+
let b1 = backend.last().unwrap();
495+
assert_eq!(b1.ext.get::<bool>(), Some(&true));
496+
}
452497

453498
#[tokio::test]
454499
async fn test_discovery_readiness() {

0 commit comments

Comments
 (0)