将附加状态传递给 rust `hyper::service::service_fn`

Dan*_*son 7 lifetime rust async-await hyper

我在将附加状态传递给我的服务函数时遇到问题,但我无法理清闭包中的生命周期。教程似乎都没有解决这个问题:

https://hyper.rs/

https://docs.rs/hyper/0.13.4/hyper/server/index.html

https://docs.rs/hyper/0.13.4/hyper/service/fn.make_service_fn.html

相关代码:

#[tokio::main]                                                                       
async fn main() {                                                               
    let addr = ([127, 0, 0, 1], 8080).into();                                   
    let db = Arc::new(Mutex::new(Slab::new()));                                 
    let server = Server::bind(&addr).serve(make_service_fn(|_conn| async {      
        let db = db.clone();                                                         
        Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))         
    }));                                                                             
    if let Err(e) = server.await {                                                   
        eprintln!("server error: {}", e)                                             
    }                                                                                
}
Run Code Online (Sandbox Code Playgroud)

错误:

   Compiling hyper-microservice v0.1.0 (/data/repos/rust/hyper-microservice)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
   --> src/main.rs:121:66
    |
121 |         Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
    |                                                                  ^^^
    |
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 121:40...
   --> src/main.rs:121:40
    |
121 |         Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `db`
   --> src/main.rs:121:66
    |
121 |         Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
    |                                                                  ^^^
note: but, the lifetime must be valid for the expression at 121:29...
   --> src/main.rs:121:29
    |
121 |         Ok::<_, Infallible>(service_fn(move |req| serve_req(req, &db)))
    |                             ^^^^^^^^^^

Run Code Online (Sandbox Code Playgroud)

我的理解是,它make_service_fn负责返回一个ServiceFn可用于为给定连接提供请求的服务,并ServiceFn为每个连接创建一个新的连接。现在,service_fn接受一个函数/闭包,该函数/闭包接受请求并返回一个返回响应(或错误)的 Future。而且,据我了解,ServiceFn每个连接可能会执行多次。粗略地说,每个客户端都有自己的线程,该线程为该连接上的每个请求执行异步服务函数(因此同一客户端可以在同一连接上发出多个请求,并在同一线程中同时提供服务)。

我相信可能发生的情况是编译器认为其中一个闭包可能比数据库寿命更长?

小智 2

正确的代码应该是:

#[tokio::main]
async fn main() {
    let addr = ([127, 0, 0, 1], 8080).into();
    let db = Arc::new(Mutex::new(Slab::new()));
    let server = Server::bind(&addr).serve(make_service_fn(move |_conn| {
        let db = db.clone();
        async move { Ok::<_, Infallible>(service_fn(move |req| serve_req(req, db.clone()))) }
    }));

    if let Err(e) = server.await {
        eprintln!("server error: {}", e)
    }
}
Run Code Online (Sandbox Code Playgroud)