<style> /* basic design */ .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p { font-family: 'Meiryo UI', 'Source Sans Pro', Helvetica, sans-serif, 'Helvetica Neue', 'Helvetica', 'Arial', 'Hiragino Sans', 'ヒラギノ角ゴシック', YuGothic, 'Yu Gothic'; text-align: left; line-height: 1.6; letter-spacing: normal; text-shadow: none; word-wrap: break-word; color: #444; } .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {font-weight: bold;} .reveal h1, .reveal h2, .reveal h3 {color: #2980b9;} .reveal th {background: #DDD;} .reveal section img {background:none; border:none; box-shadow:none; max-width: 95%; max-height: 95%;} .reveal blockquote {width: 90%; padding: 0.5vw 3.0vw;} .reveal table {margin: 1.0vw auto;} .reveal code {line-height: 1.2;} .reveal p, .reveal li {padding: 0vw; margin: 0vw;} .reveal .box {margin: -0.5vw 1.5vw 2.0vw -1.5vw; padding: 0.5vw 1.5vw 0.5vw 1.5vw; background: #EEE; border-radius: 1.5vw;} /* table design */ .reveal table {background: #f5f5f5;} .reveal th {background: #444; color: #fff;} .reveal td {position: relative; transition: all 300ms;} .reveal tbody:hover td { color: transparent; text-shadow: 0 0 3px #aaa;} .reveal tbody:hover tr:hover td {color: #444; text-shadow: 0 1px 0 #fff;} /* blockquote design */ .reveal blockquote { width: 90%; padding: 0.5vw 0 0.5vw 6.0vw; font-style: italic; background: #f5f5f5; } .reveal blockquote:before{ position: absolute; top: 0.1vw; left: 1vw; content: "\f10d"; font-family: FontAwesome; color: #2980b9; font-size: 3.0vw; } /* font size */ .reveal h1 {font-size: 5.0vw;} .reveal h2 {font-size: 4.0vw;} .reveal h3 {font-size: 2.8vw;} .reveal h4 {font-size: 2.6vw;} .reveal h5 {font-size: 2.4vw;} .reveal h6 {font-size: 2.2vw;} .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p {font-size: 2.2vw;} .reveal code {font-size: 1.6vw;} /* new color */ .red {color: #EE6557;} .blue {color: #16A6B6;} /* split slide */ #right {left: -18.33%; text-align: left; float: left; width: 50%; z-index: -10;} #left {left: 31.25%; text-align: left; float: left; width: 50%; z-index: -10;} </style> <style> /* specific design */ .reveal h2 { padding: 0 1.5vw; margin: 0.0vw 0 2.0vw -2.0vw; border-left: solid 1.2vw #2980b9; border-bottom: solid 0.8vw #d7d7d7; } </style> # Actix-webについて * リポジトリ * 機能 * アクターモデルについて * Getting Started * Hello worldやってみる * HttepSrverについて * Appについて * Stateについて * ホットリロード設定 ### 2020/9/4 原山和之 --- # リポジトリ * RustのWeb application frameworkです。 * リポジトリは[こちら](https://github.com/actix/actix-web) * サンプル * https://actix.rs/actix-web/actix_web/ * https://github.com/actix/examples * [ベンチマーク結果](https://www.techempower.com/benchmarks/) --- # 機能 * Supports HTTP/1.x and HTTP/2 * Streaming and pipelining * Keep-alive and slow requests handling * Client/server WebSockets support * Transparent content compression/decompression (br, gzip, deflate) * Powerful request routing * Multipart streams * Static assets * SSL support using OpenSSL or Rustls * Middlewares (Logger, Session, CORS, etc) * Includes an async HTTP client * Supports Actix actor framework * Runs on stable Rust 1.42+ --- # アクターモデルについて * アクターモデル実装はErlang/Elixirや、Scala/JavaにおけるAkkaが有名 * Rust * [Actor model by Rust with Actix](https://qiita.com/atsuk/items/6b620484aad019638795) * [Tatsuya Kawano](https://qiita.com/tatsuya6502) * アクターモデルに関して * https://www.slideshare.net/TakamasaMitsuji/ss-13626473 * https://tech-lab.sios.jp/archives/8738 ごめんなさい。全部日本語ですが。。。 --- # Getting Started ## Hello worldやってみる1 Cargo Newする ``` $ cargo new hello-world $ cd hello-world ``` Tomlファイルに記述 ``` [dependencies] actix-web = "2.0" actix-rt = "1.0" ``` --- ## Hello worldやってみる2 main.rs ```rust use actix_web::{web, App, HttpResponse, HttpServer, Responder}; async fn index() -> impl Responder { HttpResponse::Ok().body("Hello world!") } async fn index2() -> impl Responder { HttpResponse::Ok().body("Hello world again!") } ``` ```rust #[actix_rt::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(index)) .route("/again", web::get().to(index2)) }) .bind("127.0.0.1:8088")? .run() .await } ``` --- # HttpServerについて1 * HttpServerがTop-Level * HttpServerでは主に以下の設定を行うみたいです。 * App factory * hostname * worker thread * keep-alive * backlog * bind address * SSL ##### [Architecture overview](https://actix.rs/docs/http_server_init/) --- # HttpServerについて2 main.rs ```rust extern crate actix_web; use actix_web::{http, server, App, HttpRequest}; fn main() { server::new( || App::new() .route("/", http::Method::GET, |_: HttpRequest| "test")) .workers(100) .backlog(100) .keep_alive(server::KeepAlive::Timeout(75)) .server_hostname("test".to_string()) .bind("127.0.0.1:8080").unwrap() .run(); } ``` * ##### [チュートリアル](https://actix.rs/docs/server/) --- # Appについて1 * AppはHttpServerにおける1つのworkerが保持するアプリケーションインスタンス * Routing * State * Middleware * ##### Appは主にHttpServer作成時にnewメソッドの引数としてAppを作成するFactoryを渡し、HttpServerが各worker threadを立ち上げる際に渡されたFactoryを実行することで作成されます。 * ##### 特筆すべき点としては、各worker threadで動作するAppは全て別のインスタンスであるということです。 --- # Appについて2 * main.rs ```rust use actix_web::{web, App, Responder, HttpServer}; async fn index() -> impl Responder { "Hello world!" } #[actix_rt::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().service( web::scope("/app").route("/index.html", web::get().to(index)), ) }) .bind("127.0.0.1:8088")? .run() .await } ``` --- # Stateについて * Config情報やConnection pool、Cache map等といったApp全体で共有したい情報 ```rust use actix_web::{web, App, HttpServer}; use std::sync::Mutex; // This struct represents state struct AppState { app_name: String, } async fn index(data: web::Data<AppState>) -> String { let app_name = &data.app_name; // <- get app_name format!("Hello {}!", app_name) // <- response with app_name } #[actix_rt::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .data(AppState { app_name: String::from("Actix-web"), }) .route("/", web::get().to(index)) }) .bind("127.0.0.1:8088")? .run() .await } ``` --- # ホットリロード設定 * いちいちコンパイルして、サーバを立ち上げ直すのは少々面倒です。 * * 開発時には大変面倒。効率よく!!的な感じです。 * Tomlファイルを下記に ```toml [dependencies] actix-web = "2.0" actix-rt = "1.0" serde = "1.0.115" serde_json = "1.0.57" env_logger = "0.7.1" listenfd = "0.3.3" dotenv = "0.15" ``` cargoのglobalに``` systemfd ```, ``` cargo-watch ``` ``` $ cargo install systemfd cargo-watch ``` --- # ホットリロード * main.rs ```rust use actix_web::{get, App, HttpServer, Responder}; use dotenv::dotenv; use listenfd::ListenFd; use std::env; #[get("/hello")] async fn hello_world() -> impl Responder { format!("Hello World!") } #[actix_rt::main] async fn main() -> std::io::Result<()> { dotenv().ok(); let mut listenfd = ListenFd::from_env(); let mut server = HttpServer::new(|| { App::new() .service(hello_world) }); server = match listenfd.take_tcp_listener(0)? { Some(listener) => server.listen(listener)?, None => { let host = env::var("HOST").expect("Please set host in .env"); let port = env::var("PORT").expect("Please set port in .env"); server.bind(format!("{}:{}", host, port))? } }; server.run().await } ``` * 下記で実行 ``` $ systemfd --no-pid -s http::3000 -- cargo watch -x run ``` --- # ホットリロード ``` [dependencies] listenfd = "0.3" ``` ```rust use actix_web::{web, App, HttpRequest, HttpServer, Responder}; use listenfd::ListenFd; async fn index(_req: HttpRequest) -> impl Responder { "Hello World!" } #[actix_rt::main] async fn main() -> std::io::Result<()> { let mut listenfd = ListenFd::from_env(); let mut server = HttpServer::new(|| App::new().route("/", web::get().to(index))); server = if let Some(l) = listenfd.take_tcp_listener(0).unwrap() { server.listen(l)? } else { server.bind("127.0.0.1:3000")? }; server.run().await } ``` * 下記で実行 ``` $ systemfd --no-pid -s http::3000 -- cargo watch -x run ``` --- # 最後に * dockerizeを後日完成させたい。Dickerfileの書き方わからない。 * 次はもうちょっと勉強してMiddleware, DBアクセスについて話せたらなと思います。 --- # ツール * [Postman](https://www.postman.com/downloads/) * [Postman - Chrom Extention](https://chrome.google.com/webstore/detail/postman-interceptor/aicmkgpgakddgnaphhhpliifpcfhicfo?hl=ja) # 参考 [Rustでwebサーバハンズオン! ~actix-web & postgres~ Part1](https://qiita.com/susiyaki/items/ea4a82d15570d5af9a2b) [Web Application Server by Rust with actix-web](https://qiita.com/atsuk/items/c04fffe4ed0e73a67cd0) [systemfd](https://github.com/mitsuhiko/systemfd) ---
{"metaMigratedAt":"2023-06-15T12:22:24.977Z","metaMigratedFrom":"YAML","title":"Actix-web","breaks":true,"description":"Actix-webについて","slideOptions":"{\"theme\":\"white\",\"slideNumber\":\"c/t\",\"center\":false,\"transition\":\"none\",\"keyboard\":true}","contributors":"[{\"id\":\"ed5d0581-544f-4aa0-a6ad-2f48be3d325d\",\"add\":11515,\"del\":2208}]"}
    1159 views