使用tokio spawn速度跟单线程一样快,tokio spawn的正确方法

问题描述

我想写一个关于如何像蜘蛛一样访问互联网的程序。我使用 tokio::spawn 想让每个 url 在它得到时异步。当我在循环中使用 tokio reqwest ,这个好像和单线程是一样的过程。Rust async和js不一样。我不太明白它是怎么工作的。我想了很多天。我问过公众。这是代码。

use tokio::task;
use scraper::{Html,Selector};
use url::Url;
#[tokio::main]
async fn main() {
    let mut visited_url:Vec<String> = Vec::new();
    let mut visiting_url:Vec<String> = Vec::new();
    
    visiting_url.push("https://baike.baidu.com/".to_string());

    let client = reqwest::Client::builder()
                        .user_agent("ozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/89.0.4389.114 Safari/537.36")
                        .build().unwrap();
    let fut = tokio::spawn(async move {
        loop{
            let cclient = &client;
            let main_url = visiting_url.pop().unwrap();
            println!("{}",main_url);
            visited_url.push(main_url.clone());
            let resp = cclient.get(&main_url).send().await.unwrap();
            let status_code = resp.status().as_u16();
            let html = resp.text().await.unwrap();

            let document = Html::parse_document(&html);
            for element in document.select(&Selector::parse("[href]").unwrap()) {
                let href = element.value().attr("href").unwrap();
                let abs_url = Url::parse(&main_url).unwrap().join(href).unwrap().as_str().to_string();
                if !visited_url.contains(&abs_url) {
                    visiting_url.push(abs_url);
                }
            }
            println!("{}",status_code);
        }
        // task::yield_now().await;
    });
    task::unconstrained(fut).await;
}

[dependencies]
tokio = { version = "1.4.0",features = ["full"]}
reqwest = { version = "0.11",features = [] }
scraper = "0.12.0"
url = "2.2.1"

我就这样改了代码,但是速度提升还是很小。

use reqwest::Client;
use tokio::task;
use scraper::{Html,Selector};
use url::Url;
#[macro_use]
extern crate lazy_static;
use std::sync::Mutex;

lazy_static! {
    static ref visited_url: Mutex<Vec<String>> = Mutex::new(vec![]);
    static ref visiting_url: Mutex<Vec<String>> = Mutex::new(vec![]);
}

async fn get(client: &Client){
    let main_url = visiting_url.lock().unwrap().pop().unwrap();
    println!("{}",main_url);
    visited_url.lock().unwrap().push(main_url.clone());
    let resp = client.get(&main_url).send().await.unwrap();
    let status_code = resp.status().as_u16();
    let html = resp.text().await.unwrap();

    let document = Html::parse_document(&html);
    for element in document.select(&Selector::parse("[href]").unwrap()) {
        let href = element.value().attr("href").unwrap();
        let abs_url = Url::parse(&main_url).unwrap().join(href).unwrap().as_str().to_string();
        if !visited_url.lock().unwrap().contains(&abs_url) {
            visiting_url.lock().unwrap().push(abs_url);
        }
    }
    println!("{}",status_code);
}

#[tokio::main]
async fn main() {
    
    visiting_url.lock().unwrap().push("https://baike.baidu.com/".to_string());

    let client = reqwest::Client::builder()
                        .user_agent("ozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/89.0.4389.114 Safari/537.36")
                        .build().unwrap();
    loop{
        // get(&client).await;
        tokio::spawn(get(client.clone()));
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...