add some comments to design sticky session
This commit is contained in:
parent
4fb15a91ce
commit
2d79be5577
5 changed files with 33 additions and 8 deletions
|
|
@ -60,8 +60,8 @@ path = '/maps'
|
||||||
# For request path starting with "/maps",
|
# For request path starting with "/maps",
|
||||||
# this configuration results that any path like "/maps/org/any.ext" is mapped to "/replacing/path1/org/any.ext"
|
# this configuration results that any path like "/maps/org/any.ext" is mapped to "/replacing/path1/org/any.ext"
|
||||||
# by replacing "/maps" with "/replacing/path1" for routing to the locations given in upstream array
|
# by replacing "/maps" with "/replacing/path1" for routing to the locations given in upstream array
|
||||||
# Note that unless "path_replaced_with" is specified, the "path" is always preserved.
|
# Note that unless "replace_path" is specified, the "path" is always preserved.
|
||||||
# "path_replaced_with" must be start from "/" (root path)
|
# "replace_path" must be start from "/" (root path)
|
||||||
replace_path = "/replacing/path1"
|
replace_path = "/replacing/path1"
|
||||||
upstream = [
|
upstream = [
|
||||||
{ location = 'www.bing.com', tls = true },
|
{ location = 'www.bing.com', tls = true },
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,15 @@ use x509_parser::prelude::*;
|
||||||
#[derive(Builder)]
|
#[derive(Builder)]
|
||||||
pub struct Backend {
|
pub struct Backend {
|
||||||
#[builder(setter(into))]
|
#[builder(setter(into))]
|
||||||
|
/// backend application name, e.g., app1
|
||||||
pub app_name: String,
|
pub app_name: String,
|
||||||
#[builder(setter(custom))]
|
#[builder(setter(custom))]
|
||||||
|
/// server name, e.g., example.com, in String ascii lower case
|
||||||
pub server_name: String,
|
pub server_name: String,
|
||||||
|
/// struct of reverse proxy serving incoming request
|
||||||
pub reverse_proxy: ReverseProxy,
|
pub reverse_proxy: ReverseProxy,
|
||||||
|
|
||||||
// tls settings
|
/// tls settings
|
||||||
#[builder(setter(custom), default)]
|
#[builder(setter(custom), default)]
|
||||||
pub tls_cert_path: Option<PathBuf>,
|
pub tls_cert_path: Option<PathBuf>,
|
||||||
#[builder(setter(custom), default)]
|
#[builder(setter(custom), default)]
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ pub struct ReverseProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReverseProxy {
|
impl ReverseProxy {
|
||||||
|
/// Get an appropriate upstream destination for given path string.
|
||||||
pub fn get<'a>(&self, path_str: impl Into<Cow<'a, str>>) -> Option<&UpstreamGroup> {
|
pub fn get<'a>(&self, path_str: impl Into<Cow<'a, str>>) -> Option<&UpstreamGroup> {
|
||||||
// trie使ってlongest prefix match させてもいいけどルート記述は少ないと思われるので、
|
// trie使ってlongest prefix match させてもいいけどルート記述は少ないと思われるので、
|
||||||
// コスト的にこの程度で十分
|
// コスト的にこの程度で十分
|
||||||
|
|
@ -52,9 +53,14 @@ impl ReverseProxy {
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
/// Load Balancing Option
|
||||||
pub enum LoadBalance {
|
pub enum LoadBalance {
|
||||||
|
/// Simple round robin without session persistance
|
||||||
RoundRobin,
|
RoundRobin,
|
||||||
|
/// Randomly chose one upstream server
|
||||||
Random,
|
Random,
|
||||||
|
/// Round robin with session persistance using cookie
|
||||||
|
StickyRoundRobin,
|
||||||
}
|
}
|
||||||
impl Default for LoadBalance {
|
impl Default for LoadBalance {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|
@ -63,22 +69,32 @@ impl Default for LoadBalance {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
/// Upstream struct just containing uri without path
|
||||||
pub struct Upstream {
|
pub struct Upstream {
|
||||||
pub uri: hyper::Uri, // base uri without specific path
|
/// Base uri without specific path
|
||||||
|
pub uri: hyper::Uri,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Builder)]
|
#[derive(Debug, Clone, Builder)]
|
||||||
|
/// Struct serving multiple upstream servers for, e.g., load balancing.
|
||||||
pub struct UpstreamGroup {
|
pub struct UpstreamGroup {
|
||||||
|
/// Upstream server(s)
|
||||||
pub upstream: Vec<Upstream>,
|
pub upstream: Vec<Upstream>,
|
||||||
#[builder(setter(custom), default)]
|
#[builder(setter(custom), default)]
|
||||||
|
/// Path like "/path" in [[PathNameBytesExp]] associated with the upstream server(s)
|
||||||
pub path: PathNameBytesExp,
|
pub path: PathNameBytesExp,
|
||||||
#[builder(setter(custom), default)]
|
#[builder(setter(custom), default)]
|
||||||
|
/// Path in [[PathNameBytesExp]] that will be used to replace the "path" part of incoming url
|
||||||
pub replace_path: Option<PathNameBytesExp>,
|
pub replace_path: Option<PathNameBytesExp>,
|
||||||
|
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
|
/// Load balancing option
|
||||||
pub lb: LoadBalance,
|
pub lb: LoadBalance,
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
pub cnt: UpstreamCount, // counter for load balancing
|
/// Counter for load balancing
|
||||||
|
pub cnt: UpstreamCount,
|
||||||
#[builder(setter(custom), default)]
|
#[builder(setter(custom), default)]
|
||||||
|
/// Activated upstream options defined in [[UpstreamOption]]
|
||||||
pub opts: HashSet<UpstreamOption>,
|
pub opts: HashSet<UpstreamOption>,
|
||||||
}
|
}
|
||||||
impl UpstreamGroupBuilder {
|
impl UpstreamGroupBuilder {
|
||||||
|
|
@ -116,6 +132,7 @@ impl UpstreamGroupBuilder {
|
||||||
pub struct UpstreamCount(Arc<AtomicUsize>);
|
pub struct UpstreamCount(Arc<AtomicUsize>);
|
||||||
|
|
||||||
impl UpstreamGroup {
|
impl UpstreamGroup {
|
||||||
|
/// Get an enabled option of load balancing [[LoadBalance]]
|
||||||
pub fn get(&self) -> Option<&Upstream> {
|
pub fn get(&self) -> Option<&Upstream> {
|
||||||
match self.lb {
|
match self.lb {
|
||||||
LoadBalance::RoundRobin => {
|
LoadBalance::RoundRobin => {
|
||||||
|
|
@ -127,13 +144,16 @@ impl UpstreamGroup {
|
||||||
let max = self.upstream.len() - 1;
|
let max = self.upstream.len() - 1;
|
||||||
self.upstream.get(rng.gen_range(0..max))
|
self.upstream.get(rng.gen_range(0..max))
|
||||||
}
|
}
|
||||||
|
LoadBalance::StickyRoundRobin => todo!(), // TODO: TODO:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a current count of upstream served
|
||||||
fn current_cnt(&self) -> usize {
|
fn current_cnt(&self) -> usize {
|
||||||
self.cnt.0.load(Ordering::Relaxed)
|
self.cnt.0.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Increment count of upstream served
|
||||||
fn increment_cnt(&self) -> usize {
|
fn increment_cnt(&self) -> usize {
|
||||||
if self.current_cnt() < self.upstream.len() - 1 {
|
if self.current_cnt() < self.upstream.len() - 1 {
|
||||||
self.cnt.0.fetch_add(1, Ordering::Relaxed)
|
self.cnt.0.fetch_add(1, Ordering::Relaxed)
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,8 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fix unique upstream destination since there could be multiple ones.
|
// Fix unique upstream destination since there could be multiple ones.
|
||||||
|
// TODO: StickyならCookieをここでgetに与える必要
|
||||||
|
// TODO: Stickyで、Cookieが与えられなかったらset-cookie向けにcookieを返す必要。upstreamオブジェクトに含めるのも手。
|
||||||
let upstream_chosen = upstream_group.get().ok_or_else(|| anyhow!("Failed to get upstream"))?;
|
let upstream_chosen = upstream_group.get().ok_or_else(|| anyhow!("Failed to get upstream"))?;
|
||||||
|
|
||||||
// apply upstream-specific headers given in upstream_option
|
// apply upstream-specific headers given in upstream_option
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/// Server name (hostname or ip address) representation in bytes-based struct
|
/// Server name (hostname or ip address) representation in bytes-based struct
|
||||||
/// For searching hashmap or key list by exact or longest-prefix matching
|
/// for searching hashmap or key list by exact or longest-prefix matching
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
|
||||||
pub struct ServerNameBytesExp(pub Vec<u8>); // lowercase ascii bytes
|
pub struct ServerNameBytesExp(pub Vec<u8>); // lowercase ascii bytes
|
||||||
impl From<&[u8]> for ServerNameBytesExp {
|
impl From<&[u8]> for ServerNameBytesExp {
|
||||||
|
|
@ -8,8 +8,8 @@ impl From<&[u8]> for ServerNameBytesExp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Server name (hostname or ip address) representation in bytes-based struct
|
/// Path name, like "/path/ok", represented in bytes-based struct
|
||||||
/// For searching hashmap or key list by exact or longest-prefix matching
|
/// for searching hashmap or key list by exact or longest-prefix matching
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
|
||||||
pub struct PathNameBytesExp(pub Vec<u8>); // lowercase ascii bytes
|
pub struct PathNameBytesExp(pub Vec<u8>); // lowercase ascii bytes
|
||||||
impl PathNameBytesExp {
|
impl PathNameBytesExp {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue