From 2192217244dfabd431c0220eec3641689406dc61 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Wed, 7 Dec 2022 21:51:52 +0800 Subject: [PATCH 01/31] feat(dubbo): add unix feature --- dubbo/Cargo.toml | 3 +++ dubbo/src/triple/transport/connector/mod.rs | 2 ++ dubbo/src/triple/transport/listener/mod.rs | 5 +++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index 7b38a28f..67402e52 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -34,3 +34,6 @@ async-stream = "0.3" flate2 = "1.0" dubbo-config = {path = "../config", version = "0.2.0"} + +[features] +unix = [] \ No newline at end of file diff --git a/dubbo/src/triple/transport/connector/mod.rs b/dubbo/src/triple/transport/connector/mod.rs index 89ae555a..c4d5811a 100644 --- a/dubbo/src/triple/transport/connector/mod.rs +++ b/dubbo/src/triple/transport/connector/mod.rs @@ -16,6 +16,7 @@ */ pub mod http_connector; +#[cfg(feature = "unix")] pub mod unix_connector; use hyper::Uri; @@ -78,6 +79,7 @@ pub fn get_connector(connector: String) -> BoxCloneService { let c = unix_connector::UnixConnector::new(); BoxCloneService::new(Connector::new(c)) diff --git a/dubbo/src/triple/transport/listener/mod.rs b/dubbo/src/triple/transport/listener/mod.rs index d755cd3b..17457543 100644 --- a/dubbo/src/triple/transport/listener/mod.rs +++ b/dubbo/src/triple/transport/listener/mod.rs @@ -16,6 +16,7 @@ */ pub mod tcp_listener; +#[cfg(feature = "unix")] pub mod unix_listener; use std::net::SocketAddr; @@ -25,7 +26,6 @@ use tokio::io::{AsyncRead, AsyncWrite}; use super::io::BoxIO; pub use tcp_listener::TcpListener; -pub use unix_listener::UnixListener; #[async_trait] pub trait Listener: Send + Sync { @@ -64,7 +64,8 @@ impl Listener for WrappedListener { pub async fn get_listener(name: String, addr: SocketAddr) -> Result { match name.as_str() { "tcp" => Ok(TcpListener::bind(addr).await?.boxed()), - "unix" => Ok(UnixListener::bind(addr).await?.boxed()), + #[cfg(feature = "unix")] + "unix" => Ok(unix_listener::UnixListener::bind(addr).await?.boxed()), _ => { tracing::warn!("no support listener: {:?}", name); Err(Box::new(crate::status::DubboError::new(format!( From ea06ca18ab323b70e8c7612a86ab24e2de16d179 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Thu, 8 Dec 2022 22:22:29 +0800 Subject: [PATCH 02/31] Rft: replace feature with target_os cfg --- dubbo/Cargo.toml | 3 --- dubbo/src/framework.rs | 2 +- dubbo/src/triple/transport/connector/mod.rs | 4 ++-- dubbo/src/triple/transport/listener/mod.rs | 4 ++-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index 67402e52..7b38a28f 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -34,6 +34,3 @@ async-stream = "0.3" flate2 = "1.0" dubbo-config = {path = "../config", version = "0.2.0"} - -[features] -unix = [] \ No newline at end of file diff --git a/dubbo/src/framework.rs b/dubbo/src/framework.rs index da21ab88..412ff36b 100644 --- a/dubbo/src/framework.rs +++ b/dubbo/src/framework.rs @@ -53,7 +53,7 @@ impl Dubbo { } pub fn init(&mut self) { - let conf = self.config.get_or_insert_with(|| get_global_config()); + let conf = self.config.get_or_insert_with(get_global_config); tracing::debug!("global conf: {:?}", conf); for (name, url) in conf.registries.iter() { diff --git a/dubbo/src/triple/transport/connector/mod.rs b/dubbo/src/triple/transport/connector/mod.rs index c4d5811a..82b9281c 100644 --- a/dubbo/src/triple/transport/connector/mod.rs +++ b/dubbo/src/triple/transport/connector/mod.rs @@ -16,7 +16,7 @@ */ pub mod http_connector; -#[cfg(feature = "unix")] +#[cfg(target_os = "unix")] pub mod unix_connector; use hyper::Uri; @@ -79,7 +79,7 @@ pub fn get_connector(connector: String) -> BoxCloneService { let c = unix_connector::UnixConnector::new(); BoxCloneService::new(Connector::new(c)) diff --git a/dubbo/src/triple/transport/listener/mod.rs b/dubbo/src/triple/transport/listener/mod.rs index 17457543..6beb2157 100644 --- a/dubbo/src/triple/transport/listener/mod.rs +++ b/dubbo/src/triple/transport/listener/mod.rs @@ -16,7 +16,7 @@ */ pub mod tcp_listener; -#[cfg(feature = "unix")] +#[cfg(target_os = "unix")] pub mod unix_listener; use std::net::SocketAddr; @@ -64,7 +64,7 @@ impl Listener for WrappedListener { pub async fn get_listener(name: String, addr: SocketAddr) -> Result { match name.as_str() { "tcp" => Ok(TcpListener::bind(addr).await?.boxed()), - #[cfg(feature = "unix")] + #[cfg(target_os = "unix")] "unix" => Ok(unix_listener::UnixListener::bind(addr).await?.boxed()), _ => { tracing::warn!("no support listener: {:?}", name); From 5f5b31fe098664bb320d174b1b96b2131fd913fe Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Fri, 9 Dec 2022 21:38:04 +0800 Subject: [PATCH 03/31] Rft(dubbo): add ClientBuilder for client --- dubbo/Cargo.toml | 2 +- dubbo/src/codegen.rs | 1 + dubbo/src/triple/client/builder.rs | 87 +++++++++++++++++++++ dubbo/src/triple/client/connection.rs | 8 +- dubbo/src/triple/client/mod.rs | 1 + dubbo/src/triple/client/triple.rs | 35 ++++++--- dubbo/src/triple/transport/connector/mod.rs | 4 +- 7 files changed, 120 insertions(+), 18 deletions(-) create mode 100644 dubbo/src/triple/client/builder.rs diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index bdde2ea3..145b4a0e 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -14,7 +14,7 @@ hyper = { version = "0.14.19", features = ["full"]} http = "0.2" tower-service = "0.3.1" http-body = "0.4.4" -tower = "0.4.12" +tower = { version = "0.4.12", features = ["timeout"]} futures-util = "0.3.23" futures-core ="0.3.23" tokio = { version = "1.0", features = [ "rt-multi-thread", "time", "fs", "macros", "net", "signal"] } diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 9ffce899..f485dc53 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -38,4 +38,5 @@ pub use super::triple::server::TripleServer; pub use super::{empty_body, BoxBody, BoxFuture, StdError}; pub use crate::filter::service::FilterService; pub use crate::filter::Filter; +pub use crate::triple::client::builder::{ClientBoxService, ClientBuilder}; pub use crate::triple::client::connection::Connection; diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs new file mode 100644 index 00000000..e95070b6 --- /dev/null +++ b/dubbo/src/triple/client/builder.rs @@ -0,0 +1,87 @@ +/* + * 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 http::Uri; +use hyper::client::conn::Builder; +use tokio::time::Duration; +use tower::ServiceBuilder; + +use crate::triple::client::connection::Connection; +use crate::utils::boxed::BoxService; + +pub type ClientBoxService = + BoxService, http::Response, crate::Error>; + +#[derive(Clone, Debug, Default)] +pub struct ClientBuilder { + pub uri: Uri, + pub timeout: Option, + pub connector: &'static str, +} + +impl ClientBuilder { + pub fn new() -> ClientBuilder { + ClientBuilder { + uri: Uri::builder().build().unwrap(), + timeout: None, + connector: "", + } + } + + pub fn from_static(s: &'static str) -> ClientBuilder { + Self::from(Uri::from_static(s)) + } + + pub fn with_timeout(self, timeout: u64) -> Self { + Self { + timeout: Some(timeout), + ..self + } + } + + pub fn with_host(self, host: &'static str) -> Self { + Self { + uri: Uri::from_static(host), + ..self + } + } + + pub fn connect(self) -> ClientBoxService { + let builder = ServiceBuilder::new(); + let timeout = self.timeout.unwrap_or(0); + let builder = builder.timeout(Duration::from_secs(timeout)); + + let mut b = Builder::new(); + let hyper_builder = b.http2_only(true); + let conn = Connection::new() + .with_host(self.uri.clone()) + .with_connector(self.connector) + .with_builder(hyper_builder.to_owned()); + + BoxService::new(builder.service(conn)) + } +} + +impl From for ClientBuilder { + fn from(u: Uri) -> Self { + Self { + uri: u, + timeout: None, + connector: "", + } + } +} diff --git a/dubbo/src/triple/client/connection.rs b/dubbo/src/triple/client/connection.rs index ce453096..d9bda6fb 100644 --- a/dubbo/src/triple/client/connection.rs +++ b/dubbo/src/triple/client/connection.rs @@ -27,7 +27,7 @@ use crate::triple::transport::connector::get_connector; #[derive(Debug, Clone)] pub struct Connection { host: hyper::Uri, - connector: String, + connector: &'static str, builder: Builder, } @@ -41,12 +41,12 @@ impl Connection { pub fn new() -> Self { Connection { host: hyper::Uri::default(), - connector: "http".to_string(), + connector: "http", builder: Builder::new(), } } - pub fn with_connector(mut self, connector: String) -> Self { + pub fn with_connector(mut self, connector: &'static str) -> Self { self.connector = connector; self } @@ -83,7 +83,7 @@ where fn call(&mut self, req: http::Request) -> Self::Future { let builder = self.builder.clone().http2_only(true).to_owned(); - let mut connector = Connect::new(get_connector(self.connector.clone()), builder); + let mut connector = Connect::new(get_connector(self.connector), builder); let uri = self.host.clone(); let fut = async move { let mut con = connector.call(uri).await.unwrap(); diff --git a/dubbo/src/triple/client/mod.rs b/dubbo/src/triple/client/mod.rs index 333a60a4..48b6b22b 100644 --- a/dubbo/src/triple/client/mod.rs +++ b/dubbo/src/triple/client/mod.rs @@ -15,6 +15,7 @@ * limitations under the License. */ +pub mod builder; pub mod connection; pub mod triple; diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 36c9ce94..d4864efd 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -21,7 +21,7 @@ use futures_util::{future, stream, StreamExt, TryStreamExt}; use http::HeaderValue; use tower_service::Service; -use super::connection::Connection; +use super::builder::{ClientBoxService, ClientBuilder}; use crate::filter::service::FilterService; use crate::filter::Filter; use crate::invocation::{IntoStreamingRequest, Metadata, Request, Response}; @@ -32,33 +32,43 @@ use crate::triple::encode::encode; #[derive(Debug, Clone, Default)] pub struct TripleClient { - host: Option, + builder: Option, inner: T, send_compression_encoding: Option, } -impl TripleClient { +impl TripleClient { pub fn connect(host: String) -> Self { let uri = match http::Uri::from_str(&host) { - Ok(v) => Some(v), + Ok(v) => v, Err(err) => { tracing::error!("http uri parse error: {}, host: {}", err, host); panic!("http uri parse error: {}, host: {}", err, host) } }; + let builder = ClientBuilder::from(uri); + TripleClient { - host: uri.clone(), - inner: Connection::new().with_host(uri.unwrap()), + builder: Some(builder.clone()), + inner: builder.connect(), + send_compression_encoding: Some(CompressionEncoding::Gzip), + } + } + + pub fn with_builder(builder: ClientBuilder) -> Self { + TripleClient { + builder: Some(builder.clone()), + inner: builder.connect(), send_compression_encoding: Some(CompressionEncoding::Gzip), } } } impl TripleClient { - pub fn new(inner: T, host: Option) -> Self { + pub fn new(inner: T, builder: ClientBuilder) -> Self { TripleClient { - host, + builder: Some(builder), inner, send_compression_encoding: Some(CompressionEncoding::Gzip), } @@ -68,7 +78,10 @@ impl TripleClient { where F: Filter, { - TripleClient::new(FilterService::new(self.inner, filter), self.host) + TripleClient::new( + FilterService::new(self.inner, filter), + self.builder.unwrap(), + ) } } @@ -82,8 +95,8 @@ where path: http::uri::PathAndQuery, body: hyper::Body, ) -> http::Request { - let mut parts = match self.host.as_ref() { - Some(v) => v.to_owned().into_parts(), + let mut parts = match self.builder.as_ref() { + Some(v) => v.to_owned().uri.into_parts(), None => { tracing::error!("client host is empty"); return http::Request::new(hyper::Body::empty()); diff --git a/dubbo/src/triple/transport/connector/mod.rs b/dubbo/src/triple/transport/connector/mod.rs index 82b9281c..6e0e0622 100644 --- a/dubbo/src/triple/transport/connector/mod.rs +++ b/dubbo/src/triple/transport/connector/mod.rs @@ -73,8 +73,8 @@ where } } -pub fn get_connector(connector: String) -> BoxCloneService { - match connector.as_str() { +pub fn get_connector(connector: &'static str) -> BoxCloneService { + match connector { "http" => { let c = http_connector::HttpConnector::new(); BoxCloneService::new(Connector::new(c)) From 176cb57e5524aea0166f1eced5e19286a6340758 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Fri, 9 Dec 2022 21:39:21 +0800 Subject: [PATCH 04/31] =?UTF-8?q?Rft=C3=AF(dubbo-build):=20add=20build=20a?= =?UTF-8?q?pi=20for=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dubbo-build/src/client.rs | 12 +- examples/echo/src/echo/client.rs | 5 +- examples/echo/src/protos/hello_echo.rs | 183 +++++++++++++++++-------- 3 files changed, 137 insertions(+), 63 deletions(-) diff --git a/dubbo-build/src/client.rs b/dubbo-build/src/client.rs index 10fa4468..8d58ab16 100644 --- a/dubbo-build/src/client.rs +++ b/dubbo-build/src/client.rs @@ -70,13 +70,19 @@ pub fn generate( inner: TripleClient, } - impl #service_ident { + impl #service_ident { pub fn connect(host: String) -> Self { let cli = TripleClient::connect(host); #service_ident { inner: cli, } } + + pub fn build(builder: ClientBuilder) -> Self { + Self { + inner: TripleClient::with_builder(builder), + } + } } impl #service_ident @@ -84,9 +90,9 @@ pub fn generate( T: Service, Response = http::Response>, T::Error: Into, { - pub fn new(inner: T) -> Self { + pub fn new(inner: T, builder: ClientBuilder) -> Self { Self { - inner: TripleClient::new(inner, None), + inner: TripleClient::new(inner, builder), } } diff --git a/examples/echo/src/echo/client.rs b/examples/echo/src/echo/client.rs index 8b3cc9bf..73bc02ef 100644 --- a/examples/echo/src/echo/client.rs +++ b/examples/echo/src/echo/client.rs @@ -32,8 +32,9 @@ impl Filter for FakeFilter { #[tokio::main] async fn main() { let mut cli = EchoClient::connect("http://127.0.0.1:8888".to_string()); - let mut unary_cli = cli.clone().with_filter(FakeFilter {}); - let resp = unary_cli + // let mut unary_cli = cli.clone().with_filter(FakeFilter {}); + // let mut cli = EchoClient::build(ClientBuilder::from_static("http://127.0.0.1:8888")); + let resp = cli .unary_echo(Request::new(EchoRequest { message: "message from client".to_string(), })) diff --git a/examples/echo/src/protos/hello_echo.rs b/examples/echo/src/protos/hello_echo.rs index 86daf6fb..cca549ce 100644 --- a/examples/echo/src/protos/hello_echo.rs +++ b/examples/echo/src/protos/hello_echo.rs @@ -15,16 +15,17 @@ * limitations under the License. */ + /// EchoRequest is the request for echo. #[derive(Clone, PartialEq, ::prost::Message)] pub struct EchoRequest { - #[prost(string, tag = "1")] + #[prost(string, tag="1")] pub message: ::prost::alloc::string::String, } /// EchoResponse is the response for echo. #[derive(Clone, PartialEq, ::prost::Message)] pub struct EchoResponse { - #[prost(string, tag = "1")] + #[prost(string, tag="1")] pub message: ::prost::alloc::string::String, } /// Generated client implementations. @@ -36,20 +37,25 @@ pub mod echo_client { pub struct EchoClient { inner: TripleClient, } - impl EchoClient { + impl EchoClient { pub fn connect(host: String) -> Self { let cli = TripleClient::connect(host); EchoClient { inner: cli } } + pub fn build(builder: ClientBuilder) -> Self { + Self { + inner: TripleClient::with_builder(builder), + } + } } impl EchoClient where T: Service, Response = http::Response>, T::Error: Into, { - pub fn new(inner: T) -> Self { + pub fn new(inner: T, builder: ClientBuilder) -> Self { Self { - inner: TripleClient::new(inner, None), + inner: TripleClient::new(inner, builder), } } pub fn with_filter(self, filter: F) -> EchoClient> @@ -64,9 +70,13 @@ pub mod echo_client { &mut self, request: Request, ) -> Result, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); - let path = http::uri::PathAndQuery::from_static("/grpc.examples.echo.Echo/UnaryEcho"); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); + let path = http::uri::PathAndQuery::from_static( + "/grpc.examples.echo.Echo/UnaryEcho", + ); self.inner.unary(request, codec, path).await } /// ServerStreamingEcho is server side streaming. @@ -74,8 +84,10 @@ pub mod echo_client { &mut self, request: Request, ) -> Result>, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ServerStreamingEcho", ); @@ -86,8 +98,10 @@ pub mod echo_client { &mut self, request: impl IntoStreamingRequest, ) -> Result, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ClientStreamingEcho", ); @@ -98,8 +112,10 @@ pub mod echo_client { &mut self, request: impl IntoStreamingRequest, ) -> Result>, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/BidirectionalStreamingEcho", ); @@ -120,7 +136,9 @@ pub mod echo_server { request: Request, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the ServerStreamingEcho method. - type ServerStreamingEchoStream: futures_util::Stream> + type ServerStreamingEchoStream: futures_util::Stream< + Item = Result, + > + Send + 'static; /// ServerStreamingEcho is server side streaming. @@ -134,14 +152,19 @@ pub mod echo_server { request: Request>, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the BidirectionalStreamingEcho method. - type BidirectionalStreamingEchoStream: futures_util::Stream> + type BidirectionalStreamingEchoStream: futures_util::Stream< + Item = Result, + > + Send + 'static; /// BidirectionalStreamingEcho is bidi streaming. async fn bidirectional_streaming_echo( &self, request: Request>, - ) -> Result, dubbo::status::Status>; + ) -> Result< + Response, + dubbo::status::Status, + >; } /// Echo is the echo service. #[derive(Debug)] @@ -171,7 +194,10 @@ pub mod echo_server { type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; - fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, req: http::Request) -> Self::Future { @@ -184,18 +210,26 @@ pub mod echo_server { } impl UnarySvc for UnaryEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture, dubbo::status::Status>; - fn call(&mut self, request: Request) -> Self::Future { + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; + fn call( + &mut self, + request: Request, + ) -> Self::Future { let inner = self.inner.0.clone(); let fut = async move { inner.unary_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default()); + let mut server = TripleServer::new( + dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(), + ); let res = server.unary(UnaryEchoServer { inner }, req).await; Ok(res) }; @@ -206,22 +240,32 @@ pub mod echo_server { struct ServerStreamingEchoServer { inner: _Inner, } - impl ServerStreamingSvc for ServerStreamingEchoServer { + impl ServerStreamingSvc + for ServerStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::ServerStreamingEchoStream; - type Future = - BoxFuture, dubbo::status::Status>; - fn call(&mut self, request: Request) -> Self::Future { + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; + fn call( + &mut self, + request: Request, + ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { inner.server_streaming_echo(request).await }; + let fut = async move { + inner.server_streaming_echo(request).await + }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default()); + let mut server = TripleServer::new( + dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(), + ); let res = server .server_streaming(ServerStreamingEchoServer { inner }, req) .await; @@ -234,23 +278,31 @@ pub mod echo_server { struct ClientStreamingEchoServer { inner: _Inner, } - impl ClientStreamingSvc for ClientStreamingEchoServer { + impl ClientStreamingSvc + for ClientStreamingEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture, dubbo::status::Status>; + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; fn call( &mut self, request: Request>, ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { inner.client_streaming_echo(request).await }; + let fut = async move { + inner.client_streaming_echo(request).await + }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default()); + let mut server = TripleServer::new( + dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(), + ); let res = server .client_streaming(ClientStreamingEchoServer { inner }, req) .await; @@ -263,41 +315,56 @@ pub mod echo_server { struct BidirectionalStreamingEchoServer { inner: _Inner, } - impl StreamingSvc for BidirectionalStreamingEchoServer { + impl StreamingSvc + for BidirectionalStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::BidirectionalStreamingEchoStream; - type Future = - BoxFuture, dubbo::status::Status>; + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; fn call( &mut self, request: Request>, ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = - async move { inner.bidirectional_streaming_echo(request).await }; + let fut = async move { + inner.bidirectional_streaming_echo(request).await + }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default()); + let mut server = TripleServer::new( + dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(), + ); let res = server - .bidi_streaming(BidirectionalStreamingEchoServer { inner }, req) + .bidi_streaming( + BidirectionalStreamingEchoServer { + inner, + }, + req, + ) .await; Ok(res) }; Box::pin(fut) } - _ => Box::pin(async move { - Ok(http::Response::builder() - .status(200) - .header("grpc-status", "12") - .header("content-type", "application/grpc") - .body(empty_body()) - .unwrap()) - }), + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } } } } From b4db021407d8bfdf147238779602e6435f463cd0 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Fri, 9 Dec 2022 21:47:11 +0800 Subject: [PATCH 05/31] style(examples): cargo fmt --- examples/echo/src/protos/hello_echo.rs | 172 ++++++++----------------- 1 file changed, 55 insertions(+), 117 deletions(-) diff --git a/examples/echo/src/protos/hello_echo.rs b/examples/echo/src/protos/hello_echo.rs index cca549ce..08a1d299 100644 --- a/examples/echo/src/protos/hello_echo.rs +++ b/examples/echo/src/protos/hello_echo.rs @@ -15,17 +15,16 @@ * limitations under the License. */ - /// EchoRequest is the request for echo. #[derive(Clone, PartialEq, ::prost::Message)] pub struct EchoRequest { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub message: ::prost::alloc::string::String, } /// EchoResponse is the response for echo. #[derive(Clone, PartialEq, ::prost::Message)] pub struct EchoResponse { - #[prost(string, tag="1")] + #[prost(string, tag = "1")] pub message: ::prost::alloc::string::String, } /// Generated client implementations. @@ -70,13 +69,9 @@ pub mod echo_client { &mut self, request: Request, ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); - let path = http::uri::PathAndQuery::from_static( - "/grpc.examples.echo.Echo/UnaryEcho", - ); + let codec = + dubbo::codegen::ProstCodec::::default(); + let path = http::uri::PathAndQuery::from_static("/grpc.examples.echo.Echo/UnaryEcho"); self.inner.unary(request, codec, path).await } /// ServerStreamingEcho is server side streaming. @@ -84,10 +79,8 @@ pub mod echo_client { &mut self, request: Request, ) -> Result>, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); + let codec = + dubbo::codegen::ProstCodec::::default(); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ServerStreamingEcho", ); @@ -98,10 +91,8 @@ pub mod echo_client { &mut self, request: impl IntoStreamingRequest, ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); + let codec = + dubbo::codegen::ProstCodec::::default(); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ClientStreamingEcho", ); @@ -112,10 +103,8 @@ pub mod echo_client { &mut self, request: impl IntoStreamingRequest, ) -> Result>, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); + let codec = + dubbo::codegen::ProstCodec::::default(); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/BidirectionalStreamingEcho", ); @@ -136,9 +125,7 @@ pub mod echo_server { request: Request, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the ServerStreamingEcho method. - type ServerStreamingEchoStream: futures_util::Stream< - Item = Result, - > + type ServerStreamingEchoStream: futures_util::Stream> + Send + 'static; /// ServerStreamingEcho is server side streaming. @@ -152,19 +139,14 @@ pub mod echo_server { request: Request>, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the BidirectionalStreamingEcho method. - type BidirectionalStreamingEchoStream: futures_util::Stream< - Item = Result, - > + type BidirectionalStreamingEchoStream: futures_util::Stream> + Send + 'static; /// BidirectionalStreamingEcho is bidi streaming. async fn bidirectional_streaming_echo( &self, request: Request>, - ) -> Result< - Response, - dubbo::status::Status, - >; + ) -> Result, dubbo::status::Status>; } /// Echo is the echo service. #[derive(Debug)] @@ -194,10 +176,7 @@ pub mod echo_server { type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; - fn poll_ready( - &mut self, - _cx: &mut Context<'_>, - ) -> Poll> { + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, req: http::Request) -> Self::Future { @@ -210,26 +189,18 @@ pub mod echo_server { } impl UnarySvc for UnaryEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; - fn call( - &mut self, - request: Request, - ) -> Self::Future { + type Future = BoxFuture, dubbo::status::Status>; + fn call(&mut self, request: Request) -> Self::Future { let inner = self.inner.0.clone(); let fut = async move { inner.unary_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new( - dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default(), - ); + let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default()); let res = server.unary(UnaryEchoServer { inner }, req).await; Ok(res) }; @@ -240,32 +211,22 @@ pub mod echo_server { struct ServerStreamingEchoServer { inner: _Inner, } - impl ServerStreamingSvc - for ServerStreamingEchoServer { + impl ServerStreamingSvc for ServerStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::ServerStreamingEchoStream; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; - fn call( - &mut self, - request: Request, - ) -> Self::Future { + type Future = + BoxFuture, dubbo::status::Status>; + fn call(&mut self, request: Request) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { - inner.server_streaming_echo(request).await - }; + let fut = async move { inner.server_streaming_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new( - dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default(), - ); + let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default()); let res = server .server_streaming(ServerStreamingEchoServer { inner }, req) .await; @@ -278,31 +239,23 @@ pub mod echo_server { struct ClientStreamingEchoServer { inner: _Inner, } - impl ClientStreamingSvc - for ClientStreamingEchoServer { + impl ClientStreamingSvc for ClientStreamingEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; + type Future = BoxFuture, dubbo::status::Status>; fn call( &mut self, request: Request>, ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { - inner.client_streaming_echo(request).await - }; + let fut = async move { inner.client_streaming_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new( - dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default(), - ); + let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default()); let res = server .client_streaming(ClientStreamingEchoServer { inner }, req) .await; @@ -315,56 +268,41 @@ pub mod echo_server { struct BidirectionalStreamingEchoServer { inner: _Inner, } - impl StreamingSvc - for BidirectionalStreamingEchoServer { + impl StreamingSvc for BidirectionalStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::BidirectionalStreamingEchoStream; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; + type Future = + BoxFuture, dubbo::status::Status>; fn call( &mut self, request: Request>, ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { - inner.bidirectional_streaming_echo(request).await - }; + let fut = + async move { inner.bidirectional_streaming_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new( - dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default(), - ); + let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default()); let res = server - .bidi_streaming( - BidirectionalStreamingEchoServer { - inner, - }, - req, - ) + .bidi_streaming(BidirectionalStreamingEchoServer { inner }, req) .await; Ok(res) }; Box::pin(fut) } - _ => { - Box::pin(async move { - Ok( - http::Response::builder() - .status(200) - .header("grpc-status", "12") - .header("content-type", "application/grpc") - .body(empty_body()) - .unwrap(), - ) - }) - } + _ => Box::pin(async move { + Ok(http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap()) + }), } } } From e9e0a6780e09be8c573532ad82497f32dbcf2b52 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Tue, 20 Dec 2022 21:31:02 +0800 Subject: [PATCH 06/31] Rft: move connection from client to transport mod --- dubbo/src/codegen.rs | 2 +- dubbo/src/protocol/triple/triple_invoker.rs | 2 +- dubbo/src/triple/client/builder.rs | 2 +- dubbo/src/triple/client/mod.rs | 1 - dubbo/src/triple/{client => transport}/connection.rs | 0 dubbo/src/triple/transport/mod.rs | 1 + 6 files changed, 4 insertions(+), 4 deletions(-) rename dubbo/src/triple/{client => transport}/connection.rs (100%) diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index f485dc53..16c8c1ee 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -39,4 +39,4 @@ pub use super::{empty_body, BoxBody, BoxFuture, StdError}; pub use crate::filter::service::FilterService; pub use crate::filter::Filter; pub use crate::triple::client::builder::{ClientBoxService, ClientBuilder}; -pub use crate::triple::client::connection::Connection; +pub use crate::triple::transport::connection::Connection; diff --git a/dubbo/src/protocol/triple/triple_invoker.rs b/dubbo/src/protocol/triple/triple_invoker.rs index 2ec3f4a8..01938513 100644 --- a/dubbo/src/protocol/triple/triple_invoker.rs +++ b/dubbo/src/protocol/triple/triple_invoker.rs @@ -21,7 +21,7 @@ use tower_service::Service; use crate::common::url::Url; use crate::protocol::Invoker; -use crate::triple::client::connection::Connection; +use crate::triple::transport::connection::Connection; #[allow(dead_code)] #[derive(Clone, Default)] diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index e95070b6..14f30c97 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -20,7 +20,7 @@ use hyper::client::conn::Builder; use tokio::time::Duration; use tower::ServiceBuilder; -use crate::triple::client::connection::Connection; +use crate::triple::transport::connection::Connection; use crate::utils::boxed::BoxService; pub type ClientBoxService = diff --git a/dubbo/src/triple/client/mod.rs b/dubbo/src/triple/client/mod.rs index 48b6b22b..7a8e0131 100644 --- a/dubbo/src/triple/client/mod.rs +++ b/dubbo/src/triple/client/mod.rs @@ -16,7 +16,6 @@ */ pub mod builder; -pub mod connection; pub mod triple; pub use triple::TripleClient; diff --git a/dubbo/src/triple/client/connection.rs b/dubbo/src/triple/transport/connection.rs similarity index 100% rename from dubbo/src/triple/client/connection.rs rename to dubbo/src/triple/transport/connection.rs diff --git a/dubbo/src/triple/transport/mod.rs b/dubbo/src/triple/transport/mod.rs index 228efff3..8d1efb55 100644 --- a/dubbo/src/triple/transport/mod.rs +++ b/dubbo/src/triple/transport/mod.rs @@ -15,6 +15,7 @@ * limitations under the License. */ +pub mod connection; pub mod connector; mod io; pub mod listener; From e67e59e9b6cc489e68fe285a8af6f56737d52f27 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Mon, 26 Dec 2022 20:30:01 +0800 Subject: [PATCH 07/31] Rft(dubbo): add default timeout for client --- dubbo/src/triple/client/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 14f30c97..087f2a25 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -62,7 +62,7 @@ impl ClientBuilder { pub fn connect(self) -> ClientBoxService { let builder = ServiceBuilder::new(); - let timeout = self.timeout.unwrap_or(0); + let timeout = self.timeout.unwrap_or(5); let builder = builder.timeout(Duration::from_secs(timeout)); let mut b = Builder::new(); From e066505fd557472f521b057e9d02b31dfbfc53ad Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Tue, 27 Dec 2022 22:05:47 +0800 Subject: [PATCH 08/31] Ftr: add serverBuilder for Server, support multiple ways to start server --- config/src/config.rs | 6 +- config/src/protocol.rs | 22 +++- docs/generic-protocol-design.md | 12 ++ docs/readme.md | 10 +- dubbo.yaml | 2 + dubbo/readme.md | 24 +++- dubbo/src/codegen.rs | 1 + dubbo/src/common/url.rs | 15 ++- dubbo/src/framework.rs | 17 ++- dubbo/src/protocol/triple/triple_protocol.rs | 4 +- dubbo/src/protocol/triple/triple_server.rs | 57 ++------- dubbo/src/triple/server/builder.rs | 119 +++++++++++++++++++ dubbo/src/triple/server/mod.rs | 1 + dubbo/src/triple/transport/service.rs | 2 +- examples/echo/src/echo/server.rs | 30 +++-- 15 files changed, 246 insertions(+), 76 deletions(-) create mode 100644 dubbo/src/triple/server/builder.rs diff --git a/config/src/config.rs b/config/src/config.rs index a17e31a5..672319a4 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -115,7 +115,8 @@ impl RootConfig { let triple_config = ProtocolConfig::default() .name("triple".to_string()) .ip("0.0.0.0".to_string()) - .port("8888".to_string()); + .port("8888".to_string()) + .listener("tcp".to_string()); let service_config = service_config.add_protocol_configs(triple_config); self.service @@ -135,7 +136,8 @@ impl RootConfig { ProtocolConfig::default() .name("triple".to_string()) .ip("0.0.0.0".to_string()) - .port("8889".to_string()), + .port("8889".to_string()) + .listener("tcp".to_string()), ); provider.services = self.service.clone(); diff --git a/config/src/protocol.rs b/config/src/protocol.rs index 24531529..632e912d 100644 --- a/config/src/protocol.rs +++ b/config/src/protocol.rs @@ -24,6 +24,7 @@ pub struct ProtocolConfig { pub ip: String, pub port: String, pub name: String, + pub listener: String, #[serde(skip_serializing, skip_deserializing)] pub params: HashMap, @@ -42,11 +43,30 @@ impl ProtocolConfig { Self { port, ..self } } + pub fn listener(self, listener: String) -> Self { + Self { listener, ..self } + } + pub fn params(self, params: HashMap) -> Self { Self { params, ..self } } + pub fn add_param(mut self, key: String, value: String) -> Self { + self.params.insert(key, value); + self + } + pub fn to_url(&self) -> String { - format!("{}://{}:{}", self.name, self.ip, self.port) + let mut params_vec: Vec = Vec::new(); + for (k, v) in self.params.iter() { + // let tmp = format!("{}={}", k, v); + params_vec.push(format!("{}={}", k, v)); + } + let param = params_vec.join("&"); + + format!( + "{}://{}:{}?listener={}&{}", + self.name, self.ip, self.port, self.listener, param + ) } } diff --git a/docs/generic-protocol-design.md b/docs/generic-protocol-design.md index d91ed857..709e3481 100644 --- a/docs/generic-protocol-design.md +++ b/docs/generic-protocol-design.md @@ -18,10 +18,22 @@ Protocol模块的核心功能: + 通用、高效的Listener层 + 等等 +Protocol API支持管理多个底层协议的server以及在一个server上暴露多个服务 ++ 多个底层通信的server:location(ip:port): server ++ 一个server上暴露多个服务: + ### Exporter ### Invoker +Invoker: 客户端通用能力的封装。获取需要一个private withInvoker 接口 + +Invoker应该是基于Connection(Service)实现的Service。并且进行扩展新的接口。 +protocol.rs模块:根据Url返回初始化好的Invoker实例。 ++ 如何设计Invoker接口:扩展Service接口 ++ cluster模块如何使用Invoker实例呢?这里需要画一个数据流转图 ++ 如何将初始化好的Invoker与tower::Layer相结合 + Invoker提供的通用的接口,使得dubbo在不同的协议下遵循相同的接口抽象。 在Invoker中,需要做的功能包括 diff --git a/docs/readme.md b/docs/readme.md index ee2738f7..bba7562b 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -1,3 +1,11 @@ # Readme -There is some RFCs of dubbo-rust design. \ No newline at end of file +There is some RFCs of dubbo-rust design. + +## 关于配置的一些约定(暂时) + +所有的服务只能注册到一个或多个注册中心 +所有的服务只能使用Triple进行通信 +Triple只能对外暴露一个端口 + +一个协议上的server注册到 \ No newline at end of file diff --git a/dubbo.yaml b/dubbo.yaml index f6e7aa95..e14b5301 100644 --- a/dubbo.yaml +++ b/dubbo.yaml @@ -11,6 +11,7 @@ service: ip: 0.0.0.0 port: '8888' name: triple + listener: tcp # helloworld.Greeter: # version: 1.0.0 # group: test @@ -22,3 +23,4 @@ protocols: ip: 0.0.0.0 port: '8888' name: triple + listener: tcp diff --git a/dubbo/readme.md b/dubbo/readme.md index 0adef956..8dd713d4 100644 --- a/dubbo/readme.md +++ b/dubbo/readme.md @@ -1 +1,23 @@ -# Introduce \ No newline at end of file +# Introduce + +## Filter实现 + +客户端Filter和服务端Filter +将TripleClient扩展为通用的InvokerClient + ++ 测试客户端filter ++ 服务端filter接口设计,以及测试 ++ 服务注册接口 ++ 服务发现接口设计 + +EchoClient -> TripleClient -> FilterService -> Connection -> hyper::Connect + + +memory registry clone实现 +将服务注册接入到framework中 +url模型如何用于多个场景 +protocol模块实现 + +registry config(yaml) -> registry config(memory) -> + +Init函数初始化配置即:根据RootConfig来初始化对应的ServiceConfig \ No newline at end of file diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 16c8c1ee..ef656469 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -39,4 +39,5 @@ pub use super::{empty_body, BoxBody, BoxFuture, StdError}; pub use crate::filter::service::FilterService; pub use crate::filter::Filter; pub use crate::triple::client::builder::{ClientBoxService, ClientBuilder}; +pub use crate::triple::server::builder::ServerBuilder; pub use crate::triple::transport::connection::Connection; diff --git a/dubbo/src/common/url.rs b/dubbo/src/common/url.rs index 4f79b300..29f9e2c0 100644 --- a/dubbo/src/common/url.rs +++ b/dubbo/src/common/url.rs @@ -41,7 +41,7 @@ impl Url { tracing::error!("fail to parse url({}), err: {:?}", url, err); }) .unwrap(); - Some(Self { + let mut u = Self { uri: uri.to_string(), protocol: uri.scheme_str()?.to_string(), ip: uri.authority()?.host().to_string(), @@ -54,7 +54,18 @@ impl Url { .map(|x| x.to_string()) .collect::>(), params: HashMap::new(), - }) + }; + if uri.query().is_some() { + u.decode(uri.query().unwrap().to_string()); + u.service_key = u + .get_param("service_names".to_string()) + .unwrap() + .split(',') + .map(|x| x.to_string()) + .collect::>(); + } + + Some(u) } pub fn get_service_name(&self) -> Vec { diff --git a/dubbo/src/framework.rs b/dubbo/src/framework.rs index 412ff36b..354b65a0 100644 --- a/dubbo/src/framework.rs +++ b/dubbo/src/framework.rs @@ -77,12 +77,17 @@ impl Dubbo { protocol_url } }; - let protocol_url = format!( - "{}/{}/{}", - &protocol_url.to_url(), - service_config.name, - service_name - ); + // let protocol_url = format!( + // "{}/{}/{}", + // &protocol_url.to_url(), + // service_config.name, + // service_name + // ); + // service_names may be multiple + let protocol_url = protocol_url + .to_owned() + .add_param("service_names".to_string(), service_name.to_string()); + let protocol_url = protocol_url.to_url(); tracing::info!("url: {}", protocol_url); let protocol_url = Url::from_url(&protocol_url) diff --git a/dubbo/src/protocol/triple/triple_protocol.rs b/dubbo/src/protocol/triple/triple_protocol.rs index 5b713ada..037bfb7a 100644 --- a/dubbo/src/protocol/triple/triple_protocol.rs +++ b/dubbo/src/protocol/triple/triple_protocol.rs @@ -60,10 +60,10 @@ impl Protocol for TripleProtocol { } async fn export(mut self, url: Url) -> BoxExporter { - let server = TripleServer::new(url.service_key.clone()); + let server = TripleServer::new(); self.servers .insert(url.service_key.join(","), server.clone()); - server.serve(url.to_url()).await; + server.serve(url).await; Box::new(TripleExporter::new()) } diff --git a/dubbo/src/protocol/triple/triple_server.rs b/dubbo/src/protocol/triple/triple_server.rs index b85dbe17..d297a881 100644 --- a/dubbo/src/protocol/triple/triple_server.rs +++ b/dubbo/src/protocol/triple/triple_server.rs @@ -15,65 +15,22 @@ * limitations under the License. */ -use std::{net::ToSocketAddrs, str::FromStr}; - -use crate::triple::transport::DubboServer; +use crate::{common::url::Url, triple::server::builder::ServerBuilder}; #[derive(Default, Clone)] pub struct TripleServer { - s: DubboServer, - service_names: Vec, + builder: ServerBuilder, } impl TripleServer { - pub fn new(names: Vec) -> TripleServer { + pub fn new() -> TripleServer { Self { - service_names: names, - s: DubboServer::new(), + builder: ServerBuilder::new(), } } - pub async fn serve(mut self, url: String) { - { - let lock = super::TRIPLE_SERVICES.read().unwrap(); - for name in self.service_names.iter() { - if lock.get(name).is_none() { - tracing::warn!("service ({}) not register", name); - continue; - } - let svc = lock.get(name).unwrap(); - - self.s = self.s.add_service(name.clone(), svc.clone()); - } - } - - let uri = match http::Uri::from_str(&url) { - Ok(v) => v, - Err(err) => { - tracing::error!("http uri parse error: {}, url: {:?}", err, &url); - return; - } - }; - - let authority = match uri.authority() { - Some(v) => v.to_owned(), - None => { - tracing::error!("http authority is none"); - return; - } - }; - - self.s - .with_listener("tcp".to_string()) - .serve( - authority - .to_string() - .to_socket_addrs() - .unwrap() - .next() - .unwrap(), - ) - .await - .unwrap(); + pub async fn serve(mut self, url: Url) { + self.builder = ServerBuilder::from(url); + self.builder.build().serve().await.unwrap() } } diff --git a/dubbo/src/triple/server/builder.rs b/dubbo/src/triple/server/builder.rs new file mode 100644 index 00000000..ce494db9 --- /dev/null +++ b/dubbo/src/triple/server/builder.rs @@ -0,0 +1,119 @@ +/* + * 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::{ + net::{SocketAddr, ToSocketAddrs}, + str::FromStr, +}; + +use http::Uri; +use http::{Request, Response}; +use hyper::body::Body; +use tower_service::Service; + +use crate::BoxBody; +use crate::{common::url::Url, triple::transport::DubboServer}; + +#[derive(Clone, Default, Debug)] +pub struct ServerBuilder { + pub listener: String, + pub addr: Option, + pub service_names: Vec, + server: DubboServer, +} + +impl ServerBuilder { + pub fn new() -> Self { + ServerBuilder::default() + } + + pub fn with_listener(self, listener: String) -> ServerBuilder { + Self { listener, ..self } + } + + pub fn with_addr(self, addr: &'static str) -> ServerBuilder { + Self { + addr: addr.to_socket_addrs().unwrap().next(), + ..self + } + } + + pub fn with_service_names(self, service_names: Vec) -> ServerBuilder { + Self { + service_names, + ..self + } + } + + pub fn build(self) -> Self { + let mut server = self.server.with_listener(self.listener.clone()); + { + let lock = crate::protocol::triple::TRIPLE_SERVICES.read().unwrap(); + for name in self.service_names.iter() { + if lock.get(name).is_none() { + tracing::warn!("service ({}) not register", name); + continue; + } + let svc = lock.get(name).unwrap(); + + server = server.add_service(name.clone(), svc.clone()); + } + } + Self { server, ..self } + } + + pub fn add_service(self, name: String, service: S) -> Self + where + S: Service, Response = Response, Error = std::convert::Infallible> + + Clone + + Send + + 'static, + S::Future: Send + 'static, + S::Error: Into + Send + 'static, + { + Self { + server: self.server.add_service(name, service), + ..self + } + } + + pub async fn serve(self) -> Result<(), crate::Error> { + tracing::info!("server starting. addr: {:?}", self.addr); + self.server.serve(self.addr.unwrap()).await + } +} + +impl From for ServerBuilder { + fn from(u: Url) -> Self { + let uri = match http::Uri::from_str(&u.to_url()) { + Ok(v) => v, + Err(err) => { + tracing::error!("http uri parse error: {}, url: {:?}", err, &u); + Uri::default() + } + }; + + let authority = uri.authority().unwrap(); + + Self { + listener: u.get_param("listener".to_string()).unwrap(), + addr: authority.to_string().to_socket_addrs().unwrap().next(), + service_names: u.service_key, + server: DubboServer::default(), + } + } +} diff --git a/dubbo/src/triple/server/mod.rs b/dubbo/src/triple/server/mod.rs index 93172876..b36f7693 100644 --- a/dubbo/src/triple/server/mod.rs +++ b/dubbo/src/triple/server/mod.rs @@ -15,6 +15,7 @@ * limitations under the License. */ +pub mod builder; pub mod service; pub mod triple; diff --git a/dubbo/src/triple/transport/service.rs b/dubbo/src/triple/transport/service.rs index f8abc699..a049c1d6 100644 --- a/dubbo/src/triple/transport/service.rs +++ b/dubbo/src/triple/transport/service.rs @@ -27,7 +27,7 @@ use super::listener::get_listener; use super::router::DubboRouter; use crate::BoxBody; -#[derive(Default, Clone)] +#[derive(Default, Clone, Debug)] pub struct DubboServer { accept_http2: bool, init_stream_window_size: Option, diff --git a/examples/echo/src/echo/server.rs b/examples/echo/src/echo/server.rs index 6f2d610f..c14a67fa 100644 --- a/examples/echo/src/echo/server.rs +++ b/examples/echo/src/echo/server.rs @@ -27,8 +27,8 @@ use tokio::sync::mpsc; use tokio_stream::wrappers::ReceiverStream; use dubbo::codegen::*; -use dubbo::Dubbo; -use dubbo_config::RootConfig; +// use dubbo::Dubbo; +// use dubbo_config::RootConfig; use example_echo::protos::hello_echo::{ echo_server::{register_server, Echo, EchoServer}, EchoRequest, EchoResponse, @@ -65,15 +65,25 @@ async fn main() { dubbo::utils::boxed_clone::BoxCloneService::new(context_filter), ); + // 1. 通过读取配置文件来初始化 // Dubbo::new().start().await; - Dubbo::new() - .with_config({ - let mut r = RootConfig::new(); - r.test_config(); - r - }) - .start() - .await; + + // 2. 通过自定义配置来初始化 + // Dubbo::new() + // .with_config({ + // let mut r = RootConfig::new(); + // r.test_config(); + // r + // }) + // .start() + // .await; + + // 3. 通过serverbuilder来初始化Server + let builder = ServerBuilder::new() + .with_listener("tcp".to_string()) + .with_service_names(vec!["grpc.examples.echo.Echo".to_string()]) + .with_addr("0.0.0.0:8888"); + builder.build().serve().await.unwrap(); } #[allow(dead_code)] From bd4be4e36721c9bb230602b43fa6dd321bfd85c5 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Tue, 27 Dec 2022 22:10:03 +0800 Subject: [PATCH 09/31] Rft(examples): update yaml --- examples/greeter/dubbo.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/greeter/dubbo.yaml b/examples/greeter/dubbo.yaml index fa578d4c..b6552f80 100644 --- a/examples/greeter/dubbo.yaml +++ b/examples/greeter/dubbo.yaml @@ -14,3 +14,4 @@ protocols: ip: 0.0.0.0 port: '8888' name: triple + listener: tcp From 80f35028d49e8eedb860b74a9a9270ee07fe66be Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Mon, 16 Jan 2023 22:27:37 +0800 Subject: [PATCH 10/31] refactor(dubbo): update invoker trait --- dubbo/src/protocol/mod.rs | 2 ++ dubbo/src/protocol/triple/triple_invoker.rs | 24 ++++++++++----------- dubbo/src/triple/client/builder.rs | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/dubbo/src/protocol/mod.rs b/dubbo/src/protocol/mod.rs index 20042cb5..f58212d3 100644 --- a/dubbo/src/protocol/mod.rs +++ b/dubbo/src/protocol/mod.rs @@ -48,6 +48,8 @@ pub trait Invoker { fn get_url(&self) -> Url; + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll>; + fn call(&mut self, req: ReqBody) -> Self::Future; } diff --git a/dubbo/src/protocol/triple/triple_invoker.rs b/dubbo/src/protocol/triple/triple_invoker.rs index 01938513..1cbe2ed7 100644 --- a/dubbo/src/protocol/triple/triple_invoker.rs +++ b/dubbo/src/protocol/triple/triple_invoker.rs @@ -21,13 +21,11 @@ use tower_service::Service; use crate::common::url::Url; use crate::protocol::Invoker; -use crate::triple::transport::connection::Connection; +use crate::triple::client::builder::{ClientBoxService, ClientBuilder}; -#[allow(dead_code)] -#[derive(Clone, Default)] pub struct TripleInvoker { url: Url, - conn: Connection, + conn: ClientBoxService, } impl TripleInvoker { @@ -35,17 +33,12 @@ impl TripleInvoker { let uri = http::Uri::from_str(&url.to_url()).unwrap(); Self { url, - conn: Connection::new().with_host(uri), + conn: ClientBuilder::from(uri).connect(), } } } -impl Invoker> for TripleInvoker -where - ReqBody: http_body::Body + Unpin + Send + 'static, - ReqBody::Error: Into, - ReqBody::Data: Send + Unpin, -{ +impl Invoker> for TripleInvoker { type Response = http::Response; type Error = crate::Error; @@ -56,7 +49,14 @@ where self.url.clone() } - fn call(&mut self, req: http::Request) -> Self::Future { + fn call(&mut self, req: http::Request) -> Self::Future { self.conn.call(req) } + + fn poll_ready( + &mut self, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.conn.poll_ready(cx) + } } diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 087f2a25..67d635a3 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -81,7 +81,7 @@ impl From for ClientBuilder { Self { uri: u, timeout: None, - connector: "", + connector: "tcp", } } } From 0fcb29fde2a79334b8a169f33a55092087f732b5 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Thu, 11 May 2023 22:54:28 +0800 Subject: [PATCH 11/31] refactor(cluster): add Cluster MockImpl --- dubbo/Cargo.toml | 1 + dubbo/src/cluster/mod.rs | 82 ++++++++++++++++++--- dubbo/src/protocol/mod.rs | 10 ++- dubbo/src/protocol/triple/triple_invoker.rs | 19 +++-- dubbo/src/triple/client/builder.rs | 4 +- 5 files changed, 94 insertions(+), 22 deletions(-) diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index 94a2bd86..91b19d6f 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -34,6 +34,7 @@ axum = "0.5.9" async-stream = "0.3" flate2 = "1.0" aws-smithy-http = "0.54.1" +dyn-clone = "1.0.11" itertools.workspace = true urlencoding.workspace = true lazy_static.workspace = true diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index b6d8a7c2..e7b0a03a 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -15,24 +15,38 @@ * limitations under the License. */ -use std::{sync::Arc, task::Poll}; +use std::{sync::Arc, task::Poll, fmt::Debug, collections::HashMap}; use aws_smithy_http::body::SdkBody; +use dubbo_base::Url; use tower_service::Service; -use crate::{empty_body, protocol::BoxInvoker}; +use crate::{empty_body, protocol::{BoxInvoker, Invoker}, invocation::RpcInvocation}; pub mod directory; pub mod loadbalance; pub mod support; -pub trait Directory { - fn list(&self, meta: String) -> Vec; +pub trait Directory: Debug { + fn list(&self, invocation: Arc) -> Vec; fn is_empty(&self) -> bool; } -type BoxDirectory = Box; +type BoxDirectory = Box; +pub trait Cluster { + fn join(&self, dir: BoxDirectory) -> BoxInvoker; +} + +#[derive(Debug)] +pub struct MockCluster {} + +impl Cluster for MockCluster { + fn join(&self, dir: BoxDirectory) -> BoxInvoker { + Box::new(FailoverCluster::new(dir)) + } +} +#[derive(Clone, Debug)] pub struct FailoverCluster { dir: Arc, } @@ -43,7 +57,7 @@ impl FailoverCluster { } } -impl Service> for FailoverCluster { +impl Invoker> for FailoverCluster { type Response = http::Response; type Error = crate::Error; @@ -66,7 +80,9 @@ impl Service> for FailoverCluster { .method(req.method().clone()); *clone_req.headers_mut().unwrap() = req.headers().clone(); let r = clone_req.body(clone_body).unwrap(); - let invokers = self.dir.list("service_name".to_string()); + let invokers = self.dir.list( + RpcInvocation::default().with_service_unique_name("hello".to_string()).into() + ); for mut invoker in invokers { let fut = async move { let res = invoker.call(r).await; @@ -83,19 +99,63 @@ impl Service> for FailoverCluster { .unwrap()) }) } + + fn get_url(&self) -> dubbo_base::Url { + Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap() + } +} + +#[derive(Debug, Default)] +pub struct MockDirectory { + router_chain: RouterChain, + invokers: Vec } -pub struct MockDirectory {} +impl MockDirectory { + pub fn new(invokers: Vec) -> MockDirectory { + Self { router_chain: RouterChain::default(), invokers } + } +} impl Directory for MockDirectory { - fn list(&self, _meta: String) -> Vec { + fn list(&self, invo: Arc) -> Vec { // tracing::info!("MockDirectory: {}", meta); - // let u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); + let u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); // vec![Box::new(TripleInvoker::new(u))] - todo!() + self.router_chain.route(u, invo); + self.invokers.clone() } fn is_empty(&self) -> bool { false } } + +#[derive(Debug, Default)] +pub struct RouterChain { + router: HashMap, + invokers: Vec +} + +impl RouterChain { + pub fn route(&self, url: Url, invo: Arc) -> Vec { + let r = self.router.get("mock").unwrap(); + r.route(self.invokers.clone(), url, invo) + } +} + + +pub trait Router: Debug{ + fn route(&self, invokers: Vec, url: Url, invo: Arc) -> Vec; +} + +pub type BoxRouter = Box; + +#[derive(Debug, Default)] +pub struct MockRouter {} + +impl Router for MockRouter { + fn route(&self, invokers: Vec, url: Url, invo: Arc) -> Vec { + invokers + } +} \ No newline at end of file diff --git a/dubbo/src/protocol/mod.rs b/dubbo/src/protocol/mod.rs index 58dca5fd..629513e6 100644 --- a/dubbo/src/protocol/mod.rs +++ b/dubbo/src/protocol/mod.rs @@ -23,6 +23,7 @@ use std::{ use async_trait::async_trait; use aws_smithy_http::body::SdkBody; +use dyn_clone::DynClone; use tower_service::Service; use dubbo_base::Url; @@ -43,7 +44,7 @@ pub trait Exporter { fn unexport(&self); } -pub trait Invoker: Debug { +pub trait Invoker: Debug + DynClone { type Response; type Error; @@ -68,6 +69,13 @@ pub type BoxInvoker = Box< + Sync, >; +dyn_clone::clone_trait_object!(Invoker< + http::Request, + Response = http::Response, + Error = crate::Error, + Future = crate::BoxFuture, crate::Error>, +>); + pub struct WrapperInvoker(T); impl Service> for WrapperInvoker diff --git a/dubbo/src/protocol/triple/triple_invoker.rs b/dubbo/src/protocol/triple/triple_invoker.rs index 6139cc91..fb47bbed 100644 --- a/dubbo/src/protocol/triple/triple_invoker.rs +++ b/dubbo/src/protocol/triple/triple_invoker.rs @@ -18,23 +18,26 @@ use aws_smithy_http::body::SdkBody; use dubbo_base::Url; use std::fmt::{Debug, Formatter}; +use std::str::FromStr; use tower_service::Service; -use crate::{protocol::Invoker, triple::client::builder::ClientBoxService}; +use crate::{protocol::Invoker, triple::client::builder::ClientBoxService, utils::boxed_clone::BoxCloneService}; +use crate::triple::transport::connection::Connection; +#[derive(Clone)] pub struct TripleInvoker { url: Url, conn: ClientBoxService, } impl TripleInvoker { - // pub fn new(url: Url) -> TripleInvoker { - // let uri = http::Uri::from_str(&url.to_url()).unwrap(); - // Self { - // url, - // conn: ClientBuilder::from_uri(&uri).build()connect(), - // } - // } + pub fn new(url: Url) -> TripleInvoker { + let uri = http::Uri::from_str(&url.to_url()).unwrap(); + Self { + url, + conn: BoxCloneService::new(Connection::new().with_host(uri)), + } + } } impl Debug for TripleInvoker { diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index cf667ccd..ea1fd26d 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -19,7 +19,7 @@ use crate::{ cluster::directory::StaticDirectory, codegen::{ClusterInvoker, Directory, RegistryDirectory}, triple::compression::CompressionEncoding, - utils::boxed::BoxService, + utils::{boxed::BoxService, boxed_clone::BoxCloneService}, }; use aws_smithy_http::body::SdkBody; @@ -27,7 +27,7 @@ use aws_smithy_http::body::SdkBody; use super::TripleClient; pub type ClientBoxService = - BoxService, http::Response, crate::Error>; + BoxCloneService, http::Response, crate::Error>; #[derive(Clone, Debug, Default)] pub struct ClientBuilder { From 2cd76b66caeaf168b4f218d2138b55c84df65b1a Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Thu, 11 May 2023 23:46:44 +0800 Subject: [PATCH 12/31] refactor(triple): use ClientBuilder to init Cluster ability --- dubbo/src/cluster/mod.rs | 43 ++++++++++++++------- dubbo/src/protocol/mod.rs | 14 ++++--- dubbo/src/protocol/triple/triple_invoker.rs | 13 +++++-- dubbo/src/triple/client/builder.rs | 39 +++++++++++++++++-- dubbo/src/triple/client/triple.rs | 31 +++++---------- 5 files changed, 92 insertions(+), 48 deletions(-) diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index e7b0a03a..d2c2adb7 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -15,13 +15,16 @@ * limitations under the License. */ -use std::{sync::Arc, task::Poll, fmt::Debug, collections::HashMap}; +use std::{collections::HashMap, fmt::Debug, sync::Arc, task::Poll}; use aws_smithy_http::body::SdkBody; use dubbo_base::Url; -use tower_service::Service; -use crate::{empty_body, protocol::{BoxInvoker, Invoker}, invocation::RpcInvocation}; +use crate::{ + empty_body, + invocation::RpcInvocation, + protocol::{BoxInvoker, Invoker}, +}; pub mod directory; pub mod loadbalance; @@ -38,7 +41,7 @@ pub trait Cluster { fn join(&self, dir: BoxDirectory) -> BoxInvoker; } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct MockCluster {} impl Cluster for MockCluster { @@ -81,7 +84,9 @@ impl Invoker> for FailoverCluster { *clone_req.headers_mut().unwrap() = req.headers().clone(); let r = clone_req.body(clone_body).unwrap(); let invokers = self.dir.list( - RpcInvocation::default().with_service_unique_name("hello".to_string()).into() + RpcInvocation::default() + .with_service_unique_name("hello".to_string()) + .into(), ); for mut invoker in invokers { let fut = async move { @@ -108,12 +113,15 @@ impl Invoker> for FailoverCluster { #[derive(Debug, Default)] pub struct MockDirectory { router_chain: RouterChain, - invokers: Vec + invokers: Vec, } impl MockDirectory { pub fn new(invokers: Vec) -> MockDirectory { - Self { router_chain: RouterChain::default(), invokers } + Self { + router_chain: RouterChain::default(), + invokers, + } } } @@ -134,7 +142,7 @@ impl Directory for MockDirectory { #[derive(Debug, Default)] pub struct RouterChain { router: HashMap, - invokers: Vec + invokers: Vec, } impl RouterChain { @@ -144,9 +152,13 @@ impl RouterChain { } } - -pub trait Router: Debug{ - fn route(&self, invokers: Vec, url: Url, invo: Arc) -> Vec; +pub trait Router: Debug { + fn route( + &self, + invokers: Vec, + url: Url, + invo: Arc, + ) -> Vec; } pub type BoxRouter = Box; @@ -155,7 +167,12 @@ pub type BoxRouter = Box; pub struct MockRouter {} impl Router for MockRouter { - fn route(&self, invokers: Vec, url: Url, invo: Arc) -> Vec { + fn route( + &self, + invokers: Vec, + _url: Url, + _invo: Arc, + ) -> Vec { invokers } -} \ No newline at end of file +} diff --git a/dubbo/src/protocol/mod.rs b/dubbo/src/protocol/mod.rs index 629513e6..145bcc8e 100644 --- a/dubbo/src/protocol/mod.rs +++ b/dubbo/src/protocol/mod.rs @@ -69,12 +69,14 @@ pub type BoxInvoker = Box< + Sync, >; -dyn_clone::clone_trait_object!(Invoker< - http::Request, - Response = http::Response, - Error = crate::Error, - Future = crate::BoxFuture, crate::Error>, ->); +dyn_clone::clone_trait_object!( + Invoker< + http::Request, + Response = http::Response, + Error = crate::Error, + Future = crate::BoxFuture, crate::Error>, + > +); pub struct WrapperInvoker(T); diff --git a/dubbo/src/protocol/triple/triple_invoker.rs b/dubbo/src/protocol/triple/triple_invoker.rs index fb47bbed..fb661f9e 100644 --- a/dubbo/src/protocol/triple/triple_invoker.rs +++ b/dubbo/src/protocol/triple/triple_invoker.rs @@ -17,12 +17,17 @@ use aws_smithy_http::body::SdkBody; use dubbo_base::Url; -use std::fmt::{Debug, Formatter}; -use std::str::FromStr; +use std::{ + fmt::{Debug, Formatter}, + str::FromStr, +}; use tower_service::Service; -use crate::{protocol::Invoker, triple::client::builder::ClientBoxService, utils::boxed_clone::BoxCloneService}; -use crate::triple::transport::connection::Connection; +use crate::{ + protocol::Invoker, + triple::{client::builder::ClientBoxService, transport::connection::Connection}, + utils::boxed_clone::BoxCloneService, +}; #[derive(Clone)] pub struct TripleInvoker { diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index ea1fd26d..26ab9e9f 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -16,13 +16,14 @@ */ use crate::{ - cluster::directory::StaticDirectory, - codegen::{ClusterInvoker, Directory, RegistryDirectory}, + cluster::{directory::StaticDirectory, Cluster, MockCluster, MockDirectory}, + codegen::{ClusterInvoker, Directory, RegistryDirectory, TripleInvoker}, triple::compression::CompressionEncoding, - utils::{boxed::BoxService, boxed_clone::BoxCloneService}, + utils::boxed_clone::BoxCloneService, }; use aws_smithy_http::body::SdkBody; +use dubbo_base::Url; use super::TripleClient; @@ -35,6 +36,9 @@ pub struct ClientBuilder { pub connector: &'static str, directory: Option>, cluster_invoker: Option, + pub direct: bool, + host: String, + uri: Option, } impl ClientBuilder { @@ -44,6 +48,9 @@ impl ClientBuilder { connector: "", directory: None, cluster_invoker: None, + direct: true, + uri: None, + host: "".to_string(), } } @@ -53,6 +60,9 @@ impl ClientBuilder { connector: "", directory: Some(Box::new(StaticDirectory::new(&host))), cluster_invoker: None, + direct: true, + uri: None, + host: host.clone().to_string(), } } @@ -62,6 +72,9 @@ impl ClientBuilder { connector: "", directory: Some(Box::new(StaticDirectory::from_uri(&uri))), cluster_invoker: None, + direct: true, + uri: Some(uri.clone()), + host: "".to_string(), } } @@ -104,11 +117,29 @@ impl ClientBuilder { } } + pub fn with_direct(self, direct: bool) -> Self { + Self { direct, ..self } + } + pub fn build(self) -> TripleClient { - TripleClient { + let mut cli = TripleClient { send_compression_encoding: Some(CompressionEncoding::Gzip), directory: self.directory, cluster_invoker: self.cluster_invoker, + invoker: None, + }; + if self.direct { + cli.invoker = Some(Box::new(TripleInvoker::new( + Url::from_url(&self.host).unwrap(), + ))); + return cli; } + + let cluster = MockCluster::default().join(Box::new(MockDirectory::new(vec![Box::new( + TripleInvoker::new(Url::from_url("http://127.0.0.1:8888").unwrap()), + )]))); + + cli.invoker = Some(cluster); + cli } } diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 56edb96b..3585b486 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -30,6 +30,7 @@ use crate::codegen::{ClusterInvoker, Directory, RpcInvocation}; use crate::{ cluster::support::cluster_invoker::ClusterRequestBuilder, invocation::{IntoStreamingRequest, Metadata, Request, Response}, + protocol::BoxInvoker, triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding, encode::encode}, }; @@ -38,11 +39,12 @@ pub struct TripleClient { pub(crate) send_compression_encoding: Option, pub(crate) directory: Option>, pub(crate) cluster_invoker: Option, + pub invoker: Option, } impl TripleClient { pub fn connect(host: String) -> Self { - let builder = ClientBuilder::from_static(&host); + let builder = ClientBuilder::from_static(&host).with_direct(true); builder.build() } @@ -150,27 +152,14 @@ impl TripleClient { ) .into_stream(); let body = hyper::Body::wrap_stream(body_stream); - let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } + let bytes = hyper::body::to_bytes(body).await.unwrap(); + let sdk_body = SdkBody::from(bytes); + + // let mut conn = Connection::new().with_host(http_uri); + let mut conn = self.invoker.clone().unwrap(); + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); - let mut conn = Connection::new().with_host(http_uri); let response = conn .call(req) .await From 3cba7dc269a9ea0c171b06a1dfe9a1963bff7527 Mon Sep 17 00:00:00 2001 From: Yang Yang <962032265q@gmail.com> Date: Tue, 16 May 2023 10:51:59 +0800 Subject: [PATCH 13/31] Update builder.rs update default direct value --- dubbo/src/triple/client/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 26ab9e9f..5ec8bda4 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -48,7 +48,7 @@ impl ClientBuilder { connector: "", directory: None, cluster_invoker: None, - direct: true, + direct: false, uri: None, host: "".to_string(), } From 1e7285e799e13e0fd569cb1c81f2f01d5ee72ca1 Mon Sep 17 00:00:00 2001 From: Yang Yang <962032265q@gmail.com> Date: Tue, 16 May 2023 10:57:51 +0800 Subject: [PATCH 14/31] Update triple.rs handle unused var --- dubbo/src/triple/client/triple.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 3585b486..eb7934dd 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -137,7 +137,7 @@ impl TripleClient { req: Request, mut codec: C, path: http::uri::PathAndQuery, - invocation: RpcInvocation, + _invocation: RpcInvocation, ) -> Result, crate::status::Status> where C: Codec, From 2c567a73c08c14b3e9507f1557f07797d7d055ec Mon Sep 17 00:00:00 2001 From: Yang Yang <962032265q@gmail.com> Date: Tue, 16 May 2023 11:17:10 +0800 Subject: [PATCH 15/31] Update mod.rs comment some codes --- dubbo/src/cluster/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index d2c2adb7..4f73d2f5 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -112,25 +112,25 @@ impl Invoker> for FailoverCluster { #[derive(Debug, Default)] pub struct MockDirectory { - router_chain: RouterChain, + // router_chain: RouterChain, invokers: Vec, } impl MockDirectory { pub fn new(invokers: Vec) -> MockDirectory { Self { - router_chain: RouterChain::default(), + // router_chain: RouterChain::default(), invokers, } } } impl Directory for MockDirectory { - fn list(&self, invo: Arc) -> Vec { + fn list(&self, _invo: Arc) -> Vec { // tracing::info!("MockDirectory: {}", meta); - let u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); + let _u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); // vec![Box::new(TripleInvoker::new(u))] - self.router_chain.route(u, invo); + // self.router_chain.route(u, invo); self.invokers.clone() } From 695a880f65c75296f15feedafb64d6c4a99eff6a Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Tue, 16 May 2023 21:22:42 +0800 Subject: [PATCH 16/31] refactor(triple): rm unused var in clientBuilder --- dubbo/src/triple/client/builder.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 5ec8bda4..29957a6f 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -38,7 +38,6 @@ pub struct ClientBuilder { cluster_invoker: Option, pub direct: bool, host: String, - uri: Option, } impl ClientBuilder { @@ -49,7 +48,6 @@ impl ClientBuilder { directory: None, cluster_invoker: None, direct: false, - uri: None, host: "".to_string(), } } @@ -61,23 +59,10 @@ impl ClientBuilder { directory: Some(Box::new(StaticDirectory::new(&host))), cluster_invoker: None, direct: true, - uri: None, host: host.clone().to_string(), } } - pub fn from_uri(uri: &http::Uri) -> ClientBuilder { - Self { - timeout: None, - connector: "", - directory: Some(Box::new(StaticDirectory::from_uri(&uri))), - cluster_invoker: None, - direct: true, - uri: Some(uri.clone()), - host: "".to_string(), - } - } - pub fn with_timeout(self, timeout: u64) -> Self { Self { timeout: Some(timeout), From d2cb3831e5d37132a9963a04891643e6089796b8 Mon Sep 17 00:00:00 2001 From: G-XD <38717659+G-XD@users.noreply.github.com> Date: Tue, 16 May 2023 21:26:17 +0800 Subject: [PATCH 17/31] fix logical error of get_protocol_or_default (#137) Co-authored-by: GXD --- config/src/protocol.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/config/src/protocol.rs b/config/src/protocol.rs index 86ff0531..e2340c17 100644 --- a/config/src/protocol.rs +++ b/config/src/protocol.rs @@ -77,10 +77,26 @@ impl ProtocolRetrieve for ProtocolConfig { } else { let result = self.get_protocol(protocol_key); if let Some(..) = result { - panic!("default triple base dose not defined.") - } else { result.unwrap() + } else { + panic!("default triple base dose not defined.") } } } } + +#[cfg(test)] +mod tests { + + use super::{ProtocolConfig, ProtocolRetrieve}; + + #[test] + #[should_panic(expected = "default triple base dose not defined")] + pub fn test_get_invalid_protocol() { + let config = ProtocolConfig::default(); + + let _ = config.get_protocol_or_default(""); + + () + } +} From 54181bf417536e75ed6a4ff49efaf7a5911fd5d3 Mon Sep 17 00:00:00 2001 From: Yang Yang <962032265@qq.com> Date: Tue, 16 May 2023 21:29:31 +0800 Subject: [PATCH 18/31] Feat/cluster (#138) * refactor(cluster): add Cluster MockImpl * refactor(triple): use ClientBuilder to init Cluster ability * Update builder.rs update default direct value * Update triple.rs handle unused var * Update mod.rs comment some codes * refactor(triple): rm unused var in clientBuilder --- dubbo/Cargo.toml | 1 + dubbo/src/cluster/mod.rs | 101 +++++++++++++++++--- dubbo/src/protocol/mod.rs | 12 ++- dubbo/src/protocol/triple/triple_invoker.rs | 26 +++-- dubbo/src/triple/client/builder.rs | 44 ++++++--- dubbo/src/triple/client/triple.rs | 33 +++---- 6 files changed, 159 insertions(+), 58 deletions(-) diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index 94a2bd86..91b19d6f 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -34,6 +34,7 @@ axum = "0.5.9" async-stream = "0.3" flate2 = "1.0" aws-smithy-http = "0.54.1" +dyn-clone = "1.0.11" itertools.workspace = true urlencoding.workspace = true lazy_static.workspace = true diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index b6d8a7c2..4f73d2f5 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -15,24 +15,41 @@ * limitations under the License. */ -use std::{sync::Arc, task::Poll}; +use std::{collections::HashMap, fmt::Debug, sync::Arc, task::Poll}; use aws_smithy_http::body::SdkBody; -use tower_service::Service; +use dubbo_base::Url; -use crate::{empty_body, protocol::BoxInvoker}; +use crate::{ + empty_body, + invocation::RpcInvocation, + protocol::{BoxInvoker, Invoker}, +}; pub mod directory; pub mod loadbalance; pub mod support; -pub trait Directory { - fn list(&self, meta: String) -> Vec; +pub trait Directory: Debug { + fn list(&self, invocation: Arc) -> Vec; fn is_empty(&self) -> bool; } -type BoxDirectory = Box; +type BoxDirectory = Box; +pub trait Cluster { + fn join(&self, dir: BoxDirectory) -> BoxInvoker; +} + +#[derive(Debug, Default)] +pub struct MockCluster {} + +impl Cluster for MockCluster { + fn join(&self, dir: BoxDirectory) -> BoxInvoker { + Box::new(FailoverCluster::new(dir)) + } +} +#[derive(Clone, Debug)] pub struct FailoverCluster { dir: Arc, } @@ -43,7 +60,7 @@ impl FailoverCluster { } } -impl Service> for FailoverCluster { +impl Invoker> for FailoverCluster { type Response = http::Response; type Error = crate::Error; @@ -66,7 +83,11 @@ impl Service> for FailoverCluster { .method(req.method().clone()); *clone_req.headers_mut().unwrap() = req.headers().clone(); let r = clone_req.body(clone_body).unwrap(); - let invokers = self.dir.list("service_name".to_string()); + let invokers = self.dir.list( + RpcInvocation::default() + .with_service_unique_name("hello".to_string()) + .into(), + ); for mut invoker in invokers { let fut = async move { let res = invoker.call(r).await; @@ -83,19 +104,75 @@ impl Service> for FailoverCluster { .unwrap()) }) } + + fn get_url(&self) -> dubbo_base::Url { + Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap() + } +} + +#[derive(Debug, Default)] +pub struct MockDirectory { + // router_chain: RouterChain, + invokers: Vec, } -pub struct MockDirectory {} +impl MockDirectory { + pub fn new(invokers: Vec) -> MockDirectory { + Self { + // router_chain: RouterChain::default(), + invokers, + } + } +} impl Directory for MockDirectory { - fn list(&self, _meta: String) -> Vec { + fn list(&self, _invo: Arc) -> Vec { // tracing::info!("MockDirectory: {}", meta); - // let u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); + let _u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); // vec![Box::new(TripleInvoker::new(u))] - todo!() + // self.router_chain.route(u, invo); + self.invokers.clone() } fn is_empty(&self) -> bool { false } } + +#[derive(Debug, Default)] +pub struct RouterChain { + router: HashMap, + invokers: Vec, +} + +impl RouterChain { + pub fn route(&self, url: Url, invo: Arc) -> Vec { + let r = self.router.get("mock").unwrap(); + r.route(self.invokers.clone(), url, invo) + } +} + +pub trait Router: Debug { + fn route( + &self, + invokers: Vec, + url: Url, + invo: Arc, + ) -> Vec; +} + +pub type BoxRouter = Box; + +#[derive(Debug, Default)] +pub struct MockRouter {} + +impl Router for MockRouter { + fn route( + &self, + invokers: Vec, + _url: Url, + _invo: Arc, + ) -> Vec { + invokers + } +} diff --git a/dubbo/src/protocol/mod.rs b/dubbo/src/protocol/mod.rs index 58dca5fd..145bcc8e 100644 --- a/dubbo/src/protocol/mod.rs +++ b/dubbo/src/protocol/mod.rs @@ -23,6 +23,7 @@ use std::{ use async_trait::async_trait; use aws_smithy_http::body::SdkBody; +use dyn_clone::DynClone; use tower_service::Service; use dubbo_base::Url; @@ -43,7 +44,7 @@ pub trait Exporter { fn unexport(&self); } -pub trait Invoker: Debug { +pub trait Invoker: Debug + DynClone { type Response; type Error; @@ -68,6 +69,15 @@ pub type BoxInvoker = Box< + Sync, >; +dyn_clone::clone_trait_object!( + Invoker< + http::Request, + Response = http::Response, + Error = crate::Error, + Future = crate::BoxFuture, crate::Error>, + > +); + pub struct WrapperInvoker(T); impl Service> for WrapperInvoker diff --git a/dubbo/src/protocol/triple/triple_invoker.rs b/dubbo/src/protocol/triple/triple_invoker.rs index 6139cc91..fb661f9e 100644 --- a/dubbo/src/protocol/triple/triple_invoker.rs +++ b/dubbo/src/protocol/triple/triple_invoker.rs @@ -17,24 +17,32 @@ use aws_smithy_http::body::SdkBody; use dubbo_base::Url; -use std::fmt::{Debug, Formatter}; +use std::{ + fmt::{Debug, Formatter}, + str::FromStr, +}; use tower_service::Service; -use crate::{protocol::Invoker, triple::client::builder::ClientBoxService}; +use crate::{ + protocol::Invoker, + triple::{client::builder::ClientBoxService, transport::connection::Connection}, + utils::boxed_clone::BoxCloneService, +}; +#[derive(Clone)] pub struct TripleInvoker { url: Url, conn: ClientBoxService, } impl TripleInvoker { - // pub fn new(url: Url) -> TripleInvoker { - // let uri = http::Uri::from_str(&url.to_url()).unwrap(); - // Self { - // url, - // conn: ClientBuilder::from_uri(&uri).build()connect(), - // } - // } + pub fn new(url: Url) -> TripleInvoker { + let uri = http::Uri::from_str(&url.to_url()).unwrap(); + Self { + url, + conn: BoxCloneService::new(Connection::new().with_host(uri)), + } + } } impl Debug for TripleInvoker { diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index cf667ccd..29957a6f 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -16,18 +16,19 @@ */ use crate::{ - cluster::directory::StaticDirectory, - codegen::{ClusterInvoker, Directory, RegistryDirectory}, + cluster::{directory::StaticDirectory, Cluster, MockCluster, MockDirectory}, + codegen::{ClusterInvoker, Directory, RegistryDirectory, TripleInvoker}, triple::compression::CompressionEncoding, - utils::boxed::BoxService, + utils::boxed_clone::BoxCloneService, }; use aws_smithy_http::body::SdkBody; +use dubbo_base::Url; use super::TripleClient; pub type ClientBoxService = - BoxService, http::Response, crate::Error>; + BoxCloneService, http::Response, crate::Error>; #[derive(Clone, Debug, Default)] pub struct ClientBuilder { @@ -35,6 +36,8 @@ pub struct ClientBuilder { pub connector: &'static str, directory: Option>, cluster_invoker: Option, + pub direct: bool, + host: String, } impl ClientBuilder { @@ -44,6 +47,8 @@ impl ClientBuilder { connector: "", directory: None, cluster_invoker: None, + direct: false, + host: "".to_string(), } } @@ -53,15 +58,8 @@ impl ClientBuilder { connector: "", directory: Some(Box::new(StaticDirectory::new(&host))), cluster_invoker: None, - } - } - - pub fn from_uri(uri: &http::Uri) -> ClientBuilder { - Self { - timeout: None, - connector: "", - directory: Some(Box::new(StaticDirectory::from_uri(&uri))), - cluster_invoker: None, + direct: true, + host: host.clone().to_string(), } } @@ -104,11 +102,29 @@ impl ClientBuilder { } } + pub fn with_direct(self, direct: bool) -> Self { + Self { direct, ..self } + } + pub fn build(self) -> TripleClient { - TripleClient { + let mut cli = TripleClient { send_compression_encoding: Some(CompressionEncoding::Gzip), directory: self.directory, cluster_invoker: self.cluster_invoker, + invoker: None, + }; + if self.direct { + cli.invoker = Some(Box::new(TripleInvoker::new( + Url::from_url(&self.host).unwrap(), + ))); + return cli; } + + let cluster = MockCluster::default().join(Box::new(MockDirectory::new(vec![Box::new( + TripleInvoker::new(Url::from_url("http://127.0.0.1:8888").unwrap()), + )]))); + + cli.invoker = Some(cluster); + cli } } diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 56edb96b..eb7934dd 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -30,6 +30,7 @@ use crate::codegen::{ClusterInvoker, Directory, RpcInvocation}; use crate::{ cluster::support::cluster_invoker::ClusterRequestBuilder, invocation::{IntoStreamingRequest, Metadata, Request, Response}, + protocol::BoxInvoker, triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding, encode::encode}, }; @@ -38,11 +39,12 @@ pub struct TripleClient { pub(crate) send_compression_encoding: Option, pub(crate) directory: Option>, pub(crate) cluster_invoker: Option, + pub invoker: Option, } impl TripleClient { pub fn connect(host: String) -> Self { - let builder = ClientBuilder::from_static(&host); + let builder = ClientBuilder::from_static(&host).with_direct(true); builder.build() } @@ -135,7 +137,7 @@ impl TripleClient { req: Request, mut codec: C, path: http::uri::PathAndQuery, - invocation: RpcInvocation, + _invocation: RpcInvocation, ) -> Result, crate::status::Status> where C: Codec, @@ -150,27 +152,14 @@ impl TripleClient { ) .into_stream(); let body = hyper::Body::wrap_stream(body_stream); - let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } + let bytes = hyper::body::to_bytes(body).await.unwrap(); + let sdk_body = SdkBody::from(bytes); + + // let mut conn = Connection::new().with_host(http_uri); + let mut conn = self.invoker.clone().unwrap(); + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); - let mut conn = Connection::new().with_host(http_uri); let response = conn .call(req) .await From e9a9935e4421ceebc8833e0df56a46dac6609880 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Tue, 16 May 2023 22:03:39 +0800 Subject: [PATCH 19/31] refactor(dubbo): delete some codes --- dubbo-build/src/client.rs | 5 - dubbo/src/cluster/mod.rs | 2 +- dubbo/src/cluster/support/cluster_invoker.rs | 147 ------------------- dubbo/src/cluster/support/mod.rs | 20 --- dubbo/src/codegen.rs | 5 +- dubbo/src/registry/integration.rs | 7 - dubbo/src/triple/client/builder.rs | 9 +- dubbo/src/triple/client/triple.rs | 81 ++-------- registry/zookeeper/src/lib.rs | 11 +- 9 files changed, 20 insertions(+), 267 deletions(-) delete mode 100644 dubbo/src/cluster/support/cluster_invoker.rs delete mode 100644 dubbo/src/cluster/support/mod.rs diff --git a/dubbo-build/src/client.rs b/dubbo-build/src/client.rs index 1e1c9fbd..bfcfe45b 100644 --- a/dubbo-build/src/client.rs +++ b/dubbo-build/src/client.rs @@ -90,11 +90,6 @@ pub fn generate( } } - pub fn with_cluster(mut self, invoker: ClusterInvoker) -> Self { - self.inner = self.inner.with_cluster(invoker); - self - } - #methods } diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index 4f73d2f5..f60838e1 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -28,7 +28,7 @@ use crate::{ pub mod directory; pub mod loadbalance; -pub mod support; +// pub mod support; pub trait Directory: Debug { fn list(&self, invocation: Arc) -> Vec; diff --git a/dubbo/src/cluster/support/cluster_invoker.rs b/dubbo/src/cluster/support/cluster_invoker.rs deleted file mode 100644 index 0ccca488..00000000 --- a/dubbo/src/cluster/support/cluster_invoker.rs +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 aws_smithy_http::body::SdkBody; -use std::{str::FromStr, sync::Arc}; - -use dubbo_base::Url; -use http::{uri::PathAndQuery, Request}; - -use crate::{ - cluster::{ - loadbalance::{types::BoxLoadBalance, LOAD_BALANCE_EXTENSIONS}, - support::DEFAULT_LOADBALANCE, - }, - codegen::{Directory, RegistryDirectory, TripleClient}, - invocation::RpcInvocation, -}; - -#[derive(Debug, Clone)] -pub struct ClusterInvoker { - directory: Arc, - destroyed: bool, -} - -pub trait ClusterInvokerSelector { - /// Select a invoker using loadbalance policy. - fn select( - &self, - invocation: Arc, - invokers: Arc>, - excluded: Arc>, - ) -> Option; - - fn do_select( - &self, - loadbalance_key: Option<&str>, - invocation: Arc, - invokers: Arc>, - ) -> Option; -} - -pub trait ClusterRequestBuilder { - fn build_req( - &self, - triple_client: &mut TripleClient, - path: http::uri::PathAndQuery, - invocation: Arc, - body: SdkBody, - ) -> http::Request; -} - -impl ClusterInvoker { - pub fn with_directory(registry_directory: RegistryDirectory) -> Self { - ClusterInvoker { - directory: Arc::new(registry_directory), - destroyed: false, - } - } - - pub fn directory(&self) -> Arc { - self.directory.clone() - } - - pub fn init_loadbalance(&self, loadbalance_key: &str) -> &BoxLoadBalance { - if LOAD_BALANCE_EXTENSIONS.contains_key(loadbalance_key) { - LOAD_BALANCE_EXTENSIONS.get(loadbalance_key).unwrap() - } else { - println!( - "loadbalance {} not found, use default loadbalance {}", - loadbalance_key, DEFAULT_LOADBALANCE - ); - LOAD_BALANCE_EXTENSIONS.get(DEFAULT_LOADBALANCE).unwrap() - } - } - - pub fn is_available(&self, invocation: Arc) -> bool { - !self.destroyed() && !self.directory.list(invocation).is_empty() - } - - pub fn destroyed(&self) -> bool { - self.destroyed - } -} - -impl ClusterInvokerSelector for ClusterInvoker { - fn select( - &self, - invocation: Arc, - invokers: Arc>, - _excluded: Arc>, - ) -> Option { - if invokers.is_empty() { - return None; - } - let instance_count = invokers.len(); - return if instance_count == 1 { - Some(invokers.as_ref().first()?.clone()) - } else { - let loadbalance = Some(DEFAULT_LOADBALANCE); - self.do_select(loadbalance, invocation, invokers) - }; - } - - /// picking instance invoker url from registry directory - fn do_select( - &self, - loadbalance_key: Option<&str>, - invocation: Arc, - invokers: Arc>, - ) -> Option { - let loadbalance = self.init_loadbalance(loadbalance_key.unwrap_or(DEFAULT_LOADBALANCE)); - loadbalance.select(invokers, None, invocation) - } -} - -impl ClusterRequestBuilder for ClusterInvoker { - fn build_req( - &self, - triple_client: &mut TripleClient, - path: PathAndQuery, - invocation: Arc, - body: SdkBody, - ) -> Request { - let invokers = self.directory.list(invocation.clone()); - let invoker_url = self - .select(invocation, Arc::new(invokers), Arc::new(Vec::new())) - .expect("no valid provider"); - let http_uri = - http::Uri::from_str(&format!("http://{}:{}/", invoker_url.ip, invoker_url.port)) - .unwrap(); - triple_client.map_request(http_uri, path, body) - } -} diff --git a/dubbo/src/cluster/support/mod.rs b/dubbo/src/cluster/support/mod.rs deleted file mode 100644 index ae42cc28..00000000 --- a/dubbo/src/cluster/support/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -pub mod cluster_invoker; - -pub const DEFAULT_LOADBALANCE: &str = "random"; diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 98d784fc..5d0a2732 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -27,10 +27,7 @@ pub use hyper::Body as hyperBody; pub use tower_service::Service; pub use super::{ - cluster::{ - directory::{Directory, RegistryDirectory}, - support::cluster_invoker::ClusterInvoker, - }, + cluster::directory::{Directory, RegistryDirectory}, empty_body, invocation::{IntoStreamingRequest, Request, Response, RpcInvocation}, protocol::{triple::triple_invoker::TripleInvoker, Invoker}, diff --git a/dubbo/src/registry/integration.rs b/dubbo/src/registry/integration.rs index 15b82d01..2944f981 100644 --- a/dubbo/src/registry/integration.rs +++ b/dubbo/src/registry/integration.rs @@ -14,10 +14,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -use crate::{cluster::support::cluster_invoker::ClusterInvoker, registry::BoxRegistry}; -use std::sync::Arc; - -pub trait ClusterRegistryIntegration { - /// get cluster invoker struct - fn get_invoker(registry: BoxRegistry) -> Option>; -} diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 29957a6f..ce86641a 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -17,7 +17,7 @@ use crate::{ cluster::{directory::StaticDirectory, Cluster, MockCluster, MockDirectory}, - codegen::{ClusterInvoker, Directory, RegistryDirectory, TripleInvoker}, + codegen::{Directory, RegistryDirectory, TripleInvoker}, triple::compression::CompressionEncoding, utils::boxed_clone::BoxCloneService, }; @@ -35,7 +35,6 @@ pub struct ClientBuilder { pub timeout: Option, pub connector: &'static str, directory: Option>, - cluster_invoker: Option, pub direct: bool, host: String, } @@ -46,7 +45,6 @@ impl ClientBuilder { timeout: None, connector: "", directory: None, - cluster_invoker: None, direct: false, host: "".to_string(), } @@ -57,7 +55,6 @@ impl ClientBuilder { timeout: None, connector: "", directory: Some(Box::new(StaticDirectory::new(&host))), - cluster_invoker: None, direct: true, host: host.clone().to_string(), } @@ -74,7 +71,6 @@ impl ClientBuilder { pub fn with_directory(self, directory: Box) -> Self { Self { directory: Some(directory), - cluster_invoker: None, ..self } } @@ -82,7 +78,6 @@ impl ClientBuilder { pub fn with_registry_directory(self, registry: RegistryDirectory) -> Self { Self { directory: None, - cluster_invoker: Some(ClusterInvoker::with_directory(registry)), ..self } } @@ -97,7 +92,6 @@ impl ClientBuilder { pub fn with_connector(self, connector: &'static str) -> Self { Self { connector: connector, - cluster_invoker: None, ..self } } @@ -110,7 +104,6 @@ impl ClientBuilder { let mut cli = TripleClient { send_compression_encoding: Some(CompressionEncoding::Gzip), directory: self.directory, - cluster_invoker: self.cluster_invoker, invoker: None, }; if self.direct { diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index eb7934dd..64c8ffbc 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -25,10 +25,9 @@ use rand::prelude::SliceRandom; use tower_service::Service; use super::{super::transport::connection::Connection, builder::ClientBuilder}; -use crate::codegen::{ClusterInvoker, Directory, RpcInvocation}; +use crate::codegen::{Directory, RpcInvocation}; use crate::{ - cluster::support::cluster_invoker::ClusterRequestBuilder, invocation::{IntoStreamingRequest, Metadata, Request, Response}, protocol::BoxInvoker, triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding, encode::encode}, @@ -38,7 +37,6 @@ use crate::{ pub struct TripleClient { pub(crate) send_compression_encoding: Option, pub(crate) directory: Option>, - pub(crate) cluster_invoker: Option, pub invoker: Option, } @@ -53,13 +51,6 @@ impl TripleClient { builder.build() } - pub fn with_cluster(self, invoker: ClusterInvoker) -> Self { - TripleClient { - cluster_invoker: Some(invoker), - ..self - } - } - pub fn map_request( &self, uri: http::Uri, @@ -214,25 +205,11 @@ impl TripleClient { .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } - let mut conn = Connection::new().with_host(http_uri); + + let mut conn = self.invoker.clone().unwrap(); + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); + let response = conn .call(req) .await @@ -271,24 +248,11 @@ impl TripleClient { .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } + + let mut conn = self.invoker.clone().unwrap(); + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); + let mut conn = Connection::new().with_host(http_uri); let response = conn .call(req) @@ -344,26 +308,11 @@ impl TripleClient { .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } - let mut conn = Connection::new().with_host(http_uri); + let mut conn = self.invoker.clone().unwrap(); + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); + let response = conn .call(req) .await diff --git a/registry/zookeeper/src/lib.rs b/registry/zookeeper/src/lib.rs index 5debc0ab..2da3a53e 100644 --- a/registry/zookeeper/src/lib.rs +++ b/registry/zookeeper/src/lib.rs @@ -34,11 +34,10 @@ use serde::{Deserialize, Serialize}; use zookeeper::{Acl, CreateMode, WatchedEvent, WatchedEventType, Watcher, ZooKeeper}; use dubbo::{ - cluster::support::cluster_invoker::ClusterInvoker, codegen::BoxRegistry, registry::{ - integration::ClusterRegistryIntegration, memory_registry::MemoryRegistry, NotifyListener, - Registry, RegistryNotifyListener, ServiceEvent, + memory_registry::MemoryRegistry, NotifyListener, Registry, RegistryNotifyListener, + ServiceEvent, }, StdError, }; @@ -371,12 +370,6 @@ impl NotifyListener for ServiceInstancesChangedListener { } } -impl ClusterRegistryIntegration for ZookeeperRegistry { - fn get_invoker(registry: BoxRegistry) -> Option> { - todo!() - } -} - #[cfg(test)] mod tests { use std::sync::Arc; From 1c79aee5246db4b2ed6465936b1d94bba738025f Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Thu, 18 May 2023 20:29:29 +0800 Subject: [PATCH 20/31] refactor(cluster): rm some duplicate codes --- dubbo/src/cluster/directory.rs | 58 ++++++++++------------------------ dubbo/src/cluster/mod.rs | 16 ++++++---- dubbo/src/codegen.rs | 2 +- 3 files changed, 26 insertions(+), 50 deletions(-) diff --git a/dubbo/src/cluster/directory.rs b/dubbo/src/cluster/directory.rs index e74fc6d4..e8ce5644 100644 --- a/dubbo/src/cluster/directory.rs +++ b/dubbo/src/cluster/directory.rs @@ -23,39 +23,21 @@ use std::{ }; use crate::{ + codegen::TripleInvoker, invocation::{Invocation, RpcInvocation}, + protocol::BoxInvoker, registry::{memory_registry::MemoryNotifyListener, BoxRegistry, RegistryWrapper}, }; use dubbo_base::Url; use dubbo_logger::tracing; +use crate::cluster::Directory; + /// Directory. /// /// [Directory Service](http://en.wikipedia.org/wiki/Directory_service) -pub trait Directory: Debug + DirectoryClone { - fn list(&self, invocation: Arc) -> Vec; -} -pub trait DirectoryClone { - fn clone_box(&self) -> Box; -} - -impl DirectoryClone for T -where - T: 'static + Directory + Clone, -{ - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } -} - -impl Clone for Box { - fn clone(&self) -> Box { - self.clone_box() - } -} - -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct StaticDirectory { uri: http::Uri, } @@ -78,7 +60,7 @@ impl StaticDirectory { } impl Directory for StaticDirectory { - fn list(&self, invocation: Arc) -> Vec { + fn list(&self, invocation: Arc) -> Vec { let url = Url::from_url(&format!( "tri://{}:{}/{}", self.uri.host().unwrap(), @@ -86,19 +68,12 @@ impl Directory for StaticDirectory { invocation.get_target_service_unique_name(), )) .unwrap(); - vec![url] - } -} - -impl DirectoryClone for StaticDirectory { - fn clone_box(&self) -> Box { - Box::new(StaticDirectory { - uri: self.uri.clone(), - }) + let invoker = Box::new(TripleInvoker::new(url)); + vec![invoker] } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct RegistryDirectory { registry: RegistryWrapper, service_instances: Arc>>>, @@ -115,14 +90,8 @@ impl RegistryDirectory { } } -impl DirectoryClone for RegistryDirectory { - fn clone_box(&self) -> Box { - todo!() - } -} - impl Directory for RegistryDirectory { - fn list(&self, invocation: Arc) -> Vec { + fn list(&self, invocation: Arc) -> Vec { let service_name = invocation.get_target_service_unique_name(); let url = Url::from_url(&format!( @@ -149,6 +118,11 @@ impl Directory for RegistryDirectory { .expect("service_instances.read"); let binding = Vec::new(); let url_vec = map.get(&service_name).unwrap_or(&binding); - url_vec.to_vec() + // url_vec.to_vec() + let mut invokers: Vec = vec![]; + for item in url_vec.iter() { + invokers.push(Box::new(TripleInvoker::new(item.clone()))); + } + invokers } } diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index f60838e1..3e6c4f30 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -19,6 +19,7 @@ use std::{collections::HashMap, fmt::Debug, sync::Arc, task::Poll}; use aws_smithy_http::body::SdkBody; use dubbo_base::Url; +use dyn_clone::DynClone; use crate::{ empty_body, @@ -28,13 +29,14 @@ use crate::{ pub mod directory; pub mod loadbalance; -// pub mod support; -pub trait Directory: Debug { +pub trait Directory: Debug + DynClone { fn list(&self, invocation: Arc) -> Vec; - fn is_empty(&self) -> bool; + // fn is_empty(&self) -> bool; } +dyn_clone::clone_trait_object!(Directory); + type BoxDirectory = Box; pub trait Cluster { @@ -110,7 +112,7 @@ impl Invoker> for FailoverCluster { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct MockDirectory { // router_chain: RouterChain, invokers: Vec, @@ -134,9 +136,9 @@ impl Directory for MockDirectory { self.invokers.clone() } - fn is_empty(&self) -> bool { - false - } + // fn is_empty(&self) -> bool { + // false + // } } #[derive(Debug, Default)] diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 5d0a2732..24b73fd3 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -27,7 +27,7 @@ pub use hyper::Body as hyperBody; pub use tower_service::Service; pub use super::{ - cluster::directory::{Directory, RegistryDirectory}, + cluster::directory::RegistryDirectory, empty_body, invocation::{IntoStreamingRequest, Request, Response, RpcInvocation}, protocol::{triple::triple_invoker::TripleInvoker, Invoker}, From 06cb96950b32d536c811b9191416a2b8d1811bf6 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Thu, 18 May 2023 20:44:28 +0800 Subject: [PATCH 21/31] refactor(registry): rm unused import --- registry/zookeeper/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/registry/zookeeper/src/lib.rs b/registry/zookeeper/src/lib.rs index 2da3a53e..e8c2c5ce 100644 --- a/registry/zookeeper/src/lib.rs +++ b/registry/zookeeper/src/lib.rs @@ -34,7 +34,6 @@ use serde::{Deserialize, Serialize}; use zookeeper::{Acl, CreateMode, WatchedEvent, WatchedEventType, Watcher, ZooKeeper}; use dubbo::{ - codegen::BoxRegistry, registry::{ memory_registry::MemoryRegistry, NotifyListener, Registry, RegistryNotifyListener, ServiceEvent, From 18a61403a9b79482be6a974f125b68388800a8ef Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Thu, 18 May 2023 20:46:17 +0800 Subject: [PATCH 22/31] refactor(triple): use two build func for different usage --- dubbo/src/triple/client/builder.rs | 34 +++++++++------ dubbo/src/triple/client/triple.rs | 66 +++++++++++++++++++++++------- examples/echo/src/echo/client.rs | 4 +- 3 files changed, 76 insertions(+), 28 deletions(-) diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index ce86641a..06ecd627 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -15,9 +15,12 @@ * limitations under the License. */ +use std::sync::Arc; + use crate::{ - cluster::{directory::StaticDirectory, Cluster, MockCluster, MockDirectory}, - codegen::{Directory, RegistryDirectory, TripleInvoker}, + cluster::{directory::StaticDirectory, Cluster, Directory, MockCluster, MockDirectory}, + codegen::{RegistryDirectory, RpcInvocation, TripleInvoker}, + protocol::BoxInvoker, triple::compression::CompressionEncoding, utils::boxed_clone::BoxCloneService, }; @@ -77,7 +80,7 @@ impl ClientBuilder { pub fn with_registry_directory(self, registry: RegistryDirectory) -> Self { Self { - directory: None, + directory: Some(Box::new(registry)), ..self } } @@ -100,24 +103,31 @@ impl ClientBuilder { Self { direct, ..self } } - pub fn build(self) -> TripleClient { + pub(crate) fn direct_build(self) -> TripleClient { let mut cli = TripleClient { send_compression_encoding: Some(CompressionEncoding::Gzip), - directory: self.directory, + builder: Some(self.clone()), invoker: None, }; + cli.invoker = Some(Box::new(TripleInvoker::new( + Url::from_url(&self.host).unwrap(), + ))); + return cli; + } + + pub fn build(self, invocation: Arc) -> Option { if self.direct { - cli.invoker = Some(Box::new(TripleInvoker::new( + return Some(Box::new(TripleInvoker::new( Url::from_url(&self.host).unwrap(), ))); - return cli; } + let invokers = match self.directory { + Some(v) => v.list(invocation), + None => panic!("use direct connection"), + }; - let cluster = MockCluster::default().join(Box::new(MockDirectory::new(vec![Box::new( - TripleInvoker::new(Url::from_url("http://127.0.0.1:8888").unwrap()), - )]))); + let cluster = MockCluster::default().join(Box::new(MockDirectory::new(invokers))); - cli.invoker = Some(cluster); - cli + return Some(cluster); } } diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 64c8ffbc..124cfcfd 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -15,17 +15,15 @@ * limitations under the License. */ -use std::{str::FromStr, sync::Arc}; +use std::str::FromStr; use futures_util::{future, stream, StreamExt, TryStreamExt}; use aws_smithy_http::body::SdkBody; use http::HeaderValue; -use rand::prelude::SliceRandom; -use tower_service::Service; -use super::{super::transport::connection::Connection, builder::ClientBuilder}; -use crate::codegen::{Directory, RpcInvocation}; +use super::builder::ClientBuilder; +use crate::codegen::RpcInvocation; use crate::{ invocation::{IntoStreamingRequest, Metadata, Request, Response}, @@ -36,7 +34,7 @@ use crate::{ #[derive(Debug, Clone, Default)] pub struct TripleClient { pub(crate) send_compression_encoding: Option, - pub(crate) directory: Option>, + pub(crate) builder: Option, pub invoker: Option, } @@ -44,11 +42,15 @@ impl TripleClient { pub fn connect(host: String) -> Self { let builder = ClientBuilder::from_static(&host).with_direct(true); - builder.build() + builder.direct_build() } pub fn new(builder: ClientBuilder) -> Self { - builder.build() + TripleClient { + send_compression_encoding: Some(CompressionEncoding::Gzip), + builder: Some(builder), + invoker: None, + } } pub fn map_request( @@ -128,7 +130,7 @@ impl TripleClient { req: Request, mut codec: C, path: http::uri::PathAndQuery, - _invocation: RpcInvocation, + invocation: RpcInvocation, ) -> Result, crate::status::Status> where C: Codec, @@ -146,8 +148,16 @@ impl TripleClient { let bytes = hyper::body::to_bytes(body).await.unwrap(); let sdk_body = SdkBody::from(bytes); - // let mut conn = Connection::new().with_host(http_uri); - let mut conn = self.invoker.clone().unwrap(); + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); @@ -206,7 +216,16 @@ impl TripleClient { let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let mut conn = self.invoker.clone().unwrap(); + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); @@ -249,11 +268,20 @@ impl TripleClient { let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let mut conn = self.invoker.clone().unwrap(); + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); - let mut conn = Connection::new().with_host(http_uri); + // let mut conn = Connection::new().with_host(http_uri); let response = conn .call(req) .await @@ -309,7 +337,15 @@ impl TripleClient { let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let mut conn = self.invoker.clone().unwrap(); + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); diff --git a/examples/echo/src/echo/client.rs b/examples/echo/src/echo/client.rs index db46958c..0a2f150b 100644 --- a/examples/echo/src/echo/client.rs +++ b/examples/echo/src/echo/client.rs @@ -34,7 +34,9 @@ async fn main() { // let builder = ClientBuilder::new() // .with_connector("unix") // .with_host("unix://127.0.0.1:8888"); - let builder = ClientBuilder::from_static(&"http://127.0.0.1:8888").with_timeout(1000000); + let builder = ClientBuilder::from_static(&"http://127.0.0.1:8888") + .with_timeout(1000000) + .with_direct(true); let mut cli = EchoClient::new(builder); // let mut unary_cli = cli.clone().with_filter(FakeFilter {}); // let mut cli = EchoClient::build(ClientBuilder::from_static("http://127.0.0.1:8888")); From 7dbe5f346ef6302f8e7f7f3c803388ed6df52fbb Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Thu, 18 May 2023 23:51:24 +0800 Subject: [PATCH 23/31] style: cargo fmt --all --- dubbo/src/cluster/mod.rs | 1 - dubbo/src/triple/client/triple.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index 7447ffe0..3e6c4f30 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -21,7 +21,6 @@ use aws_smithy_http::body::SdkBody; use dubbo_base::Url; use dyn_clone::DynClone; - use crate::{ empty_body, invocation::RpcInvocation, diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index e7d26084..124cfcfd 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -130,7 +130,7 @@ impl TripleClient { req: Request, mut codec: C, path: http::uri::PathAndQuery, - _invocation: RpcInvocation, + invocation: RpcInvocation, ) -> Result, crate::status::Status> where C: Codec, From 58c6f7d41d9a8f7b08111ca4854b6fc57f7d7aae Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Fri, 19 May 2023 21:57:26 +0800 Subject: [PATCH 24/31] refactor(cluster): rm registryWrapper --- dubbo/src/cluster/directory.rs | 11 +++-------- dubbo/src/codegen.rs | 2 +- dubbo/src/registry/mod.rs | 17 ----------------- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/dubbo/src/cluster/directory.rs b/dubbo/src/cluster/directory.rs index e8ce5644..afe9657b 100644 --- a/dubbo/src/cluster/directory.rs +++ b/dubbo/src/cluster/directory.rs @@ -26,7 +26,7 @@ use crate::{ codegen::TripleInvoker, invocation::{Invocation, RpcInvocation}, protocol::BoxInvoker, - registry::{memory_registry::MemoryNotifyListener, BoxRegistry, RegistryWrapper}, + registry::{memory_registry::MemoryNotifyListener, BoxRegistry}, }; use dubbo_base::Url; use dubbo_logger::tracing; @@ -75,16 +75,14 @@ impl Directory for StaticDirectory { #[derive(Debug, Clone)] pub struct RegistryDirectory { - registry: RegistryWrapper, + registry: Arc, service_instances: Arc>>>, } impl RegistryDirectory { pub fn new(registry: BoxRegistry) -> RegistryDirectory { RegistryDirectory { - registry: RegistryWrapper { - registry: Some(registry), - }, + registry: Arc::new(registry), service_instances: Arc::new(RwLock::new(HashMap::new())), } } @@ -101,9 +99,6 @@ impl Directory for RegistryDirectory { .unwrap(); self.registry - .registry - .as_ref() - .expect("msg") .subscribe( url, Arc::new(MemoryNotifyListener { diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 24b73fd3..412feb91 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -31,7 +31,7 @@ pub use super::{ empty_body, invocation::{IntoStreamingRequest, Request, Response, RpcInvocation}, protocol::{triple::triple_invoker::TripleInvoker, Invoker}, - registry::{BoxRegistry, Registry, RegistryWrapper}, + registry::{BoxRegistry, Registry}, triple::{ client::TripleClient, codec::{prost::ProstCodec, Codec}, diff --git a/dubbo/src/registry/mod.rs b/dubbo/src/registry/mod.rs index 31106f0f..2a95452a 100644 --- a/dubbo/src/registry/mod.rs +++ b/dubbo/src/registry/mod.rs @@ -60,20 +60,3 @@ impl Debug for BoxRegistry { f.write_str("BoxRegistry") } } - -#[derive(Default)] -pub struct RegistryWrapper { - pub registry: Option>, -} - -impl Clone for RegistryWrapper { - fn clone(&self) -> Self { - Self { registry: None } - } -} - -impl Debug for RegistryWrapper { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("RegistryWrapper").finish() - } -} From 157b6c4f4de1943233df9c1de8f0e4568e7e10da Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Fri, 19 May 2023 22:18:27 +0800 Subject: [PATCH 25/31] refactor(cluster): delete print --- dubbo/src/cluster/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index 3e6c4f30..1f949b77 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -78,7 +78,6 @@ impl Invoker> for FailoverCluster { } fn call(&mut self, req: http::Request) -> Self::Future { - println!("req: {}", req.body().content_length().unwrap()); let clone_body = req.body().try_clone().unwrap(); let mut clone_req = http::Request::builder() .uri(req.uri().clone()) From aa554fee8e0e609854d1a5fd3868254607a6f204 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Sun, 21 May 2023 00:29:48 +0800 Subject: [PATCH 26/31] chore(dubbo): upgrade hyper version in cargo.toml --- dubbo/Cargo.toml | 4 ++-- examples/echo/Cargo.toml | 4 +--- examples/greeter/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index 91b19d6f..d0ab2a4d 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/apache/dubbo-rust.git" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hyper = { version = "0.14.19", features = ["full"] } +hyper = { version = "0.14.26", features = ["full"] } http = "0.2" tower-service.workspace = true http-body = "0.4.4" @@ -33,7 +33,7 @@ futures.workspace = true axum = "0.5.9" async-stream = "0.3" flate2 = "1.0" -aws-smithy-http = "0.54.1" +aws-smithy-http = "0.55.2" dyn-clone = "1.0.11" itertools.workspace = true urlencoding.workspace = true diff --git a/examples/echo/Cargo.toml b/examples/echo/Cargo.toml index 319c17b3..bc6638b8 100644 --- a/examples/echo/Cargo.toml +++ b/examples/echo/Cargo.toml @@ -30,9 +30,7 @@ async-trait = "0.1.56" tokio-stream = "0.1" dubbo-logger.workspace=true -hyper = { version = "0.14.19", features = ["full"]} - -dubbo = {path = "../../dubbo", version = "0.3.0" } +dubbo = {path = "../../dubbo"} dubbo-config = {path = "../../config", version = "0.3.0" } registry-zookeeper.workspace=true diff --git a/examples/greeter/Cargo.toml b/examples/greeter/Cargo.toml index 6ad3b1b5..d68cab7b 100644 --- a/examples/greeter/Cargo.toml +++ b/examples/greeter/Cargo.toml @@ -29,7 +29,7 @@ prost = "0.10.4" async-trait = "0.1.56" tokio-stream = "0.1" dubbo-logger = { path = "../../common/logger" } -dubbo = { path = "../../dubbo", version = "0.3.0" } +dubbo = { path = "../../dubbo"} dubbo-config = { path = "../../config", version = "0.3.0" } registry-zookeeper.workspace = true registry-nacos.workspace = true From 254fe5917f6ce460171411e1fb0f8b89745ce1ae Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Mon, 22 May 2023 22:17:49 +0800 Subject: [PATCH 27/31] refactor(cluster): comment the logic of clone body --- dubbo/src/cluster/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index 1f949b77..d1f96f95 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -78,12 +78,12 @@ impl Invoker> for FailoverCluster { } fn call(&mut self, req: http::Request) -> Self::Future { - let clone_body = req.body().try_clone().unwrap(); - let mut clone_req = http::Request::builder() - .uri(req.uri().clone()) - .method(req.method().clone()); - *clone_req.headers_mut().unwrap() = req.headers().clone(); - let r = clone_req.body(clone_body).unwrap(); + // let clone_body = req.body().try_clone().unwrap(); + // let mut clone_req = http::Request::builder() + // .uri(req.uri().clone()) + // .method(req.method().clone()); + // *clone_req.headers_mut().unwrap() = req.headers().clone(); + // let r = clone_req.body(clone_body).unwrap(); let invokers = self.dir.list( RpcInvocation::default() .with_service_unique_name("hello".to_string()) @@ -91,7 +91,7 @@ impl Invoker> for FailoverCluster { ); for mut invoker in invokers { let fut = async move { - let res = invoker.call(r).await; + let res = invoker.call(req).await; return res; }; return Box::pin(fut); From efb87b465f5d466ee8f347c389f7dfba6635f081 Mon Sep 17 00:00:00 2001 From: Yang Yang <962032265@qq.com> Date: Mon, 22 May 2023 23:23:01 +0800 Subject: [PATCH 28/31] Rft: add Cluster to ClientBuilder (#142) comment some codes * refactor(triple): rm unused var in clientBuilder * refactor(dubbo): delete some codes * refactor(cluster): rm some duplicate codes * refactor(registry): rm unused import * refactor(triple): use two build func for different usage * style: cargo fmt --all * refactor(cluster): rm registryWrapper * refactor(cluster): delete print * chore(dubbo): upgrade hyper version in cargo.toml * refactor(cluster): comment the logic of clone body --- dubbo-build/src/client.rs | 5 - dubbo/Cargo.toml | 4 +- dubbo/src/cluster/directory.rs | 69 +++------ dubbo/src/cluster/mod.rs | 31 ++-- dubbo/src/cluster/support/cluster_invoker.rs | 147 ------------------- dubbo/src/cluster/support/mod.rs | 20 --- dubbo/src/codegen.rs | 7 +- dubbo/src/registry/integration.rs | 7 - dubbo/src/registry/mod.rs | 17 --- dubbo/src/triple/client/builder.rs | 41 +++--- dubbo/src/triple/client/triple.rs | 135 ++++++++--------- examples/echo/Cargo.toml | 4 +- examples/echo/src/echo/client.rs | 4 +- examples/greeter/Cargo.toml | 2 +- registry/zookeeper/src/lib.rs | 12 +- 15 files changed, 128 insertions(+), 377 deletions(-) delete mode 100644 dubbo/src/cluster/support/cluster_invoker.rs delete mode 100644 dubbo/src/cluster/support/mod.rs diff --git a/dubbo-build/src/client.rs b/dubbo-build/src/client.rs index 1e1c9fbd..bfcfe45b 100644 --- a/dubbo-build/src/client.rs +++ b/dubbo-build/src/client.rs @@ -90,11 +90,6 @@ pub fn generate( } } - pub fn with_cluster(mut self, invoker: ClusterInvoker) -> Self { - self.inner = self.inner.with_cluster(invoker); - self - } - #methods } diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index 91b19d6f..d0ab2a4d 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/apache/dubbo-rust.git" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -hyper = { version = "0.14.19", features = ["full"] } +hyper = { version = "0.14.26", features = ["full"] } http = "0.2" tower-service.workspace = true http-body = "0.4.4" @@ -33,7 +33,7 @@ futures.workspace = true axum = "0.5.9" async-stream = "0.3" flate2 = "1.0" -aws-smithy-http = "0.54.1" +aws-smithy-http = "0.55.2" dyn-clone = "1.0.11" itertools.workspace = true urlencoding.workspace = true diff --git a/dubbo/src/cluster/directory.rs b/dubbo/src/cluster/directory.rs index e74fc6d4..afe9657b 100644 --- a/dubbo/src/cluster/directory.rs +++ b/dubbo/src/cluster/directory.rs @@ -23,39 +23,21 @@ use std::{ }; use crate::{ + codegen::TripleInvoker, invocation::{Invocation, RpcInvocation}, - registry::{memory_registry::MemoryNotifyListener, BoxRegistry, RegistryWrapper}, + protocol::BoxInvoker, + registry::{memory_registry::MemoryNotifyListener, BoxRegistry}, }; use dubbo_base::Url; use dubbo_logger::tracing; +use crate::cluster::Directory; + /// Directory. /// /// [Directory Service](http://en.wikipedia.org/wiki/Directory_service) -pub trait Directory: Debug + DirectoryClone { - fn list(&self, invocation: Arc) -> Vec; -} -pub trait DirectoryClone { - fn clone_box(&self) -> Box; -} - -impl DirectoryClone for T -where - T: 'static + Directory + Clone, -{ - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } -} - -impl Clone for Box { - fn clone(&self) -> Box { - self.clone_box() - } -} - -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct StaticDirectory { uri: http::Uri, } @@ -78,7 +60,7 @@ impl StaticDirectory { } impl Directory for StaticDirectory { - fn list(&self, invocation: Arc) -> Vec { + fn list(&self, invocation: Arc) -> Vec { let url = Url::from_url(&format!( "tri://{}:{}/{}", self.uri.host().unwrap(), @@ -86,43 +68,28 @@ impl Directory for StaticDirectory { invocation.get_target_service_unique_name(), )) .unwrap(); - vec![url] - } -} - -impl DirectoryClone for StaticDirectory { - fn clone_box(&self) -> Box { - Box::new(StaticDirectory { - uri: self.uri.clone(), - }) + let invoker = Box::new(TripleInvoker::new(url)); + vec![invoker] } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct RegistryDirectory { - registry: RegistryWrapper, + registry: Arc, service_instances: Arc>>>, } impl RegistryDirectory { pub fn new(registry: BoxRegistry) -> RegistryDirectory { RegistryDirectory { - registry: RegistryWrapper { - registry: Some(registry), - }, + registry: Arc::new(registry), service_instances: Arc::new(RwLock::new(HashMap::new())), } } } -impl DirectoryClone for RegistryDirectory { - fn clone_box(&self) -> Box { - todo!() - } -} - impl Directory for RegistryDirectory { - fn list(&self, invocation: Arc) -> Vec { + fn list(&self, invocation: Arc) -> Vec { let service_name = invocation.get_target_service_unique_name(); let url = Url::from_url(&format!( @@ -132,9 +99,6 @@ impl Directory for RegistryDirectory { .unwrap(); self.registry - .registry - .as_ref() - .expect("msg") .subscribe( url, Arc::new(MemoryNotifyListener { @@ -149,6 +113,11 @@ impl Directory for RegistryDirectory { .expect("service_instances.read"); let binding = Vec::new(); let url_vec = map.get(&service_name).unwrap_or(&binding); - url_vec.to_vec() + // url_vec.to_vec() + let mut invokers: Vec = vec![]; + for item in url_vec.iter() { + invokers.push(Box::new(TripleInvoker::new(item.clone()))); + } + invokers } } diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index 4f73d2f5..d1f96f95 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -19,6 +19,7 @@ use std::{collections::HashMap, fmt::Debug, sync::Arc, task::Poll}; use aws_smithy_http::body::SdkBody; use dubbo_base::Url; +use dyn_clone::DynClone; use crate::{ empty_body, @@ -28,13 +29,14 @@ use crate::{ pub mod directory; pub mod loadbalance; -pub mod support; -pub trait Directory: Debug { +pub trait Directory: Debug + DynClone { fn list(&self, invocation: Arc) -> Vec; - fn is_empty(&self) -> bool; + // fn is_empty(&self) -> bool; } +dyn_clone::clone_trait_object!(Directory); + type BoxDirectory = Box; pub trait Cluster { @@ -76,13 +78,12 @@ impl Invoker> for FailoverCluster { } fn call(&mut self, req: http::Request) -> Self::Future { - println!("req: {}", req.body().content_length().unwrap()); - let clone_body = req.body().try_clone().unwrap(); - let mut clone_req = http::Request::builder() - .uri(req.uri().clone()) - .method(req.method().clone()); - *clone_req.headers_mut().unwrap() = req.headers().clone(); - let r = clone_req.body(clone_body).unwrap(); + // let clone_body = req.body().try_clone().unwrap(); + // let mut clone_req = http::Request::builder() + // .uri(req.uri().clone()) + // .method(req.method().clone()); + // *clone_req.headers_mut().unwrap() = req.headers().clone(); + // let r = clone_req.body(clone_body).unwrap(); let invokers = self.dir.list( RpcInvocation::default() .with_service_unique_name("hello".to_string()) @@ -90,7 +91,7 @@ impl Invoker> for FailoverCluster { ); for mut invoker in invokers { let fut = async move { - let res = invoker.call(r).await; + let res = invoker.call(req).await; return res; }; return Box::pin(fut); @@ -110,7 +111,7 @@ impl Invoker> for FailoverCluster { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct MockDirectory { // router_chain: RouterChain, invokers: Vec, @@ -134,9 +135,9 @@ impl Directory for MockDirectory { self.invokers.clone() } - fn is_empty(&self) -> bool { - false - } + // fn is_empty(&self) -> bool { + // false + // } } #[derive(Debug, Default)] diff --git a/dubbo/src/cluster/support/cluster_invoker.rs b/dubbo/src/cluster/support/cluster_invoker.rs deleted file mode 100644 index 0ccca488..00000000 --- a/dubbo/src/cluster/support/cluster_invoker.rs +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 aws_smithy_http::body::SdkBody; -use std::{str::FromStr, sync::Arc}; - -use dubbo_base::Url; -use http::{uri::PathAndQuery, Request}; - -use crate::{ - cluster::{ - loadbalance::{types::BoxLoadBalance, LOAD_BALANCE_EXTENSIONS}, - support::DEFAULT_LOADBALANCE, - }, - codegen::{Directory, RegistryDirectory, TripleClient}, - invocation::RpcInvocation, -}; - -#[derive(Debug, Clone)] -pub struct ClusterInvoker { - directory: Arc, - destroyed: bool, -} - -pub trait ClusterInvokerSelector { - /// Select a invoker using loadbalance policy. - fn select( - &self, - invocation: Arc, - invokers: Arc>, - excluded: Arc>, - ) -> Option; - - fn do_select( - &self, - loadbalance_key: Option<&str>, - invocation: Arc, - invokers: Arc>, - ) -> Option; -} - -pub trait ClusterRequestBuilder { - fn build_req( - &self, - triple_client: &mut TripleClient, - path: http::uri::PathAndQuery, - invocation: Arc, - body: SdkBody, - ) -> http::Request; -} - -impl ClusterInvoker { - pub fn with_directory(registry_directory: RegistryDirectory) -> Self { - ClusterInvoker { - directory: Arc::new(registry_directory), - destroyed: false, - } - } - - pub fn directory(&self) -> Arc { - self.directory.clone() - } - - pub fn init_loadbalance(&self, loadbalance_key: &str) -> &BoxLoadBalance { - if LOAD_BALANCE_EXTENSIONS.contains_key(loadbalance_key) { - LOAD_BALANCE_EXTENSIONS.get(loadbalance_key).unwrap() - } else { - println!( - "loadbalance {} not found, use default loadbalance {}", - loadbalance_key, DEFAULT_LOADBALANCE - ); - LOAD_BALANCE_EXTENSIONS.get(DEFAULT_LOADBALANCE).unwrap() - } - } - - pub fn is_available(&self, invocation: Arc) -> bool { - !self.destroyed() && !self.directory.list(invocation).is_empty() - } - - pub fn destroyed(&self) -> bool { - self.destroyed - } -} - -impl ClusterInvokerSelector for ClusterInvoker { - fn select( - &self, - invocation: Arc, - invokers: Arc>, - _excluded: Arc>, - ) -> Option { - if invokers.is_empty() { - return None; - } - let instance_count = invokers.len(); - return if instance_count == 1 { - Some(invokers.as_ref().first()?.clone()) - } else { - let loadbalance = Some(DEFAULT_LOADBALANCE); - self.do_select(loadbalance, invocation, invokers) - }; - } - - /// picking instance invoker url from registry directory - fn do_select( - &self, - loadbalance_key: Option<&str>, - invocation: Arc, - invokers: Arc>, - ) -> Option { - let loadbalance = self.init_loadbalance(loadbalance_key.unwrap_or(DEFAULT_LOADBALANCE)); - loadbalance.select(invokers, None, invocation) - } -} - -impl ClusterRequestBuilder for ClusterInvoker { - fn build_req( - &self, - triple_client: &mut TripleClient, - path: PathAndQuery, - invocation: Arc, - body: SdkBody, - ) -> Request { - let invokers = self.directory.list(invocation.clone()); - let invoker_url = self - .select(invocation, Arc::new(invokers), Arc::new(Vec::new())) - .expect("no valid provider"); - let http_uri = - http::Uri::from_str(&format!("http://{}:{}/", invoker_url.ip, invoker_url.port)) - .unwrap(); - triple_client.map_request(http_uri, path, body) - } -} diff --git a/dubbo/src/cluster/support/mod.rs b/dubbo/src/cluster/support/mod.rs deleted file mode 100644 index ae42cc28..00000000 --- a/dubbo/src/cluster/support/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -pub mod cluster_invoker; - -pub const DEFAULT_LOADBALANCE: &str = "random"; diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 98d784fc..412feb91 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -27,14 +27,11 @@ pub use hyper::Body as hyperBody; pub use tower_service::Service; pub use super::{ - cluster::{ - directory::{Directory, RegistryDirectory}, - support::cluster_invoker::ClusterInvoker, - }, + cluster::directory::RegistryDirectory, empty_body, invocation::{IntoStreamingRequest, Request, Response, RpcInvocation}, protocol::{triple::triple_invoker::TripleInvoker, Invoker}, - registry::{BoxRegistry, Registry, RegistryWrapper}, + registry::{BoxRegistry, Registry}, triple::{ client::TripleClient, codec::{prost::ProstCodec, Codec}, diff --git a/dubbo/src/registry/integration.rs b/dubbo/src/registry/integration.rs index 15b82d01..2944f981 100644 --- a/dubbo/src/registry/integration.rs +++ b/dubbo/src/registry/integration.rs @@ -14,10 +14,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -use crate::{cluster::support::cluster_invoker::ClusterInvoker, registry::BoxRegistry}; -use std::sync::Arc; - -pub trait ClusterRegistryIntegration { - /// get cluster invoker struct - fn get_invoker(registry: BoxRegistry) -> Option>; -} diff --git a/dubbo/src/registry/mod.rs b/dubbo/src/registry/mod.rs index 31106f0f..2a95452a 100644 --- a/dubbo/src/registry/mod.rs +++ b/dubbo/src/registry/mod.rs @@ -60,20 +60,3 @@ impl Debug for BoxRegistry { f.write_str("BoxRegistry") } } - -#[derive(Default)] -pub struct RegistryWrapper { - pub registry: Option>, -} - -impl Clone for RegistryWrapper { - fn clone(&self) -> Self { - Self { registry: None } - } -} - -impl Debug for RegistryWrapper { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("RegistryWrapper").finish() - } -} diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 29957a6f..06ecd627 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -15,9 +15,12 @@ * limitations under the License. */ +use std::sync::Arc; + use crate::{ - cluster::{directory::StaticDirectory, Cluster, MockCluster, MockDirectory}, - codegen::{ClusterInvoker, Directory, RegistryDirectory, TripleInvoker}, + cluster::{directory::StaticDirectory, Cluster, Directory, MockCluster, MockDirectory}, + codegen::{RegistryDirectory, RpcInvocation, TripleInvoker}, + protocol::BoxInvoker, triple::compression::CompressionEncoding, utils::boxed_clone::BoxCloneService, }; @@ -35,7 +38,6 @@ pub struct ClientBuilder { pub timeout: Option, pub connector: &'static str, directory: Option>, - cluster_invoker: Option, pub direct: bool, host: String, } @@ -46,7 +48,6 @@ impl ClientBuilder { timeout: None, connector: "", directory: None, - cluster_invoker: None, direct: false, host: "".to_string(), } @@ -57,7 +58,6 @@ impl ClientBuilder { timeout: None, connector: "", directory: Some(Box::new(StaticDirectory::new(&host))), - cluster_invoker: None, direct: true, host: host.clone().to_string(), } @@ -74,15 +74,13 @@ impl ClientBuilder { pub fn with_directory(self, directory: Box) -> Self { Self { directory: Some(directory), - cluster_invoker: None, ..self } } pub fn with_registry_directory(self, registry: RegistryDirectory) -> Self { Self { - directory: None, - cluster_invoker: Some(ClusterInvoker::with_directory(registry)), + directory: Some(Box::new(registry)), ..self } } @@ -97,7 +95,6 @@ impl ClientBuilder { pub fn with_connector(self, connector: &'static str) -> Self { Self { connector: connector, - cluster_invoker: None, ..self } } @@ -106,25 +103,31 @@ impl ClientBuilder { Self { direct, ..self } } - pub fn build(self) -> TripleClient { + pub(crate) fn direct_build(self) -> TripleClient { let mut cli = TripleClient { send_compression_encoding: Some(CompressionEncoding::Gzip), - directory: self.directory, - cluster_invoker: self.cluster_invoker, + builder: Some(self.clone()), invoker: None, }; + cli.invoker = Some(Box::new(TripleInvoker::new( + Url::from_url(&self.host).unwrap(), + ))); + return cli; + } + + pub fn build(self, invocation: Arc) -> Option { if self.direct { - cli.invoker = Some(Box::new(TripleInvoker::new( + return Some(Box::new(TripleInvoker::new( Url::from_url(&self.host).unwrap(), ))); - return cli; } + let invokers = match self.directory { + Some(v) => v.list(invocation), + None => panic!("use direct connection"), + }; - let cluster = MockCluster::default().join(Box::new(MockDirectory::new(vec![Box::new( - TripleInvoker::new(Url::from_url("http://127.0.0.1:8888").unwrap()), - )]))); + let cluster = MockCluster::default().join(Box::new(MockDirectory::new(invokers))); - cli.invoker = Some(cluster); - cli + return Some(cluster); } } diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index eb7934dd..124cfcfd 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -15,20 +15,17 @@ * limitations under the License. */ -use std::{str::FromStr, sync::Arc}; +use std::str::FromStr; use futures_util::{future, stream, StreamExt, TryStreamExt}; use aws_smithy_http::body::SdkBody; use http::HeaderValue; -use rand::prelude::SliceRandom; -use tower_service::Service; -use super::{super::transport::connection::Connection, builder::ClientBuilder}; -use crate::codegen::{ClusterInvoker, Directory, RpcInvocation}; +use super::builder::ClientBuilder; +use crate::codegen::RpcInvocation; use crate::{ - cluster::support::cluster_invoker::ClusterRequestBuilder, invocation::{IntoStreamingRequest, Metadata, Request, Response}, protocol::BoxInvoker, triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding, encode::encode}, @@ -37,8 +34,7 @@ use crate::{ #[derive(Debug, Clone, Default)] pub struct TripleClient { pub(crate) send_compression_encoding: Option, - pub(crate) directory: Option>, - pub(crate) cluster_invoker: Option, + pub(crate) builder: Option, pub invoker: Option, } @@ -46,17 +42,14 @@ impl TripleClient { pub fn connect(host: String) -> Self { let builder = ClientBuilder::from_static(&host).with_direct(true); - builder.build() + builder.direct_build() } pub fn new(builder: ClientBuilder) -> Self { - builder.build() - } - - pub fn with_cluster(self, invoker: ClusterInvoker) -> Self { TripleClient { - cluster_invoker: Some(invoker), - ..self + send_compression_encoding: Some(CompressionEncoding::Gzip), + builder: Some(builder), + invoker: None, } } @@ -137,7 +130,7 @@ impl TripleClient { req: Request, mut codec: C, path: http::uri::PathAndQuery, - _invocation: RpcInvocation, + invocation: RpcInvocation, ) -> Result, crate::status::Status> where C: Codec, @@ -155,8 +148,16 @@ impl TripleClient { let bytes = hyper::body::to_bytes(body).await.unwrap(); let sdk_body = SdkBody::from(bytes); - // let mut conn = Connection::new().with_host(http_uri); - let mut conn = self.invoker.clone().unwrap(); + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); @@ -214,25 +215,20 @@ impl TripleClient { .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } - let mut conn = Connection::new().with_host(http_uri); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); + let response = conn .call(req) .await @@ -271,25 +267,21 @@ impl TripleClient { .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } - let mut conn = Connection::new().with_host(http_uri); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); + + // let mut conn = Connection::new().with_host(http_uri); let response = conn .call(req) .await @@ -344,26 +336,19 @@ impl TripleClient { .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let arc_invocation = Arc::new(invocation); - let req; - let http_uri; - if self.cluster_invoker.is_some() { - let cluster_invoker = self.cluster_invoker.as_ref().unwrap().clone(); - req = cluster_invoker.build_req(self, path, arc_invocation.clone(), sdk_body); - http_uri = req.uri().clone(); - } else { - let url_list = self - .directory - .as_ref() - .expect("msg") - .list(arc_invocation.clone()); - let real_url = url_list.choose(&mut rand::thread_rng()).expect("msg"); - http_uri = - http::Uri::from_str(&format!("http://{}:{}/", real_url.ip, real_url.port)).unwrap(); - req = self.map_request(http_uri.clone(), path, sdk_body); - } - let mut conn = Connection::new().with_host(http_uri); + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body); + let response = conn .call(req) .await diff --git a/examples/echo/Cargo.toml b/examples/echo/Cargo.toml index 319c17b3..bc6638b8 100644 --- a/examples/echo/Cargo.toml +++ b/examples/echo/Cargo.toml @@ -30,9 +30,7 @@ async-trait = "0.1.56" tokio-stream = "0.1" dubbo-logger.workspace=true -hyper = { version = "0.14.19", features = ["full"]} - -dubbo = {path = "../../dubbo", version = "0.3.0" } +dubbo = {path = "../../dubbo"} dubbo-config = {path = "../../config", version = "0.3.0" } registry-zookeeper.workspace=true diff --git a/examples/echo/src/echo/client.rs b/examples/echo/src/echo/client.rs index db46958c..0a2f150b 100644 --- a/examples/echo/src/echo/client.rs +++ b/examples/echo/src/echo/client.rs @@ -34,7 +34,9 @@ async fn main() { // let builder = ClientBuilder::new() // .with_connector("unix") // .with_host("unix://127.0.0.1:8888"); - let builder = ClientBuilder::from_static(&"http://127.0.0.1:8888").with_timeout(1000000); + let builder = ClientBuilder::from_static(&"http://127.0.0.1:8888") + .with_timeout(1000000) + .with_direct(true); let mut cli = EchoClient::new(builder); // let mut unary_cli = cli.clone().with_filter(FakeFilter {}); // let mut cli = EchoClient::build(ClientBuilder::from_static("http://127.0.0.1:8888")); diff --git a/examples/greeter/Cargo.toml b/examples/greeter/Cargo.toml index 6ad3b1b5..d68cab7b 100644 --- a/examples/greeter/Cargo.toml +++ b/examples/greeter/Cargo.toml @@ -29,7 +29,7 @@ prost = "0.10.4" async-trait = "0.1.56" tokio-stream = "0.1" dubbo-logger = { path = "../../common/logger" } -dubbo = { path = "../../dubbo", version = "0.3.0" } +dubbo = { path = "../../dubbo"} dubbo-config = { path = "../../config", version = "0.3.0" } registry-zookeeper.workspace = true registry-nacos.workspace = true diff --git a/registry/zookeeper/src/lib.rs b/registry/zookeeper/src/lib.rs index 5debc0ab..e8c2c5ce 100644 --- a/registry/zookeeper/src/lib.rs +++ b/registry/zookeeper/src/lib.rs @@ -34,11 +34,9 @@ use serde::{Deserialize, Serialize}; use zookeeper::{Acl, CreateMode, WatchedEvent, WatchedEventType, Watcher, ZooKeeper}; use dubbo::{ - cluster::support::cluster_invoker::ClusterInvoker, - codegen::BoxRegistry, registry::{ - integration::ClusterRegistryIntegration, memory_registry::MemoryRegistry, NotifyListener, - Registry, RegistryNotifyListener, ServiceEvent, + memory_registry::MemoryRegistry, NotifyListener, Registry, RegistryNotifyListener, + ServiceEvent, }, StdError, }; @@ -371,12 +369,6 @@ impl NotifyListener for ServiceInstancesChangedListener { } } -impl ClusterRegistryIntegration for ZookeeperRegistry { - fn get_invoker(registry: BoxRegistry) -> Option> { - todo!() - } -} - #[cfg(test)] mod tests { use std::sync::Arc; From b24e7307f403bafec790a2d042bce49f8b348692 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Sat, 29 Jul 2023 14:40:52 +0800 Subject: [PATCH 29/31] Rft(triple): remove Clone of Invoker --- dubbo/src/protocol/mod.rs | 26 ++++++----- dubbo/src/triple/client/builder.rs | 33 +++----------- dubbo/src/triple/client/triple.rs | 71 +++++++++++++----------------- 3 files changed, 53 insertions(+), 77 deletions(-) diff --git a/dubbo/src/protocol/mod.rs b/dubbo/src/protocol/mod.rs index 145bcc8e..f4de85b5 100644 --- a/dubbo/src/protocol/mod.rs +++ b/dubbo/src/protocol/mod.rs @@ -23,7 +23,6 @@ use std::{ use async_trait::async_trait; use aws_smithy_http::body::SdkBody; -use dyn_clone::DynClone; use tower_service::Service; use dubbo_base::Url; @@ -44,7 +43,7 @@ pub trait Exporter { fn unexport(&self); } -pub trait Invoker: Debug + DynClone { +pub trait Invoker: Debug { type Response; type Error; @@ -69,14 +68,21 @@ pub type BoxInvoker = Box< + Sync, >; -dyn_clone::clone_trait_object!( - Invoker< - http::Request, - Response = http::Response, - Error = crate::Error, - Future = crate::BoxFuture, crate::Error>, - > -); +impl Service> for BoxInvoker { + type Response = http::Response; + + type Error = crate::Error; + + type Future = crate::BoxFuture, crate::Error>; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.poll_ready(cx) + } + + fn call(&mut self, req: http::Request) -> Self::Future { + self.call(req) + } +} pub struct WrapperInvoker(T); diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 06ecd627..d68067a8 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -21,15 +21,12 @@ use crate::{ cluster::{directory::StaticDirectory, Cluster, Directory, MockCluster, MockDirectory}, codegen::{RegistryDirectory, RpcInvocation, TripleInvoker}, protocol::BoxInvoker, - triple::compression::CompressionEncoding, utils::boxed_clone::BoxCloneService, }; use aws_smithy_http::body::SdkBody; use dubbo_base::Url; -use super::TripleClient; - pub type ClientBoxService = BoxCloneService, http::Response, crate::Error>; @@ -37,7 +34,7 @@ pub type ClientBoxService = pub struct ClientBuilder { pub timeout: Option, pub connector: &'static str, - directory: Option>, + directory: Option>>, pub direct: bool, host: String, } @@ -57,7 +54,7 @@ impl ClientBuilder { Self { timeout: None, connector: "", - directory: Some(Box::new(StaticDirectory::new(&host))), + directory: Some(Arc::new(Box::new(StaticDirectory::new(&host)))), direct: true, host: host.clone().to_string(), } @@ -73,21 +70,21 @@ impl ClientBuilder { /// host: http://0.0.0.0:8888 pub fn with_directory(self, directory: Box) -> Self { Self { - directory: Some(directory), + directory: Some(Arc::new(directory)), ..self } } pub fn with_registry_directory(self, registry: RegistryDirectory) -> Self { Self { - directory: Some(Box::new(registry)), + directory: Some(Arc::new(Box::new(registry))), ..self } } pub fn with_host(self, host: &'static str) -> Self { Self { - directory: Some(Box::new(StaticDirectory::new(&host))), + directory: Some(Arc::new(Box::new(StaticDirectory::new(&host)))), ..self } } @@ -103,30 +100,14 @@ impl ClientBuilder { Self { direct, ..self } } - pub(crate) fn direct_build(self) -> TripleClient { - let mut cli = TripleClient { - send_compression_encoding: Some(CompressionEncoding::Gzip), - builder: Some(self.clone()), - invoker: None, - }; - cli.invoker = Some(Box::new(TripleInvoker::new( - Url::from_url(&self.host).unwrap(), - ))); - return cli; - } - - pub fn build(self, invocation: Arc) -> Option { + pub fn build(self, _invocation: Arc) -> Option { if self.direct { return Some(Box::new(TripleInvoker::new( Url::from_url(&self.host).unwrap(), ))); } - let invokers = match self.directory { - Some(v) => v.list(invocation), - None => panic!("use direct connection"), - }; - let cluster = MockCluster::default().join(Box::new(MockDirectory::new(invokers))); + let cluster = MockCluster::default().join(Box::new(MockDirectory::new())); return Some(cluster); } diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 124cfcfd..b81661cd 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -27,29 +27,29 @@ use crate::codegen::RpcInvocation; use crate::{ invocation::{IntoStreamingRequest, Metadata, Request, Response}, - protocol::BoxInvoker, triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding, encode::encode}, }; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Default, Clone)] pub struct TripleClient { pub(crate) send_compression_encoding: Option, pub(crate) builder: Option, - pub invoker: Option, } impl TripleClient { pub fn connect(host: String) -> Self { let builder = ClientBuilder::from_static(&host).with_direct(true); - builder.direct_build() + TripleClient { + send_compression_encoding: Some(CompressionEncoding::Gzip), + builder: Some(builder), + } } pub fn new(builder: ClientBuilder) -> Self { TripleClient { send_compression_encoding: Some(CompressionEncoding::Gzip), builder: Some(builder), - invoker: None, } } @@ -148,15 +148,12 @@ impl TripleClient { let bytes = hyper::body::to_bytes(body).await.unwrap(); let sdk_body = SdkBody::from(bytes); - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; + let mut conn = self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(); let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); @@ -216,15 +213,12 @@ impl TripleClient { let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; + let mut conn = self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(); let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); @@ -268,15 +262,12 @@ impl TripleClient { let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; + let mut conn = self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(); let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); @@ -337,15 +328,13 @@ impl TripleClient { let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; + let mut conn = self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(); + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); let req = self.map_request(http_uri.clone(), path, sdk_body); From 6999bbb272ae49dce136b96bf1911c2145a9aa41 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Sat, 29 Jul 2023 14:46:06 +0800 Subject: [PATCH 30/31] Rft(cluster): use ready_cache to manage Invokers, add ready_cache in FailoverCluster --- dubbo/Cargo.toml | 2 +- dubbo/src/cluster/mod.rs | 134 ++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 73 deletions(-) diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index d0ab2a4d..51ccc193 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -14,7 +14,7 @@ hyper = { version = "0.14.26", features = ["full"] } http = "0.2" tower-service.workspace = true http-body = "0.4.4" -tower = { workspace = true, features = ["timeout"] } +tower = { workspace = true, features = ["timeout", "ready-cache"] } futures-util = "0.3.23" futures-core ="0.3.23" argh = "0.1" diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index d1f96f95..a60ab90f 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -15,28 +15,25 @@ * limitations under the License. */ -use std::{collections::HashMap, fmt::Debug, sync::Arc, task::Poll}; +use std::{fmt::Debug, sync::Arc, task::Poll}; use aws_smithy_http::body::SdkBody; use dubbo_base::Url; -use dyn_clone::DynClone; +use futures_util::TryFutureExt; +use tower::ready_cache::ReadyCache; use crate::{ - empty_body, invocation::RpcInvocation, - protocol::{BoxInvoker, Invoker}, + protocol::{triple::triple_invoker::TripleInvoker, BoxInvoker, Invoker}, }; pub mod directory; pub mod loadbalance; -pub trait Directory: Debug + DynClone { +pub trait Directory: Debug { fn list(&self, invocation: Arc) -> Vec; - // fn is_empty(&self) -> bool; } -dyn_clone::clone_trait_object!(Directory); - type BoxDirectory = Box; pub trait Cluster { @@ -51,14 +48,20 @@ impl Cluster for MockCluster { Box::new(FailoverCluster::new(dir)) } } -#[derive(Clone, Debug)] + +// 在Cluster上进行缓存Service +#[derive(Debug)] pub struct FailoverCluster { dir: Arc, + caches: ReadyCache>, } impl FailoverCluster { pub fn new(dir: BoxDirectory) -> FailoverCluster { - Self { dir: Arc::new(dir) } + Self { + dir: Arc::new(dir), + caches: ReadyCache::default(), + } } } @@ -89,21 +92,29 @@ impl Invoker> for FailoverCluster { .with_service_unique_name("hello".to_string()) .into(), ); - for mut invoker in invokers { - let fut = async move { - let res = invoker.call(req).await; - return res; - }; - return Box::pin(fut); + let mut i: usize = 0; + for invoker in invokers { + self.caches.push(i, invoker); + i += 1; } - Box::pin(async move { - Ok(http::Response::builder() - .status(200) - .header("grpc-status", "12") - .header("content-type", "application/grpc") - .body(empty_body()) - .unwrap()) - }) + + Box::pin(self.caches.call_ready_index(0, req).map_err(Into::into)) + + // let fut = async move { + // let (_, invoker) = self.caches.get_ready_index_mut(i).unwrap(); + // let res = invoker.call(req).await; + // return res; + // }; + // return Box::pin(fut); + + // Box::pin(async move { + // Ok(http::Response::builder() + // .status(200) + // .header("grpc-status", "12") + // .header("content-type", "application/grpc") + // .body(empty_body()) + // .unwrap()) + // }) } fn get_url(&self) -> dubbo_base::Url { @@ -111,17 +122,15 @@ impl Invoker> for FailoverCluster { } } -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default)] pub struct MockDirectory { // router_chain: RouterChain, - invokers: Vec, } impl MockDirectory { - pub fn new(invokers: Vec) -> MockDirectory { + pub fn new() -> MockDirectory { Self { // router_chain: RouterChain::default(), - invokers, } } } @@ -129,51 +138,32 @@ impl MockDirectory { impl Directory for MockDirectory { fn list(&self, _invo: Arc) -> Vec { // tracing::info!("MockDirectory: {}", meta); - let _u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); - // vec![Box::new(TripleInvoker::new(u))] + let u = Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap(); + vec![Box::new(TripleInvoker::new(u))] // self.router_chain.route(u, invo); - self.invokers.clone() } - - // fn is_empty(&self) -> bool { - // false - // } -} - -#[derive(Debug, Default)] -pub struct RouterChain { - router: HashMap, - invokers: Vec, } -impl RouterChain { - pub fn route(&self, url: Url, invo: Arc) -> Vec { - let r = self.router.get("mock").unwrap(); - r.route(self.invokers.clone(), url, invo) - } -} - -pub trait Router: Debug { - fn route( - &self, - invokers: Vec, - url: Url, - invo: Arc, - ) -> Vec; -} - -pub type BoxRouter = Box; - -#[derive(Debug, Default)] -pub struct MockRouter {} - -impl Router for MockRouter { - fn route( - &self, - invokers: Vec, - _url: Url, - _invo: Arc, - ) -> Vec { - invokers - } -} +// #[derive(Debug, Default)] +// pub struct RouterChain { +// router: HashMap, +// invokers: Arc>, +// } + +// impl RouterChain { +// pub fn route(&mut self, url: Url, invo: Arc) -> Arc> { +// let r = self.router.get("mock").unwrap(); +// r.route(self.invokers.clone(), url, invo) +// } +// } + +// pub trait Router: Debug { +// fn route( +// &self, +// invokers: Arc>, +// url: Url, +// invo: Arc, +// ) -> Arc>; +// } + +// pub type BoxRouter = Box; From 0a5ee224d014ee94de61e1faf5a298b1667d6379 Mon Sep 17 00:00:00 2001 From: yangyang <962032265@qq.com> Date: Sat, 29 Jul 2023 19:00:37 +0800 Subject: [PATCH 31/31] Rft(protocol): use interface Inheritance to redesign Invoker --- dubbo/src/cluster/mod.rs | 21 +++------------ dubbo/src/protocol/mod.rs | 29 +-------------------- dubbo/src/protocol/triple/triple_invoker.rs | 12 +++++---- 3 files changed, 12 insertions(+), 50 deletions(-) diff --git a/dubbo/src/cluster/mod.rs b/dubbo/src/cluster/mod.rs index a60ab90f..afc3cc91 100644 --- a/dubbo/src/cluster/mod.rs +++ b/dubbo/src/cluster/mod.rs @@ -21,6 +21,7 @@ use aws_smithy_http::body::SdkBody; use dubbo_base::Url; use futures_util::TryFutureExt; use tower::ready_cache::ReadyCache; +use tower_service::Service; use crate::{ invocation::RpcInvocation, @@ -65,7 +66,7 @@ impl FailoverCluster { } } -impl Invoker> for FailoverCluster { +impl Service> for FailoverCluster { type Response = http::Response; type Error = crate::Error; @@ -99,24 +100,10 @@ impl Invoker> for FailoverCluster { } Box::pin(self.caches.call_ready_index(0, req).map_err(Into::into)) - - // let fut = async move { - // let (_, invoker) = self.caches.get_ready_index_mut(i).unwrap(); - // let res = invoker.call(req).await; - // return res; - // }; - // return Box::pin(fut); - - // Box::pin(async move { - // Ok(http::Response::builder() - // .status(200) - // .header("grpc-status", "12") - // .header("content-type", "application/grpc") - // .body(empty_body()) - // .unwrap()) - // }) } +} +impl Invoker> for FailoverCluster { fn get_url(&self) -> dubbo_base::Url { Url::from_url("triple://127.0.0.1:8888/helloworld.Greeter").unwrap() } diff --git a/dubbo/src/protocol/mod.rs b/dubbo/src/protocol/mod.rs index f4de85b5..4dceb45e 100644 --- a/dubbo/src/protocol/mod.rs +++ b/dubbo/src/protocol/mod.rs @@ -17,7 +17,6 @@ use std::{ fmt::Debug, - future::Future, task::{Context, Poll}, }; @@ -43,18 +42,8 @@ pub trait Exporter { fn unexport(&self); } -pub trait Invoker: Debug { - type Response; - - type Error; - - type Future: Future>; - +pub trait Invoker: Debug + Service { fn get_url(&self) -> Url; - - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll>; - - fn call(&mut self, req: ReqBody) -> Self::Future; } pub type BoxExporter = Box; @@ -68,22 +57,6 @@ pub type BoxInvoker = Box< + Sync, >; -impl Service> for BoxInvoker { - type Response = http::Response; - - type Error = crate::Error; - - type Future = crate::BoxFuture, crate::Error>; - - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.poll_ready(cx) - } - - fn call(&mut self, req: http::Request) -> Self::Future { - self.call(req) - } -} - pub struct WrapperInvoker(T); impl Service> for WrapperInvoker diff --git a/dubbo/src/protocol/triple/triple_invoker.rs b/dubbo/src/protocol/triple/triple_invoker.rs index fb661f9e..db18f5f1 100644 --- a/dubbo/src/protocol/triple/triple_invoker.rs +++ b/dubbo/src/protocol/triple/triple_invoker.rs @@ -51,17 +51,13 @@ impl Debug for TripleInvoker { } } -impl Invoker> for TripleInvoker { +impl Service> for TripleInvoker { type Response = http::Response; type Error = crate::Error; type Future = crate::BoxFuture; - fn get_url(&self) -> Url { - self.url.clone() - } - fn call(&mut self, req: http::Request) -> Self::Future { self.conn.call(req) } @@ -73,3 +69,9 @@ impl Invoker> for TripleInvoker { self.conn.poll_ready(cx) } } + +impl Invoker> for TripleInvoker { + fn get_url(&self) -> Url { + self.url.clone() + } +}