Rust 人造丝 tcp 阻塞
Rust rayon tcp blocking
我正在编写一个程序,它使用 ssh 在服务器上执行命令并获取输出。
我不明白的部分在代码的下方。
如果函数等待然后 returns 一个字符串,它会按预期工作,但如果使用 TCP,它开始表现非常糟糕。我预计在 100 台主机上使用 100 个线程将执行速度快 100 倍,
因为会同时打开 100 个套接字。
在睡眠版本中,更改poolThreads
直接影响执行时间。在带有 TCP 流的版本中,将 pool
从 1 更改为 100 并使用 100 台主机只会将其从 90 加速到 67,因为某些主机处于离线状态。
我阅读了文档,但找不到任何帮助我的东西。
use clap::{App, Arg};
use rayon::prelude::*;
use rayon::ThreadPoolBuilder;
use ssh2::Session;
use std::fmt::Display;
use std::io::prelude::*;
use std::io::{BufReader, Read};
use std::net::{TcpStream, ToSocketAddrs};
use std::thread::sleep;
use std::time::Duration;
fn process_host<A>(hostname: A) -> Result<String, String>
where
A: ToSocketAddrs + Display,
{
sleep(Duration::from_secs(1));
return Ok(hostname.to_string());
// here is the problem
// -----------------------------------------------------------
let tcp = match TcpStream::connect(&hostname) {
Ok(a) => a,
Err(e) => {
return Err(format!("{}:{}", hostname, e).to_string());
}
};
let mut sess = match Session::new() {
Ok(a) => a,
Err(e) => {
// todo logging
return Err(format!("{}:{}", hostname, e).to_string());
}
};
sess.set_tcp_stream(tcp);
match sess.handshake() {
Ok(a) => a,
Err(e) => {
return Err(format!("{}:{}", hostname, e).to_string());
}
};
Ok(format!("{}", hostname))
}
fn main() {
let hosts = vec!["aaaaa:22", "bbbbbbb:22"];
let pool = ThreadPoolBuilder::new()
.num_threads(10)
.build()
.expect("failed creating pool");
pool.install(|| {
hosts
.par_iter()
.map(|x| process_host(x))
.for_each(|x| println!("{:?}", x))
});
}
要调试这样的问题,您需要分析您的程序在哪里浪费了时间。
有办法:
TCP 连接的概要分析。
我建议你采用两种方式,因为它更容易。
使用 wireshark 转储流量,通过端口 22 对其进行过滤。
在此之后,使用 conversations
标签。在这里您可以按时间对连接进行排序,并且可以看到,由于 ssh 连接没有时间限制,该程序没有加速。
我正在编写一个程序,它使用 ssh 在服务器上执行命令并获取输出。
我不明白的部分在代码的下方。
如果函数等待然后 returns 一个字符串,它会按预期工作,但如果使用 TCP,它开始表现非常糟糕。我预计在 100 台主机上使用 100 个线程将执行速度快 100 倍, 因为会同时打开 100 个套接字。
在睡眠版本中,更改poolThreads
直接影响执行时间。在带有 TCP 流的版本中,将 pool
从 1 更改为 100 并使用 100 台主机只会将其从 90 加速到 67,因为某些主机处于离线状态。
我阅读了文档,但找不到任何帮助我的东西。
use clap::{App, Arg};
use rayon::prelude::*;
use rayon::ThreadPoolBuilder;
use ssh2::Session;
use std::fmt::Display;
use std::io::prelude::*;
use std::io::{BufReader, Read};
use std::net::{TcpStream, ToSocketAddrs};
use std::thread::sleep;
use std::time::Duration;
fn process_host<A>(hostname: A) -> Result<String, String>
where
A: ToSocketAddrs + Display,
{
sleep(Duration::from_secs(1));
return Ok(hostname.to_string());
// here is the problem
// -----------------------------------------------------------
let tcp = match TcpStream::connect(&hostname) {
Ok(a) => a,
Err(e) => {
return Err(format!("{}:{}", hostname, e).to_string());
}
};
let mut sess = match Session::new() {
Ok(a) => a,
Err(e) => {
// todo logging
return Err(format!("{}:{}", hostname, e).to_string());
}
};
sess.set_tcp_stream(tcp);
match sess.handshake() {
Ok(a) => a,
Err(e) => {
return Err(format!("{}:{}", hostname, e).to_string());
}
};
Ok(format!("{}", hostname))
}
fn main() {
let hosts = vec!["aaaaa:22", "bbbbbbb:22"];
let pool = ThreadPoolBuilder::new()
.num_threads(10)
.build()
.expect("failed creating pool");
pool.install(|| {
hosts
.par_iter()
.map(|x| process_host(x))
.for_each(|x| println!("{:?}", x))
});
}
要调试这样的问题,您需要分析您的程序在哪里浪费了时间。
有办法:
TCP 连接的概要分析。
我建议你采用两种方式,因为它更容易。
使用 wireshark 转储流量,通过端口 22 对其进行过滤。
在此之后,使用 conversations
标签。在这里您可以按时间对连接进行排序,并且可以看到,由于 ssh 连接没有时间限制,该程序没有加速。