我有两个版本的图层,
EndpointTimer_1
和EndpointTimer_2
,它们跟踪的指标略有不同。我希望将 EndpointTimer_1
应用于 Server_1
,并将 EndpointTimer_2
应用于 Server_2
。
使用通用 ServerBuilder 对象来实现此目的的正确方法是什么?目前我有类似的东西
use tonic::transport::Server;
let mut server_builder = Server::builder()
.layer(EndpointTimerLayer::new())
.layer(ConcurrencyGaugeLayer::new());
let provider_1 = provider_1_impl::new(&CONFIG)?;
let provider_2 = provider_2_impl::new(&CONFIG)?;
let router = server_builder
.add_service(Server_1::new(provider_1))
.add_service(Server_2::new(provider_2));
router.serve(addr).await?;
我想要类似的东西
use tonic::transport::Server;
let mut server_builder = Server::builder()
.layer(ConcurrencyGauge::new());
let provider_1 = provider_1_impl::new(&CONFIG)?;
let provider_2 = provider_2_impl::new(&CONFIG)?;
let router = server_builder
.add_service(Server_1::new(provider_1).layer(EndpointTimerLayer_1::new())
.add_service(Server_2::new(provider_2).layer(EndpointTimerLayer_2::new());
router.serve(addr).await?;
但我无法找出使其发挥作用的正确方法。
进行了大量的实验和阅读 tonic 源代码,我仍然有一些不明白的东西,但功能性的答案是首先,为每一层实现
NamedService
特征:
use tonic::transport::server::NamedService;
impl<T> NamedService for EndpointTimer_1<T>
where
T: NamedService,
{
const NAME: &'static str = T::NAME;
}
注意,图层服务的错误类型必须是
Infallible
,例如
use std::convert::Infallible;
impl<T, RequestBody, ResponseBody> Service<tonic::codegen::http::Request<RequestBody>>
for EndpointTimer_1<T>
where
T: Service<
tonic::codegen::http::Request<RequestBody>,
Response = tonic::codegen::http::Response<ResponseBody>,
Error = Infallible,
> + Send,
而不是提供的示例
type Error = Box<dyn Error + Send + Sync>;
。 AFAICT 这是可行的,因为 protobuf 生成的服务器也是Infallible
?不确定,希望知情者对此进行解释。
最后,可以通过单独分层包装服务来注册服务:
let mut server_builder = Server::builder()
.layer(ConcurrencyGauge::new());
let provider_1 = provider_1_impl::new(&CONFIG)?;
let server_1 = Server_1::new(provider_1);
let provider_2 = provider_2_impl::new(&CONFIG)?;
let server_2 = Server_2::new(provider_2);
let router = server_builder
.add_service(EndpointTimer_1::new(Server_1))
.add_service(EndpointTimer_2::new(Server_2));
router.serve(addr).await?;