You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2022/07/06 09:40:33 UTC

[dubbo-rust] 21/28: feat(dubbo): define the API of protocol module, provide simple impl of tonic(grpc)

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-rust.git

commit e03e4cd915ba76d2b977a0b3f952ce6843e510b4
Author: yang <96...@qq.com>
AuthorDate: Sun Jun 26 22:51:01 2022 +0800

    feat(dubbo): define the API of protocol module, provide simple impl of tonic(grpc)
---
 Cargo.toml                              |   2 +-
 dubbo/Cargo.lock                        | 929 ++++++++++++++++++++++++++++++++
 dubbo/Cargo.toml                        |  28 +
 dubbo/readme.md                         |   1 +
 dubbo/src/common/mod.rs                 |   1 +
 dubbo/src/common/url.rs                 |   5 +
 dubbo/src/helloworld/client.rs          |  23 +
 dubbo/src/helloworld/helloworld.rs      | 272 ++++++++++
 dubbo/src/helloworld/mod.rs             |   1 +
 dubbo/src/helloworld/server.rs          |   0
 dubbo/src/lib.rs                        |   6 +
 dubbo/src/main.rs                       |  10 +
 dubbo/src/service/grpc/grpc_exporter.rs |  34 ++
 dubbo/src/service/grpc/grpc_invoker.rs  |  73 +++
 dubbo/src/service/grpc/grpc_protocol.rs |  60 +++
 dubbo/src/service/grpc/grpc_server.rs   | 116 ++++
 dubbo/src/service/grpc/mod.rs           |  59 ++
 dubbo/src/service/invocation.rs         |  45 ++
 dubbo/src/service/mod.rs                |   4 +
 dubbo/src/service/protocol.rs           |  31 ++
 dubbo/src/utils/boxed.rs                |  74 +++
 dubbo/src/utils/boxed_clone.rs          |  88 +++
 dubbo/src/utils/mod.rs                  |   2 +
 protocol/Cargo.toml                     |   8 -
 protocol/src/lib.rs                     |  25 -
 25 files changed, 1863 insertions(+), 34 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 3720b7d..8c2e58e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,9 +1,9 @@
 [workspace]
 members = [
   "xds",
-  "protocol",
   "registry",
   "metadata",
   "common",
   "config",
+  "dubbo"
 ]
\ No newline at end of file
diff --git a/dubbo/Cargo.lock b/dubbo/Cargo.lock
new file mode 100644
index 0000000..a69c71b
--- /dev/null
+++ b/dubbo/Cargo.lock
@@ -0,0 +1,929 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "anyhow"
+version = "1.0.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
+
+[[package]]
+name = "async-stream"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "axum"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc47084705629d09d15060d70a8dbfce479c842303d05929ce29c74c995916ae"
+dependencies = [
+ "async-trait",
+ "axum-core",
+ "bitflags",
+ "bytes 1.1.0",
+ "futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde",
+ "sync_wrapper",
+ "tokio",
+ "tower",
+ "tower-http",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2efed1c501becea07ce48118786ebcf229531d0d3b28edf224a720020d9e106"
+dependencies = [
+ "async-trait",
+ "bytes 1.1.0",
+ "futures-util",
+ "http",
+ "http-body",
+ "mime",
+]
+
+[[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bytes"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+
+[[package]]
+name = "bytes"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "dubbo"
+version = "0.1.0"
+dependencies = [
+ "async-trait",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "lazy_static",
+ "prost 0.10.4",
+ "prost-derive 0.10.1",
+ "prost-types",
+ "tokio",
+ "tonic",
+ "tower",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "flate2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "futures-channel"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
+
+[[package]]
+name = "futures-task"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
+
+[[package]]
+name = "futures-util"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57"
+dependencies = [
+ "bytes 1.1.0",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "http"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
+dependencies = [
+ "bytes 1.1.0",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes 1.1.0",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-range-header"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
+
+[[package]]
+name = "httparse"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
+
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "hyper"
+version = "0.14.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f"
+dependencies = [
+ "bytes 1.1.0",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "itertools"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.126"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "matchit"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "mime"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "pin-project"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "prost"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212"
+dependencies = [
+ "bytes 0.5.6",
+ "prost-derive 0.6.1",
+]
+
+[[package]]
+name = "prost"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e"
+dependencies = [
+ "bytes 1.1.0",
+ "prost-derive 0.10.1",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72"
+dependencies = [
+ "anyhow",
+ "itertools 0.8.2",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc"
+dependencies = [
+ "anyhow",
+ "itertools 0.10.3",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa"
+dependencies = [
+ "bytes 0.5.6",
+ "prost 0.6.1",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.137"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
+
+[[package]]
+name = "socket2"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.96"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sync_wrapper"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
+
+[[package]]
+name = "tokio"
+version = "1.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
+dependencies = [
+ "bytes 1.1.0",
+ "libc",
+ "memchr",
+ "mio",
+ "num_cpus",
+ "once_cell",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "winapi",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
+dependencies = [
+ "bytes 1.1.0",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "tonic"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be9d60db39854b30b835107500cf0aca0b0d14d6e1c3de124217c23a29c2ddb"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "axum",
+ "base64",
+ "bytes 1.1.0",
+ "flate2",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost 0.10.4",
+ "prost-derive 0.10.1",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-http"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba"
+dependencies = [
+ "bitflags",
+ "bytes 1.1.0",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-range-header",
+ "pin-project-lite",
+ "tower",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
+
+[[package]]
+name = "tower-service"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
+
+[[package]]
+name = "tracing"
+version = "0.1.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
+dependencies = [
+ "cfg-if",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+dependencies = [
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml
new file mode 100644
index 0000000..7ce6865
--- /dev/null
+++ b/dubbo/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+name = "dubbo"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[[bin]]
+name = "helloworld-client"
+path = "src/helloworld/client.rs"
+
+[dependencies]
+h2 = {version = "0.3", optional = true}
+hyper = "0.14.19"
+http = "0.2"
+tonic = {version ="0.7.2", features = ["compression",]}
+tower-service = "0.3.1"
+http-body = "0.4.4"
+tower = "0.4.12"
+futures-util = {version = "0.3", default-features = false}
+tokio = { version = "1.0", features = [ "rt-multi-thread", "time", "fs", "macros", "net", "signal"] }
+prost-derive = {version = "0.10", optional = true}
+prost = "0.10.4"
+prost-types = { version = "0.6", default-features = false }
+lazy_static = "1.3.0"
+async-trait = "0.1.56"
+tower-layer = "0.3"
+
diff --git a/dubbo/readme.md b/dubbo/readme.md
new file mode 100644
index 0000000..0adef95
--- /dev/null
+++ b/dubbo/readme.md
@@ -0,0 +1 @@
+# Introduce
\ No newline at end of file
diff --git a/dubbo/src/common/mod.rs b/dubbo/src/common/mod.rs
new file mode 100644
index 0000000..aff8e30
--- /dev/null
+++ b/dubbo/src/common/mod.rs
@@ -0,0 +1 @@
+pub mod url;
\ No newline at end of file
diff --git a/dubbo/src/common/url.rs b/dubbo/src/common/url.rs
new file mode 100644
index 0000000..879a1a0
--- /dev/null
+++ b/dubbo/src/common/url.rs
@@ -0,0 +1,5 @@
+#[derive(Debug, Clone)]
+pub struct Url {
+    pub url: String,
+    pub service_key: String
+}
\ No newline at end of file
diff --git a/dubbo/src/helloworld/client.rs b/dubbo/src/helloworld/client.rs
new file mode 100644
index 0000000..f4517b4
--- /dev/null
+++ b/dubbo/src/helloworld/client.rs
@@ -0,0 +1,23 @@
+use dubbo::helloworld::helloworld::greeter_client::GreeterClient;
+use dubbo::helloworld::helloworld::HelloRequest;
+
+// pub mod hello_world {
+//     tonic::include_proto!("helloworld");
+// }
+
+// cargo run --bin helloworld-client
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+    let mut client = GreeterClient::connect("http://[::1]:50051").await?;
+
+    let request = tonic::Request::new(HelloRequest {
+        name: "Tonic".into(),
+    });
+
+    let response = client.say_hello(request).await?;
+
+    println!("RESPONSE={:?}", response);
+
+    Ok(())
+}
\ No newline at end of file
diff --git a/dubbo/src/helloworld/helloworld.rs b/dubbo/src/helloworld/helloworld.rs
new file mode 100644
index 0000000..b951157
--- /dev/null
+++ b/dubbo/src/helloworld/helloworld.rs
@@ -0,0 +1,272 @@
+/// The request message containing the user's name.
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct HelloRequest {
+    #[prost(string, tag="1")]
+    pub name: ::prost::alloc::string::String,
+}
+/// The response message containing the greetings
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct HelloReply {
+    #[prost(string, tag="1")]
+    pub message: ::prost::alloc::string::String,
+}
+/// Generated client implementations.
+pub mod greeter_client {
+    #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
+    use tonic::codegen::*;
+    /// The greeting service definition.
+    #[derive(Debug, Clone)]
+    pub struct GreeterClient<T> {
+        inner: tonic::client::Grpc<T>,
+    }
+    impl GreeterClient<tonic::transport::Channel> {
+        /// Attempt to create a new client by connecting to a given endpoint.
+        pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
+        where
+            D: std::convert::TryInto<tonic::transport::Endpoint>,
+            D::Error: Into<StdError>,
+        {
+            let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
+            Ok(Self::new(conn))
+        }
+    }
+    impl<T> GreeterClient<T>
+    where
+        T: tonic::client::GrpcService<tonic::body::BoxBody>,
+        T::Error: Into<StdError>,
+        T::ResponseBody: Body<Data = Bytes> + Send + 'static,
+        <T::ResponseBody as Body>::Error: Into<StdError> + Send,
+    {
+        pub fn new(inner: T) -> Self {
+            let inner = tonic::client::Grpc::new(inner);
+            Self { inner }
+        }
+        pub fn with_interceptor<F>(
+            inner: T,
+            interceptor: F,
+        ) -> GreeterClient<InterceptedService<T, F>>
+        where
+            F: tonic::service::Interceptor,
+            T::ResponseBody: Default,
+            T: tonic::codegen::Service<
+                http::Request<tonic::body::BoxBody>,
+                Response = http::Response<
+                    <T as tonic::client::GrpcService<tonic::body::BoxBody>>::ResponseBody,
+                >,
+            >,
+            <T as tonic::codegen::Service<
+                http::Request<tonic::body::BoxBody>,
+            >>::Error: Into<StdError> + Send + Sync,
+        {
+            GreeterClient::new(InterceptedService::new(inner, interceptor))
+        }
+        /// Compress requests with `gzip`.
+        ///
+        /// This requires the server to support it otherwise it might respond with an
+        /// error.
+        #[must_use]
+        pub fn send_gzip(mut self) -> Self {
+            self.inner = self.inner.send_gzip();
+            self
+        }
+        /// Enable decompressing responses with `gzip`.
+        #[must_use]
+        pub fn accept_gzip(mut self) -> Self {
+            self.inner = self.inner.accept_gzip();
+            self
+        }
+        /// Sends a greeting
+        pub async fn say_hello(
+            &mut self,
+            request: impl tonic::IntoRequest<super::HelloRequest>,
+        ) -> Result<tonic::Response<super::HelloReply>, tonic::Status> {
+            self.inner
+                .ready()
+                .await
+                .map_err(|e| {
+                    tonic::Status::new(
+                        tonic::Code::Unknown,
+                        format!("Service was not ready: {}", e.into()),
+                    )
+                })?;
+            let codec = tonic::codec::ProstCodec::default();
+            let path = http::uri::PathAndQuery::from_static(
+                "/helloworld.Greeter/SayHello",
+            );
+            self.inner.unary(request.into_request(), path, codec).await
+        }
+    }
+}
+/// Generated server implementations.
+pub mod greeter_server {
+    #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
+
+    use tonic::codegen::*;
+    use crate::service::protocol::Invoker;
+    use crate::service::grpc::grpc_server::DubboGrpcService;
+    use crate::service::grpc::grpc_server::ServiceDesc;
+
+    ///Generated trait containing gRPC methods that should be implemented for use with GreeterServer.
+    #[async_trait]
+    pub trait Greeter: Send + Sync + 'static {
+        /// Sends a greeting
+        async fn say_hello(
+            &self,
+            request: tonic::Request<super::HelloRequest>,
+        ) -> Result<tonic::Response<super::HelloReply>, tonic::Status>;
+    }
+    /// The greeting service definition.
+    #[derive(Debug)]
+    pub struct GreeterServer<T: Greeter, I> {
+        inner: _Inner<T>,
+        invoker: Option<_Inner<I>>,
+        accept_compression_encodings: EnabledCompressionEncodings,
+        send_compression_encodings: EnabledCompressionEncodings,
+    }
+    struct _Inner<T>(Arc<T>);
+    impl<T: Greeter, I> GreeterServer<T, I> {
+        pub fn new(inner: T) -> Self {
+            Self::from_arc(Arc::new(inner))
+        }
+        pub fn from_arc(inner: Arc<T>) -> Self {
+            let inner = _Inner(inner);
+            Self {
+                inner,
+                invoker: None,
+                accept_compression_encodings: Default::default(),
+                send_compression_encodings: Default::default(),
+            }
+        }
+        pub fn with_interceptor<F>(
+            inner: T,
+            interceptor: F,
+        ) -> InterceptedService<Self, F>
+        where
+            F: tonic::service::Interceptor,
+        {
+            InterceptedService::new(Self::new(inner), interceptor)
+        }
+        /// Enable decompressing requests with `gzip`.
+        #[must_use]
+        pub fn accept_gzip(mut self) -> Self {
+            self.accept_compression_encodings.enable_gzip();
+            self
+        }
+        /// Compress responses with `gzip`, if the client supports it.
+        #[must_use]
+        pub fn send_gzip(mut self) -> Self {
+            self.send_compression_encodings.enable_gzip();
+            self
+        }
+    }
+    impl<T, B, I> tonic::codegen::Service<http::Request<B>> for GreeterServer<T, I>
+    where
+        T: Greeter,
+        B: Body + Send + 'static,
+        B::Error: Into<StdError> + Send + 'static,
+    {
+        type Response = http::Response<tonic::body::BoxBody>;
+        type Error = std::convert::Infallible;
+        type Future = BoxFuture<Self::Response, Self::Error>;
+        fn poll_ready(
+            &mut self,
+            _cx: &mut Context<'_>,
+        ) -> Poll<Result<(), Self::Error>> {
+            Poll::Ready(Ok(()))
+        }
+        fn call(&mut self, req: http::Request<B>) -> Self::Future {
+            let inner = self.inner.clone();
+            match req.uri().path() {
+                "/helloworld.Greeter/SayHello" => {
+                    #[allow(non_camel_case_types)]
+                    struct SayHelloSvc<T: Greeter>(pub Arc<T>);
+                    impl<T: Greeter> tonic::server::UnaryService<super::HelloRequest>
+                    for SayHelloSvc<T> {
+                        type Response = super::HelloReply;
+                        type Future = BoxFuture<
+                            tonic::Response<Self::Response>,
+                            tonic::Status,
+                        >;
+                        fn call(
+                            &mut self,
+                            request: tonic::Request<super::HelloRequest>,
+                        ) -> Self::Future {
+                            let inner = self.0.clone();
+                            let fut = async move { (*inner).say_hello(request).await };
+                            Box::pin(fut)
+                        }
+                    }
+                    let accept_compression_encodings = self.accept_compression_encodings;
+                    let send_compression_encodings = self.send_compression_encodings;
+                    let inner = self.inner.clone();
+                    let fut = async move {
+                        let inner = inner.0;
+                        let method = SayHelloSvc(inner);
+                        let codec = tonic::codec::ProstCodec::default();
+                        let mut grpc = tonic::server::Grpc::new(codec)
+                            .apply_compression_config(
+                                accept_compression_encodings,
+                                send_compression_encodings,
+                            );
+                        let res = grpc.unary(method, 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(),
+                        )
+                    })
+                }
+            }
+        }
+    }
+    impl<T: Greeter, I: Invoker+ Send+ Sync + 'static> Clone for GreeterServer<T, I> {
+        fn clone(&self) -> Self {
+            let inner = self.inner.clone();
+            Self {
+                inner,
+                invoker: None,
+                // invoker: if let Some(v) = self.invoker.borrow_mut() {
+                //     Some(v.clone())
+                // } else {
+                //     None
+                // },
+                accept_compression_encodings: self.accept_compression_encodings,
+                send_compression_encodings: self.send_compression_encodings,
+            }
+        }
+
+    }
+
+    impl<T: Greeter> Clone for _Inner<T> {
+        fn clone(&self) -> Self {
+            Self(self.0.clone())
+        }
+    }
+    impl<T: std::fmt::Debug> std::fmt::Debug for _Inner<T> {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "{:?}", self.0)
+        }
+    }
+    impl<T: Greeter, I: Invoker> DubboGrpcService<I> for GreeterServer<T, I> {
+        fn set_proxy_impl(&mut self, invoker: I) {
+            self.invoker = Some(_Inner(Arc::new(invoker)));
+        }
+
+        fn service_desc(&self) -> ServiceDesc {
+            ServiceDesc::new("helloworld.Greeter".to_string(), std::collections::HashMap::new())
+        }
+    }
+
+    impl<T: Greeter, I> tonic::transport::NamedService for GreeterServer<T, I> {
+        const NAME: &'static str = "helloworld.Greeter";
+    }
+}
diff --git a/dubbo/src/helloworld/mod.rs b/dubbo/src/helloworld/mod.rs
new file mode 100644
index 0000000..5f1509d
--- /dev/null
+++ b/dubbo/src/helloworld/mod.rs
@@ -0,0 +1 @@
+pub mod helloworld;
\ No newline at end of file
diff --git a/dubbo/src/helloworld/server.rs b/dubbo/src/helloworld/server.rs
new file mode 100644
index 0000000..e69de29
diff --git a/dubbo/src/lib.rs b/dubbo/src/lib.rs
new file mode 100644
index 0000000..7a10cf1
--- /dev/null
+++ b/dubbo/src/lib.rs
@@ -0,0 +1,6 @@
+pub mod helloworld;
+pub mod service;
+pub mod common;
+pub mod utils;
+
+pub(crate) type Error = Box<dyn std::error::Error + Send + Sync>;
\ No newline at end of file
diff --git a/dubbo/src/main.rs b/dubbo/src/main.rs
new file mode 100644
index 0000000..ecc7b56
--- /dev/null
+++ b/dubbo/src/main.rs
@@ -0,0 +1,10 @@
+pub mod service;
+pub mod common;
+pub mod utils;
+pub mod helloworld;
+
+#[tokio::main]
+async fn main() {
+    println!("hello, dubbo-rust~")
+}
+
diff --git a/dubbo/src/service/grpc/grpc_exporter.rs b/dubbo/src/service/grpc/grpc_exporter.rs
new file mode 100644
index 0000000..2940429
--- /dev/null
+++ b/dubbo/src/service/grpc/grpc_exporter.rs
@@ -0,0 +1,34 @@
+
+use crate::service::protocol::*;
+use crate::service::protocol::Invoker;    
+
+pub struct GrpcExporter<T> {
+    invoker: T
+}
+
+impl<T> GrpcExporter<T> {
+    pub fn new(key: String, invoker: T) -> GrpcExporter<T> {
+        Self { invoker }
+    }
+}
+
+impl<T: Invoker+Clone> Exporter for GrpcExporter<T>
+{
+    type InvokerType = T;
+
+    fn unexport(&self) {
+    }
+
+    fn get_invoker(&self) -> Self::InvokerType {
+        self.invoker.clone()
+    }
+
+}
+
+impl<T: Invoker+Clone> Clone for GrpcExporter<T> {
+    
+    fn clone(&self) -> Self {
+        Self { invoker: self.invoker.clone() }
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo/src/service/grpc/grpc_invoker.rs b/dubbo/src/service/grpc/grpc_invoker.rs
new file mode 100644
index 0000000..fd48e73
--- /dev/null
+++ b/dubbo/src/service/grpc/grpc_invoker.rs
@@ -0,0 +1,73 @@
+use std::sync::Once;
+
+use tonic::client::Grpc;
+use tonic::transport::Channel;
+use tonic::transport::Endpoint;
+
+use crate::service::protocol::*;
+use crate::service::invocation;
+use crate::common::url::Url;
+
+pub struct GrpcInvoker {
+    client: Grpc<Channel>,
+    url: Url,
+    once: Once
+}
+
+
+
+impl GrpcInvoker {
+    pub fn new(url: Url) -> GrpcInvoker {
+
+        let endpoint = Endpoint::new(url.url.clone()).unwrap();
+        let conn = endpoint.connect_lazy();
+        Self {
+            url,
+            client: Grpc::new(conn),
+            once: Once::new()
+        }
+    }
+}
+
+impl Invoker for GrpcInvoker {
+
+    fn is_available(&self) -> bool {
+        true
+    }
+
+    fn destroy(&self) {
+        self.once.call_once(|| {
+            println!("destroy...")
+        })
+    }
+
+    fn get_url(&self) -> Url {
+        self.url.to_owned()
+    }
+
+    // 根据req中的数据发起req,由Client发起请求,获取响应
+   fn invoke<M1>(&self, req: invocation::Request<M1>) -> invocation::Response<String>
+    where
+        M1: Send + 'static,
+    {
+        let (metadata, _) = req.into_parts();
+
+        let resp = invocation::Response::new("string");
+        let (resp_meta, msg) = resp.into_parts();
+ 
+        invocation::Response::from_parts(metadata, msg.to_string())
+    }
+}
+
+impl<T> invocation::Request<T> {
+
+    pub(crate) fn to_tonic_req(self) -> tonic::Request<T> {
+        tonic::Request::new(self.message)
+    }
+}
+
+impl Clone for GrpcInvoker {
+    fn clone(&self) -> Self {
+        Self { client: self.client.clone(), url: self.url.clone(), once: Once::new() }
+    }
+}
\ No newline at end of file
diff --git a/dubbo/src/service/grpc/grpc_protocol.rs b/dubbo/src/service/grpc/grpc_protocol.rs
new file mode 100644
index 0000000..08fe921
--- /dev/null
+++ b/dubbo/src/service/grpc/grpc_protocol.rs
@@ -0,0 +1,60 @@
+
+use std::collections::HashMap;
+
+use super::grpc_invoker::GrpcInvoker;
+use super::grpc_exporter::GrpcExporter;
+use crate::common::url::Url;
+use crate::service::protocol::Protocol;
+use super::grpc_server::GrpcServer;
+
+pub struct GrpcProtocol {
+    server_map: HashMap<String, GrpcServer>,
+    export_map: HashMap<String, GrpcExporter<GrpcInvoker>>
+}
+
+impl GrpcProtocol {
+    pub fn new() -> Self {
+        Self {
+            server_map: HashMap::new(),
+            export_map: HashMap::new(),
+        }
+    }
+}
+
+impl Default for GrpcProtocol {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+#[async_trait::async_trait]
+impl Protocol for GrpcProtocol
+{
+    type Invoker = GrpcInvoker;
+
+    type Exporter = GrpcExporter<Self::Invoker>;
+
+    fn destroy(&self) {
+        todo!()
+    }
+
+    async fn refer(&self, url: Url) -> Self::Invoker {
+        GrpcInvoker::new(url)
+    }
+
+    async fn export(self, url: Url) -> Self::Exporter {
+        let service_key = url.service_key.clone();
+
+        let exporter: GrpcExporter<GrpcInvoker> = GrpcExporter::new(service_key.clone(), GrpcInvoker::new(url.clone()));
+        let mut export = self.export_map;
+        export.insert(service_key.clone(), exporter.clone());
+
+        // 启动服务
+
+        let server = super::grpc_server::GrpcServer::new(service_key.clone());
+        let mut server_map = self.server_map;
+        server_map.insert(service_key.clone(), server.clone());
+        server.serve(url.clone()).await;
+        exporter
+    }
+}
\ No newline at end of file
diff --git a/dubbo/src/service/grpc/grpc_server.rs b/dubbo/src/service/grpc/grpc_server.rs
new file mode 100644
index 0000000..3a9c6a8
--- /dev/null
+++ b/dubbo/src/service/grpc/grpc_server.rs
@@ -0,0 +1,116 @@
+use std::collections::HashMap;
+use std::task::Context;
+use std::task::Poll;
+
+use tonic::transport;
+use tower::Service;
+use tonic::transport::NamedService;
+use tonic::codegen::BoxFuture;
+
+
+use crate::common::url::Url;
+use crate::helloworld::helloworld::greeter_server::GreeterServer;
+use super::grpc_invoker::GrpcInvoker;
+use crate::helloworld::helloworld::greeter_server::*;
+use crate::utils::boxed_clone::BoxCloneService;
+
+pub trait DubboGrpcService<T>
+{
+    fn set_proxy_impl(&mut self, invoker: T);
+    fn service_desc(&self) -> ServiceDesc;
+}
+
+//type ServiceDesc struct {
+//     ServiceName string
+//     // The pointer to the service interface. Used to check whether the user
+//     // provided implementation satisfies the interface requirements.
+//     HandlerType interface{}
+//     Methods     []MethodDesc
+//     Streams     []StreamDesc
+//     Metadata    interface{}
+// }
+
+pub struct ServiceDesc {
+    service_name: String,
+    methods: HashMap<String, String> // "/Greeter/hello": "unary"
+}
+
+impl  ServiceDesc {
+    pub fn new(service_name: String, methods: HashMap<String, String>) -> Self {
+        Self { service_name, methods }
+    }
+
+    pub fn get_service_name(&self) -> String {
+        self.service_name.clone()
+    }
+}
+
+// codegen
+pub fn register_greeter_server<T: Greeter>(server: T) -> (super::GrpcBoxCloneService, super::DubboGrpcBox) {
+    let hello = GreeterServer::<T, GrpcInvoker>::new(server);
+    (BoxCloneService::new(hello.clone()), Box::new(hello.clone()))
+}
+
+// 每个service对应一个Server
+#[derive(Clone)]
+pub struct GrpcServer {
+    inner: transport::Server,
+    name: String,
+}
+
+impl GrpcServer
+{
+    pub fn new(name: String) -> GrpcServer {
+        Self {
+            inner: transport::Server::builder(),
+            name
+        }
+    }
+
+    pub async fn serve(mut self, url: Url)
+    where
+    {
+        let addr = url.url.clone().parse().unwrap();
+        let svc = super::GRPC_SERVICES.read().unwrap().get(self.name.as_str()).unwrap().clone();
+        println!("server{:?} start...", url);
+        self.inner.add_service(MakeSvc::new(svc)).serve(
+            addr
+        ).await.unwrap();
+        println!("server{:?} start...", url);
+    }
+
+}
+
+struct MakeSvc<T, U, E> {
+    inner: BoxCloneService<T, U, E>
+}
+
+impl<T, U, E> MakeSvc<T, U, E> {
+    pub fn new(inner: BoxCloneService<T, U, E>) -> Self {
+        Self { inner}
+    }
+}
+
+impl<T, U, E> NamedService for MakeSvc<T, U, E> {
+    const NAME: &'static str = "helloworld.Greeter";
+}
+
+impl<T, U, E> Service<T> for MakeSvc<T, U, E> {
+    type Response = U;
+    type Error = E;
+    type Future = BoxFuture<U, E>;
+
+    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> {
+        self.inner.poll_ready(cx)
+    }
+
+    fn call(&mut self, request: T) -> BoxFuture<U, E> {
+        self.inner.call(request)
+    }
+}
+
+impl<T, U, E> Clone for MakeSvc<T, U, E> {
+    fn clone(&self) -> Self {
+        Self { inner: self.inner.clone() }
+    }
+}
\ No newline at end of file
diff --git a/dubbo/src/service/grpc/mod.rs b/dubbo/src/service/grpc/mod.rs
new file mode 100644
index 0000000..3350638
--- /dev/null
+++ b/dubbo/src/service/grpc/mod.rs
@@ -0,0 +1,59 @@
+pub mod grpc_protocol;
+pub mod grpc_invoker;
+pub mod grpc_exporter;
+pub mod grpc_server;
+
+use std::collections::HashMap;
+use std::sync::RwLock;
+use lazy_static::lazy_static;
+
+use grpc_server::DubboGrpcService;
+use grpc_invoker::GrpcInvoker;
+use crate::helloworld::helloworld::greeter_server::Greeter;
+use crate::utils::boxed_clone::BoxCloneService;
+use crate::helloworld::helloworld::{HelloRequest, HelloReply};
+
+pub type GrpcBoxCloneService = BoxCloneService<http::Request<hyper::Body>, http::Response<tonic::body::BoxBody>, std::convert::Infallible>;
+
+pub type DubboGrpcBox = Box<dyn DubboGrpcService<GrpcInvoker>+ Send + Sync + 'static>;
+
+lazy_static! {
+    pub static ref DUBBO_GRPC_SERVICES: RwLock<HashMap<String, Box<dyn DubboGrpcService<GrpcInvoker> + Send + Sync + 'static>>> = RwLock::new(HashMap::new());
+    pub static ref GRPC_SERVICES: RwLock<HashMap<String, GrpcBoxCloneService>> = RwLock::new(HashMap::new());
+}
+
+#[tokio::test]
+async fn test_hello() {
+    use grpc_server::register_greeter_server;
+    use crate::service::protocol::Protocol;
+    use crate::common::url::Url;
+    
+    let (svc, dubbo_svc) = register_greeter_server(MyGreeter{});
+    let svc_name = dubbo_svc.service_desc().get_service_name();
+    DUBBO_GRPC_SERVICES.write().unwrap().insert(svc_name.clone(), dubbo_svc);
+    GRPC_SERVICES.write().unwrap().insert(svc_name.clone(), svc);
+
+    // server start, api: 0.0.0.0:8888/helloworld.Greeter/SayHello
+    let pro = grpc_protocol::GrpcProtocol::new();
+    pro.export(Url{url: "[::1]:50051".to_string(), service_key: svc_name.clone()}).await;
+
+}
+
+
+#[derive(Default)]
+pub struct MyGreeter {}
+
+#[tonic::async_trait]
+impl Greeter for MyGreeter {
+    async fn say_hello(
+        &self,
+        request: tonic::Request<HelloRequest>,
+    ) -> Result<tonic::Response<HelloReply>, tonic::Status> {
+        println!("Got a request from {:?}", request.remote_addr());
+
+        let reply = HelloReply {
+            message: format!("Hello {}!", request.into_inner().name),
+        };
+        Ok(tonic::Response::new(reply))
+    }
+}
\ No newline at end of file
diff --git a/dubbo/src/service/invocation.rs b/dubbo/src/service/invocation.rs
new file mode 100644
index 0000000..dff46fa
--- /dev/null
+++ b/dubbo/src/service/invocation.rs
@@ -0,0 +1,45 @@
+use tonic::metadata::MetadataMap;
+
+pub struct Request<T> {
+    pub message: T,
+    pub metadata: MetadataMap,
+}
+
+
+impl<T> Request<T> {
+    pub fn new(message: T) -> Request<T> {
+        Self {
+            message,
+            metadata: MetadataMap::new()
+        }
+    }
+
+    pub fn into_parts(self) -> (MetadataMap, T) {
+        (self.metadata, self.message)
+    }
+}
+
+pub struct Response<T> {
+    message: T,
+    metadata: MetadataMap,
+}
+
+impl<T> Response<T> {
+    pub fn new(message: T) -> Response<T> {
+        Self {
+            message,
+            metadata: MetadataMap::new(),
+        }
+    }
+
+    pub fn from_parts(metadata: MetadataMap, message: T) -> Self {
+        Self {
+            message,
+            metadata,
+        }
+    }
+
+    pub fn into_parts(self) -> (MetadataMap, T) {
+        (self.metadata, self.message)
+    }
+}
\ No newline at end of file
diff --git a/dubbo/src/service/mod.rs b/dubbo/src/service/mod.rs
new file mode 100644
index 0000000..55bcb2f
--- /dev/null
+++ b/dubbo/src/service/mod.rs
@@ -0,0 +1,4 @@
+pub mod protocol;
+pub mod grpc;
+pub mod invocation;
+
diff --git a/dubbo/src/service/protocol.rs b/dubbo/src/service/protocol.rs
new file mode 100644
index 0000000..18d2d7b
--- /dev/null
+++ b/dubbo/src/service/protocol.rs
@@ -0,0 +1,31 @@
+use super::invocation;
+use crate::common::url::Url;
+
+use async_trait::async_trait;
+
+#[async_trait]
+pub trait Protocol {
+    type Invoker;
+    type Exporter;
+    
+    fn destroy(&self);
+    async fn export(self, url: Url) -> Self::Exporter;
+    async fn refer(&self, url: Url) -> Self::Invoker;
+}
+
+
+pub trait Exporter {
+    type InvokerType: Invoker;
+
+    fn unexport(&self);
+    fn get_invoker(&self) -> Self::InvokerType;
+}
+
+pub trait Invoker {
+    fn invoke<M1>(&self, req: invocation::Request<M1>) -> invocation::Response<String>
+    where
+        M1: Send + 'static;
+    fn is_available(&self) -> bool;
+    fn destroy(&self);
+    fn get_url(&self) -> Url;
+}
\ No newline at end of file
diff --git a/dubbo/src/utils/boxed.rs b/dubbo/src/utils/boxed.rs
new file mode 100644
index 0000000..63297e9
--- /dev/null
+++ b/dubbo/src/utils/boxed.rs
@@ -0,0 +1,74 @@
+use tower::ServiceExt;
+use tower_layer::{layer_fn, LayerFn};
+use tower_service::Service;
+
+use std::fmt;
+use std::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+/// A boxed `Service + Send` trait object.
+///
+/// [`BoxService`] turns a service into a trait object, allowing the response
+/// future type to be dynamic. This type requires both the service and the
+/// response future to be [`Send`].
+///
+/// If you need a boxed [`Service`] that implements [`Clone`] consider using
+/// [`BoxCloneService`](crate::util::BoxCloneService).
+///
+/// See module level documentation for more details.
+pub struct BoxService<T, U, E> {
+    inner: Box<dyn Service<T, Response = U, Error = E, Future = BoxFuture<U, E>> + Send+ Sync+>,
+}
+
+/// A boxed `Future + Send` trait object.
+///
+/// This type alias represents a boxed future that is [`Send`] and can be moved
+/// across threads.
+type BoxFuture<T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send>>;
+
+impl<T, U, E> BoxService<T, U, E> {
+    #[allow(missing_docs)]
+    pub fn new<S>(inner: S) -> Self
+    where
+        S: Service<T, Response = U, Error = E> + Send + Sync + 'static,
+        S::Future: Send + 'static,
+    {
+        let inner = Box::new(inner.map_future(|f: S::Future| Box::pin(f) as _));
+        BoxService { inner }
+    }
+
+    // /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxService`]
+    // /// middleware.
+    // ///
+    // /// [`Layer`]: crate::Layer
+    pub fn layer<S>() -> LayerFn<fn(S) -> Self>
+    where
+        S: Service<T, Response = U, Error = E> + Send + Sync + 'static,
+        S::Future: Send + 'static,
+    {
+        layer_fn(Self::new)
+    }
+}
+
+impl<T, U, E> Service<T> for BoxService<T, U, E> {
+    type Response = U;
+    type Error = E;
+    type Future = BoxFuture<U, E>;
+
+    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> {
+        self.inner.poll_ready(cx)
+    }
+
+    fn call(&mut self, request: T) -> BoxFuture<U, E> {
+        self.inner.call(request)
+    }
+}
+
+impl<T, U, E> fmt::Debug for BoxService<T, U, E> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("BoxService").finish()
+    }
+}
diff --git a/dubbo/src/utils/boxed_clone.rs b/dubbo/src/utils/boxed_clone.rs
new file mode 100644
index 0000000..0e5e6c3
--- /dev/null
+++ b/dubbo/src/utils/boxed_clone.rs
@@ -0,0 +1,88 @@
+use tower::ServiceExt;
+use futures_util::future::BoxFuture;
+use std::{
+    fmt,
+    task::{Context, Poll},
+};
+use tower_layer::{layer_fn, LayerFn};
+use tower_service::Service;
+
+pub struct BoxCloneService<T, U, E>(
+    Box<
+        dyn CloneService<T, Response = U, Error = E, Future = BoxFuture<'static, Result<U, E>>>
+            + Send+Sync,
+    >,
+);
+
+impl<T, U, E> BoxCloneService<T, U, E> {
+    /// Create a new `BoxCloneService`.
+    pub fn new<S>(inner: S) -> Self
+    where
+        S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static,
+        S::Future: Send + 'static,
+    {
+        let inner = inner.map_future(|f| Box::pin(f) as _);
+        BoxCloneService(Box::new(inner))
+    }
+
+    /// Returns a [`Layer`] for wrapping a [`Service`] in a [`BoxCloneService`]
+    /// middleware.
+    ///
+    /// [`Layer`]: crate::Layer
+    pub fn layer<S>() -> LayerFn<fn(S) -> Self>
+    where
+        S: Service<T, Response = U, Error = E> + Clone + Send + Sync + 'static,
+        S::Future: Send + 'static,
+    {
+        layer_fn(Self::new)
+    }
+}
+
+impl<T, U, E> Service<T> for BoxCloneService<T, U, E> {
+    type Response = U;
+    type Error = E;
+    type Future = BoxFuture<'static, Result<U, E>>;
+
+    #[inline]
+    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), E>> {
+        self.0.poll_ready(cx)
+    }
+
+    #[inline]
+    fn call(&mut self, request: T) -> Self::Future {
+        self.0.call(request)
+    }
+}
+
+impl<T, U, E> Clone for BoxCloneService<T, U, E> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone_box())
+    }
+}
+
+trait CloneService<R>: Service<R> {
+    fn clone_box(
+        &self,
+    ) -> Box<
+        dyn CloneService<R, Response = Self::Response, Error = Self::Error, Future = Self::Future>
+            + Send + Sync,
+    >;
+}
+
+impl<R, T> CloneService<R> for T
+where
+    T: Service<R> + Send + Sync + Clone + 'static,
+{
+    fn clone_box(
+        &self,
+    ) -> Box<dyn CloneService<R, Response = T::Response, Error = T::Error, Future = T::Future> + Send + Sync>
+    {
+        Box::new(self.clone())
+    }
+}
+
+impl<T, U, E> fmt::Debug for BoxCloneService<T, U, E> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.debug_struct("BoxCloneService").finish()
+    }
+}
diff --git a/dubbo/src/utils/mod.rs b/dubbo/src/utils/mod.rs
new file mode 100644
index 0000000..a3bbaaa
--- /dev/null
+++ b/dubbo/src/utils/mod.rs
@@ -0,0 +1,2 @@
+pub mod boxed;
+pub mod boxed_clone;
\ No newline at end of file
diff --git a/protocol/Cargo.toml b/protocol/Cargo.toml
deleted file mode 100644
index 77c8260..0000000
--- a/protocol/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "protocol"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs
deleted file mode 100644
index 3e01853..0000000
--- a/protocol/src/lib.rs
+++ /dev/null
@@ -1,25 +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.
- */
-
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn it_works() {
-        let result = 2 + 2;
-        assert_eq!(result, 4);
-    }
-}