Multi-threading http server with hyper and tokio-runtime


#1

I’d like to make multi-threading http server, and I found new released tokio-runtime https://tokio.rs/blog/2018-03-tokio-runtime/ whick has work-stealing based thread pool for scheduling and executing the application’s code. I think it’s very nice.

I guess the future representing hyper::Response does not implement Send trait and it’s not thread safe. How can I integrate with hyper?

My code is like below:

struct RealService;

impl Service for RealService {
    type Request = hyper::Request;
    type Response = hyper::Response;
    type Error = hyper::Error;
    type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;

    fn call(&self, _req: Self::Request) -> Self::Future { ... }
fn main() {
    ....
   let listener = TcpListener::bind(&addr).unwrap();
    let server = listener.incoming().for_each(|stream| {
        let future = Http::<hyper::Chunk>::new()
            .serve_connection( stream, RealService)
            .map_err(|e| {
                std::io::Error::new( std::io::ErrorKind::Other, format!("Failed to serve connection: {}", e))
            });
        tokio::spawn(future);
        Ok(())
    });
    tokio::run(server);
}

I got error like below:

error[E0271]: type mismatch resolving `<[closure@src/main.rs:170:22: 172:14] as std::ops::FnOnce<(hyper::Error,)>>::Output == ()`
   --> src/main.rs:173:9
    |
173 |         tokio::spawn(future);
    |         ^^^^^^^^^^^^ expected struct `std::io::Error`, found ()
    |
    = note: expected type `std::io::Error`
               found type `()`
    = note: required because of the requirements on the impl of `futures::Future` for `futures::MapErr<hyper::server::Connection<tokio::net::TcpStream, RealService>, [closure@src/main.rs:170:22: 172:14]>`
    = note: required by `tokio::spawn`

error[E0277]: the trait bound `futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static: std::marker::Send` is not satisfied
   --> src/main.rs:173:9
    |
173 |         tokio::spawn(future);
    |         ^^^^^^^^^^^^ `futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>`
    = note: required because it appears within the type `std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>`
    = note: required because it appears within the type `std::option::Option<std::boxed::Box<futures::Future<Error=hyper::Error, Item=hyper::Response> + 'static>>`
    = note: required because it appears within the type `hyper::proto::h1::dispatch::Server<RealService>`
    = note: required because it appears within the type `hyper::proto::h1::dispatch::Dispatcher<hyper::proto::h1::dispatch::Server<RealService>, hyper::Body, tokio::net::TcpStream, hyper::Chunk, hyper::proto::h1::role::Server<hyper::proto::h1::role::YesUpgrades>>`
    = note: required because it appears within the type `hyper::server::Connection<tokio::net::TcpStream, RealService>`
    = note: required because it appears within the type `futures::MapErr<hyper::server::Connection<tokio::net::TcpStream, RealService>, [closure@src/main.rs:170:22: 172:14]>`
    = note: required by `tokio::spawn`

error[E0271]: type mismatch resolving `<futures::stream::ForEach<tokio::net::Incoming, [closure@src/main.rs:159:47: 175:6 handle:_, pool:_], std::result::Result<(), std::io::Error>> as futures::Future>::Error == ()`
   --> src/main.rs:176:5
    |
176 |     tokio::run(server);
    |     ^^^^^^^^^^ expected struct `std::io::Error`, found ()
    |
    = note: expected type `std::io::Error`
               found type `()`
    = note: required by `tokio::run`

error: aborting due to 3 previous errors


#2

I think you’ll need the (unreleased as of yet) hyper 0.12 version.