微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我不能使用 rust tonic 并行发送多个请求?

如何解决为什么我不能使用 rust tonic 并行发送多个请求?

我实施了补品 helloworld 教程。然后我尝试更改客户端代码,以便我可以在等待任何请求之前发送多个请求。

#[tokio::main]
async fn main() -> Result<(),Box<dyn std::error::Error>> {
    let num_requests = 10;
    let mut client = GreeterClient::connect("http://[::1]:50051").await?;

    let mut responses = Vec::with_capacity(num_requests);
    for _ in 0..num_requests {
        let request = tonic::Request::new(HelloRequest {
            name: "Tonic".into(),});

        responses.push(client.say_hello(request));
    }
    for resp in responses {
        assert!(resp.await.is_ok());
    }

    Ok(())
}

这会导致编译错误

error[E0499]: cannot borrow `client` as mutable more than once at a time
  --> src/client.rs:19:24
   |
19 |         responses.push(client.say_hello(request));
   |                        ^^^^^^ mutable borrow starts here in prevIoUs iteration of loop

这是否意味着 'client.say_hello()' 返回一个仍然引用 client 的类型,因此我不能再次调用 'say_hello',它本身需要 '&mut self'?有没有办法在调用“await”之前继续提出请求?

解决方法

来自Tonic documentation

在频道上发送请求需要 &mut self,因此只能发送一个请求。这是有意为之,并且需要遵循 Service 库中的 tower 合同,此频道实现建立在该库之上。
...
为了解决这个问题并简化通道的使用,Channel 提供了一个便宜Clone实现。这是因为在最顶层,通道由 tower_buffer::Buffer 支持,它在后台任务中运行连接并提供 mpsc 通道接口。由于这种克隆,Channel 类型便宜且值得鼓励。

因此,您可以为您发出的每个并发请求克隆客户端。这消除了单个客户端在任何给定时间被多次可变借用的可能性,因此借用检查器被安抚了。

let num_requests = 10;
let client = GreeterClient::connect("http://[::1]:50051").await?;

let mut responses = Vec::with_capacity(num_requests);

for _ in 0..num_requests {
    let mut client = client.clone();

    let request = tonic::Request::new(HelloRequest {
        name: "Tonic".into(),});

    responses.push(tokio::spawn(async move {
        client.say_hello(request).await
    }));
}

for resp in responses {
    let resp = resp.await;
    assert!(resp.is_ok());
    assert!(resp.unwrap().is_ok());
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。