为什么hyper需要Handler来实现Sync,而不是每个线程使用独立的Handler?

Why does hyper require Handler to implement Sync instead of using independent Handlers per thread?

Hyper 具有实现 SyncHandler 的以下 example

use std::sync::Mutex;
use std::sync::mpsc::{channel, Sender};
use hyper::server::{Handler, Server, Request, Response};

struct SenderHandler {
    sender: Mutex<Sender<&'static str>>
}

impl Handler for SenderHandler {
    fn handle(&self, req: Request, res: Response) {
        self.sender.lock().unwrap().send("start").unwrap();
    }
}

并声明 Handler 必须实现 Sync,因为 Handler 可以从不同线程调用。

对我来说,这听起来像是不必要的性能损失。我更愿意为每个线程设置一个 SenderHandler,每个线程都是独立的,这将消除实现 Sync.

的要求

我是不是误解了 Hyper,Rust 的类型系统,或者这是不可能的?

好的,目前这在 Hyper 中似乎是不可能的。它在 issue 248 中进行了讨论,开发人员更喜欢 Sync 而不是 Clone:

We talked through this on IRC. Simple synopsis is that if it were Clone, users could easily have state on their handler that they think is modified with each request, but instead, it would have been cloned several times and not modify what they hoped. Instead, it's better force the user to make sure their state is synchronized.

这是一个剪纸问题。

Sync 对于任何无状态处理程序都可以轻松实现;相反,具有 Clone 绑定将意味着多个并发状态相互独立发展(请求被随机分派)。我什至不确定是否可以保证在处理请求期间等待时会调用同一个线程并返回结果。

通过使用 Sync,作者迫使您思考跨查询(甚至查询内)共享状态意味着什么。


As in the supplied example, I would love to remove the Mutex protecting the Sender since Sender is already designed for lock-free intrathread message-passing. All it requires is a clone per thread.

您可以让 Sender 实现 Sync(如果是)(显然要仔细考虑),然后删除 Mutex

虽然不太优雅,但也可以使用 thread_local! 宏为每个线程创建一个实例,然后蹦床处理程序在调用时将工作分派给本地线程 Sender


最后,请注意 hyper 目前正在重新设计;它应该移动到 Future,这可能会或可能不会引起一些重新考虑。