Rust 超链接中的共享可变状态

Rust 超链接中的共享可变状态,rust,hyper,rust-tokio,Rust,Hyper,Rust Tokio,我正在尝试在Hyper web服务器中创建一个计数器,用于统计它收到的请求数。我用一个Arc来保持计数。但是,我还没有找到满足闭包类型的move和.clone()的正确组合。下面是一些编译的代码,但会在每次请求时重置计数器: extern crate hyper; use hyper::rt::Future; use hyper::service::service_fn_ok; use hyper::{Body, Response, Server}; use std::sync::{Arc,

我正在尝试在Hyper web服务器中创建一个计数器,用于统计它收到的请求数。我用一个
Arc
来保持计数。但是,我还没有找到满足闭包类型的
move
.clone()
的正确组合。下面是一些编译的代码,但会在每次请求时重置计数器:

extern crate hyper;

use hyper::rt::Future;
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server};
use std::sync::{Arc, Mutex};

fn main() {
    let addr = "0.0.0.0:3000".parse().unwrap();
    // FIXME want to create the counter here, not below
    let server = Server::bind(&addr)
        .serve(|| {
            service_fn_ok(|_req| {
                let counter = Arc::new(Mutex::new(0));
                use_counter(counter)
            })
        })
        .map_err(|e| eprintln!("Error: {}", e));
    hyper::rt::run(server)
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}
extern板条箱超链接;
使用hyper::rt::Future;
使用hyper::service::service\u fn\u ok;
使用hyper::{Body,Response,Server};
使用std::sync::{Arc,Mutex};
fn main(){
让addr=“0.0.0.0:3000”。parse().unwrap();
//FIXME想在这里创建计数器,而不是在下面
让server=server::bind(&addr)
.发球{
服务正常(|要求|{
让计数器=弧::新(互斥体::新(0));
使用计数器(计数器)
})
})
.map|u err(| e | eprintln!(“错误:{},e));
hyper::rt::运行(服务器)
}
fn使用计数器(计数器:Arc)->响应{
让mut data=counter.lock().unwrap();
*数据+=1;
响应::新建(正文::from(格式)(“计数器:{}\n”,数据)))
}

事实证明,我非常接近,通过查看其他几个示例,我认识到了这个问题。因为这里有两层闭包,所以我需要将
计数器
移动到外部闭包中,克隆它,然后将该克隆移动到内部闭包中,然后再次克隆。也就是说:

extern crate hyper; // 0.12.10

use hyper::rt::Future;
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server};
use std::sync::{Arc, Mutex};

fn main() {
    let addr = "0.0.0.0:3000".parse().unwrap();
    let counter = Arc::new(Mutex::new(0));
    let server = Server::bind(&addr)
        .serve(move || {
            let counter = counter.clone();
            service_fn_ok(move |_req| use_counter(counter.clone()))
        })
        .map_err(|e| eprintln!("Error: {}", e));
    hyper::rt::run(server)
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}
extern板条箱超链接;//0.12.10
使用hyper::rt::Future;
使用hyper::service::service\u fn\u ok;
使用hyper::{Body,Response,Server};
使用std::sync::{Arc,Mutex};
fn main(){
让addr=“0.0.0.0:3000”。parse().unwrap();
让计数器=弧::新(互斥体::新(0));
让server=server::bind(&addr)
.发球(移动){
让counter=counter.clone();
服务| fn |确定(移动| |请求|使用|计数器(counter.clone()))
})
.map|u err(| e | eprintln!(“错误:{},e));
hyper::rt::运行(服务器)
}
fn使用计数器(计数器:Arc)->响应{
让mut data=counter.lock().unwrap();
*数据+=1;
响应::新建(正文::from(格式)(“计数器:{}\n”,数据)))
}

2020年2月更新以下是使用hyper 0.13的版本:

use hyper::{Body, Response, Server, Request};
use std::sync::{Arc, Mutex};
use hyper::service::{make_service_fn, service_fn};
use std::convert::Infallible;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "0.0.0.0:3000".parse()?;
    let counter = Arc::new(Mutex::new(0));

    let make_service = make_service_fn(move |_conn| {
        let counter = counter.clone();
        async move {
            Ok::<_, Infallible>(service_fn(move |_req: Request<Body>| {
                let counter = counter.clone();
                async move {
                    Ok::<_, Infallible>(use_counter(counter))
                }
            }))
        }
    });

    Server::bind(&addr).serve(make_service).await?;
    Ok(())
}

fn use_counter(counter: Arc<Mutex<u64>>) -> Response<Body> {
    let mut data = counter.lock().unwrap();
    *data += 1;
    Response::new(Body::from(format!("Counter: {}\n", data)))
}
使用hyper:{Body,Response,Server,Request};
使用std::sync::{Arc,Mutex};
使用hyper::service::{make_service_fn,service_fn};
使用std::convert::绝对正确;
#[tokio::main]
异步fn main()->结果{
让addr=“0.0.0.0:3000”。parse()?;
让计数器=弧::新(互斥体::新(0));
让我们做服务=做服务(移动连接){
让counter=counter.clone();
异步移动{
确定::(服务请求(移动请求:请求){
让counter=counter.clone();
异步移动{
Ok::(使用_计数器(计数器))
}
}))
}
});
服务器::绑定(&addr).服务(生成服务).等待?;
好(())
}
fn使用计数器(计数器:Arc)->响应{
让mut data=counter.lock().unwrap();
*数据+=1;
响应::新建(正文::from(格式)(“计数器:{}\n”,数据)))
}

我还提供了一个hyper 0.13版本