diff --git a/Cargo.lock b/Cargo.lock index 73f037995c..b8d869de0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1424,16 +1424,19 @@ dependencies = [ "bytes", "clap", "hex", + "hyper", "lazy_static", "md5", "parking_lot", "rand", "reqwest", + "routerify", "rustls 0.19.1", "serde", "serde_json", "tokio", "tokio-postgres", + "zenith_metrics", "zenith_utils", ] diff --git a/proxy/Cargo.toml b/proxy/Cargo.toml index 42287b04bb..6efd1d674d 100644 --- a/proxy/Cargo.toml +++ b/proxy/Cargo.toml @@ -13,6 +13,8 @@ lazy_static = "1.4.0" md5 = "0.7.0" rand = "0.8.3" hex = "0.4.3" +hyper = "0.14" +routerify = "2" parking_lot = "0.11.2" serde = "1" serde_json = "1" @@ -23,3 +25,4 @@ rustls = "0.19.1" reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "rustls-tls"] } zenith_utils = { path = "../zenith_utils" } +zenith_metrics = { path = "../zenith_metrics" } diff --git a/proxy/src/http.rs b/proxy/src/http.rs new file mode 100644 index 0000000000..7a65d76e6d --- /dev/null +++ b/proxy/src/http.rs @@ -0,0 +1,15 @@ +use hyper::{Body, Request, Response, StatusCode}; +use routerify::RouterBuilder; + +use zenith_utils::http::endpoint; +use zenith_utils::http::error::ApiError; +use zenith_utils::http::json::json_response; + +async fn status_handler(_: Request) -> Result, ApiError> { + Ok(json_response(StatusCode::OK, "")?) +} + +pub fn make_router() -> RouterBuilder { + let router = endpoint::make_router(); + router.get("/v1/status", status_handler) +} diff --git a/proxy/src/main.rs b/proxy/src/main.rs index 8b397c4444..0f7a6981f1 100644 --- a/proxy/src/main.rs +++ b/proxy/src/main.rs @@ -9,15 +9,18 @@ use anyhow::bail; use clap::{App, Arg}; use state::{ProxyConfig, ProxyState}; use std::thread; +use zenith_utils::http::endpoint; use zenith_utils::{tcp_listener, GIT_VERSION}; mod cplane_api; +mod http; mod mgmt; mod proxy; mod state; mod waiters; fn main() -> anyhow::Result<()> { + zenith_metrics::set_common_metrics_prefix("zenith_proxy"); let arg_matches = App::new("Zenith proxy/router") .version(GIT_VERSION) .arg( @@ -36,6 +39,14 @@ fn main() -> anyhow::Result<()> { .help("listen for management callback connection on ip:port") .default_value("127.0.0.1:7000"), ) + .arg( + Arg::with_name("http") + .short("h") + .long("http") + .takes_value(true) + .help("listen for incoming http connections (metrics, etc) on ip:port") + .default_value("127.0.0.1:7001"), + ) .arg( Arg::with_name("uri") .short("u") @@ -82,6 +93,7 @@ fn main() -> anyhow::Result<()> { let config = ProxyConfig { proxy_address: arg_matches.value_of("proxy").unwrap().parse()?, mgmt_address: arg_matches.value_of("mgmt").unwrap().parse()?, + http_address: arg_matches.value_of("http").unwrap().parse()?, redirect_uri: arg_matches.value_of("uri").unwrap().parse()?, auth_endpoint: arg_matches.value_of("auth-endpoint").unwrap().parse()?, ssl_config, @@ -91,6 +103,9 @@ fn main() -> anyhow::Result<()> { println!("Version: {}", GIT_VERSION); // Check that we can bind to address before further initialization + println!("Starting http on {}", state.conf.http_address); + let http_listener = tcp_listener::bind(state.conf.http_address)?; + println!("Starting proxy on {}", state.conf.proxy_address); let pageserver_listener = tcp_listener::bind(state.conf.proxy_address)?; @@ -98,6 +113,12 @@ fn main() -> anyhow::Result<()> { let mgmt_listener = tcp_listener::bind(state.conf.mgmt_address)?; let threads = [ + thread::Builder::new() + .name("Http thread".into()) + .spawn(move || { + let router = http::make_router(); + endpoint::serve_thread_main(router, http_listener) + })?, // Spawn a thread to listen for connections. It will spawn further threads // for each connection. thread::Builder::new() diff --git a/proxy/src/state.rs b/proxy/src/state.rs index 191dd5a902..04726a0756 100644 --- a/proxy/src/state.rs +++ b/proxy/src/state.rs @@ -10,8 +10,12 @@ pub struct ProxyConfig { /// main entrypoint for users to connect to pub proxy_address: SocketAddr, - /// http management endpoint. Upon user account creation control plane + /// internally used for status and prometheus metrics + pub http_address: SocketAddr, + + /// management endpoint. Upon user account creation control plane /// will notify us here, so that we can 'unfreeze' user session. + /// TODO It uses postgres protocol over TCP but should be migrated to http. pub mgmt_address: SocketAddr, /// send unauthenticated users to this URI