| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – Rust</title><link>https://dubbo.apache.org/en/docs3-v2/rust-sdk/</link><description>Recent content in Rust on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://dubbo.apache.org/en/docs3-v2/rust-sdk/index.xml" rel="self" type="application/rss+xml"/><item><title>Docs3-V2: Quick start</title><link>https://dubbo.apache.org/en/docs3-v2/rust-sdk/quick-start/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs3-v2/rust-sdk/quick-start/</guid><description> |
| <p>See the full example <a href="https://github.com/apache/dubbo-rust/tree/main/examples/greeter">here</a>.</p> |
| <h2 id="1-prerequisite">1 Prerequisite</h2> |
| <ul> |
| <li>Install <a href="https://rustup.rs/">Rust development environment</a>.</li> |
| <li>Install <a href="https://grpc.io/docs/protoc-installation/">protoc</a>.</li> |
| </ul> |
| <h2 id="2-use-idl-to-define-dubbo-service">2 Use IDL to define Dubbo service</h2> |
| <p>The Greeter service is defined as follows, contains a Unary, Client stream, Server stream, Bidirectional stream model Dubbo service:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-protobuf" data-lang="protobuf"><span style="display:flex;"><span><span style="color:#586e75">// ./proto/greeter.proto |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>syntax <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;proto3&#34;</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">option</span> java_multiple_files <span style="color:#719e07">=</span> <span style="color:#cb4b16">true</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> org<span style="color:#719e07">.</span>apache.dubbo.sample.tri; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The request message containing the user&#39;s name. |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">message</span> <span style="color:#268bd2">GreeterRequest</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> name <span style="color:#719e07">=</span> <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The response message containing the greetings |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">message</span> <span style="color:#268bd2">GreeterReply</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> <span style="color:#268bd2">message</span> <span style="color:#719e07">=</span> <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">service</span> Greeter{ |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// unary |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">rpc</span> greet(GreeterRequest) <span style="color:#719e07">returns</span> (GreeterReply); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// clientStream |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">rpc</span> greetClientStream(stream GreeterRequest) <span style="color:#719e07">returns</span> (GreeterReply); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// serverStream |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">rpc</span> greetServerStream(GreeterRequest) <span style="color:#719e07">returns</span> (stream GreeterReply); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// bi streaming |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">rpc</span> greetStream(stream GreeterRequest) <span style="color:#719e07">returns</span> (stream GreeterReply); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h2 id="3-add-dubbo-rust-and-other-dependencies">3 Add Dubbo-rust and other dependencies</h2> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#586e75"># ./Cargo.toml</span> |
| </span></span><span style="display:flex;"><span>[package] |
| </span></span><span style="display:flex;"><span>name = <span style="color:#2aa198">&#34;example-greeter&#34;</span> |
| </span></span><span style="display:flex;"><span>version = <span style="color:#2aa198">&#34;0.1.0&#34;</span> |
| </span></span><span style="display:flex;"><span>edition = <span style="color:#2aa198">&#34;2021&#34;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>[[bin]] |
| </span></span><span style="display:flex;"><span>name = <span style="color:#2aa198">&#34;greeter-server&#34;</span> |
| </span></span><span style="display:flex;"><span>path = <span style="color:#2aa198">&#34;src/greeter/server.rs&#34;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>[[bin]] |
| </span></span><span style="display:flex;"><span>name = <span style="color:#2aa198">&#34;greeter-client&#34;</span> |
| </span></span><span style="display:flex;"><span>path = <span style="color:#2aa198">&#34;src/greeter/client.rs&#34;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>[dependencies] |
| </span></span><span style="display:flex;"><span>http = <span style="color:#2aa198">&#34;0.2&#34;</span> |
| </span></span><span style="display:flex;"><span>http-body = <span style="color:#2aa198">&#34;0.4.4&#34;</span> |
| </span></span><span style="display:flex;"><span>futures-util = {version = <span style="color:#2aa198">&#34;0.3&#34;</span>, default-features = <span style="color:#cb4b16">false</span>} |
| </span></span><span style="display:flex;"><span>tokio = { version = <span style="color:#2aa198">&#34;1.0&#34;</span>, features = [ <span style="color:#2aa198">&#34;rt-multi-thread&#34;</span>, <span style="color:#2aa198">&#34;time&#34;</span>, <span style="color:#2aa198">&#34;fs&#34;</span>, <span style="color:#2aa198">&#34;macros&#34;</span>, <span style="color:#2aa198">&#34;net&#34;</span>, <span style="color:#2aa198">&#34;signal&#34;</span>] } |
| </span></span><span style="display:flex;"><span>prost-derive = {version = <span style="color:#2aa198">&#34;0.10&#34;</span>, optional = <span style="color:#cb4b16">true</span>} |
| </span></span><span style="display:flex;"><span>prost = <span style="color:#2aa198">&#34;0.10.4&#34;</span> |
| </span></span><span style="display:flex;"><span>async-trait = <span style="color:#2aa198">&#34;0.1.56&#34;</span> |
| </span></span><span style="display:flex;"><span>tokio-stream = <span style="color:#2aa198">&#34;0.1&#34;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>dubbo = <span style="color:#2aa198">&#34;0.1.0&#34;</span> |
| </span></span><span style="display:flex;"><span>dubbo-config = <span style="color:#2aa198">&#34;0.1.0&#34;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>[build-dependencies] |
| </span></span><span style="display:flex;"><span>dubbo-build = <span style="color:#2aa198">&#34;0.1.0&#34;</span> |
| </span></span></code></pre></div><h2 id="4-configure-dubbo-build-to-compile-idl">4 Configure dubbo-build to compile IDL</h2> |
| <p>Create <code>build.rs</code> at project root directory:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#586e75">// ./build.rs |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#719e07">fn</span> <span style="color:#268bd2">main</span>() -&gt; <span style="color:#b58900">Result</span><span style="color:#719e07">&lt;</span>(), <span style="color:#b58900">Box</span><span style="color:#719e07">&lt;</span><span style="color:#719e07">dyn</span> std::error::Error<span style="color:#719e07">&gt;&gt;</span> { |
| </span></span><span style="display:flex;"><span> tonic_build::compile_protos(<span style="color:#2aa198">&#34;proto/helloworld.proto&#34;</span>)<span style="color:#719e07">?</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(()) |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>After this configuration, the project compiling will generate Dubbo stub code, where the path is usually located <code>./target/debug/build/example-greeter-&lt;id&gt;/out/org.apache.dubbo.sample.tri.rs</code>.</p> |
| <h2 id="5-implement-server-and-client">5 Implement server and client</h2> |
| <h3 id="51-write-dubbo-rust-server">5.1 Write Dubbo-rust Server</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#586e75">// ./src/greeter/server.rs |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#719e07">pub</span> <span style="color:#719e07">mod</span> protos { |
| </span></span><span style="display:flex;"><span> include!(concat!(env!(<span style="color:#2aa198">&#34;OUT_DIR&#34;</span>), <span style="color:#2aa198">&#34;/org.apache.dubbo.sample.tri.rs&#34;</span>)); |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> futures_util::StreamExt; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> protos::{ |
| </span></span><span style="display:flex;"><span> greeter_server::{register_server, Greeter}, |
| </span></span><span style="display:flex;"><span> GreeterReply, GreeterRequest, |
| </span></span><span style="display:flex;"><span>}; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> std::{io::ErrorKind, pin::Pin}; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> async_trait::async_trait; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> futures_util::Stream; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> tokio::sync::mpsc; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> tokio_stream::wrappers::ReceiverStream; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> dubbo_config::RootConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> dubbo::{codegen::<span style="color:#719e07">*</span>, Dubbo}; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">type</span> <span style="color:#268bd2">ResponseStream</span> <span style="color:#719e07">=</span> |
| </span></span><span style="display:flex;"><span> Pin<span style="color:#719e07">&lt;</span><span style="color:#b58900">Box</span><span style="color:#719e07">&lt;</span><span style="color:#719e07">dyn</span> Stream<span style="color:#719e07">&lt;</span>Item <span style="color:#719e07">=</span> <span style="color:#b58900">Result</span><span style="color:#719e07">&lt;</span>GreeterReply, dubbo::status::Status<span style="color:#719e07">&gt;&gt;</span> <span style="color:#719e07">+</span> <span style="color:#b58900">Send</span><span style="color:#719e07">&gt;&gt;</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">#[tokio::main]</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">async</span> <span style="color:#719e07">fn</span> <span style="color:#268bd2">main</span>() { |
| </span></span><span style="display:flex;"><span> register_server(GreeterServerImpl { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;greeter&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// Dubbo::new().start().await; |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> Dubbo::new() |
| </span></span><span style="display:flex;"><span> .with_config({ |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> r <span style="color:#719e07">=</span> RootConfig::new(); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">match</span> r.load() { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(config) <span style="color:#719e07">=&gt;</span> config, |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Err</span>(_err) <span style="color:#719e07">=&gt;</span> panic!(<span style="color:#2aa198">&#34;err: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, _err), <span style="color:#586e75">// response was droped |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> } |
| </span></span><span style="display:flex;"><span> }) |
| </span></span><span style="display:flex;"><span> .start() |
| </span></span><span style="display:flex;"><span> .<span style="color:#719e07">await</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">#[allow(dead_code)]</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">#[derive(Default, Clone)]</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">struct</span> <span style="color:#268bd2">GreeterServerImpl</span> { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#b58900">String</span>, |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// #[async_trait] |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#719e07">#[async_trait]</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">impl</span> Greeter <span style="color:#719e07">for</span> GreeterServerImpl { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">async</span> <span style="color:#719e07">fn</span> <span style="color:#268bd2">greet</span>( |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">&amp;</span><span style="color:#268bd2">self</span>, |
| </span></span><span style="display:flex;"><span> request: <span style="color:#268bd2">Request</span><span style="color:#719e07">&lt;</span>GreeterRequest<span style="color:#719e07">&gt;</span>, |
| </span></span><span style="display:flex;"><span> ) -&gt; <span style="color:#b58900">Result</span><span style="color:#719e07">&lt;</span>Response<span style="color:#719e07">&lt;</span>GreeterReply<span style="color:#719e07">&gt;</span>, dubbo::status::Status<span style="color:#719e07">&gt;</span> { |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;GreeterServer::greet </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, request.metadata); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(Response::new(GreeterReply { |
| </span></span><span style="display:flex;"><span> message: <span style="color:#2aa198">&#34;hello, dubbo-rust&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> })) |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">async</span> <span style="color:#719e07">fn</span> <span style="color:#268bd2">greet_client_stream</span>( |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">&amp;</span><span style="color:#268bd2">self</span>, |
| </span></span><span style="display:flex;"><span> request: <span style="color:#268bd2">Request</span><span style="color:#719e07">&lt;</span>Decoding<span style="color:#719e07">&lt;</span>GreeterRequest<span style="color:#719e07">&gt;&gt;</span>, |
| </span></span><span style="display:flex;"><span> ) -&gt; <span style="color:#b58900">Result</span><span style="color:#719e07">&lt;</span>Response<span style="color:#719e07">&lt;</span>GreeterReply<span style="color:#719e07">&gt;</span>, dubbo::status::Status<span style="color:#719e07">&gt;</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> <span style="color:#719e07">mut</span> s <span style="color:#719e07">=</span> request.into_inner(); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">loop</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> result <span style="color:#719e07">=</span> s.next().<span style="color:#719e07">await</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">match</span> result { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Some</span>(<span style="color:#b58900">Ok</span>(val)) <span style="color:#719e07">=&gt;</span> println!(<span style="color:#2aa198">&#34;result: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, val), |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Some</span>(<span style="color:#b58900">Err</span>(val)) <span style="color:#719e07">=&gt;</span> println!(<span style="color:#2aa198">&#34;err: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, val), |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">None</span> <span style="color:#719e07">=&gt;</span> <span style="color:#719e07">break</span>, |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(Response::new(GreeterReply { |
| </span></span><span style="display:flex;"><span> message: <span style="color:#2aa198">&#34;hello client streaming&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> })) |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">type</span> <span style="color:#268bd2">greetServerStreamStream</span> <span style="color:#719e07">=</span> ResponseStream; |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">async</span> <span style="color:#719e07">fn</span> <span style="color:#268bd2">greet_server_stream</span>( |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">&amp;</span><span style="color:#268bd2">self</span>, |
| </span></span><span style="display:flex;"><span> request: <span style="color:#268bd2">Request</span><span style="color:#719e07">&lt;</span>GreeterRequest<span style="color:#719e07">&gt;</span>, |
| </span></span><span style="display:flex;"><span> ) -&gt; <span style="color:#b58900">Result</span><span style="color:#719e07">&lt;</span>Response<span style="color:#719e07">&lt;</span><span style="color:#268bd2">Self</span>::greetServerStreamStream<span style="color:#719e07">&gt;</span>, dubbo::status::Status<span style="color:#719e07">&gt;</span> { |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;greet_server_stream: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, request.into_inner()); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> data <span style="color:#719e07">=</span> vec![ |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Result</span>::<span style="color:#719e07">&lt;</span>_, dubbo::status::Status<span style="color:#719e07">&gt;</span>::<span style="color:#b58900">Ok</span>(GreeterReply { |
| </span></span><span style="display:flex;"><span> message: <span style="color:#2aa198">&#34;msg1 from server&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }), |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Result</span>::<span style="color:#719e07">&lt;</span>_, dubbo::status::Status<span style="color:#719e07">&gt;</span>::<span style="color:#b58900">Ok</span>(GreeterReply { |
| </span></span><span style="display:flex;"><span> message: <span style="color:#2aa198">&#34;msg2 from server&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }), |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Result</span>::<span style="color:#719e07">&lt;</span>_, dubbo::status::Status<span style="color:#719e07">&gt;</span>::<span style="color:#b58900">Ok</span>(GreeterReply { |
| </span></span><span style="display:flex;"><span> message: <span style="color:#2aa198">&#34;msg3 from server&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }), |
| </span></span><span style="display:flex;"><span> ]; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> resp <span style="color:#719e07">=</span> futures_util::stream::iter(data); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(Response::new(<span style="color:#b58900">Box</span>::pin(resp))) |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">type</span> <span style="color:#268bd2">greetStreamStream</span> <span style="color:#719e07">=</span> ResponseStream; |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">async</span> <span style="color:#719e07">fn</span> <span style="color:#268bd2">greet_stream</span>( |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">&amp;</span><span style="color:#268bd2">self</span>, |
| </span></span><span style="display:flex;"><span> request: <span style="color:#268bd2">Request</span><span style="color:#719e07">&lt;</span>Decoding<span style="color:#719e07">&lt;</span>GreeterRequest<span style="color:#719e07">&gt;&gt;</span>, |
| </span></span><span style="display:flex;"><span> ) -&gt; <span style="color:#b58900">Result</span><span style="color:#719e07">&lt;</span>Response<span style="color:#719e07">&lt;</span><span style="color:#268bd2">Self</span>::greetStreamStream<span style="color:#719e07">&gt;</span>, dubbo::status::Status<span style="color:#719e07">&gt;</span> { |
| </span></span><span style="display:flex;"><span> println!( |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;GreeterServer::greet_stream, grpc header: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, |
| </span></span><span style="display:flex;"><span> request.metadata |
| </span></span><span style="display:flex;"><span> ); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> <span style="color:#719e07">mut</span> in_stream <span style="color:#719e07">=</span> request.into_inner(); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> (tx, rx) <span style="color:#719e07">=</span> mpsc::channel(<span style="color:#2aa198">128</span>); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// this spawn here is required if you want to handle connection error. |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// If we just map `in_stream` and write it back as `out_stream` the `out_stream` |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// will be drooped when connection error occurs and error will never be propagated |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// to mapped version of `in_stream`. |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> tokio::spawn(<span style="color:#719e07">async</span> <span style="color:#719e07">move</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">while</span> <span style="color:#268bd2">let</span> <span style="color:#b58900">Some</span>(result) <span style="color:#719e07">=</span> in_stream.next().<span style="color:#719e07">await</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">match</span> result { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(v) <span style="color:#719e07">=&gt;</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// if v.name.starts_with(&#34;msg2&#34;) { |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// tx.send(Err(dubbo::status::Status::internal(format!(&#34;err: args is invalid, {:?}&#34;, v.name)) |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// )).await.expect(&#34;working rx&#34;); |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// continue; |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// } |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> tx.send(<span style="color:#b58900">Ok</span>(GreeterReply { |
| </span></span><span style="display:flex;"><span> message: <span style="color:#268bd2">format</span><span style="color:#719e07">!</span>(<span style="color:#2aa198">&#34;server reply: {:?}&#34;</span>, v.name), |
| </span></span><span style="display:flex;"><span> })) |
| </span></span><span style="display:flex;"><span> .<span style="color:#719e07">await</span> |
| </span></span><span style="display:flex;"><span> .expect(<span style="color:#2aa198">&#34;working rx&#34;</span>) |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Err</span>(err) <span style="color:#719e07">=&gt;</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#268bd2">let</span> <span style="color:#b58900">Some</span>(io_err) <span style="color:#719e07">=</span> match_for_io_error(<span style="color:#719e07">&amp;</span>err) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> io_err.kind() <span style="color:#719e07">==</span> ErrorKind::BrokenPipe { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// here you can handle special case when client |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// disconnected in unexpected way |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> eprintln!(<span style="color:#2aa198">&#34;</span><span style="color:#cb4b16">\t</span><span style="color:#2aa198">client disconnected: broken pipe&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">break</span>; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">match</span> tx.send(<span style="color:#b58900">Err</span>(err)).<span style="color:#719e07">await</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(_) <span style="color:#719e07">=&gt;</span> (), |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Err</span>(_err) <span style="color:#719e07">=&gt;</span> <span style="color:#719e07">break</span>, <span style="color:#586e75">// response was droped |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;</span><span style="color:#cb4b16">\t</span><span style="color:#2aa198">stream ended&#34;</span>); |
| </span></span><span style="display:flex;"><span> }); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// echo just write the same data that was received |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#268bd2">let</span> out_stream <span style="color:#719e07">=</span> ReceiverStream::new(rx); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(Response::new( |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Box</span>::pin(out_stream) <span style="color:#719e07">as</span> <span style="color:#268bd2">Self</span>::greetStreamStream |
| </span></span><span style="display:flex;"><span> )) |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">fn</span> <span style="color:#268bd2">match_for_io_error</span>(err_status: <span style="color:#719e07">&amp;</span><span style="color:#268bd2">dubbo</span>::status::Status) -&gt; <span style="color:#b58900">Option</span><span style="color:#719e07">&lt;&amp;</span>std::io::Error<span style="color:#719e07">&gt;</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> <span style="color:#719e07">mut</span> err: <span style="color:#719e07">&amp;</span>(<span style="color:#719e07">dyn</span> std::error::Error <span style="color:#719e07">+</span> <span style="color:#b58900">&#39;static</span>) <span style="color:#719e07">=</span> err_status; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">loop</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#268bd2">let</span> <span style="color:#b58900">Some</span>(io_err) <span style="color:#719e07">=</span> err.downcast_ref::<span style="color:#719e07">&lt;</span>std::io::Error<span style="color:#719e07">&gt;</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#b58900">Some</span>(io_err); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> err <span style="color:#719e07">=</span> <span style="color:#719e07">match</span> err.source() { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Some</span>(err) <span style="color:#719e07">=&gt;</span> err, |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">None</span> <span style="color:#719e07">=&gt;</span> <span style="color:#719e07">return</span> <span style="color:#b58900">None</span>, |
| </span></span><span style="display:flex;"><span> }; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h3 id="52-configure-dubboyaml">5.2 Configure dubbo.yaml</h3> |
| <p><code>dubbo.yaml</code> indicates the configuration of the server, including the exposed service list, protocol configuration, listening configuration, and so on.</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># ./dubbo.yaml</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">name</span>: dubbo |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">service</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">org.apache.dubbo.sample.tri.Greeter</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">version</span>: <span style="color:#2aa198">1.0.0</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">group</span>: test |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">protocol</span>: triple |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">registry</span>: <span style="color:#2aa198">&#39;&#39;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">serializer</span>: json |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">protocol_configs</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">triple</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">ip</span>: <span style="color:#2aa198">0.0.0.0</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">port</span>: <span style="color:#2aa198">&#39;8888&#39;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">name</span>: triple |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">protocols</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">triple</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">ip</span>: <span style="color:#2aa198">0.0.0.0</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">port</span>: <span style="color:#2aa198">&#39;8888&#39;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">name</span>: triple |
| </span></span></code></pre></div><h3 id="53-write-dubbo-rust-client">5.3 Write Dubbo-rust Client</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#586e75">// ./src/greeter/client.rs |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#719e07">pub</span> <span style="color:#719e07">mod</span> protos { |
| </span></span><span style="display:flex;"><span> include!(concat!(env!(<span style="color:#2aa198">&#34;OUT_DIR&#34;</span>), <span style="color:#2aa198">&#34;/org.apache.dubbo.sample.tri.rs&#34;</span>)); |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> dubbo::codegen::<span style="color:#719e07">*</span>; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> futures_util::StreamExt; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">use</span> protos::{greeter_client::GreeterClient, GreeterRequest}; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">#[tokio::main]</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">async</span> <span style="color:#719e07">fn</span> <span style="color:#268bd2">main</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> <span style="color:#719e07">mut</span> cli <span style="color:#719e07">=</span> GreeterClient::new().with_uri(<span style="color:#2aa198">&#34;http://127.0.0.1:8888&#34;</span>.to_string()); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;# unary call&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> resp <span style="color:#719e07">=</span> cli |
| </span></span><span style="display:flex;"><span> .greet(Request::new(GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;message from client&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> })) |
| </span></span><span style="display:flex;"><span> .<span style="color:#719e07">await</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> resp <span style="color:#719e07">=</span> <span style="color:#719e07">match</span> resp { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(resp) <span style="color:#719e07">=&gt;</span> resp, |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Err</span>(err) <span style="color:#719e07">=&gt;</span> <span style="color:#719e07">return</span> println!(<span style="color:#2aa198">&#34;</span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, err), |
| </span></span><span style="display:flex;"><span> }; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> (_parts, body) <span style="color:#719e07">=</span> resp.into_parts(); |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;Response: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, body); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;# client stream&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> data <span style="color:#719e07">=</span> vec![ |
| </span></span><span style="display:flex;"><span> GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;msg1 from client streaming&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }, |
| </span></span><span style="display:flex;"><span> GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;msg2 from client streaming&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }, |
| </span></span><span style="display:flex;"><span> GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;msg3 from client streaming&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }, |
| </span></span><span style="display:flex;"><span> ]; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> req <span style="color:#719e07">=</span> futures_util::stream::iter(data); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> resp <span style="color:#719e07">=</span> cli.greet_client_stream(req).<span style="color:#719e07">await</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> client_streaming_resp <span style="color:#719e07">=</span> <span style="color:#719e07">match</span> resp { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(resp) <span style="color:#719e07">=&gt;</span> resp, |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Err</span>(err) <span style="color:#719e07">=&gt;</span> <span style="color:#719e07">return</span> println!(<span style="color:#2aa198">&#34;</span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, err), |
| </span></span><span style="display:flex;"><span> }; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> (_parts, resp_body) <span style="color:#719e07">=</span> client_streaming_resp.into_parts(); |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;client streaming, Response: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, resp_body); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;# bi stream&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> data <span style="color:#719e07">=</span> vec![ |
| </span></span><span style="display:flex;"><span> GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;msg1 from client&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }, |
| </span></span><span style="display:flex;"><span> GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;msg2 from client&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }, |
| </span></span><span style="display:flex;"><span> GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;msg3 from client&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> }, |
| </span></span><span style="display:flex;"><span> ]; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> req <span style="color:#719e07">=</span> futures_util::stream::iter(data); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> bidi_resp <span style="color:#719e07">=</span> cli.greet_stream(req).<span style="color:#719e07">await</span>.unwrap(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> (parts, <span style="color:#719e07">mut</span> body) <span style="color:#719e07">=</span> bidi_resp.into_parts(); |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;parts: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, parts); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">while</span> <span style="color:#268bd2">let</span> <span style="color:#b58900">Some</span>(item) <span style="color:#719e07">=</span> body.next().<span style="color:#719e07">await</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">match</span> item { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(v) <span style="color:#719e07">=&gt;</span> { |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;reply: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, v); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Err</span>(err) <span style="color:#719e07">=&gt;</span> { |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;err: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, err); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> trailer <span style="color:#719e07">=</span> body.trailer().<span style="color:#719e07">await</span>.unwrap(); |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;trailer: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, trailer); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;# server stream&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> resp <span style="color:#719e07">=</span> cli |
| </span></span><span style="display:flex;"><span> .greet_server_stream(Request::new(GreeterRequest { |
| </span></span><span style="display:flex;"><span> name: <span style="color:#2aa198">&#34;server streaming req&#34;</span>.to_string(), |
| </span></span><span style="display:flex;"><span> })) |
| </span></span><span style="display:flex;"><span> .<span style="color:#719e07">await</span> |
| </span></span><span style="display:flex;"><span> .unwrap(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> (parts, <span style="color:#719e07">mut</span> body) <span style="color:#719e07">=</span> resp.into_parts(); |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;parts: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, parts); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">while</span> <span style="color:#268bd2">let</span> <span style="color:#b58900">Some</span>(item) <span style="color:#719e07">=</span> body.next().<span style="color:#719e07">await</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">match</span> item { |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Ok</span>(v) <span style="color:#719e07">=&gt;</span> { |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;reply: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, v); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#b58900">Err</span>(err) <span style="color:#719e07">=&gt;</span> { |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;err: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, err); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">let</span> trailer <span style="color:#719e07">=</span> body.trailer().<span style="color:#719e07">await</span>.unwrap(); |
| </span></span><span style="display:flex;"><span> println!(<span style="color:#2aa198">&#34;trailer: </span><span style="color:#2aa198">{:?}</span><span style="color:#2aa198">&#34;</span>, trailer); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h2 id="6-run">6 Run</h2> |
| <ol> |
| <li>Compile</li> |
| </ol> |
| <p>Run <code>cargo build</code> to compile server and client.</p> |
| <ol start="2"> |
| <li>Run server</li> |
| </ol> |
| <p>Run <code>./target/debug/greeter-server</code> to start server. as configured above by dubbo.yaml, the server listens on port 8888 and provides RPC services over triple protocol:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ ./target/debug/greeter-server |
| </span></span><span style="display:flex;"><span>2022-09-28T23:33:28.104577Z INFO dubbo::framework: url: Some<span style="color:#719e07">(</span>Url <span style="color:#719e07">{</span> uri: <span style="color:#2aa198">&#34;triple://0.0.0.0:8888/org.apache.dubbo.sample.tri.Greeter&#34;</span>, protocol: <span style="color:#2aa198">&#34;triple&#34;</span>, location: <span style="color:#2aa198">&#34;0.0.0.0:8888&#34;</span>, ip: <span style="color:#2aa198">&#34;0.0.0.0&#34;</span>, port: <span style="color:#2aa198">&#34;8888&#34;</span>, service_key: <span style="color:#719e07">[</span><span style="color:#2aa198">&#34;org.apache.dubbo.sample.tri.Greeter&#34;</span><span style="color:#719e07">]</span>, params: <span style="color:#719e07">{}</span> <span style="color:#719e07">})</span> |
| </span></span></code></pre></div><ol start="3"> |
| <li>Run client, verify that the call was successful</li> |
| </ol> |
| <p>Run <code>./target/debug/greeter-client</code> to start client, which will call methods under <code>triple://127.0.0.1:8888/org.apache.dubbo.sample.tri.Greeter</code>:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ ./target/debug/greeter-client |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># unary call</span> |
| </span></span><span style="display:flex;"><span>Response: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;hello, dubbo-rust&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># client stream</span> |
| </span></span><span style="display:flex;"><span>client streaming, Response: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;hello client streaming&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># bi stream</span> |
| </span></span><span style="display:flex;"><span>parts: Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;date&#34;</span>: <span style="color:#2aa198">&#34;Wed, 28 Sep 2022 23:34:20 GMT&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;server reply: \&#34;msg1 from client\&#34;&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;server reply: \&#34;msg2 from client\&#34;&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;server reply: \&#34;msg3 from client\&#34;&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>trailer: Some<span style="color:#719e07">(</span>Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;grpc-status&#34;</span>: <span style="color:#2aa198">&#34;0&#34;</span>, <span style="color:#2aa198">&#34;grpc-message&#34;</span>: <span style="color:#2aa198">&#34;poll trailer successfully.&#34;</span>, <span style="color:#2aa198">&#34;grpc-accept-encoding&#34;</span>: <span style="color:#2aa198">&#34;gzip,identity&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># server stream</span> |
| </span></span><span style="display:flex;"><span>parts: Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;date&#34;</span>: <span style="color:#2aa198">&#34;Wed, 28 Sep 2022 23:34:20 GMT&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;msg1 from server&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;msg2 from server&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;msg3 from server&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>trailer: Some<span style="color:#719e07">(</span>Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;grpc-status&#34;</span>: <span style="color:#2aa198">&#34;0&#34;</span>, <span style="color:#2aa198">&#34;grpc-message&#34;</span>: <span style="color:#2aa198">&#34;poll trailer successfully.&#34;</span>, <span style="color:#2aa198">&#34;grpc-accept-encoding&#34;</span>: <span style="color:#2aa198">&#34;gzip,identity&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">})</span> |
| </span></span></code></pre></div></description></item><item><title>Docs3-V2: Rust and Java interoperability</title><link>https://dubbo.apache.org/en/docs3-v2/rust-sdk/java-interoperability/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/en/docs3-v2/rust-sdk/java-interoperability/</guid><description> |
| <h2 id="1-prerequisite">1 Prerequisite</h2> |
| <ul> |
| <li>Install <a href="https://rustup.rs/">Rust development environment</a>.</li> |
| <li>Install <a href="https://grpc.io/docs/protoc-installation/">protoc</a>.</li> |
| <li>Install Java development environment.</li> |
| </ul> |
| <h2 id="2-run-example-of-java-dubbo-provider">2 Run example of Java Dubbo provider</h2> |
| <p>Java version of Dubbo provider example <a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple">https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple</a>.</p> |
| <p>Clone the source code, compile, and run provider:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ <span style="color:#586e75"># clone the source code</span> |
| </span></span><span style="display:flex;"><span>$ git clone https://github.com/apache/dubbo-samples.git |
| </span></span><span style="display:flex;"><span>$ <span style="color:#b58900">cd</span> dubbo-samples/dubbo-samples-triple/ |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>$ <span style="color:#586e75"># compile and build</span> |
| </span></span><span style="display:flex;"><span>$ mvn clean compile package -DskipTests |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>$ <span style="color:#586e75"># run provider</span> |
| </span></span><span style="display:flex;"><span>$ java -Dprovider.port<span style="color:#719e07">=</span><span style="color:#2aa198">8888</span> -jar ./target/dubbo-samples-triple-1.0-SNAPSHOT.jar |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># … some logs</span> |
| </span></span><span style="display:flex;"><span>Dubbo triple stub server started, <span style="color:#268bd2">port</span><span style="color:#719e07">=</span><span style="color:#2aa198">8888</span> |
| </span></span></code></pre></div><p><a href="https://github.com/apache/dubbo-samples/blob/master/3-extensions/protocol/dubbo-samples-triple/src/main/proto/greeter.proto">The interface defination on Java side</a></p> |
| <h2 id="3-run-rust-version-of--dubbo-consumer">3 Run Rust version of Dubbo consumer</h2> |
| <p>Rust version of Dubbo consumer <a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple">https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple</a>.</p> |
| <p>Clone the source code, compile and run consumer:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ <span style="color:#586e75"># clone the source code</span> |
| </span></span><span style="display:flex;"><span>$ git clone https://github.com/apache/dubbo-rust.git |
| </span></span><span style="display:flex;"><span>$ <span style="color:#b58900">cd</span> dubbo-rust/examples/greeter/ |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>$ <span style="color:#586e75"># build</span> |
| </span></span><span style="display:flex;"><span>$ cargo build |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>$ <span style="color:#586e75"># run consumer, call provider</span> |
| </span></span><span style="display:flex;"><span>$ ../../target/debug/greeter-client |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># unary call</span> |
| </span></span><span style="display:flex;"><span>Response: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;hello, dubbo-rust&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># client stream</span> |
| </span></span><span style="display:flex;"><span>client streaming, Response: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;hello client streaming&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># bi stream</span> |
| </span></span><span style="display:flex;"><span>parts: Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;date&#34;</span>: <span style="color:#2aa198">&#34;Wed, 28 Sep 2022 23:54:56 GMT&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;server reply: \&#34;msg1 from client\&#34;&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;server reply: \&#34;msg2 from client\&#34;&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;server reply: \&#34;msg3 from client\&#34;&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>trailer: Some<span style="color:#719e07">(</span>Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;grpc-message&#34;</span>: <span style="color:#2aa198">&#34;poll trailer successfully.&#34;</span>, <span style="color:#2aa198">&#34;grpc-accept-encoding&#34;</span>: <span style="color:#2aa198">&#34;gzip,identity&#34;</span>, <span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;grpc-status&#34;</span>: <span style="color:#2aa198">&#34;0&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># server stream</span> |
| </span></span><span style="display:flex;"><span>parts: Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;date&#34;</span>: <span style="color:#2aa198">&#34;Wed, 28 Sep 2022 23:54:56 GMT&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;msg1 from server&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;msg2 from server&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: GreeterReply <span style="color:#719e07">{</span> message: <span style="color:#2aa198">&#34;msg3 from server&#34;</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>trailer: Some<span style="color:#719e07">(</span>Metadata <span style="color:#719e07">{</span> inner: <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span>, <span style="color:#2aa198">&#34;grpc-message&#34;</span>: <span style="color:#2aa198">&#34;poll trailer successfully.&#34;</span>, <span style="color:#2aa198">&#34;grpc-accept-encoding&#34;</span>: <span style="color:#2aa198">&#34;gzip,identity&#34;</span>, <span style="color:#2aa198">&#34;grpc-status&#34;</span>: <span style="color:#2aa198">&#34;0&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">})</span> |
| </span></span></code></pre></div><p><a href="https://github.com/apache/dubbo-rust/blob/main/examples/greeter/proto/greeter.proto">The interface defination on Rust side</a></p></description></item></channel></rss> |