"Connection reset by peer" 使用 ab 对简单的 Rust HTTP 服务器进行基准测试时

"Connection reset by peer" when benchmarking a simple Rust HTTP server with ab

我正在尝试用 Rust 编写一个极其简单的并发服务器,以使用该语言的并发原语及其线程模型。这是我的代码:

use std::io::prelude::*;
use std::io::Result;
use std::net::{TcpListener, TcpStream, Shutdown};
use std::sync::{Arc, Mutex};
use std::thread;

fn handle_client(mut stream: TcpStream) -> Result<()> {
    try!(stream.write(b"HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nPong!\r\n"));
    // try!(stream.shutdown(Shutdown::Both));

    Ok(())
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:1337").unwrap();
    // let count = Arc::new(Mutex::new(0));

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                // let count = count.clone();
                thread::spawn(move || {
                    let _ = handle_client(stream);

                    // let mut count = count.lock().unwrap();
                    // *count += 1;
                    // println!("{:?}", *count);
                });
            }
            Err(e) => {
                println!("Error: {}", e);
            }
        }
    }

    drop(listener);
}

当我 运行 ab -c 100 -n 100 http://127.0.0.1:1337/ 使用上面列出的程序 运行ning 时,我几乎立即得到 apr_socket_recv: Connection reset by peer (104)。为什么?

当我添加 try!(stream.shutdown(Shutdown::Both)); 时(在上面的顶部附近注释掉)我不再像以前那样收到 apr_socket_recv 错误,但是 apachebench 给我的结果是 199 个由于异常而失败的请求。为什么?我做错了什么?

Concurrency Level:      100
Time taken for tests:   0.008 seconds
Complete requests:      100
Failed requests:        199
   (Connect: 0, Receive: 0, Length: 0, Exceptions: 199)
Total transferred:      500 bytes

documentation of TcpStream 表示

The socket will be closed when the value is dropped.

由于您的函数在没有正确关闭 TCP 流而仅通过关闭套接字的情况下结束,因此您会收到 Connection reset by peer 错误。完全关闭 TCP 需要在两个方向上发送多条消息。这显然不会再发生,因为套接字已关闭。

你的第二个问题我没有答案。另外,在 Whosebug 上,每个问题你应该只问一个问题。

我认为问题在于您没有完全读取从客户端发送的数据,因此客户端永远没有机会转换为读取响应。当它尝试写入更多数据时,它注意到套接字已关闭并失败。

我已经扩充了您的示例以在回复之前阅读所有 HTTP headers,忽略任何请求 body。我正在尝试漂亮的错误处理,如果有错误,我会惊慌失措:

use std::io::prelude::*;
use std::io::BufReader;
use std::net::{TcpListener, TcpStream};
use std::thread;

fn handle_client(mut stream: TcpStream) {
    // Read all the headers
    for header in BufReader::new(&mut stream).lines() {
        let header = header.unwrap();
        if header == "\r" { break }
    }

    // Write our response
    stream.write_all(b"HTTP/1.0 200 OK\r\n\r\n").unwrap();
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1:8080").unwrap();

    for stream in listener.incoming() {
        let stream = stream.unwrap();
        thread::spawn(|| {
            handle_client(stream);
        });
    }
}

这适用于 ab -c 50 -n 5000 http://127.0.0.1:8080/:

Benchmarking 127.0.0.1 (be patient)
Completed 500 requests
Completed 1000 requests
Completed 1500 requests
Completed 2000 requests
Completed 2500 requests
Completed 3000 requests
Completed 3500 requests
Completed 4000 requests
Completed 4500 requests
Completed 5000 requests
Finished 5000 requests


Server Software:
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /
Document Length:        0 bytes

Concurrency Level:      50
Time taken for tests:   1.293 seconds
Complete requests:      5000
Failed requests:        0
Total transferred:      95000 bytes
HTML transferred:       0 bytes
Requests per second:    3868.22 [#/sec] (mean)
Time per request:       12.926 [ms] (mean)
Time per request:       0.259 [ms] (mean, across all concurrent requests)
Transfer rate:          71.77 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    6   1.7      6      14
Processing:     1    6   1.7      6      14
Waiting:        1    6   1.7      6      14
Total:          5   13   2.6     12      23

Percentage of the requests served within a certain time (ms)
  50%     12
  66%     13
  75%     13
  80%     14
  90%     17
  95%     19
  98%     21
  99%     22
 100%     23 (longest request)