mat*_*ind 2 rust rust-tokio rust-async-std
我实现了 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(())
}
Run Code Online (Sandbox Code Playgroud)
这会导致编译错误:
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
Run Code Online (Sandbox Code Playgroud)
这是否意味着“client.say_hello()”返回一个仍然引用客户端的类型,因此我无法再次调用“say_hello”,而“say_hello”本身需要“&mut self”?有没有办法在调用“等待”之前继续发出请求?
小智 7
来自补品文档:
在通道上发送请求需要 a
&mut self,因此只能发送一个正在运行的请求。这是有意为之的,并且需要遵循该通道实现所构建的库Service的合同。 ... 为了解决这个问题并简化通道的使用,提供了一种廉价的实现。这是因为在最顶层,通道由在后台任务中运行连接并提供通道接口的支持。由于这种克隆方式很便宜并且受到鼓励。towerChannelClonetower_buffer::BuffermpscChannel
因此,您可以为发出的每个并发请求克隆客户端。这消除了单个客户在任何给定时间被多次可变借用的可能性,因此借用检查器得到安抚。
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());
}
Run Code Online (Sandbox Code Playgroud)