满足一个请求后如何终止超级服务器?

问题描述

我需要一个简单的超级服务器,该服务器可以处理单个请求,然后退出。到目前为止,这是我的代码,我相信我所需要的只是使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,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(())
}

Rust playground

相关的板条箱:

tokio = { version = "0.2",features = ["full"] }
hyper = "0.13.7"

How to share mutable state for a Hyper handler?How to share mutable state for a Hyper handler?起,超级API发生了变化,我是unable to compile the code when edited to work with the current version

解决方法

一个简单的解决方案是为此使用全局状态,这是由tokio的Mutex类型实现的,如下所示:

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

在此版本的代码中,我们将关闭信号通道的发送方一半存储在由互斥锁保护的全局变量中,然后尝试消耗该通道以在每次请求时发送信号。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...