sentinel-group/sentinel-rust

tokio的例子跑不起来,异步使用报错

FourSpaces opened this issue · 2 comments

有以下几个问题:
1、taokio的例子 在运行时会报错,错误内容:

error: future cannot be sent between threads safely
   --> src/main.rs:13:23
    |
13  |         handlers.push(tokio::spawn(async move {
    |                       ^^^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: within `impl Future<Output = [async output]>`, the trait `Send` is not implemented for `Rc<RefCell<SentinelEntry>>`

2、使用异步的时候,会报错,主要代码如下:

pub async fn sentinel_limiting(
    req: Request<Body>,
    next: Next<Body>,) -> Result<impl IntoResponse, (StatusCode, String)> {
    
    let entry_builder = EntryBuilder::new(String::from(RESOURCE_NAME))
        .with_traffic_type(base::TrafficType::Inbound);

    match entry_builder.build() {
        Ok(entry) => {
            let res = {next.run(req).await};
            entry.exit();
            Ok(res)
        },
        Err(_) => {
            log::info!("被限流了"); 
            Err((StatusCode::PAYLOAD_TOO_LARGE, String::from("")))},
        }
    }

主要报错如下:

error: future cannot be sent between threads safely
   --> src/main.rs:48:10
    |
48  |         .layer(middleware::from_fn(sentinel_limiting))
    |          ^^^^^ future returned by `sentinel_limiting` is not `Send`
    |
    = help: within `FromFnResponseFuture<impl Future<Output = std::result::Result<Opaque(DefId(0:548 ~ rs_logonline[3f0a]::middlewares::limiting::sentinel_limiting::{opaque#0}::{opaque#0}), []), (StatusCode, std::string::String)>>>`, the trait `Send` is not implemented for `Rc<RefCell<SentinelEntry>>`
note: future is not `Send` as this value is used across an await
   --> src/middlewares/limiting.rs:41:37
    |
40  |         Ok(entry) => {
    |            ----- has type `EntryStrongPtr` which is not `Send`
41  |             let res = {next.run(req).await};
    |                                     ^^^^^^ await occurs here, with `entry` maybe used later
...
44  |         },
    |         - `entry` is later dropped here
note: required by a bound in `Router::<B>::layer`
   --> /Users/weicheng/.cargo/registry/src/github.com-1ecc6299db9ec823/axum-0.5.1/src/routing/mod.rs:298:63
    |
298 |         <L::Service as Service<Request<NewReqBody>>>::Future: Send + 'static,
    |                                                               ^^^^ required by this bound in `Router::<B>::layer`


我已经找到问题了,由于用到了异步,需要在Cargo.toml 中添加 features = ["async"]
原来的 Cargo.toml 中

sentinel-core = { version = "0.1.1", features = ["full"] 

调整后的 Cargo.toml :

sentinel-core = { version = "0.1.1", features = ["async"] }

调整后,entry 的类 由 Rc<RefCell> 变为了 Arc<RwLock>,就解决了 Send约束问题。

总之:使用异步时候需要在 Cargo.toml 中 指定 features 为 "async"

不好意思前段时间没有关注邮件。您是使用的 0.1.0 吗?

如果要运行示例,可以参考 sentinel-core/Cargo,toml 中各个示例的 feature 要求。或者在根目录下运行 Cargo run --example=tokio 后会有需求特性的提示。

0.1.1 版确实有问题

849e9b7 中我无意间延长了锁的生命周期