宣布Tonic 0.5版本
我们很高兴地宣布 Tonic 的0.5版本,它是 Rust 的原生 gRPC 实现。0.5是一个重要的版本,已经酝酿了一段时间。
一些关键的新功能是:
gRPC-Web
gRPC-Web 是一个协议,允许客户端通过 HTTP/1.1 连接到 gRPC 服务,而不是通常的HTTP/2。gRPC-Web 的一个常见用例是在浏览器中运行的JavaScript客户端。以前,这需要使用一个代理来将 HTTP/2 请求翻译成 HTTP/1.1。
然而,新的 crate tonic-web
允许普通的 Tonic 服务器接受 gRPC-Web
请求,而不需要外部代理。
启用gRPC-Web支持很简单:
use tonic::transport::Server;
// code generated by tonic-build
use hello_world::greeter_server::{GreeterServer, Greeter};
struct MyGreeter;
#[tonic::async_trait]
impl Greeter for MyGreeter {
// ...
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "0.0.0.0:3000".parse().unwrap();
let greeter = GreeterServer::new(MyGreeter);
// enable grpc-web support for our `greeter` service
let service = tonic_web::enable(greeter);
Server::builder()
// by default, tonic servers only accept http2 requests
// so we have to enable receiving http1 as well
.accept_http1(true)
.add_service(service)
.serve(addr)
.await?;
Ok(())
}
更多细节请见tonic-web crate。
压缩
Tonic现在可以透明地压缩和解压请求、响应和数据流。
在客户端上启用压缩功能是这样做的:
let client = GreeterClient::new(channel)
// compress requests
.send_gzip()
/// accept compressed responses
.accept_gzip();
而在服务器上:
let service = GreeterServer::new(greeter)
// accept compressed requests
.accept_gzip()
// compress responses, if supported by the client
.send_gzip();
注意这需要在 Tonic
和 tonic-build
上启用 compression
功能。更多细节请参见文档。
改进的Tower集成
Tonic 一直支持通过 Tower 的 Service trait 来扩展客户端和服务器,但在0.5版本中,新的 Server::layer
方法使其更加简单。例如,我们可以通过使用来自 tower-http
的中间件来为一个服务添加追踪和授权:
use tonic::transport::Server;
use tower_http::{
auth::RequireAuthorizationLayer,
trace::TraceLayer,
};
// The stack of middleware our service will be wrapped in
let layer = tower::ServiceBuilder::new()
// High level tracing of requests and responses
.layer(TraceLayer::new_for_grpc())
// Authorize all requests using a token
.layer(RequireAuthorizationLayer::bearer("my-secret-token"))
// Convert our `ServiceBuilder` into a `tower::Layer`
.into_inner();
Server::builder()
// Apply our middleware stack to the server
.layer(layer)
.add_service(GreeterServer::new(MyGreeter)
.serve(addr)
.await?;
更灵活的拦截器
拦截器是轻量级的中间件,除其他外,可以用来修改传入请求的元数据,也可以选择用状态拒绝它们。
然而,Tonic对拦截器的支持一直是相当有限的。例如,你不能结合多个拦截器,而必须使用Tower的 service
抽象,它更强大,但也需要更多的代码来设置。
在Tonic 0.5中,我们有一个新的拦截器API,和以前一样容易使用,但现在内部使用Tower。这意味着拦截器可以像其他Tower中间件一样被应用。例如,在一个客户端添加多个拦截器,现在可以用:
use tonic::{
Request, Status,
service::interceptor_fn,
transport::Endpoint
};
fn intercept_one(req: Request<()>) -> Result<Request<()>, Status> {
// ...
}
fn intercept_two(req: Request<()>) -> Result<Request<()>, Status> {
// ...
}
let channel = Endpoint::from_static("http://[::1]:50051").connect_lazy()?;
let intercepted_channel = tower::ServiceBuilder::new()
.layer(interceptor_fn(intercept_one))
.layer(interceptor_fn(intercept_two))
.service(channel);
let client = GreeterClient::new(intercepted_channel);
0.5包括许多其他较小的功能和改进。更新日志里有所有的细节。
如同以往,如果你有问题,你可以在Tokio Discord服务器的#tonic找到我们。