Actix Actor 调用异步函数(HTTP 获取请求)

Actix Actor calling an async function (HTTP get request)

我有一个定期运行的 actor。 它一直有效,直到我尝试使用 reqwest

添加 HTTP 请求
pub struct Scheduler;
impl actix::actor::Actor for Scheduler {
    type Context = Context<Self>;
    fn started(&mut self, ctx: &mut Context<Self>) {
        ctx.run_interval(Duration::from_secs(60), move |this, ctx| { this.announce(ctx, EVENT_NONE); });
    }
}
impl Scheduler {
    fn announce(&self, _ctx: &mut Context<Self>, event: &str) {
        //...
        let mut client = reqwest::blocking::Client::new().get("http://127.0.0.1:10080");
        let res = client.send(); 
        //...
    }
}

但是我有以下错误:Cannot drop a runtime in a context where blocking is not allowed. This happens when a runtime is dropped from within an asynchronous context. /home/me/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.17.0/src/runtime/blocking/shutdown.rs:51:21

根据消息我认为我应该使用 async 但我没有找到正确的实现。你能帮帮我吗?

提前致谢

我终于找到了 2 个解决方案:

解决方案 1

pub struct Scheduler;
impl actix::actor::Actor for Scheduler {
  type Context = Context<Self>;
  fn started(&mut self, ctx: &mut Context<Self>) {
      ctx.run_interval(Duration::from_secs(60), move |this, ctx| { this.announce(ctx, EVENT_NONE); });
  }
}
impl Scheduler {
  fn announce(&self, ctx: &mut Context<Self>, event: &str) {
      //...
      self.send_announce(ctx, url, id); //outside the announce function because it is in a loop
      //...
  }
  fn send_announce(&self, _ctx: &mut Context<Self>, url:String, id: u32) {
      actix_web::rt::spawn(async move {
          let client = reqwest::Client::builder().build().expect("Cannot build web client");
          let res = client.get(&url).send().await;
          if res.is_ok() {
              info!("It works!");
          }
      }
  }
}

我不知道这是否是最好的方法,但它确实有效

解决方案 2

是使用ureq作为使用阻塞I/O的HTTP客户端,我可以调用ctx.run_later

一切都可以留在announce()功能