This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-website.git
The following commit(s) were added to refs/heads/master by this push:
new 86d443efa89 improve english rust docs (#1531)
86d443efa89 is described below
commit 86d443efa894dbc657e81f387ba3238fc13143c3
Author: Robert LU <[email protected]>
AuthorDate: Thu Sep 29 13:34:11 2022 +0800
improve english rust docs (#1531)
---
content/en/docs3-v2/_index.md | 10 +
content/en/docs3-v2/rust-sdk/_index.md | 9 +
.../en/docs3-v2/rust-sdk/java-interoperability.md | 70 ++++
content/en/docs3-v2/rust-sdk/quick-start.md | 458 +++++++++++++++++++++
content/en/latest/download/_index.md | 3 -
5 files changed, 547 insertions(+), 3 deletions(-)
diff --git a/content/en/docs3-v2/_index.md b/content/en/docs3-v2/_index.md
new file mode 100755
index 00000000000..4a5694e41ac
--- /dev/null
+++ b/content/en/docs3-v2/_index.md
@@ -0,0 +1,10 @@
+
+---
+type: docs
+title: "SDK Manual"
+linkTitle: "SDK Manual"
+hide_summary: true
+menu:
+ main:
+ weight: 21
+---
diff --git a/content/en/docs3-v2/rust-sdk/_index.md
b/content/en/docs3-v2/rust-sdk/_index.md
new file mode 100755
index 00000000000..018a89bfb4c
--- /dev/null
+++ b/content/en/docs3-v2/rust-sdk/_index.md
@@ -0,0 +1,9 @@
+
+---
+type: docs
+title: "Rust"
+linkTitle: "Rust"
+weight: 100
+description: "Rust SDK Manual"
+---
+
diff --git a/content/en/docs3-v2/rust-sdk/java-interoperability.md
b/content/en/docs3-v2/rust-sdk/java-interoperability.md
new file mode 100644
index 00000000000..d3af6182765
--- /dev/null
+++ b/content/en/docs3-v2/rust-sdk/java-interoperability.md
@@ -0,0 +1,70 @@
+---
+type: docs
+title: "Rust and Java interoperability"
+linkTitle: "Rust and Java interoperability"
+weight: 2
+description: "Use Dubbo-rust call Duboo Java service"
+---
+
+## 1 Prerequisite
+- Install [Rust development environment](https://rustup.rs/).
+- Install [protoc](https://grpc.io/docs/protoc-installation/).
+- Install Java development environment.
+
+## 2 Run example of Java Dubbo provider
+
+Java version of Dubbo provider example
<https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-triple>.
+
+Clone the source code, compile, and run provider:
+
+```sh
+$ # clone the source code
+$ git clone https://github.com/apache/dubbo-samples.git
+$ cd dubbo-samples/dubbo-samples-triple/
+
+$ # compile and build
+$ mvn clean compile package -DskipTests
+
+$ # run provider
+$ java -Dprovider.port=8888 -jar ./target/dubbo-samples-triple-1.0-SNAPSHOT.jar
+# … some logs
+Dubbo triple stub server started, port=8888
+```
+
+[The interface defination on Java
side](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-triple/src/main/proto/greeter.proto)
+
+## 3 Run Rust version of Dubbo consumer
+
+Rust version of Dubbo consumer
<https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-triple>.
+
+Clone the source code, compile and run consumer:
+
+```sh
+$ # clone the source code
+$ git clone https://github.com/apache/dubbo-rust.git
+$ cd dubbo-rust/examples/greeter/
+
+$ # build
+$ cargo build
+
+$ # run consumer, call provider
+$ ../../target/debug/greeter-client
+# unary call
+Response: GreeterReply { message: "hello, dubbo-rust" }
+# client stream
+client streaming, Response: GreeterReply { message: "hello client streaming" }
+# bi stream
+parts: Metadata { inner: {"content-type": "application/grpc", "date": "Wed, 28
Sep 2022 23:54:56 GMT"} }
+reply: GreeterReply { message: "server reply: \"msg1 from client\"" }
+reply: GreeterReply { message: "server reply: \"msg2 from client\"" }
+reply: GreeterReply { message: "server reply: \"msg3 from client\"" }
+trailer: Some(Metadata { inner: {"grpc-message": "poll trailer successfully.",
"grpc-accept-encoding": "gzip,identity", "content-type": "application/grpc",
"grpc-status": "0"} })
+# server stream
+parts: Metadata { inner: {"content-type": "application/grpc", "date": "Wed, 28
Sep 2022 23:54:56 GMT"} }
+reply: GreeterReply { message: "msg1 from server" }
+reply: GreeterReply { message: "msg2 from server" }
+reply: GreeterReply { message: "msg3 from server" }
+trailer: Some(Metadata { inner: {"content-type": "application/grpc",
"grpc-message": "poll trailer successfully.", "grpc-accept-encoding":
"gzip,identity", "grpc-status": "0"} })
+```
+
+[The interface defination on Rust
side](https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-triple)
diff --git a/content/en/docs3-v2/rust-sdk/quick-start.md
b/content/en/docs3-v2/rust-sdk/quick-start.md
new file mode 100644
index 00000000000..a70d529a65a
--- /dev/null
+++ b/content/en/docs3-v2/rust-sdk/quick-start.md
@@ -0,0 +1,458 @@
+---
+type: docs
+title: "Quick start"
+linkTitle: "Quick start"
+weight: 1
+description: "Quick start to use Dubbo-rust"
+---
+
+See the full example
[here](https://github.com/apache/dubbo-rust/tree/main/examples/greeter).
+
+## 1 Prerequisite
+- Install [Rust development environment](https://rustup.rs/).
+- Install [protoc](https://grpc.io/docs/protoc-installation/).
+
+## 2 Use IDL to define Dubbo service
+
+The Greeter service is defined as follows, contains a Unary, Client stream,
Server stream, Bidirectional stream model Dubbo service:
+
+```protobuf
+// ./proto/greeter.proto
+syntax = "proto3";
+
+option java_multiple_files = true;
+
+package org.apache.dubbo.sample.tri;
+
+
+// The request message containing the user's name.
+message GreeterRequest {
+ string name = 1;
+}
+
+// The response message containing the greetings
+message GreeterReply {
+ string message = 1;
+}
+
+service Greeter{
+
+ // unary
+ rpc greet(GreeterRequest) returns (GreeterReply);
+
+ // clientStream
+ rpc greetClientStream(stream GreeterRequest) returns (GreeterReply);
+
+ // serverStream
+ rpc greetServerStream(GreeterRequest) returns (stream GreeterReply);
+
+ // bi streaming
+ rpc greetStream(stream GreeterRequest) returns (stream GreeterReply);
+
+}
+```
+
+## 3 Add Dubbo-rust and other dependencies
+```toml
+# ./Cargo.toml
+[package]
+name = "example-greeter"
+version = "0.1.0"
+edition = "2021"
+
+[[bin]]
+name = "greeter-server"
+path = "src/greeter/server.rs"
+
+[[bin]]
+name = "greeter-client"
+path = "src/greeter/client.rs"
+
+[dependencies]
+http = "0.2"
+http-body = "0.4.4"
+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"
+async-trait = "0.1.56"
+tokio-stream = "0.1"
+
+dubbo = "0.1.0"
+dubbo-config = "0.1.0"
+
+[build-dependencies]
+dubbo-build = "0.1.0"
+```
+
+## 4 Configure dubbo-build to compile IDL
+
+Create `build.rs` at project root directory:
+
+```rust
+// ./build.rs
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ tonic_build::compile_protos("proto/helloworld.proto")?;
+ Ok(())
+}
+```
+
+After this configuration, the project compiling will generate Dubbo stub code,
where the path is usually located
`./target/debug/build/example-greeter-<id>/out/org.apache.dubbo.sample.tri.rs`.
+
+## 5 Implement server and client
+
+### 5.1 Write Dubbo-rust Server
+
+```rust
+// ./src/greeter/server.rs
+pub mod protos {
+ include!(concat!(env!("OUT_DIR"), "/org.apache.dubbo.sample.tri.rs"));
+}
+
+use futures_util::StreamExt;
+use protos::{
+ greeter_server::{register_server, Greeter},
+ GreeterReply, GreeterRequest,
+};
+
+use std::{io::ErrorKind, pin::Pin};
+
+use async_trait::async_trait;
+use futures_util::Stream;
+use tokio::sync::mpsc;
+use tokio_stream::wrappers::ReceiverStream;
+
+use dubbo_config::RootConfig;
+use dubbo::{codegen::*, Dubbo};
+
+type ResponseStream =
+ Pin<Box<dyn Stream<Item = Result<GreeterReply, dubbo::status::Status>> +
Send>>;
+
+#[tokio::main]
+async fn main() {
+ register_server(GreeterServerImpl {
+ name: "greeter".to_string(),
+ });
+
+ // Dubbo::new().start().await;
+ Dubbo::new()
+ .with_config({
+ let r = RootConfig::new();
+ match r.load() {
+ Ok(config) => config,
+ Err(_err) => panic!("err: {:?}", _err), // response was droped
+ }
+ })
+ .start()
+ .await;
+}
+
+#[allow(dead_code)]
+#[derive(Default, Clone)]
+struct GreeterServerImpl {
+ name: String,
+}
+
+// #[async_trait]
+#[async_trait]
+impl Greeter for GreeterServerImpl {
+ async fn greet(
+ &self,
+ request: Request<GreeterRequest>,
+ ) -> Result<Response<GreeterReply>, dubbo::status::Status> {
+ println!("GreeterServer::greet {:?}", request.metadata);
+
+ Ok(Response::new(GreeterReply {
+ message: "hello, dubbo-rust".to_string(),
+ }))
+ }
+
+ async fn greet_client_stream(
+ &self,
+ request: Request<Decoding<GreeterRequest>>,
+ ) -> Result<Response<GreeterReply>, dubbo::status::Status> {
+ let mut s = request.into_inner();
+ loop {
+ let result = s.next().await;
+ match result {
+ Some(Ok(val)) => println!("result: {:?}", val),
+ Some(Err(val)) => println!("err: {:?}", val),
+ None => break,
+ }
+ }
+ Ok(Response::new(GreeterReply {
+ message: "hello client streaming".to_string(),
+ }))
+ }
+
+ type greetServerStreamStream = ResponseStream;
+ async fn greet_server_stream(
+ &self,
+ request: Request<GreeterRequest>,
+ ) -> Result<Response<Self::greetServerStreamStream>,
dubbo::status::Status> {
+ println!("greet_server_stream: {:?}", request.into_inner());
+
+ let data = vec![
+ Result::<_, dubbo::status::Status>::Ok(GreeterReply {
+ message: "msg1 from server".to_string(),
+ }),
+ Result::<_, dubbo::status::Status>::Ok(GreeterReply {
+ message: "msg2 from server".to_string(),
+ }),
+ Result::<_, dubbo::status::Status>::Ok(GreeterReply {
+ message: "msg3 from server".to_string(),
+ }),
+ ];
+ let resp = futures_util::stream::iter(data);
+
+ Ok(Response::new(Box::pin(resp)))
+ }
+
+ type greetStreamStream = ResponseStream;
+ async fn greet_stream(
+ &self,
+ request: Request<Decoding<GreeterRequest>>,
+ ) -> Result<Response<Self::greetStreamStream>, dubbo::status::Status> {
+ println!(
+ "GreeterServer::greet_stream, grpc header: {:?}",
+ request.metadata
+ );
+
+ let mut in_stream = request.into_inner();
+ let (tx, rx) = mpsc::channel(128);
+
+ // this spawn here is required if you want to handle connection error.
+ // If we just map `in_stream` and write it back as `out_stream` the
`out_stream`
+ // will be drooped when connection error occurs and error will never
be propagated
+ // to mapped version of `in_stream`.
+ tokio::spawn(async move {
+ while let Some(result) = in_stream.next().await {
+ match result {
+ Ok(v) => {
+ // if v.name.starts_with("msg2") {
+ //
tx.send(Err(dubbo::status::Status::internal(format!("err: args is invalid,
{:?}", v.name))
+ // )).await.expect("working rx");
+ // continue;
+ // }
+ tx.send(Ok(GreeterReply {
+ message: format!("server reply: {:?}", v.name),
+ }))
+ .await
+ .expect("working rx")
+ }
+ Err(err) => {
+ if let Some(io_err) = match_for_io_error(&err) {
+ if io_err.kind() == ErrorKind::BrokenPipe {
+ // here you can handle special case when client
+ // disconnected in unexpected way
+ eprintln!("\tclient disconnected: broken
pipe");
+ break;
+ }
+ }
+
+ match tx.send(Err(err)).await {
+ Ok(_) => (),
+ Err(_err) => break, // response was droped
+ }
+ }
+ }
+ }
+ println!("\tstream ended");
+ });
+
+ // echo just write the same data that was received
+ let out_stream = ReceiverStream::new(rx);
+
+ Ok(Response::new(
+ Box::pin(out_stream) as Self::greetStreamStream
+ ))
+ }
+}
+
+fn match_for_io_error(err_status: &dubbo::status::Status) ->
Option<&std::io::Error> {
+ let mut err: &(dyn std::error::Error + 'static) = err_status;
+
+ loop {
+ if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
+ return Some(io_err);
+ }
+
+ err = match err.source() {
+ Some(err) => err,
+ None => return None,
+ };
+ }
+}
+```
+
+### 5.2 Configure dubbo.yaml
+
+`dubbo.yaml` indicates the configuration of the server, including the exposed
service list, protocol configuration, listening configuration, and so on.
+
+```yaml
+# ./dubbo.yaml
+name: dubbo
+service:
+ org.apache.dubbo.sample.tri.Greeter:
+ version: 1.0.0
+ group: test
+ protocol: triple
+ registry: ''
+ serializer: json
+ protocol_configs:
+ triple:
+ ip: 0.0.0.0
+ port: '8888'
+ name: triple
+protocols:
+ triple:
+ ip: 0.0.0.0
+ port: '8888'
+ name: triple
+```
+
+### 5.3 Write Dubbo-rust Client
+
+```rust
+// ./src/greeter/client.rs
+pub mod protos {
+ include!(concat!(env!("OUT_DIR"), "/org.apache.dubbo.sample.tri.rs"));
+}
+
+use dubbo::codegen::*;
+use futures_util::StreamExt;
+use protos::{greeter_client::GreeterClient, GreeterRequest};
+
+#[tokio::main]
+async fn main() {
+ let mut cli =
GreeterClient::new().with_uri("http://127.0.0.1:8888".to_string());
+
+ println!("# unary call");
+ let resp = cli
+ .greet(Request::new(GreeterRequest {
+ name: "message from client".to_string(),
+ }))
+ .await;
+ let resp = match resp {
+ Ok(resp) => resp,
+ Err(err) => return println!("{:?}", err),
+ };
+ let (_parts, body) = resp.into_parts();
+ println!("Response: {:?}", body);
+
+ println!("# client stream");
+ let data = vec![
+ GreeterRequest {
+ name: "msg1 from client streaming".to_string(),
+ },
+ GreeterRequest {
+ name: "msg2 from client streaming".to_string(),
+ },
+ GreeterRequest {
+ name: "msg3 from client streaming".to_string(),
+ },
+ ];
+ let req = futures_util::stream::iter(data);
+ let resp = cli.greet_client_stream(req).await;
+ let client_streaming_resp = match resp {
+ Ok(resp) => resp,
+ Err(err) => return println!("{:?}", err),
+ };
+ let (_parts, resp_body) = client_streaming_resp.into_parts();
+ println!("client streaming, Response: {:?}", resp_body);
+
+ println!("# bi stream");
+ let data = vec![
+ GreeterRequest {
+ name: "msg1 from client".to_string(),
+ },
+ GreeterRequest {
+ name: "msg2 from client".to_string(),
+ },
+ GreeterRequest {
+ name: "msg3 from client".to_string(),
+ },
+ ];
+ let req = futures_util::stream::iter(data);
+
+ let bidi_resp = cli.greet_stream(req).await.unwrap();
+
+ let (parts, mut body) = bidi_resp.into_parts();
+ println!("parts: {:?}", parts);
+ while let Some(item) = body.next().await {
+ match item {
+ Ok(v) => {
+ println!("reply: {:?}", v);
+ }
+ Err(err) => {
+ println!("err: {:?}", err);
+ }
+ }
+ }
+ let trailer = body.trailer().await.unwrap();
+ println!("trailer: {:?}", trailer);
+
+ println!("# server stream");
+ let resp = cli
+ .greet_server_stream(Request::new(GreeterRequest {
+ name: "server streaming req".to_string(),
+ }))
+ .await
+ .unwrap();
+
+ let (parts, mut body) = resp.into_parts();
+ println!("parts: {:?}", parts);
+ while let Some(item) = body.next().await {
+ match item {
+ Ok(v) => {
+ println!("reply: {:?}", v);
+ }
+ Err(err) => {
+ println!("err: {:?}", err);
+ }
+ }
+ }
+ let trailer = body.trailer().await.unwrap();
+ println!("trailer: {:?}", trailer);
+}
+```
+
+## 6 Run
+
+1. Compile
+
+Run `cargo build` to compile server and client.
+
+2. Run server
+
+Run `./target/debug/greeter-server` to start server. as configured above by
dubbo.yaml, the server listens on port 8888 and provides RPC services over
triple protocol:
+
+```sh
+$ ./target/debug/greeter-server
+2022-09-28T23:33:28.104577Z INFO dubbo::framework: url: Some(Url { uri:
"triple://0.0.0.0:8888/org.apache.dubbo.sample.tri.Greeter", protocol:
"triple", location: "0.0.0.0:8888", ip: "0.0.0.0", port: "8888", service_key:
["org.apache.dubbo.sample.tri.Greeter"], params: {} })
+```
+
+3. Run client, verify that the call was successful
+
+Run `./target/debug/greeter-client` to start client, which will call methods
under `triple://127.0.0.1:8888/org.apache.dubbo.sample.tri.Greeter`:
+
+
+```sh
+$ ./target/debug/greeter-client
+# unary call
+Response: GreeterReply { message: "hello, dubbo-rust" }
+# client stream
+client streaming, Response: GreeterReply { message: "hello client streaming" }
+# bi stream
+parts: Metadata { inner: {"content-type": "application/grpc", "date": "Wed, 28
Sep 2022 23:34:20 GMT"} }
+reply: GreeterReply { message: "server reply: \"msg1 from client\"" }
+reply: GreeterReply { message: "server reply: \"msg2 from client\"" }
+reply: GreeterReply { message: "server reply: \"msg3 from client\"" }
+trailer: Some(Metadata { inner: {"content-type": "application/grpc",
"grpc-status": "0", "grpc-message": "poll trailer successfully.",
"grpc-accept-encoding": "gzip,identity"} })
+# server stream
+parts: Metadata { inner: {"content-type": "application/grpc", "date": "Wed, 28
Sep 2022 23:34:20 GMT"} }
+reply: GreeterReply { message: "msg1 from server" }
+reply: GreeterReply { message: "msg2 from server" }
+reply: GreeterReply { message: "msg3 from server" }
+trailer: Some(Metadata { inner: {"content-type": "application/grpc",
"grpc-status": "0", "grpc-message": "poll trailer successfully.",
"grpc-accept-encoding": "gzip,identity"} })
+```
diff --git a/content/en/latest/download/_index.md
b/content/en/latest/download/_index.md
index a63be278f0f..53fbd62fb0f 100755
--- a/content/en/latest/download/_index.md
+++ b/content/en/latest/download/_index.md
@@ -4,9 +4,6 @@ type: docs
title: "Download"
linkTitle: "Download"
weight: 20
-menu:
- main:
- weight: 30
---