Rust网络服务框架ntex-service的使用:高性能异步服务构建与中间件扩展
Rust网络服务框架ntex-service的使用:高性能异步服务构建与中间件扩展
安装
在项目目录中运行以下Cargo命令:
cargo add ntex-service
或在Cargo.toml中添加以下行:
ntex-service = "3.5.0"
基本使用
以下是一个使用ntex-service构建高性能异步服务的完整示例:
use ntex_service::{Service, ServiceFactory};
use std::future::{ready, Ready};
use std::task::{Context, Poll};
// 定义简单的服务
struct EchoService;
impl Service<String> for EchoService {
type Response = String;
type Error = std::io::Error;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&self, req: String) -> Self::Future {
ready(Ok(req))
}
}
// 定义服务工厂
struct EchoServiceFactory;
impl ServiceFactory<String> for EchoServiceFactory {
type Response = String;
type Error = std::io::Error;
type Service = EchoService;
type InitError = ();
type Future = Ready<Result<Self::Service, Self::InitError>>;
fn new_service(&self, _: ()) -> Self::Future {
ready(Ok(EchoService))
}
}
#[ntex::main]
async fn main() -> std::io::Result<()> {
// 使用服务工厂创建服务
let factory = EchoServiceFactory;
let service = factory.new_service(()).await.unwrap();
// 调用服务
let response = service.call("Hello, ntex!".to_string()).await?;
println!("Received: {}", response);
Ok(())
}
中间件扩展
ntex-service支持通过中间件扩展服务功能。以下是添加日志中间件的示例:
use ntex_service::{Middleware, Service, ServiceCall, Transform};
use std::future::{ready, Ready};
use std::task::{Context, Poll};
// 日志中间件
struct LogMiddleware;
impl<S> Transform<S> for LogMiddleware {
type Service = LogService<S>;
fn new_transform(&self, service: S) -> Self::Service {
LogService { service }
}
}
struct LogService<S> {
service: S,
}
impl<S, Req> Service<Req> for LogService<S>
where
S: Service<Req>,
{
type Response = S::Response;
type Error = S::Error;
type Future = ServiceCall<S, Req>;
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
fn call(&self, req: Req) -> Self::Future {
println!("Request received");
ServiceCall::new(self.service.call(req))
}
}
// 使用中间件
#[ntex::main]
async fn main() -> std::io::Result<()> {
let service = EchoService;
let logged_service = LogMiddleware.new_transform(service);
let response = logged_service.call("Hello with logging!".to_string()).await?;
println!("Received: {}", response);
Ok(())
}
完整示例
基于上述内容,这里提供一个结合了基本服务和中间件的完整示例:
use ntex_service::{Middleware, Service, ServiceCall, ServiceFactory, Transform};
use std::future::{ready, Ready};
use std::task::{Context, Poll};
// 1. 定义基本服务
struct GreetService;
impl Service<String> for GreetService {
type Response = String;
type Error = std::io::Error;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&self, name: String) -> Self::Future {
ready(Ok(format!("Hello, {}!", name)))
}
}
// 2. 定义服务工厂
struct GreetServiceFactory;
impl ServiceFactory<String> for GreetServiceFactory {
type Response = String;
type Error = std::io::Error;
type Service = GreetService;
type InitError = ();
type Future = Ready<Result<Self::Service, Self::InitError>>;
fn new_service(&self, _: ()) -> Self::Future {
ready(Ok(GreetService))
}
}
// 3. 定义计时中间件
struct TimingMiddleware;
impl<S> Transform<S> for TimingMiddleware {
type Service = TimingService<S>;
fn new_transform(&self, service: S) -> Self::Service {
TimingService { service }
}
}
struct TimingService<S> {
service: S,
}
impl<S, Req> Service<Req> for TimingService<S>
where
S: Service<Req>,
{
type Response = S::Response;
type Error = S::Error;
type Future = ServiceCall<S, Req>;
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
fn call(&self, req: Req) -> Self::Future {
let start = std::time::Instant::now();
let fut = self.service.call(req);
println!("Request processed in {:?}", start.elapsed());
fut
}
}
// 4. 主程序
#[ntex::main]
async fn main() -> std::io::Result<()> {
// 创建基础服务
let factory = GreetServiceFactory;
let service = factory.new_service(()).await.unwrap();
// 添加中间件
let timed_service = TimingMiddleware.new_transform(service);
// 调用服务
let response = timed_service.call("World".to_string()).await?;
println!("{}", response);
Ok(())
}
这个完整示例展示了:
- 定义一个基本的问候服务
- 创建服务工厂
- 添加计时中间件来测量请求处理时间
- 在主程序中组合这些组件并运行服务
项目信息
- 许可证: MIT OR Apache-2.0
- 版本: v1.75.0
- 分类: 异步编程, 网络编程
所有者
- ntex-rs/core团队
- Nikolay Kim (fafhrd91)
1 回复
Rust网络服务框架ntex-service的使用:高性能异步服务构建与中间件扩展
简介
ntex-service是Rust生态中一个高性能的异步网络服务框架,专注于构建可扩展的web服务和API。它基于tokio运行时,提供了简洁的API和强大的中间件系统,适合构建从简单到复杂的网络应用。
完整示例代码
下面是一个结合了基本HTTP服务、中间件、状态共享和WebSocket的完整示例:
use ntex::web::{self, middleware, App, HttpRequest, HttpResponse};
use ntex::service::{Service, Transform};
use ntex::ws;
use std::sync::Arc;
use std::future::{ready, Ready};
// 应用状态
struct AppState {
visit_count: usize,
}
// 自定义中间件
struct LoggingMiddleware;
impl<S> Transform<S> for LoggingMiddleware {
type Service = LoggingMiddlewareService<S>;
fn new_transform(&self, service: S) -> Self::Service {
LoggingMiddlewareService { service }
}
}
struct LoggingMiddlewareService<S> {
service: S,
}
impl<S, Err> Service<web::WebRequest<Err>> for LoggingMiddlewareService<S>
where
S: Service<web::WebRequest<Err>, Response = web::WebResponse>,
{
type Response = web::WebResponse;
type Error = S::Error;
type Future = S::Future;
fn call(&self, req: web::WebRequest<Err>) -> Self::Future {
println!("Request received: {}", req.path());
self.service.call(req)
}
}
// WebSocket处理器
struct WsConnection;
impl ws::WsHandler for WsConnection {
fn handle_frame(&mut self, frame: ws::Frame) -> Result<Option<ws::Message>, ws::ProtocolError> {
match frame {
ws::Frame::Text(text) => Ok(Some(ws::Message::Text(text.to_string()))),
_ => Ok(None),
}
}
}
async fn ws_handler(
req: HttpRequest,
stream: web::types::Payload,
state: web::types::State<Arc<AppState>>,
) -> Result<HttpResponse, web::Error> {
println!("WebSocket connection from {} (total visits: {})",
req.connection_info().peer_addr().unwrap_or("unknown"),
state.visit_count);
ws::start::<_, _, web::Error>(WsConnection {}, &req, stream)
}
// HTTP路由处理器
async fn index(state: web::types::State<Arc<AppState>>) -> String {
format!("Visit count: {}", state.visit_count)
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
// 初始化共享状态
let state = Arc::new(AppState { visit_count: 0 });
// 创建HTTP服务器
web::HttpServer::new(move || {
// 克隆状态用于每个worker线程
let state = state.clone();
web::App::new()
// 添加共享状态
.state(state)
// 添加中间件
.wrap(LoggingMiddleware)
.wrap(middleware::Logger::default())
// 添加HTTP路由
.service(web::resource("/").to(index))
// 添加WebSocket路由
.service(web::resource("/ws").to(ws_handler))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
代码说明
- 应用状态:使用
Arc<AppState>
实现线程安全的共享状态,记录访问次数 - 自定义中间件:实现
Transform
和Service
trait创建日志中间件 - WebSocket支持:
- 实现
WsHandler
trait处理WebSocket消息 - 可以访问共享状态
- 实现
- HTTP路由:
- 根路由显示访问次数
- 使用
state
访问共享状态
- 服务器配置:
- 使用
wrap
添加中间件 - 使用
service
添加路由 - 绑定到127.0.0.1:8080
- 使用
运行效果
- 访问
http://localhost:8080
会显示当前的访问次数 - 访问
ws://localhost:8080/ws
可以建立WebSocket连接 - 服务器日志会记录所有请求和WebSocket连接信息
这个示例展示了ntex-service框架的核心功能,包括路由处理、中间件、状态共享和WebSocket支持,可以作为构建更复杂应用的起点。