В этой статье я собираюсь сравнить очень популярный Hyper framework с Actix. Я собираюсь запустить простой HTTP-сервер Hello world.
Hyper - это быстрая и корректная реализация HTTP для Rust. Гипер - это:
- HTTP/1 и HTTP/2
- Асинхронный дизайн
- Лидерство в производительности
- Проверен и корректен
- Широкое использование в производстве
Actix Web - это мощный, прагматичный и чрезвычайно быстрый веб-фреймворк для Rust. Actix - это:
- Typesafe: Забудьте о не строго типизированных объектах, от запроса до ответа, у всего есть типы.
- Многофункциональность: Actix предоставляет множество функций “из коробки”. HTTP/2, ведение журнала и т.д.
- Расширяемый: Легко создавайте свои собственные библиотеки, которые может использовать любое приложение Actix.
- Очень быстрый
Оба утверждают, что они быстрые!
Тесты выполняются на MacBook Pro M1 с 16 ГБ оперативной памяти.
Версия rust - v1.69.0. Оба сервера hyper и actix построены в режиме релиза. Я использую Hyper 1.0.0-rc.3 и Actix web 4.
Образцы кода были взяты с их веб-сайтов.
Hyper
use std::convert::Infallible;
use std::net::SocketAddr;
use bytes::Bytes;
use http_body_util::Full;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::{Request, Response};
use tokio::net::TcpListener;
async fn hello(_: Request<hyper::body::Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
let response = Response::builder()
.header("Content-type", "text/plain")
.body(Full::new(Bytes::from("Hello World!")))
.unwrap();
Ok(response)
}
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let addr: SocketAddr = ([127, 0, 0, 1], 3000).into();
let listener = TcpListener::bind(addr).await?;
loop {
let (stream, _) = listener.accept().await?;
tokio::task::spawn(async move {
if let Err(err) = http1::Builder::new()
.serve_connection(stream, service_fn(hello)).await {
println!("Error serving connection: {:?}", err);
}
});
}
}
Actix
use actix_web::{get, web, App, HttpServer, Responder};
#[get("/")]
async fn index() -> impl Responder {
"Hello, World!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(index))
.bind(("127.0.0.1", 3000))?
.run()
.await
}
Одно из отличий заключается в том, что Actix поставляется с маршрутизатором, в то время как Hyper - нет. Это может сделать его несправедливым по отношению к Actix.
Тестирование
Каждый тест выполняется для 5 миллионов запросов. Тесты выполняются для 25, 100, 200 и 300 одновременных подключений. Нагрузочный тест выполняется с помощью инструмента HTTP-тестирования Bombardier. Перед снятием показаний проводится прогрев из 1000 запросов.
Ниже приведены таблицы, показывающие результаты для каждого уровня параллелизма:
Итог
Сейчас это жесткая конкуренция. Я не вижу здесь явного победителя. Оба работают очень хорошо. Использование ресурсов также остается таким же. Мне больше нравится приложение Actix, так как оно более читабельное. Кроме того, Actix кажется более многофункциональным.