Rust 如何在完成一个请求后终止超级服务器?

Rust 如何在完成一个请求后终止超级服务器?,rust,hyper,Rust,Hyper,我需要一个简单的超服务器,服务于一个单一的请求,然后退出。这是到目前为止我的代码,我相信我所需要的是一种方法,让tx进入hello,这样我就可以使用tx.send(()),它应该按照我想要的方式工作。然而,如果没有编译器对我大喊大叫,我无法找到一种方法来实现这一点 use std::convert::Infallible; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Request, Response

我需要一个简单的超服务器,服务于一个单一的请求,然后退出。这是到目前为止我的代码,我相信我所需要的是一种方法,让
tx
进入
hello
,这样我就可以使用
tx.send(())
,它应该按照我想要的方式工作。然而,如果没有编译器对我大喊大叫,我无法找到一种方法来实现这一点

use std::convert::Infallible;

use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};

async fn hello(_: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new(Body::from("Hello World!")))
}

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {

    let (tx, rx) = tokio::sync::oneshot::channel::<()>();

    let make_svc = make_service_fn(|_conn| {
        async { Ok::<_, Infallible>(service_fn(hello)) }
    });

    let addr = ([127, 0, 0, 1], 3000).into();

    let server = Server::bind(&addr).serve(make_svc);

    println!("Listening on http://{}", addr);

    let graceful = server.with_graceful_shutdown(async {
        rx.await.ok();
    });

    graceful.await?;

    Ok(())
}

自和以来,hyper API发生了变化,而我是。

一个简单的解决方案是为此使用全局状态,tokio的
互斥类型使之成为可能,如下所示:

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

lazy_static! {
    /// Channel used to send shutdown signal - wrapped in an Option to allow
    /// it to be taken by value (since oneshot channels consume themselves on
    /// send) and an Arc<Mutex> to allow it to be safely shared between threads
    static ref SHUTDOWN_TX: Arc<Mutex<Option<Sender<()>>>> = <_>::default();
}

async fn hello(_: Request<Body>) -> Result<Response<Body>, Infallible> {
    // Attempt to send a shutdown signal, if one hasn't already been sent
    if let Some(tx) = SHUTDOWN_TX.lock().await.take() {
        let _ = tx.send(());
    }

    Ok(Response::new(Body::from("Hello World!")))
}

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let (tx, rx) = tokio::sync::oneshot::channel::<()>();
    SHUTDOWN_TX.lock().await.replace(tx);

    let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(hello)) });

    let addr = ([127, 0, 0, 1], 3000).into();

    let server = Server::bind(&addr).serve(make_svc);

    println!("Listening on http://{}", addr);

    let graceful = server.with_graceful_shutdown(async {
        rx.await.ok();
    });

    graceful.await?;

    Ok(())
}
使用hyper::service::{make_service_fn,service_fn};
使用hyper::{Body,Request,Response,Server};
使用lazy\u static::lazy\u static;
使用std::convert::绝对正确;
使用std::sync::Arc;
使用tokio::sync::oneshot::Sender;
使用东京::同步::互斥;
懒惰的人!{
///用于发送关机信号的通道-包装在允许的选项中
///它是按值计算的(因为oneshot频道在
///发送)和Arc,以便在线程之间安全共享
静态参考关闭_TX:Arc=::default();
}
异步fn hello(u3;:请求)->Result{
//尝试发送关机信号(如果尚未发送)
如果让一些(tx)=关机\u tx.lock().wait.take(){
让ux=tx.send(());
}
好(回复::新建(正文::from(“Hello World!”))
}
#[tokio::main]
pub async fn main()->结果{
let(tx,rx)=东京::同步::单点::频道:();
关闭_TX.lock().等待更换(TX);
设make_svc=make_service_fn(|u conn|async{Ok::(service_fn(hello))});
让addr=([127,0,0,1],3000).into();
让server=server::bind(&addr).service(make_svc);
println!(“在http://{}上侦听”,addr);
让优雅=服务器。在关闭(异步)的情况下{
rx.wait.ok();
});
优雅。等待?;
好(())
}

在这个版本的代码中,我们将关机信号通道的发送方一半存储在一个受互斥锁保护的全局变量中,然后尝试使用通道在每次请求时发送信号。

我们如何猜测编译器的叫声?它在@AlexLarionov@Shepmaster中工作正常当前代码没有错误。我问的是如何完成一些事情,即如何在hello方法中使用tx.send()。我无法发布完整的错误消息,没有错误消息。我的代码也存在于fulI中,没有我没有提到的其他类型、特征或字段,所有
use
都存在,所有板条箱都是最新版本。我已经用你要求的其他细节编辑了这篇文章。
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
use lazy_static::lazy_static;
use std::convert::Infallible;
use std::sync::Arc;
use tokio::sync::oneshot::Sender;
use tokio::sync::Mutex;

lazy_static! {
    /// Channel used to send shutdown signal - wrapped in an Option to allow
    /// it to be taken by value (since oneshot channels consume themselves on
    /// send) and an Arc<Mutex> to allow it to be safely shared between threads
    static ref SHUTDOWN_TX: Arc<Mutex<Option<Sender<()>>>> = <_>::default();
}

async fn hello(_: Request<Body>) -> Result<Response<Body>, Infallible> {
    // Attempt to send a shutdown signal, if one hasn't already been sent
    if let Some(tx) = SHUTDOWN_TX.lock().await.take() {
        let _ = tx.send(());
    }

    Ok(Response::new(Body::from("Hello World!")))
}

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let (tx, rx) = tokio::sync::oneshot::channel::<()>();
    SHUTDOWN_TX.lock().await.replace(tx);

    let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(hello)) });

    let addr = ([127, 0, 0, 1], 3000).into();

    let server = Server::bind(&addr).serve(make_svc);

    println!("Listening on http://{}", addr);

    let graceful = server.with_graceful_shutdown(async {
        rx.await.ok();
    });

    graceful.await?;

    Ok(())
}