You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by ya...@apache.org on 2022/12/27 13:50:35 UTC
[dubbo-rust] branch main updated: Support timeout after waiting RPC response for a maximum time. #47 (#92)
This is an automated email from the ASF dual-hosted git repository.
yangyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-rust.git
The following commit(s) were added to refs/heads/main by this push:
new b3fce7f Support timeout after waiting RPC response for a maximum time. #47 (#92)
b3fce7f is described below
commit b3fce7fe3c4c7ec94c5b09c7805d116ad758892d
Author: daedalus2022 <11...@users.noreply.github.com>
AuthorDate: Tue Dec 27 21:50:30 2022 +0800
Support timeout after waiting RPC response for a maximum time. #47 (#92)
* Support timeout after waiting RPC response for a maximum time. #47
* timeout key by define const
Co-authored-by: qunwei <qu...@prevailcloud.com>
---
dubbo/src/filter/context.rs | 71 ++++++++++++++++++++++++++++++++++++++++
dubbo/src/filter/mod.rs | 6 ++++
dubbo/src/filter/timeout.rs | 65 ++++++++++++++++++++++++++++++++++++
examples/echo/src/echo/server.rs | 7 +++-
4 files changed, 148 insertions(+), 1 deletion(-)
diff --git a/dubbo/src/filter/context.rs b/dubbo/src/filter/context.rs
new file mode 100644
index 0000000..3f73fd0
--- /dev/null
+++ b/dubbo/src/filter/context.rs
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use std::time::{SystemTime, UNIX_EPOCH};
+
+use serde_json::Value;
+
+use crate::{
+ codegen::Request,
+ context::{Context, RpcContext},
+ filter::{TIMEOUT_COUNTDOWN, TIMEOUT_DEFAULT, TRI_TIMEOUT_DEADLINE_IN_NANOS},
+ status::Status,
+};
+
+use super::Filter;
+
+#[derive(Clone)]
+pub struct ContextFilter {}
+
+impl Filter for ContextFilter {
+ fn call(&mut self, req: Request<()>) -> Result<Request<()>, Status> {
+ let headers = &mut req.metadata.into_headers();
+
+ let timeout = headers.get(TIMEOUT_COUNTDOWN);
+
+ let time = SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap()
+ .as_nanos();
+
+ let mut dead_line_in_nanos = 0_u128;
+
+ if let Some(t) = timeout {
+ let timeout: u128 = t.to_str().unwrap().parse().unwrap();
+ if timeout > 0_u128 {
+ dead_line_in_nanos = time + timeout * 1000000;
+ }
+ } else {
+ let timeout: u128 = TIMEOUT_DEFAULT * 1000000;
+ dead_line_in_nanos = time + timeout;
+ }
+
+ tracing::debug!(
+ "ContextFilter tri-timeout-deadline-in-nanos : {}",
+ dead_line_in_nanos
+ );
+ if let Some(at) = RpcContext::get_attachments() {
+ let mut attachments = at.lock().unwrap();
+ attachments.insert(
+ String::from(TRI_TIMEOUT_DEADLINE_IN_NANOS),
+ Value::from(dead_line_in_nanos.to_string()),
+ );
+ }
+
+ Ok(req)
+ }
+}
diff --git a/dubbo/src/filter/mod.rs b/dubbo/src/filter/mod.rs
index 075781a..9523020 100644
--- a/dubbo/src/filter/mod.rs
+++ b/dubbo/src/filter/mod.rs
@@ -15,10 +15,16 @@
* limitations under the License.
*/
+pub mod context;
pub mod service;
+pub mod timeout;
use crate::invocation::Request;
+pub const TRI_TIMEOUT_DEADLINE_IN_NANOS: &str = "tri-timeout-deadline-in-nanos";
+pub const TIMEOUT_COUNTDOWN: &str = "timeout-countdown";
+pub const TIMEOUT_DEFAULT: u128 = 1000;
+
pub trait Filter {
fn call(&mut self, req: Request<()>) -> Result<Request<()>, crate::status::Status>;
}
diff --git a/dubbo/src/filter/timeout.rs b/dubbo/src/filter/timeout.rs
new file mode 100644
index 0000000..353585d
--- /dev/null
+++ b/dubbo/src/filter/timeout.rs
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+use std::time::{SystemTime, UNIX_EPOCH};
+
+use crate::{
+ codegen::Request,
+ context::{Context, RpcContext},
+ filter::TRI_TIMEOUT_DEADLINE_IN_NANOS,
+ status::{Code, Status},
+};
+
+use super::Filter;
+
+#[derive(Clone)]
+pub struct TimeoutFilter {}
+
+/// timeout count
+/// 1. ContextFilter 初始化 timeout 时间,初始化后将 tri-timeout-deadline-in-nanos 放入 context 中
+/// 2. TimeoutFilter read context tri-timeout-deadline-in-nanos
+/// 3. 响应时计算 tri-timeout-deadline-in-nanos - current_nanos <= 0
+///
+impl Filter for TimeoutFilter {
+ fn call(&mut self, req: Request<()>) -> Result<Request<()>, Status> {
+ if let Some(attachments) = RpcContext::get_attachments() {
+ let current_nanos = SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap()
+ .as_nanos();
+
+ let attachments = attachments.lock().unwrap();
+ let tri_timeout_deadline_in_nanos =
+ attachments.get(TRI_TIMEOUT_DEADLINE_IN_NANOS).unwrap();
+ let tri_timeout_deadline_in_nanos: u128 = tri_timeout_deadline_in_nanos
+ .as_str()
+ .unwrap()
+ .parse()
+ .unwrap();
+
+ tracing::debug!(
+ "TimeoutFilter tri-timeout-deadline-in-nanos : {}, current-nanos:{}",
+ tri_timeout_deadline_in_nanos,
+ current_nanos
+ );
+ if tri_timeout_deadline_in_nanos - current_nanos <= 0 {
+ return Err(Status::new(Code::DeadlineExceeded, String::from("Timeout")));
+ }
+ }
+
+ Ok(req)
+ }
+}
diff --git a/examples/echo/src/echo/server.rs b/examples/echo/src/echo/server.rs
index 2be45b0..6f2d610 100644
--- a/examples/echo/src/echo/server.rs
+++ b/examples/echo/src/echo/server.rs
@@ -19,6 +19,8 @@ use std::io::ErrorKind;
use std::pin::Pin;
use async_trait::async_trait;
+use dubbo::filter::context::ContextFilter;
+use dubbo::filter::timeout::TimeoutFilter;
use futures_util::Stream;
use futures_util::StreamExt;
use tokio::sync::mpsc;
@@ -52,12 +54,15 @@ async fn main() {
});
let server = EchoServerImpl::default();
let s = EchoServer::<EchoServerImpl>::with_filter(server, FakeFilter {});
+ let timeout_filter = FilterService::new(s, TimeoutFilter {});
+ let context_filter = FilterService::new(timeout_filter, ContextFilter {});
+
dubbo::protocol::triple::TRIPLE_SERVICES
.write()
.unwrap()
.insert(
"grpc.examples.echo.Echo".to_string(),
- dubbo::utils::boxed_clone::BoxCloneService::new(s),
+ dubbo::utils::boxed_clone::BoxCloneService::new(context_filter),
);
// Dubbo::new().start().await;