1

Rust的并发线程 - ibraheem

 2 years ago
source link: https://www.jdon.com/58486
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rust的并发线程 - ibraheem

下面是一个简单的 Web 服务器:

use std::net::{TcpListener, TcpStream};
use std::io::{BufRead, BufReader, Write};

fn main() {
    let listener = TcpListener::bind("localhost:3000").expect("failed to create TCP listener");

    for connection in listener.incoming() {
        let stream = connection.expect("client connection failed");
        handle_connection(stream)
    }
}

fn handle_connection(mut stream: TcpStream) {
    let mut reader = BufReader::new(&mut stream);

    let mut request = Vec::new();
    reader
        .read_until(b'\n', &mut request)
        .expect("failed to read from stream");

    let request = String::from_utf8(request).expect("malformed request line");
    print!("HTTP request line: {}", request);

    let response = concat!(
        "HTTP/1.1 200 OK\r\n",
        "Content-Length: 12\n",
        "Connection: close\r\n\r\n",
        "Hello world!"
    );

    stream
        .write(response.as_bytes())
        .expect("failed to write to stream");
    stream.flush().expect("failed to flush stream");
}

但是这个Web一次只能处理一个请求,我们需要能够同时(同时)处理多个请求。为此,我们将使用多线程。

每个程序都从一个线程开始,即主线程。我们可以用std::thread::spawn. 因为我们希望能够同时处理多个请求,所以我们将每个请求处理程序派生到一个新线程上:

fn main() {
    let listener = TcpListener::bind("localhost:3000").expect("failed to create TCP listener");

    for connection in listener.incoming() {
        let stream = connection.expect("client connection failed");
        std::thread::spawn(|| handle_connection(stream));
    }
}

spawn函数在创建一个新线程后立即返回,而不是在主线程上运行。

通过这个简单的更改,我们现在可以同时处理许多请求。当一个线程正在等待读取、写入或执行任何其他操作时,其他准备就绪的线程将被允许运行。而且由于操作系统调度程序是抢占式的,我们的服务器永远不会因需要很长时间的请求而被阻塞。

这个解决方案效果很好,因为我们的服务器是I/O bound。在我们要求从连接中读取数据和取回数据之间,我们不一定要做任何事情。我们只是在等待,受到网络数据输入/输出速度的限制。一个CPU限制,另一方面应用处理器的限制,因为它不断地做工作。让它运行得更快的唯一方法是添加更多的 CPU 内核或将工作分配到多台机器上。

让我们看看服务器现在真的快了多少!

单线程版本每秒能够处理 10 个请求,平均需要 10秒来响应。另一方面,多线程服务器每秒处理近 5000 个请求,延迟仅超过 100 毫秒。鉴于我们在处理程序中让线程sleep了 100 毫秒,这非常好:)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK