tokio-rs / tokio-minihttp

Protocol implementation experimentations
Apache License 2.0
448 stars 50 forks source link

hanging connection - tests with ab #6

Closed szagi3891 closed 8 years ago

szagi3891 commented 8 years ago

I have this code :

extern crate tokio_proto;
extern crate tokio_service;
extern crate tokio_minihttp as http;
extern crate futures;
extern crate futures_cpupool;
extern crate env_logger;

use tokio_service::Service;
use futures::{Async, Future};
use std::io;
use futures_cpupool::CpuPool;
use std::time;
use std::io::Read;
use std::fs::File;
use std::sync::{Arc, Mutex};

#[derive(Clone)]
struct HelloWorld {
    pool: CpuPool,
    counter: Arc<Mutex<u32>>,
}

impl HelloWorld {
    fn new() -> HelloWorld {
        HelloWorld {
            pool: CpuPool::new(4),
            counter: Arc::new(Mutex::new(0)),
        }
    }

    fn get_counter(&self) -> u32 {
        let mut guard = self.counter.lock().unwrap();

        let counter = *guard;
        *guard += 1;
        counter
    }
}

impl Service for HelloWorld {
    type Request = http::Request;
    type Response = http::Response;
    type Error = io::Error;
    type Future = Box<Future<Item=http::Response, Error=io::Error>>;

    fn call(&self, _request: http::Request) -> Self::Future {

        //let (sender, receiver) = futures::oneshot();
        let mut resp = http::Response::new();
        let request_number = self.get_counter();

        println!("spanw run: {:?}", request_number);

        self.pool.spawn_fn(move || -> Result<String, io::Error> {
            let s = get_file("./test.txt".to_owned());
            println!("open file {:?}", request_number);
            Ok(s)
        }).and_then(move |str| {
            resp.body(str.as_str());
            Ok(resp)
        }).boxed()
    }

    fn poll_ready(&self) -> Async<()> {
        Async::Ready(())
    }
}

fn get_file(path: String) -> String {
    let mut f = File::open(path.as_str()).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();

    s
}

pub fn main() {
    let _ = ::env_logger::init();

    let addr = "0.0.0.0:8080".parse().unwrap();

    println!("start server at: 0.0.0.0:8080");

    http::serve(addr, HelloWorld::new());
}

When I run ab :

grzegorz@grzegorz:~/Pulpit/rust/test_http_futures$ ab -n 100 -c 10 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)...apr_pollset_poll: The timeout specified has expired (70007)

Out from server :

grzegorz@grzegorz:~/Pulpit/rust/test_http_futures$ cargo run --example static
    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/examples/static`
start server at: 0.0.0.0:8080
spanw run: 0
open file 0
spanw run: 1
open file 1
spanw run: 2
open file 2
spanw run: 3
open file 3
spanw run: 4
open file 4
spanw run: 5
open file 5
spanw run: 6
open file 6
spanw run: 7
open file 7
spanw run: 8
open file 8
spanw run: 9
open file 9

It seems that the server can not handle another request in the same connection.

help please :)

stalkerg commented 8 years ago

You must use siege because tokio-minihttp response HTTP 1.1 but ab use HTTP 1.0 (and he is waiting when socket will have closed)

demonov commented 8 years ago

@szagi3891 you need to enable keep-alive support in your ab benchmark: ab -k -n 100 -c 10 http://127.0.0.1:8080/

stalkerg commented 8 years ago

@ademonov are you tested this? For me keep-alive didn't help me here.

demonov commented 8 years ago

@stalkerg, I have tested this in windows environment only. It is the only http 1.1 compatible benchmark I found, which works in windows environment

stalkerg commented 8 years ago

@ademonov ok, I will test it again

alexcrichton commented 8 years ago

Thanks for the report, and sorry for the delay in responding! I think that this may actually be a bug in ab as I've seen historical reports mentioning this as well. This create also recently underwent some changes so I believe this is taken care of now.

I'm going to close this but if it still crops up please let me know!

szagi3891 commented 8 years ago

Unfortunately there was an error in the compilation :

grzegorz@grzegorz:~/Pulpit/rust/test_http_futures$ cargo run --example static
   Compiling tokio-minihttp v0.1.0 (https://github.com/tokio-rs/tokio-minihttp#9647d992)
error[E0432]: unresolved import `tokio_core::easy::EasyBuf`
 --> /home/grzegorz/.cargo/git/checkouts/tokio-minihttp-cf614aa2e575fe98/master/src/request.rs:4:24
  |
4 | use tokio_core::easy::{EasyBuf, Parse};
  |                        ^^^^^^^ Could not find `easy` in `tokio_core`

error[E0432]: unresolved import `tokio_core::easy::Parse`
 --> /home/grzegorz/.cargo/git/checkouts/tokio-minihttp-cf614aa2e575fe98/master/src/request.rs:4:33
  |
4 | use tokio_core::easy::{EasyBuf, Parse};
  |                                 ^^^^^ Could not find `easy` in `tokio_core`

error[E0432]: unresolved import `tokio_core::easy::Serialize`
 --> /home/grzegorz/.cargo/git/checkouts/tokio-minihttp-cf614aa2e575fe98/master/src/response.rs:3:5
  |
3 | use tokio_core::easy::Serialize;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not find `easy` in `tokio_core`

error[E0432]: unresolved import `tokio_core::easy::EasyFramed`
  --> /home/grzegorz/.cargo/git/checkouts/tokio-minihttp-cf614aa2e575fe98/master/src/lib.rs:24:5
   |
24 | use tokio_core::easy::EasyFramed;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not find `easy` in `tokio_core`

error: cannot continue compilation due to previous error

error: Could not compile `tokio-minihttp`.

To learn more, run the command again with --verbose.
grzegorz@grzegorz:~/Pulpit/rust/test_http_futures$ 
alexcrichton commented 8 years ago

Ah yeah right now this relies on an unpublished version of tokio-core, but you can use that with a [replace] section like this -- https://github.com/tokio-rs/tokio-minihttp/blob/master/Cargo.toml#L21-L22

stalkerg commented 7 years ago

Thanks it helped me. But what about HTTP 1.0 support?