cloudflare / pingora

A library for building fast, reliable and evolvable network services.
Apache License 2.0
20.21k stars 1.1k forks source link

how to let the Pingora server just run its tasks inside the provided current runtime #292

Open futurist opened 1 week ago

futurist commented 1 week ago

Describe the bug

Thread panic when run_forever within tokio::spawn, like below:


pub async fn proxy_start() {
    // read command line arguments
    let opt: Opt = Opt::from_args();
    let mut my_server = Server::new(Some(opt)).unwrap();
    my_server.bootstrap();

    let mut my_proxy = pingora_proxy::http_proxy_service(
        &my_server.configuration,
        MyProxy {
            beta_counter: Mutex::new(0),
        },
    );
    my_proxy.add_tcp("0.0.0.0:6190");

    my_server.add_service(my_proxy);
    my_server.run_forever();
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
  tokio::spawn(async {
      proxy_start().await;
      println!("proxy server exited.");
  });
  // other server logic, like spawn a localhost for proxy.
}

Above will panic,

Cannot start a runtime from within a runtime.
This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.

Pingora info

Please include the following information about your environment:

Pingora version: 0.2.0 from crates.io Rust version: cargo 1.78.0 (54d8815d0 2024-03-26) Operating system version: MacOS 13.4

eaufavor commented 1 week ago

Pingora Server inside an async runtime is not supported. The reason is the Server itself needs to spawn and manage the async runtimes but Tokio doesn't support doing so inside a runtime.

futurist commented 1 week ago

So how to run tokio::spawn?

Even I've changed the conf.work_stealing = false when start the proxy server, the problem still exits.

eaufavor commented 1 week ago

What is the goal you want to achieve here? run_forever() shouldn't be and doesn't need to be inside a tokio runtime.

futurist commented 1 week ago

The goal is to run pingora and many backend service at the same time, since it's mono app, only one executable deployed.

eaufavor commented 1 week ago

I see now.

Maybe you can try thread::spawn(|| { my_server.run_forever(); }); so that the pingora server is free from the current tokio runtime so that it can manage its own.

Or, if the question is "how to let the Pingora server just run its tasks inside the provided current runtime", that is a feature request that we might implement.

futurist commented 1 week ago

@eaufavor yes exactly. I've changed the title.

futurist commented 1 week ago

also the process::exit behavior prevent other runtime service to shutdown gracefully, which is also related issue: https://github.com/cloudflare/pingora/issues/154

github-actions[bot] commented 3 hours ago

This question has been stale for a week. It will be closed in an additional day if not updated.