Browse Source

Rust axum optimizations (#6939)

Dragos Varovici 3 years ago
parent
commit
13f1dc7c4f

+ 267 - 1
frameworks/Rust/axum/Cargo.lock

@@ -56,6 +56,111 @@ dependencies = [
  "winapi",
  "winapi",
 ]
 ]
 
 
+[[package]]
+name = "async-channel"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
+dependencies = [
+ "concurrent-queue",
+ "event-listener",
+ "futures-core",
+]
+
+[[package]]
+name = "async-executor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
+dependencies = [
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "once_cell",
+ "slab",
+]
+
+[[package]]
+name = "async-global-executor"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6"
+dependencies = [
+ "async-channel",
+ "async-executor",
+ "async-io",
+ "async-mutex",
+ "blocking",
+ "futures-lite",
+ "num_cpus",
+ "once_cell",
+]
+
+[[package]]
+name = "async-io"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b"
+dependencies = [
+ "concurrent-queue",
+ "futures-lite",
+ "libc",
+ "log",
+ "once_cell",
+ "parking",
+ "polling",
+ "slab",
+ "socket2 0.4.2",
+ "waker-fn",
+ "winapi",
+]
+
+[[package]]
+name = "async-lock"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b"
+dependencies = [
+ "event-listener",
+]
+
+[[package]]
+name = "async-mutex"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
+dependencies = [
+ "event-listener",
+]
+
+[[package]]
+name = "async-std"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952"
+dependencies = [
+ "async-channel",
+ "async-global-executor",
+ "async-io",
+ "async-lock",
+ "crossbeam-utils",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-lite",
+ "gloo-timers",
+ "kv-log-macro",
+ "log",
+ "memchr",
+ "num_cpus",
+ "once_cell",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+ "wasm-bindgen-futures",
+]
+
 [[package]]
 [[package]]
 name = "async-stream"
 name = "async-stream"
 version = "0.3.2"
 version = "0.3.2"
@@ -77,6 +182,12 @@ dependencies = [
  "syn",
  "syn",
 ]
 ]
 
 
+[[package]]
+name = "async-task"
+version = "4.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
+
 [[package]]
 [[package]]
 name = "async-trait"
 name = "async-trait"
 version = "0.1.51"
 version = "0.1.51"
@@ -97,6 +208,12 @@ dependencies = [
  "num-traits",
  "num-traits",
 ]
 ]
 
 
+[[package]]
+name = "atomic-waker"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
+
 [[package]]
 [[package]]
 name = "atty"
 name = "atty"
 version = "0.2.14"
 version = "0.2.14"
@@ -116,8 +233,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
 
 [[package]]
 [[package]]
 name = "axum"
 name = "axum"
-version = "0.1.1"
+version = "0.1.2"
 dependencies = [
 dependencies = [
+ "async-std",
  "async-stream",
  "async-stream",
  "async-trait",
  "async-trait",
  "axum 0.3.2",
  "axum 0.3.2",
@@ -267,6 +385,20 @@ dependencies = [
  "generic-array",
  "generic-array",
 ]
 ]
 
 
+[[package]]
+name = "blocking"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427"
+dependencies = [
+ "async-channel",
+ "async-task",
+ "atomic-waker",
+ "fastrand",
+ "futures-lite",
+ "once_cell",
+]
+
 [[package]]
 [[package]]
 name = "bson"
 name = "bson"
 version = "2.0.1"
 version = "2.0.1"
@@ -341,6 +473,12 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
 checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
 
 
+[[package]]
+name = "cache-padded"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
+
 [[package]]
 [[package]]
 name = "cc"
 name = "cc"
 version = "1.0.71"
 version = "1.0.71"
@@ -378,6 +516,15 @@ dependencies = [
  "winapi",
  "winapi",
 ]
 ]
 
 
+[[package]]
+name = "concurrent-queue"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
+dependencies = [
+ "cache-padded",
+]
+
 [[package]]
 [[package]]
 name = "console"
 name = "console"
 version = "0.14.1"
 version = "0.14.1"
@@ -497,6 +644,16 @@ dependencies = [
  "subtle",
  "subtle",
 ]
 ]
 
 
+[[package]]
+name = "ctor"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
+dependencies = [
+ "quote",
+ "syn",
+]
+
 [[package]]
 [[package]]
 name = "darling"
 name = "darling"
 version = "0.13.0"
 version = "0.13.0"
@@ -700,6 +857,12 @@ dependencies = [
  "version_check 0.9.3",
  "version_check 0.9.3",
 ]
 ]
 
 
+[[package]]
+name = "event-listener"
+version = "2.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
+
 [[package]]
 [[package]]
 name = "fallible-iterator"
 name = "fallible-iterator"
 version = "0.2.0"
 version = "0.2.0"
@@ -716,6 +879,15 @@ dependencies = [
  "regex",
  "regex",
 ]
 ]
 
 
+[[package]]
+name = "fastrand"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e"
+dependencies = [
+ "instant",
+]
+
 [[package]]
 [[package]]
 name = "flate2"
 name = "flate2"
 version = "1.0.22"
 version = "1.0.22"
@@ -818,6 +990,21 @@ version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
 checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
 
 
+[[package]]
+name = "futures-lite"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
 [[package]]
 [[package]]
 name = "futures-macro"
 name = "futures-macro"
 version = "0.3.17"
 version = "0.3.17"
@@ -920,6 +1107,19 @@ dependencies = [
  "regex",
  "regex",
 ]
 ]
 
 
+[[package]]
+name = "gloo-timers"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
 [[package]]
 [[package]]
 name = "grep-cli"
 name = "grep-cli"
 version = "0.1.6"
 version = "0.1.6"
@@ -1144,6 +1344,15 @@ dependencies = [
  "wasm-bindgen",
  "wasm-bindgen",
 ]
 ]
 
 
+[[package]]
+name = "kv-log-macro"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
+dependencies = [
+ "log",
+]
+
 [[package]]
 [[package]]
 name = "lazy_static"
 name = "lazy_static"
 version = "1.4.0"
 version = "1.4.0"
@@ -1193,6 +1402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
 checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
 dependencies = [
 dependencies = [
  "cfg-if",
  "cfg-if",
+ "value-bag",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -1462,6 +1672,12 @@ dependencies = [
  "winapi",
  "winapi",
 ]
 ]
 
 
+[[package]]
+name = "parking"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
+
 [[package]]
 [[package]]
 name = "parking_lot"
 name = "parking_lot"
 version = "0.11.2"
 version = "0.11.2"
@@ -1590,6 +1806,19 @@ dependencies = [
  "xml-rs",
  "xml-rs",
 ]
 ]
 
 
+[[package]]
+name = "polling"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "log",
+ "wepoll-ffi",
+ "winapi",
+]
+
 [[package]]
 [[package]]
 name = "postgres-protocol"
 name = "postgres-protocol"
 version = "0.6.2"
 version = "0.6.2"
@@ -2737,6 +2966,16 @@ dependencies = [
  "v_escape",
  "v_escape",
 ]
 ]
 
 
+[[package]]
+name = "value-bag"
+version = "1.0.0-alpha.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f"
+dependencies = [
+ "ctor",
+ "version_check 0.9.3",
+]
+
 [[package]]
 [[package]]
 name = "vcpkg"
 name = "vcpkg"
 version = "0.2.15"
 version = "0.2.15"
@@ -2755,6 +2994,12 @@ version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
 checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
 
 
+[[package]]
+name = "waker-fn"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+
 [[package]]
 [[package]]
 name = "walkdir"
 name = "walkdir"
 version = "2.3.2"
 version = "2.3.2"
@@ -2807,6 +3052,18 @@ dependencies = [
  "wasm-bindgen-shared",
  "wasm-bindgen-shared",
 ]
 ]
 
 
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
 [[package]]
 [[package]]
 name = "wasm-bindgen-macro"
 name = "wasm-bindgen-macro"
 version = "0.2.78"
 version = "0.2.78"
@@ -2865,6 +3122,15 @@ dependencies = [
  "webpki",
  "webpki",
 ]
 ]
 
 
+[[package]]
+name = "wepoll-ffi"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 [[package]]
 name = "whoami"
 name = "whoami"
 version = "1.2.0"
 version = "1.2.0"

+ 2 - 1
frameworks/Rust/axum/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 [package]
 name = "axum"
 name = "axum"
-version = "0.1.1"
+version = "0.1.2"
 authors = ["Dragos Varovici <[email protected]>"]
 authors = ["Dragos Varovici <[email protected]>"]
 edition = "2018"
 edition = "2018"
 
 
@@ -26,6 +26,7 @@ rand = { version = "^0.8", features = ["small_rng"]}
 yarte = { version = "^0.15" }
 yarte = { version = "^0.15" }
 async-stream = { version = "^0.3" }
 async-stream = { version = "^0.3" }
 async-trait = { version = "0.1" }
 async-trait = { version = "0.1" }
+async-std = "1.10"
 futures = { version = "^0.3" }
 futures = { version = "^0.3" }
 futures-util = { version = "^0.3" }
 futures-util = { version = "^0.3" }
 dotenv = { version = "^0.15" }
 dotenv = { version = "^0.15" }

+ 4 - 1
frameworks/Rust/axum/axum-bb8.dockerfile

@@ -11,10 +11,13 @@ COPY ./src ./src
 COPY ./templates ./templates
 COPY ./templates ./templates
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.lock ./Cargo.lock
 COPY ./Cargo.lock ./Cargo.lock
+COPY ./run.sh ./run.sh
+RUN chmod +x ./run.sh
 
 
 ENV RUSTFLAGS "-C target-cpu=native"
 ENV RUSTFLAGS "-C target-cpu=native"
 RUN cargo build --release
 RUN cargo build --release
+RUN cp ./target/release/axum-bb8 ./target/release/axum-techempower
 
 
 EXPOSE 8000
 EXPOSE 8000
 
 
-CMD ["./target/release/axum-bb8"]
+CMD ["./run.sh"]

+ 4 - 1
frameworks/Rust/axum/axum-mongo.dockerfile

@@ -11,10 +11,13 @@ COPY ./src ./src
 COPY ./templates ./templates
 COPY ./templates ./templates
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.lock ./Cargo.lock
 COPY ./Cargo.lock ./Cargo.lock
+COPY ./run.sh ./run.sh
+RUN chmod +x ./run.sh
 
 
 ENV RUSTFLAGS "-C target-cpu=native"
 ENV RUSTFLAGS "-C target-cpu=native"
 RUN cargo build --release
 RUN cargo build --release
+RUN cp ./target/release/axum-mongo ./target/release/axum-techempower
 
 
 EXPOSE 8000
 EXPOSE 8000
 
 
-CMD ["./target/release/axum-mongo"]
+CMD ["./run.sh"]

+ 5 - 1
frameworks/Rust/axum/axum-sqlx.dockerfile

@@ -11,10 +11,14 @@ COPY ./src ./src
 COPY ./templates ./templates
 COPY ./templates ./templates
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.lock ./Cargo.lock
 COPY ./Cargo.lock ./Cargo.lock
+COPY ./run.sh ./run.sh
+RUN chmod +x ./run.sh
 
 
 ENV RUSTFLAGS "-C target-cpu=native"
 ENV RUSTFLAGS "-C target-cpu=native"
 RUN cargo build --release
 RUN cargo build --release
+RUN cp ./target/release/axum-sqlx ./target/release/axum-techempower
+
 
 
 EXPOSE 8000
 EXPOSE 8000
 
 
-CMD ["./target/release/axum-sqlx"]
+CMD ["./run.sh"]

+ 4 - 1
frameworks/Rust/axum/axum.dockerfile

@@ -9,10 +9,13 @@ COPY ./src ./src
 COPY ./templates ./templates
 COPY ./templates ./templates
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.toml ./Cargo.toml
 COPY ./Cargo.lock ./Cargo.lock
 COPY ./Cargo.lock ./Cargo.lock
+COPY ./run.sh ./run.sh
+RUN chmod +x ./run.sh
 
 
 ENV RUSTFLAGS "-C target-cpu=native"
 ENV RUSTFLAGS "-C target-cpu=native"
 RUN cargo build --release
 RUN cargo build --release
+RUN cp ./target/release/axum ./target/release/axum-techempower
 
 
 EXPOSE 8000
 EXPOSE 8000
 
 
-CMD ["./target/release/axum"]
+CMD ["./run.sh"]

+ 3 - 0
frameworks/Rust/axum/run.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./target/release/axum-techempower

+ 1 - 0
frameworks/Rust/axum/src/common.rs

@@ -0,0 +1 @@
+pub const POOL_SIZE: u32 = 56;

+ 0 - 17
frameworks/Rust/axum/src/common_handlers.rs

@@ -1,17 +0,0 @@
-use axum::http::StatusCode;
-use axum::Json;
-use axum::response::IntoResponse;
-
-use crate::models_common::{Message};
-
-pub async fn plaintext() -> &'static str {
-    "Hello, World!"
-}
-
-pub async fn json() -> impl IntoResponse {
-    let message = Message {
-        message: "Hello, World!",
-    };
-
-    (StatusCode::OK, Json(message))
-}

+ 2 - 1
frameworks/Rust/axum/src/database_bb8.rs

@@ -3,6 +3,7 @@ use axum::http::StatusCode;
 use bb8::{Pool, PooledConnection};
 use bb8::{Pool, PooledConnection};
 use bb8_postgres::PostgresConnectionManager;
 use bb8_postgres::PostgresConnectionManager;
 use bb8_postgres::tokio_postgres::NoTls;
 use bb8_postgres::tokio_postgres::NoTls;
+use crate::common::POOL_SIZE;
 use crate::utils::internal_error;
 use crate::utils::internal_error;
 
 
 pub type ConnectionManager = PostgresConnectionManager<NoTls>;
 pub type ConnectionManager = PostgresConnectionManager<NoTls>;
@@ -12,7 +13,7 @@ pub type Connection = PooledConnection<'static, ConnectionManager>;
 pub async fn create_bb8_pool(database_url: String) -> ConnectionPool {
 pub async fn create_bb8_pool(database_url: String) -> ConnectionPool {
     let manager = PostgresConnectionManager::new_from_stringlike(database_url, NoTls).unwrap();
     let manager = PostgresConnectionManager::new_from_stringlike(database_url, NoTls).unwrap();
 
 
-    Pool::builder().build(manager).await.unwrap()
+    Pool::builder().max_size(POOL_SIZE).build(manager).await.unwrap()
 }
 }
 
 
 pub struct DatabaseConnection(pub Connection);
 pub struct DatabaseConnection(pub Connection);

+ 2 - 1
frameworks/Rust/axum/src/database_sqlx.rs

@@ -4,10 +4,11 @@ use axum::http::StatusCode;
 use sqlx::{PgPool, Postgres};
 use sqlx::{PgPool, Postgres};
 use sqlx::pool::PoolConnection;
 use sqlx::pool::PoolConnection;
 use sqlx::postgres::PgPoolOptions;
 use sqlx::postgres::PgPoolOptions;
+use crate::common::POOL_SIZE;
 use crate::utils::internal_error;
 use crate::utils::internal_error;
 
 
 pub async fn create_pool(database_url: String) -> PgPool {
 pub async fn create_pool(database_url: String) -> PgPool {
-    PgPoolOptions::new().max_connections(100).connect(&*database_url).await.unwrap()
+    PgPoolOptions::new().max_connections(POOL_SIZE).min_connections(56).connect(&*database_url).await.unwrap()
 }
 }
 
 
 pub struct DatabaseConnection(pub PoolConnection<Postgres>);
 pub struct DatabaseConnection(pub PoolConnection<Postgres>);

+ 20 - 6
frameworks/Rust/axum/src/main.rs

@@ -4,30 +4,44 @@ extern crate async_trait;
 extern crate tokio_pg_mapper_derive;
 extern crate tokio_pg_mapper_derive;
 extern crate tokio_pg_mapper;
 extern crate tokio_pg_mapper;
 
 
-mod common_handlers;
 mod models_common;
 mod models_common;
+mod server;
+mod common;
 
 
+use models_common::{Message};
+
+use axum::http::StatusCode;
+use axum::Json;
 use dotenv::dotenv;
 use dotenv::dotenv;
-use std::net::{Ipv4Addr, SocketAddr};
 use axum::{Router, routing::get};
 use axum::{Router, routing::get};
 use axum::http::{header, HeaderValue};
 use axum::http::{header, HeaderValue};
+use axum::response::IntoResponse;
 use tower_http::set_header::SetResponseHeaderLayer;
 use tower_http::set_header::SetResponseHeaderLayer;
 use hyper::Body;
 use hyper::Body;
 
 
-use common_handlers::{json, plaintext};
+pub async fn plaintext() -> &'static str {
+    "Hello, World!"
+}
+
+pub async fn json() -> impl IntoResponse {
+    let message = Message {
+        message: "Hello, World!",
+    };
+
+    (StatusCode::OK, Json(message))
+}
 
 
 #[tokio::main]
 #[tokio::main]
 async fn main() {
 async fn main() {
     dotenv().ok();
     dotenv().ok();
 
 
-    let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8000));
-
     let app =  Router::new()
     let app =  Router::new()
         .route("/plaintext", get(plaintext))
         .route("/plaintext", get(plaintext))
         .route("/json", get(json))
         .route("/json", get(json))
         .layer(SetResponseHeaderLayer::<_, Body>::if_not_present(header::SERVER, HeaderValue::from_static("Axum")));
         .layer(SetResponseHeaderLayer::<_, Body>::if_not_present(header::SERVER, HeaderValue::from_static("Axum")));
 
 
-    axum::Server::bind(&addr)
+    server::builder()
+        .http1_pipeline_flush(true)
         .serve(app.into_make_service())
         .serve(app.into_make_service())
         .await
         .await
         .unwrap();
         .unwrap();

+ 3 - 8
frameworks/Rust/axum/src/main_bb8.rs

@@ -3,14 +3,14 @@ extern crate dotenv;
 #[macro_use]
 #[macro_use]
 extern crate async_trait;
 extern crate async_trait;
 
 
-mod common_handlers;
 mod models_common;
 mod models_common;
 mod models_bb8;
 mod models_bb8;
 mod database_bb8;
 mod database_bb8;
 mod utils;
 mod utils;
+mod server;
+mod common;
 
 
 use dotenv::dotenv;
 use dotenv::dotenv;
-use std::net::{Ipv4Addr, SocketAddr};
 use std::env;
 use std::env;
 use crate::database_bb8::{Connection, create_bb8_pool, DatabaseConnection};
 use crate::database_bb8::{Connection, create_bb8_pool, DatabaseConnection};
 use axum::{
 use axum::{
@@ -30,7 +30,6 @@ use tokio_pg_mapper::FromTokioPostgresRow;
 use yarte::Template;
 use yarte::Template;
 
 
 use models_bb8::{World, Fortune};
 use models_bb8::{World, Fortune};
-use common_handlers::{json, plaintext};
 use utils::{Params, parse_params, random_number};
 use utils::{Params, parse_params, random_number};
 use crate::utils::Utf8Html;
 use crate::utils::Utf8Html;
 
 
@@ -142,14 +141,10 @@ async fn main() {
     let database_url = env::var("AXUM_TECHEMPOWER_DATABASE_URL").ok()
     let database_url = env::var("AXUM_TECHEMPOWER_DATABASE_URL").ok()
         .expect("AXUM_TECHEMPOWER_DATABASE_URL environment variable was not set");
         .expect("AXUM_TECHEMPOWER_DATABASE_URL environment variable was not set");
 
 
-    let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8000));
-
     // setup connection pool
     // setup connection pool
     let pool = create_bb8_pool(database_url).await;
     let pool = create_bb8_pool(database_url).await;
 
 
     let router = Router::new()
     let router = Router::new()
-        .route("/plaintext", get(plaintext))
-        .route("/json", get(json))
         .route("/fortunes", get(fortunes))
         .route("/fortunes", get(fortunes))
         .route("/db", get(db))
         .route("/db", get(db))
         .route("/queries", get(queries))
         .route("/queries", get(queries))
@@ -157,7 +152,7 @@ async fn main() {
         .layer(AddExtensionLayer::new(pool))
         .layer(AddExtensionLayer::new(pool))
         .layer(SetResponseHeaderLayer::<_, Body>::if_not_present(header::SERVER, HeaderValue::from_static("Axum")));
         .layer(SetResponseHeaderLayer::<_, Body>::if_not_present(header::SERVER, HeaderValue::from_static("Axum")));
 
 
-    axum::Server::bind(&addr)
+    server::builder()
         .serve(router.into_make_service())
         .serve(router.into_make_service())
         .await
         .await
         .unwrap();
         .unwrap();

+ 9 - 11
frameworks/Rust/axum/src/main_mongo.rs

@@ -3,15 +3,16 @@ extern crate dotenv;
 #[macro_use]
 #[macro_use]
 extern crate async_trait;
 extern crate async_trait;
 
 
-mod common_handlers;
 mod models_common;
 mod models_common;
 mod models_mongo;
 mod models_mongo;
 mod database_mongo;
 mod database_mongo;
 mod utils;
 mod utils;
+mod server;
+mod common;
 
 
 use dotenv::dotenv;
 use dotenv::dotenv;
-use std::net::{Ipv4Addr, SocketAddr};
 use std::env;
 use std::env;
+use std::time::Duration;
 use axum::{
 use axum::{
     extract::{Query},
     extract::{Query},
     http::StatusCode,
     http::StatusCode,
@@ -30,10 +31,9 @@ use mongodb::{bson::doc, Client, Database};
 use mongodb::options::ClientOptions;
 use mongodb::options::ClientOptions;
 
 
 use models_mongo::{World, Fortune};
 use models_mongo::{World, Fortune};
-use common_handlers::{json, plaintext};
 use utils::{Params, parse_params, random_number, Utf8Html};
 use utils::{Params, parse_params, random_number, Utf8Html};
-use crate::database_mongo::DatabaseConnection;
-use crate::models_mongo::FortuneInfo;
+use database_mongo::DatabaseConnection;
+use models_mongo::FortuneInfo;
 
 
 async fn db(DatabaseConnection(mut db): DatabaseConnection) -> impl IntoResponse {
 async fn db(DatabaseConnection(mut db): DatabaseConnection) -> impl IntoResponse {
     let mut rng = SmallRng::from_entropy();
     let mut rng = SmallRng::from_entropy();
@@ -107,24 +107,22 @@ async fn main() {
     let database_url = env::var("AXUM_TECHEMPOWER_MONGODB_URL").ok()
     let database_url = env::var("AXUM_TECHEMPOWER_MONGODB_URL").ok()
         .expect("AXUM_TECHEMPOWER_MONGODB_URL environment variable was not set");
         .expect("AXUM_TECHEMPOWER_MONGODB_URL environment variable was not set");
 
 
-    let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8000));
-
     // setup connection pool
     // setup connection pool
     let mut client_options = ClientOptions::parse(database_url).await.unwrap();
     let mut client_options = ClientOptions::parse(database_url).await.unwrap();
-    client_options.max_pool_size = Some(100);
+    client_options.max_pool_size = Some(common::POOL_SIZE);
+    client_options.min_pool_size = Some(common::POOL_SIZE);
+    client_options.connect_timeout = Some(Duration::from_millis(200));
 
 
     let client = Client::with_options(client_options).unwrap();
     let client = Client::with_options(client_options).unwrap();
 
 
     let app = Router::new()
     let app = Router::new()
-        .route("/plaintext", get(plaintext))
-        .route("/json", get(json))
         .route("/fortunes", get(fortunes))
         .route("/fortunes", get(fortunes))
         .route("/db", get(db))
         .route("/db", get(db))
         .route("/queries", get(queries))
         .route("/queries", get(queries))
         .layer(AddExtensionLayer::new(client))
         .layer(AddExtensionLayer::new(client))
         .layer(SetResponseHeaderLayer::<_, Body>::if_not_present(header::SERVER, HeaderValue::from_static("Axum")));
         .layer(SetResponseHeaderLayer::<_, Body>::if_not_present(header::SERVER, HeaderValue::from_static("Axum")));
 
 
-    axum::Server::bind(&addr)
+    server::builder()
         .serve(app.into_make_service())
         .serve(app.into_make_service())
         .await
         .await
         .unwrap();
         .unwrap();

+ 3 - 8
frameworks/Rust/axum/src/main_sqlx.rs

@@ -3,14 +3,14 @@ extern crate dotenv;
 #[macro_use]
 #[macro_use]
 extern crate async_trait;
 extern crate async_trait;
 
 
-mod common_handlers;
 mod models_common;
 mod models_common;
 mod models_sqlx;
 mod models_sqlx;
 mod database_sqlx;
 mod database_sqlx;
 mod utils;
 mod utils;
+mod server;
+mod common;
 
 
 use dotenv::dotenv;
 use dotenv::dotenv;
-use std::net::{Ipv4Addr, SocketAddr};
 use std::env;
 use std::env;
 use crate::database_sqlx::{DatabaseConnection};
 use crate::database_sqlx::{DatabaseConnection};
 use axum::{
 use axum::{
@@ -30,7 +30,6 @@ use yarte::Template;
 
 
 use models_sqlx::{World, Fortune};
 use models_sqlx::{World, Fortune};
 use database_sqlx::create_pool;
 use database_sqlx::create_pool;
-use common_handlers::{json, plaintext};
 use utils::{Params, parse_params, random_number, Utf8Html};
 use utils::{Params, parse_params, random_number, Utf8Html};
 
 
 async fn db(DatabaseConnection(mut conn): DatabaseConnection) -> impl IntoResponse {
 async fn db(DatabaseConnection(mut conn): DatabaseConnection) -> impl IntoResponse {
@@ -115,14 +114,12 @@ async fn main() {
     let database_url = env::var("AXUM_TECHEMPOWER_DATABASE_URL").ok()
     let database_url = env::var("AXUM_TECHEMPOWER_DATABASE_URL").ok()
         .expect("AXUM_TECHEMPOWER_DATABASE_URL environment variable was not set");
         .expect("AXUM_TECHEMPOWER_DATABASE_URL environment variable was not set");
 
 
-    let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8000));
-
     // setup connection pool
     // setup connection pool
     let pool = create_pool(database_url).await;
     let pool = create_pool(database_url).await;
 
 
     let app = router(pool).await;
     let app = router(pool).await;
 
 
-    axum::Server::bind(&addr)
+    server::builder()
         .serve(app.into_make_service())
         .serve(app.into_make_service())
         .await
         .await
         .unwrap();
         .unwrap();
@@ -130,8 +127,6 @@ async fn main() {
 
 
 async fn router(pool: PgPool) -> Router {
 async fn router(pool: PgPool) -> Router {
     Router::new()
     Router::new()
-        .route("/plaintext", get(plaintext))
-        .route("/json", get(json))
         .route("/fortunes", get(fortunes))
         .route("/fortunes", get(fortunes))
         .route("/db", get(db))
         .route("/db", get(db))
         .route("/queries", get(queries))
         .route("/queries", get(queries))

+ 35 - 0
frameworks/Rust/axum/src/server.rs

@@ -0,0 +1,35 @@
+
+use std::io;
+use std::net::{Ipv4Addr, SocketAddr};
+
+use hyper::server::conn::AddrIncoming;
+use tokio::net::{TcpListener, TcpSocket};
+use crate::common::POOL_SIZE;
+
+pub fn builder() -> hyper::server::Builder<AddrIncoming> {
+    let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8000));
+    let listener = reuse_listener(addr).expect("couldn't bind to addr");
+    let incoming = AddrIncoming::from_listener(listener).unwrap();
+
+    println!("Started axum server at 8000 with pool size {pool_size}", pool_size=POOL_SIZE);
+
+    axum::Server::builder(incoming).http1_only(true).tcp_nodelay(true)
+}
+
+fn reuse_listener(addr: SocketAddr) -> io::Result<TcpListener> {
+    let socket = match addr {
+        SocketAddr::V4(_) => TcpSocket::new_v4()?,
+        SocketAddr::V6(_) => TcpSocket::new_v6()?,
+    };
+
+    #[cfg(unix)]
+        {
+            if let Err(e) = socket.set_reuseport(true) {
+                eprintln!("error setting SO_REUSEPORT: {}", e);
+            }
+        }
+
+    socket.set_reuseaddr(true)?;
+    socket.bind(addr)?;
+    socket.listen(1024)
+}