Created
March 16, 2024 02:45
-
-
Save andrewhavck/3dc29b96cf8272885db8cc3880bed6be to your computer and use it in GitHub Desktop.
Multi LB path routing example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use async_trait::async_trait; | |
use pingora::{ | |
lb::selection::{BackendIter, BackendSelection}, | |
prelude::*, | |
services::background::GenBackgroundService, | |
}; | |
use std::sync::Arc; | |
struct Router { | |
cluster_one: Arc<LoadBalancer<RoundRobin>>, | |
cluster_two: Arc<LoadBalancer<RoundRobin>>, | |
} | |
#[async_trait] | |
impl ProxyHttp for Router { | |
type CTX = (); | |
fn new_ctx(&self) {} | |
async fn upstream_peer(&self, session: &mut Session, _ctx: &mut ()) -> Result<Box<HttpPeer>> { | |
let cluster = if session.req_header().uri.path().starts_with("/one/") { | |
&self.cluster_one | |
} else { | |
&self.cluster_two | |
}; | |
let upstream = cluster | |
.select(b"", 256) // hash doesn't matter for round robin | |
.unwrap(); | |
println!("upstream peer is: {upstream:?}"); | |
// Set SNI to one.one.one.one | |
let peer = Box::new(HttpPeer::new(upstream, true, "one.one.one.one".to_string())); | |
Ok(peer) | |
} | |
} | |
fn build_cluster_service<S: BackendSelection>( | |
upstreams: &[&str], | |
) -> GenBackgroundService<LoadBalancer<S>> | |
where | |
S: BackendSelection + 'static, | |
S::Iter: BackendIter, | |
{ | |
let mut cluster = LoadBalancer::try_from_iter(upstreams).unwrap(); | |
cluster.set_health_check(TcpHealthCheck::new()); | |
cluster.health_check_frequency = Some(std::time::Duration::from_secs(1)); | |
background_service("cluster health check", cluster) | |
} | |
fn main() { | |
let mut my_server = Server::new(None).unwrap(); | |
my_server.bootstrap(); | |
let cluster_one = build_cluster_service::<RoundRobin>(&["1.1.1.1:443", "127.0.0.1:343"]); | |
let cluster_two = build_cluster_service::<RoundRobin>(&["1.0.0.1:443", "127.0.0.2:343"]); | |
let router = Router { | |
cluster_one: cluster_one.task(), | |
cluster_two: cluster_two.task(), | |
}; | |
let mut router_service = http_proxy_service(&my_server.configuration, router); | |
router_service.add_tcp("0.0.0.0:6188"); | |
my_server.add_service(router_service); | |
my_server.add_service(cluster_one); | |
my_server.add_service(cluster_two); | |
my_server.run_forever(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment