【发布时间】:2022-09-24 05:39:04
【问题描述】:
我两周前开始学习 rust,并且一直在制作这个应用程序来监视日志文件,并将大量信息发送到弹性搜索数据库。
问题是在一定时间后,它会冻结(使用 100% CPU),我不明白为什么。
我已经减少了很多代码来试图找出问题所在,但根据 clion 调试器,它仍然在这条线上冻结
let _response = reqwest::Client::new()
.post(\"http://127.0.0.1/test.php\")
.header(\"Content-Type\", \"application/json\")
.body(\"{\\\"test\\\": true}\")
.timeout(Duration::from_secs(30))
.send() // <-- Exactly here
.await;
它冻结并且不返回任何错误消息。
这是上下文中的代码:
use std::{env};
use std::io::{stdout, Write};
use std::path::Path;
use std::time::Duration;
use logwatcher::{LogWatcher, LogWatcherAction};
use serde_json::{json, Value};
use serde_json::Value::Null;
use tokio;
#[tokio::main]
async fn main() {
let mut log_watcher = LogWatcher::register(\"/var/log/test.log\").unwrap();
let mut counter = 0;
let BULK_SIZE = 500;
log_watcher.watch(&mut move |line: String| { // This triggers each time a new line is appended to /var/log/test.log
counter += 1;
if counter >= BULK_SIZE {
futures::executor::block_on(async { // This has to be async because log_watcher is not async
let _response = reqwest::Client::new()
.post(\"http://127.0.0.1/test.php\") // <-- This is just for testing, it fails towards the DB too
.header(\"Content-Type\", \"application/json\")
.body(\"{\\\"test\\\": true}\")
.timeout(Duration::from_secs(30))
.send() // <-- Freezes here
.await;
if _response.is_ok(){
println!(\"Ok\");
}
});
counter = 0;
}
LogWatcherAction::None
});
}
日志文件每分钟获取大约 625 行新行。崩溃发生在大约 5500 - 25000 行之后,或者总体上看起来有点随机。
我怀疑这个问题与LogWatcher、reqwest、block_on 或异步混合有关。
有谁知道为什么它会随机冻结?
-
我不熟悉 log-watcher 的工作原理,但您正在以可能导致问题的方式混合同步和异步操作。如果这是整个应用程序,我可能会建议完全放弃 tokio 和 futures,而只使用 reqwest 的 blocking 客户端(而不是异步客户端)。好吧,我刚刚看到您也提到了与数据库交谈,所以也许没关系。
-
这是问题的主要要点,整个应用程序有点大。删除 tokio 并在
block_on中移动异步调用会带来更多问题和挑战thread \'main\' panicked at \'there is no reactor running, must be called from the context of a Tokio 1.x runtime\' -
在 tokio 运行时调用 futures executor 可能不是一个好主意。要在 tokio 中运行同步代码,您可以使用
spawn_blocking(将您的日志观察器循环放在那里)并从那里执行异步代码,使用tokio::spawn或通过通道发送数据或使用同步 reqwest 客户端等。 -
一旦
log_watcher.watch(范围打开,它内部就不再是异步的。我将如何用spawn_blocking包装它?因为在log_watcher.watch(内等待 tokio spawn 是不可能的 -
好吧,我对代码进行了相当大的更改,将 main 更改为同步而不是异步,并将
futures::executor::block_on替换为 tokio\ 的 block_on 函数。它至少在过去一个小时内没有冻结,目前还无法确认。
标签: http asynchronous rust reqwest