<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}]"}