超级服务器在将来返回Async :: NotReady时断开连接

时间:2019-01-18 10:57:04

标签: rust rust-tokio hyper

我正在尝试使用将来对请求的异步响应运行超级服务器。当调用future的poll方法并返回Async::NotReady时,连接将被删除(“删除I / O源:0”)。我希望多次调用poll方法,直到返回Async::Ready

example shown返回一个异步io future,它正在做(我猜)是同一件事。

为什么将来的poll函数仅被调用一次,为什么在将来返回Async::NotReady之后hyper断开连接?

示例代码:(超级版本为:v0.12.21)

use futures::{Async, Future, Poll};
use hyper::http::{Request, Response};
use hyper::service::service_fn;
use hyper::{Body, Server};

fn main() {
    let addr = ([127, 0, 0, 1], 3335).into();
    println!("Start request handler. (Listening on http://{})", addr);

    hyper::rt::run(
        Server::bind(&addr)
            .serve(|| service_fn(|request: Request<Body>| handle_request(request.uri().path())))
            .map_err(|e| println!("server error: {}", e)),
    );
}

type BoxedResponseFuture = Box<Future<Item = Response<Body>, Error = tokio::io::Error> + Send>;

fn handle_request(path: &str) -> BoxedResponseFuture {
    println!("Handle request {:?}", path);
    Box::new(
        ResponseFuture { ready: false }
            .and_then(|_| {
                let response = Response::new(Body::from("Success".to_string()));

                Ok(response)
            })
            .or_else(|e| {
                let response = Response::new(Body::from(format!("Error: {:?}", e)));

                Ok(response)
            }),
    )
}

struct ResponseFuture {
    ready: bool,
}

impl Future for ResponseFuture {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        println!("Poll future");

        if self.ready {
            println!("Future ready");

            return Ok(Async::Ready(()));
        }

        println!("Future not ready");
        self.ready = true;
        Ok(Async::NotReady)
    }
}

1 个答案:

答案 0 :(得分:1)

Hyper建立在期货板条箱的顶部,并使用其称为“就绪”或“拉动”的期货模型,其中按需从期货中提取价值,否则将通知当某个值可能准备好被拉出时。

poll返回NotReady时,当前任务必须注册以准备就绪更改通知,否则该任务可能永远无法完成。返回Async的任何函数都必须遵守。

换句话说,您应该等到poll返回Ready或通知当前任务以表明它已准备好前进并返回NotReady

// notify about progress
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    println!("Poll future");

    if self.ready {
        println!("Future ready");

        return Ok(Async::Ready(()));
    }

    println!("Future not ready");
    self.ready = true;

    // The executor will poll this task next iteration
    futures::task::current().notify();
    Ok(Async::NotReady)
}

// wait until it is Ready
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
    loop {
        println!("Poll future");

        if self.ready {
            println!("Future ready");
            return Ok(Async::Ready(()));
        }

        println!("Future not ready");
        self.ready = true;
    }
}

Tokio的文档1 2可能会阐明这一点。