| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – Rust SDK 手册</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/</link><description>Recent content in Rust SDK 手册 on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview: 快速开始</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/quick-start/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/quick-start/</guid><description> |
| <p>请在此查看完整 <a href="https://github.com/apache/dubbo-rust/tree/main/examples/greeter">示例</a>。</p> |
| <h2 id="1-前置条件">1 前置条件</h2> |
| <ul> |
| <li>安装 <a href="https://rustup.rs/">Rust</a> 开发环境</li> |
| <li>安装 <a href="https://grpc.io/docs/protoc-installation/">protoc</a> 工具</li> |
| </ul> |
| <h2 id="2-使用-idl-定义-dubbo-服务">2 使用 IDL 定义 Dubbo 服务</h2> |
| <p>Greeter 服务定义如下,包含一个 Unary(request-response) 模型的 Dubbo 服务。</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 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></code></pre></div><h2 id="3-添加-dubbo-rust-及相关依赖到项目">3 添加 Dubbo-rust 及相关依赖到项目</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-配置-dubbo-build-编译-idl">4 配置 dubbo-build 编译 IDL</h2> |
| <p>在项目根目录创建 (not /src),创建 <code>build.rs</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-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>() { |
| </span></span><span style="display:flex;"><span> dubbo_build::prost::configure() |
| </span></span><span style="display:flex;"><span> .compile(<span style="color:#719e07">&amp;</span>[<span style="color:#2aa198">&#34;proto/greeter.proto&#34;</span>], <span style="color:#719e07">&amp;</span>[<span style="color:#2aa198">&#34;proto/&#34;</span>]) |
| </span></span><span style="display:flex;"><span> .unwrap(); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>这样配置之后,编译项目就可以生成 Dubbo Stub 相关代码,路径一般在<code>./target/debug/build/example-greeter-&lt;id&gt;/out/org.apache.dubbo.sample.tri.rs</code>。</p> |
| <h2 id="5-编写-dubbo-业务代码">5 编写 Dubbo 业务代码</h2> |
| <h3 id="51-编写-dubbo-server">5.1 编写 Dubbo 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">use</span> <span style="color:#719e07">..</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></code></pre></div><h3 id="52-配置dubboyaml">5.2 配置dubbo.yaml</h3> |
| <p>dubbo.yaml指示server端的配置,包括暴露的服务列表、协议配置、监听配置等。</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-编写-dubbo-client">5.3 编写 Dubbo 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">use</span> <span style="color:#719e07">..</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> <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></code></pre></div><h2 id="6-运行并总结">6 运行并总结</h2> |
| <ol> |
| <li>编译</li> |
| </ol> |
| <p>执行<code>cargo build</code>来编译server和client。</p> |
| <ol start="2"> |
| <li>运行server</li> |
| </ol> |
| <p>执行<code>./target/debug/greeter-server</code>来运行server,如上文dubbo.yaml所配置,server会监听8888端口,并以triple协议提供RPC服务:</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>运行client,验证调用是否成功</li> |
| </ol> |
| <p>执行<code>./target/debug/greeter-client</code>来运行client,调用<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>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></code></pre></div></description></item><item><title>Overview: Rust和Java互相调用</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/java-interoperability/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/java-interoperability/</guid><description> |
| <h2 id="1-前置条件">1 前置条件</h2> |
| <ul> |
| <li>安装 <a href="https://rustup.rs/">Rust</a> 开发环境</li> |
| <li>安装 <a href="https://grpc.io/docs/protoc-installation/">protoc</a> 工具</li> |
| <li>安装 Java 开发环境</li> |
| </ul> |
| <h2 id="2-运行示例-java-版本的-dubbo-provider">2 运行示例 Java 版本的 Dubbo provider</h2> |
| <p>Java 版本的 Dubbo provider 示例源码见<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 源代码、编译构建,并运行 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 源代码</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"># 构建</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"># 运行 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"># ……省略部分日志</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">Java 侧的接口定义</a></p> |
| <h2 id="3-运行-rust-版本的-dubbo-consumer">3 运行 Rust 版本的 Dubbo consumer</h2> |
| <p>Rust 版本的 Dubbo consumer 示例源码见<a href="https://github.com/apache/dubbo-rust/tree/main/examples/greeter">https://github.com/apache/dubbo-rust/tree/main/examples/greeter</a>。</p> |
| <p>Clone 源代码、编译构建,并运行 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 源代码</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"># 构建</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"># 运行 consumer,调用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">Rust侧的接口定义</a></p></description></item><item><title>Overview: Streaming 通信模型</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/streaming/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/streaming/</guid><description> |
| <p>本文重点讲解 Dubbo Rust Streaming 通信模式,请先查看 <a href="../quick-start">Quick Start</a> 了解 Dubbo Rust 基本使用,在此查看本文的<a href="https://github.com/apache/dubbo-rust/tree/main/examples/greeter">完整示例</a>。</p> |
| <h2 id="1-idl-中增加-streaming-模型定义">1 IDL 中增加 Streaming 模型定义</h2> |
| <p>完整 Greeter 服务定义如下,包含一个 Unary、Client stream、Server stream、Bidirectional stream 模型的 Dubbo 服务。</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="2-使用-streaming-模型定义编写逻辑">2 使用 Streaming 模型定义编写逻辑</h2> |
| <h3 id="21-编写-streaming-server">2.1 编写 Streaming 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="22-编写-streaming-client">2.2 编写 Streaming 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="3-运行示例">3 运行示例</h2> |
| <ol> |
| <li>编译</li> |
| </ol> |
| <p>执行<code>cargo build</code>来编译server和client。</p> |
| <ol start="2"> |
| <li>运行server</li> |
| </ol> |
| <p>执行<code>./target/debug/greeter-server</code>来运行server,如上文dubbo.yaml所配置,server会监听8888端口,并以triple协议提供RPC服务:</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>运行client,可以看到 Streaming 通信效果</li> |
| </ol> |
| <p>执行<code>./target/debug/greeter-client</code>来运行client,调用<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>Overview: 使用Unix套接字连接器通信</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/unix-transport/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/rust-sdk/unix-transport/</guid><description> |
| <p>本文重点讲解 Dubbo Rust Triple 协议使用Unix 套接,请先查看 <a href="../quick-start">Quick Start</a> 了解 Dubbo Rust 基本使用,在此查看本文的<a href="https://github.com/apache/dubbo-rust/tree/main/examples/greeter">完整示例</a>。</p> |
| <h2 id="1-使用-unix-套接字连接器-说明">1 使用 Unix 套接字连接器 说明</h2> |
| <blockquote> |
| <p>#[cfg(any(target_os = &ldquo;macos&rdquo;, target_os=&ldquo;unix&rdquo;))] 当操作系统符合cfg配置时,unix 模块会被编译使用,否则无法使用</p> |
| </blockquote> |
| <h2 id="2-使用-clientconnection-使用-unix-套接字连接器编写逻辑">2 使用 client/connection 使用 Unix 套接字连接器编写逻辑</h2> |
| <h3 id="21-编写-client-端">2.1 编写 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">// examples/echo/src/echo/client.rs |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75">// 使用 ClientBuilder 初始化 Client |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">let</span> builder <span style="color:#719e07">=</span> ClientBuilder::new().with_connector(<span style="color:#2aa198">&#34;unix&#34;</span>).with_host(<span style="color:#2aa198">&#34;unix://127.0.0.1:8888&#34;</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> EchoClient::build(builder); |
| </span></span></code></pre></div><h3 id="22-编写-server-端">2.2 编写 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">// examples/echo/src/echo/server.rs |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75">// 通过 serverbuilder 来初始化 Server |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">let</span> builder <span style="color:#719e07">=</span> ServerBuilder::new() |
| </span></span><span style="display:flex;"><span> .with_listener(<span style="color:#2aa198">&#34;unix&#34;</span>.to_string()) |
| </span></span><span style="display:flex;"><span> .with_service_names(vec![<span style="color:#2aa198">&#34;grpc.examples.echo.Echo&#34;</span>.to_string()]) |
| </span></span><span style="display:flex;"><span> .with_addr(<span style="color:#2aa198">&#34;127.0.0.1:8888&#34;</span>); |
| </span></span><span style="display:flex;"><span>builder.build().serve().<span style="color:#719e07">await</span>.unwrap(); |
| </span></span></code></pre></div><h2 id="3-运行示例">3 运行示例</h2> |
| <ol> |
| <li>编译</li> |
| </ol> |
| <p>执行<code>cargo build</code>来编译server和client。</p> |
| <ol start="2"> |
| <li>运行server</li> |
| </ol> |
| <p>执行<code>cargo run --bin echo-server</code>来运行server,如上文dubbo.yaml所配置,server会监听8888端口,并以triple协议提供RPC服务:</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>$ cargo run --bin echo-server |
| </span></span><span style="display:flex;"><span>2023-01-19T08:36:25.663138Z INFO dubbo::triple::server::builder: server starting. addr: Some<span style="color:#719e07">(</span>127.0.0.1:8888<span style="color:#719e07">)</span> |
| </span></span></code></pre></div><ol start="3"> |
| <li>运行client,可以看到 Unix 通信效果</li> |
| </ol> |
| <p>执行<code>cargo run --bin echo-client</code>来运行client,调用<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>$ cargo run --bin echo-client |
| </span></span><span style="display:flex;"><span>2023-01-19T08:38:52.516792Z INFO dubbo::triple::transport::connector::unix_connector: host is ip address: <span style="color:#2aa198">&#34;127.0.0.1&#34;</span> |
| </span></span><span style="display:flex;"><span>Response: EchoResponse <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>2023-01-19T08:38:52.526697Z INFO dubbo::triple::transport::connector::unix_connector: host is ip address: <span style="color:#2aa198">&#34;127.0.0.1&#34;</span> |
| </span></span><span style="display:flex;"><span>client streaming, Response: EchoResponse <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>2023-01-19T08:38:52.539439Z INFO dubbo::triple::transport::connector::unix_connector: host is ip address: <span style="color:#2aa198">&#34;127.0.0.1&#34;</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;Thu, 19 Jan 2023 08:38:52 GMT&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: EchoResponse <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: EchoResponse <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: EchoResponse <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-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:#2aa198">&#34;grpc-message&#34;</span>: <span style="color:#2aa198">&#34;poll trailer successfully.&#34;</span>, <span style="color:#2aa198">&#34;content-type&#34;</span>: <span style="color:#2aa198">&#34;application/grpc&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span>2023-01-19T08:38:52.645035Z INFO dubbo::triple::transport::connector::unix_connector: host is ip address: <span style="color:#2aa198">&#34;127.0.0.1&#34;</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;Thu, 19 Jan 2023 08:38:52 GMT&#34;</span><span style="color:#719e07">}</span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span>reply: EchoResponse <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: EchoResponse <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: EchoResponse <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;grpc-status&#34;</span>: <span style="color:#2aa198">&#34;0&#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-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></channel></rss> |