gpt4 book ai didi

rust - 负载测试后,每个新的 mio 连接都会立即挂断

转载 作者:行者123 更新时间:2023-11-29 07:50:55 26 4
gpt4 key购买 nike

我使用 mio 在 Rust 中编写了一个多线程异步 HTTP 服务器。当我运行负载测试(使用 siege)时,服务器在第一次负载测试时运行良好,但是当负载测试完成时,对服务器的所有请求都开始失败。

使用一些日志记录,我注意到我通过 accept() 获得的每个新连接都会立即收到挂断事件。服务器连接本身不会收到任何错误或挂断事件。

我在 OS X 10.11 El Capitan 上运行 Rust 1.12.0 和 mio 0.6

这是我的服务器的主要事件循环:

pub fn run(self) {
let poll = Poll::new().unwrap();
let server = TcpListener::bind(&SocketAddr::from_str(&self.host).unwrap()).unwrap();
poll.register(&server, SERVER, Ready::readable(), PollOpt::edge()).unwrap();
let mut events = Events::with_capacity(1024);
let mut next_conn: usize = 1;
let mut workers = Vec::new();
// Create worker threads.
for _ in 0..self.num_workers {
let (tx, rx) = channel();
let worker_handler = self.event_handler.duplicate();
thread::spawn(move || {
Self::process_events(rx, worker_handler);
});
workers.push(tx);
}
loop {
println!("Polling...");
match poll.poll(&mut events, None) {
Err(e) => panic!("Error during poll(): {}", e),
Ok(_) => {}
}
for event in events.iter() {
match event.token() {
SERVER => {
println!("Accepting..");
match server.accept() {
Ok((stream, _)) => {
println!("Registering new connection...");
match poll.register(&stream,
Token(next_conn),
Ready::readable(),
PollOpt::edge()) {
Err(e) => panic!("Error during register(): {}", e),
Ok(_) => {
println!("New connection on worker {} ",
next_conn % self.num_workers);
workers[next_conn % self.num_workers]
.send(Msg::NewConn(next_conn, stream))
.unwrap();
next_conn += 1;
}
}
}
Err(e) => panic!("Error during accept() : {}", e),
}
}
Token(id) => {
println!("Sending event on conn {} to worker {}",
id,
id % self.num_workers);
workers[id % self.num_workers]
.send(Msg::ConnEvent(id, event.kind()))
.unwrap();
}
}
}
}
}

fn process_events(channel: Receiver<Msg>, mut event_handler: Box<EventHandler>) {
loop {
let msg = channel.recv().unwrap();
match msg {
Msg::NewConn(id, conn) => {
event_handler.new_conn(id, conn);
}
Msg::ConnEvent(id, event) => {
event_handler.conn_event(id, event);
}
}
}
}

我正在使用的示例 webapp 的完整代码是 available on GitHub .

加载测试命令:

siege -b -c10 -d10 -t20S http://localhost:8080

最佳答案

我不知道为什么负载测试应用程序不能更好地记录这一点。几个月前我遇到了同样的问题。听起来你已经到达了 "Ephemeral Port Limit" .以下是文章中的一些引述,总结了这个想法:

Whenever a connection is made between a client and server, the system binds that connection to an ephemeral port – a set of ports specified at the high end of the valid port range.

The total number of ephemeral ports available on OS X is 16,383.

Note that this limitation does not affect real-world requests to a live server because each TCP connection is defined by the tuple of source IP, source port, destination IP and destination port – so the ephemeral port limit only applies to a single client / server pair.

换句话说,它的发生是因为您正在运行从本地主机到本地主机的负载测试,并且在可能大约 16,383 个连接后用完了临时端口。

您可以做几件事来测试这是否是问题所在:

  1. 让您的负载测试仪报告建立的连接数。如果它在 16,000 左右,那么这可能是罪魁祸首。

  2. 增加临时端口限制并再次运行负载测试。如果您获得更多的连接,那么这可能就是问题所在。但请记住,如果这是问题所在,那么在野外就不会成为问题。

您可以使用此命令查看您的临时端口范围:

$ sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last

你可以使用这个命令增加它:

$ sysctl -w net.inet.ip.portrange.first=32768

运行测试后,您可能应该将端口范围设置回之前的值,因为这种增加表示一个非标准范围。

关于rust - 负载测试后,每个新的 mio 连接都会立即挂断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40063892/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com