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(())
}

这个完整示例展示了:

  1. 定义一个基本的问候服务
  2. 创建服务工厂
  3. 添加计时中间件来测量请求处理时间
  4. 在主程序中组合这些组件并运行服务

项目信息

  • 许可证: 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
}

代码说明

  1. 应用状态:使用Arc<AppState>实现线程安全的共享状态,记录访问次数
  2. 自定义中间件:实现TransformService trait创建日志中间件
  3. WebSocket支持
    • 实现WsHandler trait处理WebSocket消息
    • 可以访问共享状态
  4. HTTP路由
    • 根路由显示访问次数
    • 使用state访问共享状态
  5. 服务器配置
    • 使用wrap添加中间件
    • 使用service添加路由
    • 绑定到127.0.0.1:8080

运行效果

  1. 访问http://localhost:8080会显示当前的访问次数
  2. 访问ws://localhost:8080/ws可以建立WebSocket连接
  3. 服务器日志会记录所有请求和WebSocket连接信息

这个示例展示了ntex-service框架的核心功能,包括路由处理、中间件、状态共享和WebSocket支持,可以作为构建更复杂应用的起点。

回到顶部