アクターモデル実装はErlang/Elixirや、Scala/JavaにおけるAkkaが有名
Rust
アクターモデルに関して
ごめんなさい。全部日本語ですが。。。
Cargo Newする
$ cargo new hello-world
$ cd hello-world
Tomlファイルに記述
[dependencies]
actix-web = "2.0"
actix-rt = "1.0"
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!")
}
#[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
}
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();
}
AppはHttpServerにおける1つのworkerが保持するアプリケーションインスタンス
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
}
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ファイルを下記に
[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
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"
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