服务器

HttpServer类型负责服务的HTTP请求。

HttpServer接受应用程序工厂作为参数,并且应用程序工厂必须具有Send+ Sync边界。p 要绑定到特定的套接字地址, bind() 必须使用,并且可能会多次调用它。绑定ssl套接字使用bind_ssl()bind_tls()。启动http服务器,启动方法之一是:

HttpServer是一位actix actor。它必须在正确配置的actix系统中初始化:

  1. use actix_web::{server::HttpServer, App, HttpResponse};
  2. fn main() {
  3. let sys = actix::System::new("guide");
  4. HttpServer::new(|| App::new().resource("/", |r| r.f(|_| HttpResponse::Ok())))
  5. .bind("127.0.0.1:59080")
  6. .unwrap()
  7. .start();
  8. let _ = sys.run();
  9. }

可以使用该run()方法在单独的线程中启动服务器。在这种情况下,服务器会产生一个新线程并在其中创建一个新的actix系统。要停止此服务器,请发送StopServer消息。

HttpServer被实施为actix actor。可以通过消息传递系统与服务器进行通信。启动方法,例如start(),返回启动的http服务器的地址。它接受几种消息:

  • PauseServer - 暂停接受传入连接
  • ResumeServer - 继续接受传入连接
  • StopServer - 停止传入连接处理,停止所有workers并退出
  1. use actix_web::{server, App, HttpResponse};
  2. use std::sync::mpsc;
  3. use std::thread;
  4. fn main() {
  5. let (tx, rx) = mpsc::channel();
  6. thread::spawn(move || {
  7. let sys = actix::System::new("http-server");
  8. let addr = server::new(|| {
  9. App::new()
  10. .resource("/", |r| r.f(|_| HttpResponse::Ok()))
  11. })
  12. .bind("127.0.0.1:0").expect("Can not bind to 127.0.0.1:0")
  13. .shutdown_timeout(60) // <- Set shutdown timeout to 60 seconds
  14. .start();
  15. let _ = tx.send(addr);
  16. let _ = sys.run();
  17. });
  18. let addr = rx.recv().unwrap();
  19. let _ = addr.send(server::StopServer { graceful: true }).wait(); // <- Send `StopServer` message to server.
  20. }


多线程

HttpServer自动启动一些http worker,默认情况下这个数量等于系统中逻辑CPU的数量。该数量可以用该HttpServer::workers()方法覆盖 。

  1. use actix_web::{server::HttpServer, App, HttpResponse};
  2. fn main() {
  3. HttpServer::new(|| App::new().resource("/", |r| r.f(|_| HttpResponse::Ok())))
  4. .workers(4); // <- Start 4 workers
  5. }

服务器为每个创建的worker创建一个单独的应用实例。应用程序状态不在线程之间共享。分享状态,可以使用Arc。

应用程序状态并不需要是Send和Sync,但是工厂必须是Send+ Sync。

SSL

有两种功能的ssl服务器:tlsalpn。该tls功能由native-tls集成,alpn由openssl。

  1. [dependencies]
  2. actix-web = { version = "o.7", features = ["alpn"] }
  1. use actix_web::{server, App, HttpRequest, Responder};
  2. use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
  3. fn index(req: HttpRequest) -> impl Responder {
  4. "Welcome!"
  5. }
  6. fn main() {
  7. // load ssl keys
  8. let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
  9. builder
  10. .set_private_key_file("key.pem", SslFiletype::PEM)
  11. .unwrap();
  12. builder.set_certificate_chain_file("cert.pem").unwrap();
  13. server::new(|| App::new().resource("/index.html", |r| r.f(index)))
  14. .bind_ssl("127.0.0.1:8080", builder)
  15. .unwrap()
  16. .run();
  17. }

注意:HTTP / 2.0协议需要tls alpn。目前,只有openssl有alpn支持。完整示例,请查看examples/tls.

要创建key.pem和cert.pem,请使用以下命令。Fill in your own subject

  1. $ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
  2. -days 365 -sha256 -subj "/C=CN/ST=Fujian/L=Xiamen/O=TVlinux/OU=Org/CN=muro.lxd"

要删除密码,请将nopass.pem复制到key.pem

  1. $ openssl rsa -in key.pem -out nopass.pem


Keep-Alive

Actix可以等待keep-alive的请求。

keep-alive连接行为由服务器设置定义。

  • 75, Some(75), KeepAlive::Timeout(75) - 75秒keep alive定时器。
  • None or KeepAlive::Disabled - 禁用 keep alive.
  • KeepAlive::Tcp(75) - 使用 SO_KEEPALIVE socket 选项.
  1. use actix_web::{server, App, HttpResponse};
  2. fn main() {
  3. server::new(|| App::new().resource("/", |r| r.f(|_| HttpResponse::Ok())))
  4. .keep_alive(75); // <- Set keep-alive to 75 seconds
  5. server::new(|| App::new().resource("/", |r| r.f(|_| HttpResponse::Ok())))
  6. .keep_alive(server::KeepAlive::Tcp(75)); // <- Use `SO_KEEPALIVE` socket option.
  7. server::new(|| App::new().resource("/", |r| r.f(|_| HttpResponse::Ok())))
  8. .keep_alive(None); // <- Disable keep-alive
  9. }

如果选择第一个选项,则keep alive状态根据响应的connection-type计算。默认情况下HttpResponse::connection_type未定义。在这种情况下, keep alive 状态由请求的http版本定义。

keep alive关闭 对于 HTTP/1.0 然而是 打开 对于 HTTP/1.1HTTP/2.0.

Connection type可以用HttpResponseBuilder::connection_type()方法改变。

  1. use actix_web::{http, HttpRequest, HttpResponse};
  2. fn index(req: HttpRequest) -> HttpResponse {
  3. HttpResponse::Ok()
  4. .connection_type(http::ConnectionType::Close) // <- Close connection
  5. .force_close() // <- Alternative method
  6. .finish()
  7. }


优雅的关机

HttpServer支持优雅的关机。收到停止信号后,workers会有特定的时间完成服务请求。任何在超时后仍然活着的workers(工作线程)都会被迫停止。默认情况下,关机超时设置为30秒。您可以使用HttpServer::shutdown_timeout()方法更改此参数 。

您可以使用服务器地址向服务器发送停止消息,并指定是否要进行正常关机。start()方法返回服务器的地址。

HttpServer处理几个OS信号。所有操作系统都提供CTRL-C,其他信号在unix系统上可用。

  • SIGINT - 强制关闭工作线程
  • SIGTERM - 优雅的停止工作线程
  • SIGQUIT - 制关闭 workers工作线程

可以用HttpServer::disable_signals() 方法禁用信号处理 。