| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – Dubbo3 通信协议 -- Triple</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/</link><description>Recent content in Dubbo3 通信协议 -- Triple on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview: 使用 IDL + Protobuf 跨语言定义服务</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/idl/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/idl/</guid><description> |
| <p>服务是 Dubbo 中的核心概念,一个服务代表一组 RPC 方法的集合,服务是面向用户编程、服务发现机制等的基本单位。Dubbo 开发的基本流程是:用户定义 RPC 服务,通过约定的配置 |
| 方式将 RPC 声明为 Dubbo 服务,然后就可以基于服务 API 进行编程了。对服务提供者来说是提供 RPC 服务的具体实现,而对服务消费者来说则是使用特定数据发起服务调用。</p> |
| <p>下面从定义服务、编译服务、配置并加载服务三个方面说明如何快速的开发 Dubbo 服务。</p> |
| <p>具体用例可以参考:<a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple/src/main/java/org/apache/dubbo/sample/tri/stub">dubbo-samples-triple/stub</a>;</p> |
| <h2 id="定义服务">定义服务</h2> |
| <p>Dubbo3 推荐使用 IDL 定义跨语言服务,如您更习惯使用特定语言的服务定义方式,请移步<a href="https://dubbo.apache.org/zh-cn/overview/mannual/">多语言 SDK</a>查看。</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-text" data-lang="text"><span style="display:flex;"><span>syntax = &#34;proto3&#34;; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>option java_multiple_files = true; |
| </span></span><span style="display:flex;"><span>option java_package = &#34;org.apache.dubbo.demo&#34;; |
| </span></span><span style="display:flex;"><span>option java_outer_classname = &#34;DemoServiceProto&#34;; |
| </span></span><span style="display:flex;"><span>option objc_class_prefix = &#34;DEMOSRV&#34;; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>package demoservice; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>// The demo service definition. |
| </span></span><span style="display:flex;"><span>service DemoService { |
| </span></span><span style="display:flex;"><span> rpc SayHello (HelloRequest) returns (HelloReply) {} |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>// The request message containing the user&#39;s name. |
| </span></span><span style="display:flex;"><span>message HelloRequest { |
| </span></span><span style="display:flex;"><span> string name = 1; |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>// The response message containing the greetings |
| </span></span><span style="display:flex;"><span>message HelloReply { |
| </span></span><span style="display:flex;"><span> string message = 1; |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>以上是使用 IDL 定义服务的一个简单示例,我们可以把它命名为 <code>DemoService.proto</code>,proto 文件中定义了 RPC 服务名称 <code>DemoService</code> 与方法签名 |
| <code>SayHello (HelloRequest) returns (HelloReply) {}</code>,同时还定义了方法的入参结构体、出参结构体 <code>HelloRequest</code> 与 <code>HelloReply</code>。 |
| IDL 格式的服务依赖 Protobuf 编译器,用来生成可以被用户调用的客户端与服务端编程 API,Dubbo 在原生 Protobuf Compiler 的基础上提供了适配多种语言的特有插件,用于适配 Dubbo 框架特有的 API 与编程模型。</p> |
| <blockquote> |
| <p>使用 Dubbo3 IDL 定义的服务只允许一个入参与出参,这种形式的服务签名有两个优势,一是对多语言实现更友好,二是可以保证服务的向后兼容性,依赖于 Protobuf 序列化的兼容性,我们可以很容易的调整传输的数据结构如增、删字段等,完全不用担心接口的兼容性。</p> |
| </blockquote> |
| <h2 id="编译服务">编译服务</h2> |
| <p>根据当前采用的语言,配置相应的 Protobuf 插件,编译后将生产语言相关的服务定义 stub。</p> |
| <h3 id="java">Java</h3> |
| <p>Java compiler 配置参考:</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.xolstice.maven.plugins<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>protobuf-maven-plugin<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>0.6.1<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;protocArtifact&gt;</span>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier} |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/protocArtifact&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;pluginId&gt;</span>grpc-java<span style="color:#268bd2">&lt;/pluginId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;pluginArtifact&gt;</span>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/pluginArtifact&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;protocPlugins&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;protocPlugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;id&gt;</span>dubbo<span style="color:#268bd2">&lt;/id&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.apache.dubbo<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>dubbo-compiler<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>3.0.10<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;mainClass&gt;</span>org.apache.dubbo.gen.tri.Dubbo3TripleGenerator<span style="color:#268bd2">&lt;/mainClass&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/protocPlugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/protocPlugins&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;executions&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goal&gt;</span>compile<span style="color:#268bd2">&lt;/goal&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goal&gt;</span>test-compile<span style="color:#268bd2">&lt;/goal&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goal&gt;</span>compile-custom<span style="color:#268bd2">&lt;/goal&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goal&gt;</span>test-compile-custom<span style="color:#268bd2">&lt;/goal&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/executions&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/plugin&gt;</span> |
| </span></span></code></pre></div><p>Java 语言生成的 stub 如下,核心是一个接口定义</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@javax.annotation.Generated</span>( |
| </span></span><span style="display:flex;"><span>value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;by Dubbo generator&#34;</span>, |
| </span></span><span style="display:flex;"><span>comments <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;Source: DemoService.proto&#34;</span>) |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">DemoService</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> String JAVA_SERVICE_NAME <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;org.apache.dubbo.demo.DemoService&#34;</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> String SERVICE_NAME <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;demoservice.DemoService&#34;</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> org.apache.dubbo.demo.HelloReply <span style="color:#268bd2">sayHello</span>(org.apache.dubbo.demo.HelloRequest request); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> CompletableFuture<span style="color:#719e07">&lt;</span>org.apache.dubbo.demo.HelloReply<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHelloAsync</span>(org.apache.dubbo.demo.HelloRequest request); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h3 id="golang">Golang</h3> |
| <p>Go 语言生成的 stub 如下,这个 stub 里存了用户定义的接口和数据的类型。</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-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">_DUBBO_Greeter_SayHello_Handler</span>(srv <span style="color:#268bd2">interface</span>{}, ctx context.Context, dec <span style="color:#268bd2">func</span>(<span style="color:#268bd2">interface</span>{}) <span style="color:#dc322f">error</span>, interceptor grpc.UnaryServerInterceptor) (<span style="color:#268bd2">interface</span>{}, <span style="color:#dc322f">error</span>) { |
| </span></span><span style="display:flex;"><span> in <span style="color:#719e07">:=</span> <span style="color:#b58900">new</span>(HelloRequest) |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> err <span style="color:#719e07">:=</span> <span style="color:#268bd2">dec</span>(in); err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#cb4b16">nil</span>, err |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> base <span style="color:#719e07">:=</span> srv.(dgrpc.Dubbo3GrpcService) |
| </span></span><span style="display:flex;"><span> args <span style="color:#719e07">:=</span> []<span style="color:#268bd2">interface</span>{}{} |
| </span></span><span style="display:flex;"><span> args = <span style="color:#b58900">append</span>(args, in) |
| </span></span><span style="display:flex;"><span> invo <span style="color:#719e07">:=</span> invocation.<span style="color:#268bd2">NewRPCInvocation</span>(<span style="color:#2aa198">&#34;SayHello&#34;</span>, args, <span style="color:#cb4b16">nil</span>) |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> interceptor <span style="color:#719e07">==</span> <span style="color:#cb4b16">nil</span> { |
| </span></span><span style="display:flex;"><span> result <span style="color:#719e07">:=</span> base.<span style="color:#268bd2">GetProxyImpl</span>().<span style="color:#268bd2">Invoke</span>(ctx, invo) |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> result.<span style="color:#268bd2">Result</span>(), result.<span style="color:#268bd2">Error</span>() |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> info <span style="color:#719e07">:=</span> <span style="color:#719e07">&amp;</span>grpc.UnaryServerInfo{ |
| </span></span><span style="display:flex;"><span> Server: srv, |
| </span></span><span style="display:flex;"><span> FullMethod: <span style="color:#2aa198">&#34;/main.Greeter/SayHello&#34;</span>, |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> handler <span style="color:#719e07">:=</span> <span style="color:#268bd2">func</span>(ctx context.Context, req <span style="color:#268bd2">interface</span>{}) (<span style="color:#268bd2">interface</span>{}, <span style="color:#dc322f">error</span>) { |
| </span></span><span style="display:flex;"><span> result <span style="color:#719e07">:=</span> base.<span style="color:#268bd2">GetProxyImpl</span>().<span style="color:#268bd2">Invoke</span>(context.<span style="color:#268bd2">Background</span>(), invo) |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> result.<span style="color:#268bd2">Result</span>(), result.<span style="color:#268bd2">Error</span>() |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#268bd2">interceptor</span>(ctx, in, info, handler) |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h2 id="配置并加载服务">配置并加载服务</h2> |
| <p>提供端负责提供具体的 Dubbo 服务实现,也就是遵循 RPC 签名所约束的格式,去实现具体的业务逻辑代码。在实现服务之后,要将服务实现注册为标准的 Dubbo 服务, |
| 之后 Dubbo 框架就能根据接收到的请求转发给服务实现,执行方法,并将结果返回。</p> |
| <p>消费端的配置会更简单一些,只需要声明 IDL 定义的服务为标准的 Dubbo 服务,框架就可以帮助开发者生成相应的 proxy,开发者将完全面向 proxy 编程, |
| 基本上 Dubbo 所有语言的实现都保证了 proxy 依据 IDL 服务定义暴露标准化的接口。</p> |
| <h3 id="java-1">Java</h3> |
| <p>提供端,实现服务</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">DemoServiceImpl</span> <span style="color:#268bd2">implements</span> DemoService { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> Logger logger <span style="color:#719e07">=</span> LoggerFactory.getLogger(DemoServiceImpl.class); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> HelloReply <span style="color:#268bd2">sayHello</span>(HelloRequest request) { |
| </span></span><span style="display:flex;"><span> logger.info(<span style="color:#2aa198">&#34;Hello &#34;</span> <span style="color:#719e07">+</span> request.getName() <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;, request from consumer: &#34;</span> <span style="color:#719e07">+</span> RpcContext.getContext().getRemoteAddress()); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> HelloReply.newBuilder() |
| </span></span><span style="display:flex;"><span> .setMessage(<span style="color:#2aa198">&#34;Hello &#34;</span> <span style="color:#719e07">+</span> request.getName() <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;, response from provider: &#34;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">+</span> RpcContext.getContext().getLocalAddress()) |
| </span></span><span style="display:flex;"><span> .build(); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> CompletableFuture<span style="color:#719e07">&lt;</span>HelloReply<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHelloAsync</span>(HelloRequest request) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> CompletableFuture.completedFuture(sayHello(request)); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>提供端,注册服务(以 Spring XML 为例)</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;bean</span> id=<span style="color:#2aa198">&#34;demoServiceImpl&#34;</span> class=<span style="color:#2aa198">&#34;org.apache.dubbo.demo.provider.DemoServiceImpl&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> serialization=<span style="color:#2aa198">&#34;protobuf&#34;</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.demo.DemoService&#34;</span> ref=<span style="color:#2aa198">&#34;demoServiceImpl&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>消费端,引用服务</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> scope=<span style="color:#2aa198">&#34;remote&#34;</span> id=<span style="color:#2aa198">&#34;demoService&#34;</span> check=<span style="color:#2aa198">&#34;false&#34;</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.demo.DemoService&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>消费端,使用服务 proxy</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">callService</span>() <span style="color:#268bd2">throws</span> Exception { |
| </span></span><span style="display:flex;"><span> ... |
| </span></span><span style="display:flex;"><span> DemoService demoService <span style="color:#719e07">=</span> context.getBean(<span style="color:#2aa198">&#34;demoService&#34;</span>, DemoService.class); |
| </span></span><span style="display:flex;"><span> HelloRequest request <span style="color:#719e07">=</span> HelloRequest.newBuilder().setName(<span style="color:#2aa198">&#34;Hello&#34;</span>).build(); |
| </span></span><span style="display:flex;"><span> HelloReply reply <span style="color:#719e07">=</span> demoService.sayHello(request); |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;result: &#34;</span> <span style="color:#719e07">+</span> reply.getMessage()); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h3 id="golang-1">Golang</h3> |
| <p>提供端,实现服务</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-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">type</span> User <span style="color:#268bd2">struct</span> { |
| </span></span><span style="display:flex;"><span> ID <span style="color:#dc322f">string</span> |
| </span></span><span style="display:flex;"><span> Name <span style="color:#dc322f">string</span> |
| </span></span><span style="display:flex;"><span> Age <span style="color:#dc322f">int32</span> |
| </span></span><span style="display:flex;"><span> Time time.Time |
| </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">type</span> UserProvider <span style="color:#268bd2">struct</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">func</span> (u <span style="color:#719e07">*</span>UserProvider) <span style="color:#268bd2">GetUser</span>(ctx context.Context, req []<span style="color:#268bd2">interface</span>{}) (<span style="color:#719e07">*</span>User, <span style="color:#dc322f">error</span>) { |
| </span></span><span style="display:flex;"><span> gxlog.<span style="color:#268bd2">CInfo</span>(<span style="color:#2aa198">&#34;req:%#v&#34;</span>, req) |
| </span></span><span style="display:flex;"><span> rsp <span style="color:#719e07">:=</span> User{<span style="color:#2aa198">&#34;A001&#34;</span>, <span style="color:#2aa198">&#34;Alex Stocks&#34;</span>, <span style="color:#2aa198">18</span>, time.<span style="color:#268bd2">Now</span>()} |
| </span></span><span style="display:flex;"><span> gxlog.<span style="color:#268bd2">CInfo</span>(<span style="color:#2aa198">&#34;rsp:%#v&#34;</span>, rsp) |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">&amp;</span>rsp, <span style="color:#cb4b16">nil</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">func</span> (u <span style="color:#719e07">*</span>UserProvider) <span style="color:#268bd2">Reference</span>() <span style="color:#dc322f">string</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;UserProvider&#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:#268bd2">func</span> (u User) <span style="color:#268bd2">JavaClassName</span>() <span style="color:#dc322f">string</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;org.apache.dubbo.User&#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:#268bd2">func</span> <span style="color:#268bd2">main</span>() { |
| </span></span><span style="display:flex;"><span> hessian.<span style="color:#268bd2">RegisterPOJO</span>(<span style="color:#719e07">&amp;</span>User{}) |
| </span></span><span style="display:flex;"><span> config.<span style="color:#268bd2">SetProviderService</span>(<span style="color:#b58900">new</span>(UserProvider)) |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>消费端,使用服务 proxy</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-go" data-lang="go"><span style="display:flex;"><span><span style="color:#268bd2">func</span> <span style="color:#268bd2">main</span>() { |
| </span></span><span style="display:flex;"><span> config.<span style="color:#268bd2">Load</span>() |
| </span></span><span style="display:flex;"><span> user <span style="color:#719e07">:=</span> <span style="color:#719e07">&amp;</span>pkg.User{} |
| </span></span><span style="display:flex;"><span> err <span style="color:#719e07">:=</span> userProvider.<span style="color:#268bd2">GetUser</span>(context.<span style="color:#268bd2">TODO</span>(), []<span style="color:#268bd2">interface</span>{}{<span style="color:#2aa198">&#34;A001&#34;</span>}, user) |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> err <span style="color:#719e07">!=</span> <span style="color:#cb4b16">nil</span> { |
| </span></span><span style="display:flex;"><span> os.<span style="color:#268bd2">Exit</span>(<span style="color:#2aa198">1</span>) |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> gxlog.<span style="color:#268bd2">CInfo</span>(<span style="color:#2aa198">&#34;response result: %v\n&#34;</span>, user) |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></description></item><item><title>Overview: Pojo 序列化兼容模式</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/wrap/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/wrap/</guid><description> |
| <p>这篇教程会通过从零构建一个简单的工程来演示如何基于 POJO 方式使用 Dubbo Triple, 在应用不改变已有接口定义的同时升级到 Triple 协议。<strong>此模式下 Triple 使用方式与 Dubbo 协议一样。</strong></p> |
| <p>具体用例可以参考:<a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple/src/main/java/org/apache/dubbo/sample/tri/pojo">dubbo-samples-triple/pojo</a>;</p> |
| <h3 id="前置条件">前置条件</h3> |
| <ul> |
| <li><a href="https://jdk.java.net/">JDK</a> 版本 &gt;= 8</li> |
| <li>已安装 <a href="https://maven.apache.org/">Maven</a></li> |
| <li>已安装并启动 <a href="https://zookeeper.apache.org/">Zookeeper</a></li> |
| </ul> |
| <h3 id="创建工程">创建工程</h3> |
| <ol> |
| <li> |
| <p>首先创建一个空的 maven 工程</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-fallback" data-lang="fallback"><span style="display:flex;"><span>$ mvn archetype:generate \ |
| </span></span><span style="display:flex;"><span> -DgroupId=org.apache.dubbo \ |
| </span></span><span style="display:flex;"><span> -DartifactId=tri-pojo-demo \ |
| </span></span><span style="display:flex;"><span> -DarchetypeArtifactId=maven-archetype-quickstart \ |
| </span></span><span style="display:flex;"><span> -DarchetypeVersion=1.4 \ |
| </span></span><span style="display:flex;"><span> -DarchetypeGroupId=org.apache.maven.archetypes \ |
| </span></span><span style="display:flex;"><span> -Dversion=1.0-SNAPSHOT |
| </span></span></code></pre></div></li> |
| <li> |
| <p>切换到工程目录</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-fallback" data-lang="fallback"><span style="display:flex;"><span>$ cd tri-pojo-demo |
| </span></span></code></pre></div></li> |
| <li> |
| <p>在 <code>pom.xml</code> 中设置 JDK 版本,添加 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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;properties&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;project.build.sourceEncoding&gt;</span>UTF-8<span style="color:#268bd2">&lt;/project.build.sourceEncoding&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;maven.compiler.source&gt;</span>1.8<span style="color:#268bd2">&lt;/maven.compiler.source&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;maven.compiler.target&gt;</span>1.8<span style="color:#268bd2">&lt;/maven.compiler.target&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/properties&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dependencies&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>junit<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>junit<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>4.13<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;scope&gt;</span>test<span style="color:#268bd2">&lt;/scope&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.apache.dubbo<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>dubbo<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>3.0.8<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.apache.dubbo<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>dubbo-dependencies-zookeeper-curator5<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;type&gt;</span>pom<span style="color:#268bd2">&lt;/type&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>3.0.8<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>com.google.protobuf<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>protobuf-java<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>3.19.4<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dependencies&gt;</span> |
| </span></span></code></pre></div></li> |
| <li> |
| <p>添加接口定义<code>src/main/java/org/apache/dubbo/Greeter.java</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> org.apache.dubbo; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">Greeter</span> { |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHello</span>(String name); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></li> |
| <li> |
| <p>添加服务端接口实现<code>src/main/java/org/apache/dubbo/GreeterImpl.java</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> org.apache.dubbo; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">GreeterImpl</span> <span style="color:#268bd2">implements</span> Greeter { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span>(String name) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;Hello,&#34;</span> <span style="color:#719e07">+</span> name <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;!&#34;</span>; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></li> |
| <li> |
| <p>添加服务端启动类 <code>src/main/java/org/apache/dubbo/MyDubboServer.java</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> org.apache.dubbo; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.common.constants.CommonConstants; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.ApplicationConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.ProtocolConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.RegistryConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.ServiceConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.bootstrap.DubboBootstrap; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> java.io.IOException; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">MyDubboServer</span> { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">main</span>(String<span style="color:#719e07">[]</span> args) <span style="color:#268bd2">throws</span> IOException { |
| </span></span><span style="display:flex;"><span> ServiceConfig<span style="color:#719e07">&lt;</span>Greeter<span style="color:#719e07">&gt;</span> service <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ServiceConfig<span style="color:#719e07">&lt;&gt;</span>(); |
| </span></span><span style="display:flex;"><span> service.setInterface(Greeter.class); |
| </span></span><span style="display:flex;"><span> service.setRef(<span style="color:#719e07">new</span> GreeterImpl()); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> DubboBootstrap bootstrap <span style="color:#719e07">=</span> DubboBootstrap.getInstance(); |
| </span></span><span style="display:flex;"><span> bootstrap.application(<span style="color:#719e07">new</span> ApplicationConfig(<span style="color:#2aa198">&#34;tri-pojo-server&#34;</span>)) |
| </span></span><span style="display:flex;"><span> .registry(<span style="color:#719e07">new</span> RegistryConfig(<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span>)) |
| </span></span><span style="display:flex;"><span> .protocol(<span style="color:#719e07">new</span> ProtocolConfig(CommonConstants.TRIPLE, 50051)) |
| </span></span><span style="display:flex;"><span> .service(service) |
| </span></span><span style="display:flex;"><span> .start(); |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;Dubbo triple pojo server started&#34;</span>); |
| </span></span><span style="display:flex;"><span> System.in.read(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></li> |
| <li> |
| <p>添加客户端启动类<code>src/main/java/org/apache/dubbo/MyDubboClient.java</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> org.apache.dubbo; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.common.constants.CommonConstants; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.ApplicationConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.ReferenceConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.RegistryConfig; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.config.bootstrap.DubboBootstrap; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">MyDubboClient</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">main</span>(String<span style="color:#719e07">[]</span> args) { |
| </span></span><span style="display:flex;"><span> DubboBootstrap bootstrap <span style="color:#719e07">=</span> DubboBootstrap.getInstance(); |
| </span></span><span style="display:flex;"><span> ReferenceConfig<span style="color:#719e07">&lt;</span>Greeter<span style="color:#719e07">&gt;</span> ref <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ReferenceConfig<span style="color:#719e07">&lt;&gt;</span>(); |
| </span></span><span style="display:flex;"><span> ref.setInterface(Greeter.class); |
| </span></span><span style="display:flex;"><span> ref.setProtocol(CommonConstants.TRIPLE); |
| </span></span><span style="display:flex;"><span> ref.setTimeout(3000); |
| </span></span><span style="display:flex;"><span> bootstrap.application(<span style="color:#719e07">new</span> ApplicationConfig(<span style="color:#2aa198">&#34;tri-pojo-client&#34;</span>)) |
| </span></span><span style="display:flex;"><span> .registry(<span style="color:#719e07">new</span> RegistryConfig(<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span>)) |
| </span></span><span style="display:flex;"><span> .reference(ref) |
| </span></span><span style="display:flex;"><span> .start(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> Greeter greeter <span style="color:#719e07">=</span> ref.get(); |
| </span></span><span style="display:flex;"><span> String reply <span style="color:#719e07">=</span> greeter.sayHello(<span style="color:#2aa198">&#34;pojo&#34;</span>); |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;Received reply:&#34;</span> <span style="color:#719e07">+</span> reply); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></li> |
| <li> |
| <p>编译代码</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-fallback" data-lang="fallback"><span style="display:flex;"><span>$ mvn clean install |
| </span></span></code></pre></div></li> |
| <li> |
| <p>启动服务端</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-fallback" data-lang="fallback"><span style="display:flex;"><span>$ mvn org.codehaus.mojo:exec-maven-plugin:3.0.0:java -Dexec.mainClass=&#34;org.apache.dubbo.MyDubboServer&#34; |
| </span></span><span style="display:flex;"><span>Dubbo triple pojo server started |
| </span></span></code></pre></div></li> |
| <li> |
| <p>打开新的终端,启动客户端</p> |
| </li> |
| </ol> |
| <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-fallback" data-lang="fallback"><span style="display:flex;"><span>$ mvn org.codehaus.mojo:exec-maven-plugin:3.0.0:java -Dexec.mainClass=&#34;org.apache.dubbo.MyDubboClient&#34; |
| </span></span><span style="display:flex;"><span>Received reply:message: &#34;Hello,Demo!&#34; |
| </span></span></code></pre></div><h3 id="常见问题">常见问题</h3> |
| <ol> |
| <li>protobuf 类找不到</li> |
| </ol> |
| <p>由于 Triple 协议底层需要依赖 protobuf 协议进行传输,即使定义的服务接口不使用 protobuf 也需要在环境中引入 protobuf 的依赖。</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-xml" data-lang="xml"><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>com.google.protobuf<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>protobuf-java<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>3.19.4<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Overview: Streaming 通信模式</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/streaming/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/triple/streaming/</guid><description> |
| <p>具体用例可以参考:<a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple/src/main/java/org/apache/dubbo/sample/tri/pojo">dubbo-samples-triple/pojo</a>;</p> |
| <h2 id="stream-流">Stream (流)</h2> |
| <p>Stream 是 Dubbo3 新提供的一种调用类型,在以下场景时建议使用流的方式:</p> |
| <ul> |
| <li>接口需要发送大量数据,这些数据无法被放在一个 RPC 的请求或响应中,需要分批发送,但应用层如果按照传统的多次 RPC 方式无法解决顺序和性能的问题,如果需要保证有序,则只能串行发送</li> |
| <li>流式场景,数据需要按照发送顺序处理, 数据本身是没有确定边界的</li> |
| <li>推送类场景,多个消息在同一个调用的上下文中被发送和处理</li> |
| </ul> |
| <p>Stream 分为以下三种:</p> |
| <ul> |
| <li>SERVER_STREAM(服务端流) |
| <img src="https://dubbo.apache.org/imgs/v3/migration/tri/migrate-server-stream.png" alt="SERVER_STREAM"></li> |
| <li>CLIENT_STREAM(客户端流) |
| <img src="https://dubbo.apache.org/imgs/v3/migration/tri/migrate-client-stream.png" alt="CLIENT_STREAM"></li> |
| <li>BIDIRECTIONAL_STREAM(双向流) |
| <img src="https://dubbo.apache.org/imgs/v3/migration/tri/migrate-bi-stream.png" alt="BIDIRECTIONAL_STREAM"></li> |
| </ul> |
| <blockquote> |
| <p>由于 <code>java</code> 语言的限制,BIDIRECTIONAL_STREAM 和 CLIENT_STREAM 的实现是一样的。</p> |
| </blockquote> |
| <p>在 Dubbo3 中,流式接口以 <code>SteamObserver</code> 声明和使用,用户可以通过使用和实现这个接口来发送和处理流的数据、异常和结束。</p> |
| <blockquote> |
| <p>对于 Dubbo2 用户来说,可能会对StreamObserver感到陌生,这是Dubbo3定义的一种流类型,Dubbo2 中并不存在 Stream 的类型,所以对于迁移场景没有任何影响。</p> |
| </blockquote> |
| <p>流的语义保证</p> |
| <ul> |
| <li>提供消息边界,可以方便地对消息单独处理</li> |
| <li>严格有序,发送端的顺序和接收端顺序一致</li> |
| <li>全双工,发送不需要等待</li> |
| <li>支持取消和超时</li> |
| </ul> |
| <h2 id="非-pb-序列化的流">非 PB 序列化的流</h2> |
| <ol> |
| <li>api</li> |
| </ol> |
| <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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">IWrapperGreeter</span> { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHelloStream</span>(StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> response); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">sayHelloServerStream</span>(String request, StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> response); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><blockquote> |
| <p>Stream 方法的方法入参和返回值是严格约定的,为防止写错而导致问题,Dubbo3 框架侧做了对参数的检查, 如果出错则会抛出异常。 |
| 对于 <code>双向流(BIDIRECTIONAL_STREAM)</code>, 需要注意参数中的 <code>StreamObserver</code> 是响应流,返回参数中的 <code>StreamObserver</code> 为请求流。</p> |
| </blockquote> |
| <ol start="2"> |
| <li>实现类</li> |
| </ol> |
| <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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">WrapGreeterImpl</span> <span style="color:#268bd2">implements</span> WrapGreeter { |
| </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> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHelloStream</span>(StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> response) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onNext</span>(String data) { |
| </span></span><span style="display:flex;"><span> System.out.println(data); |
| </span></span><span style="display:flex;"><span> response.onNext(<span style="color:#2aa198">&#34;hello,&#34;</span><span style="color:#719e07">+</span>data); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onError</span>(Throwable throwable) { |
| </span></span><span style="display:flex;"><span> throwable.printStackTrace(); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onCompleted</span>() { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onCompleted&#34;</span>); |
| </span></span><span style="display:flex;"><span> response.onCompleted(); |
| </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:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">sayHelloServerStream</span>(String request, StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> response) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">for</span> (<span style="color:#dc322f">int</span> i <span style="color:#719e07">=</span> 0; i <span style="color:#719e07">&lt;</span> 10; i<span style="color:#719e07">++</span>) { |
| </span></span><span style="display:flex;"><span> response.onNext(<span style="color:#2aa198">&#34;hello,&#34;</span> <span style="color:#719e07">+</span> request); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> response.onCompleted(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><ol start="3"> |
| <li>调用方式</li> |
| </ol> |
| <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-java" data-lang="java"><span style="display:flex;"><span>delegate.sayHelloServerStream(<span style="color:#2aa198">&#34;server stream&#34;</span>, <span style="color:#719e07">new</span> StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onNext</span>(String data) { |
| </span></span><span style="display:flex;"><span> System.out.println(data); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onError</span>(Throwable throwable) { |
| </span></span><span style="display:flex;"><span> throwable.printStackTrace(); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onCompleted</span>() { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onCompleted&#34;</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></span><span style="display:flex;"><span>StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> request <span style="color:#719e07">=</span> delegate.sayHelloStream(<span style="color:#719e07">new</span> StreamObserver<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onNext</span>(String data) { |
| </span></span><span style="display:flex;"><span> System.out.println(data); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onError</span>(Throwable throwable) { |
| </span></span><span style="display:flex;"><span> throwable.printStackTrace(); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onCompleted</span>() { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onCompleted&#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">for</span> (<span style="color:#dc322f">int</span> i <span style="color:#719e07">=</span> 0; i <span style="color:#719e07">&lt;</span> n; i<span style="color:#719e07">++</span>) { |
| </span></span><span style="display:flex;"><span> request.onNext(<span style="color:#2aa198">&#34;stream request&#34;</span> <span style="color:#719e07">+</span> i); |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span>request.onCompleted(); |
| </span></span></code></pre></div><h2 id="使用-protobuf-序列化的流">使用 Protobuf 序列化的流</h2> |
| <p>对于 <code>Protobuf</code> 序列化方式,推荐编写 <code>IDL</code> 使用 <code>compiler</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">PbGreeter</span> { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> String JAVA_SERVICE_NAME <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;org.apache.dubbo.sample.tri.PbGreeter&#34;</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> String SERVICE_NAME <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;org.apache.dubbo.sample.tri.PbGreeter&#34;</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> <span style="color:#dc322f">boolean</span> inited <span style="color:#719e07">=</span> PbGreeterDubbo.init(); |
| </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> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">greetServerStream</span>(org.apache.dubbo.sample.tri.GreeterRequest request, org.apache.dubbo.common.stream.StreamObserver<span style="color:#719e07">&lt;</span>org.apache.dubbo.sample.tri.GreeterReply<span style="color:#719e07">&gt;</span> responseObserver); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> org.apache.dubbo.common.stream.StreamObserver<span style="color:#719e07">&lt;</span>org.apache.dubbo.sample.tri.GreeterRequest<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">greetStream</span>(org.apache.dubbo.common.stream.StreamObserver<span style="color:#719e07">&lt;</span>org.apache.dubbo.sample.tri.GreeterReply<span style="color:#719e07">&gt;</span> responseObserver); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h3 id="完整用例">完整用例</h3> |
| <ol> |
| <li> |
| <p>编写 Java 接口</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.common.stream.StreamObserver; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.hello.HelloReply; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.hello.HelloRequest; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">IGreeter</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">/** |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * &lt;pre&gt; |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * Sends greeting by stream |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * &lt;/pre&gt; |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> */</span> |
| </span></span><span style="display:flex;"><span> StreamObserver<span style="color:#719e07">&lt;</span>HelloRequest<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHello</span>(StreamObserver<span style="color:#719e07">&lt;</span>HelloReply<span style="color:#719e07">&gt;</span> replyObserver); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></li> |
| <li> |
| <p>编写实现类</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">IStreamGreeterImpl</span> <span style="color:#268bd2">implements</span> IStreamGreeter { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> StreamObserver<span style="color:#719e07">&lt;</span>HelloRequest<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHello</span>(StreamObserver<span style="color:#719e07">&lt;</span>HelloReply<span style="color:#719e07">&gt;</span> replyObserver) { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> StreamObserver<span style="color:#719e07">&lt;</span>HelloRequest<span style="color:#719e07">&gt;</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> List<span style="color:#719e07">&lt;</span>HelloReply<span style="color:#719e07">&gt;</span> replyList <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ArrayList<span style="color:#719e07">&lt;&gt;</span>(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onNext</span>(HelloRequest helloRequest) { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onNext receive request name:&#34;</span> <span style="color:#719e07">+</span> helloRequest.getName()); |
| </span></span><span style="display:flex;"><span> replyList.add(HelloReply.newBuilder() |
| </span></span><span style="display:flex;"><span> .setMessage(<span style="color:#2aa198">&#34;receive name:&#34;</span> <span style="color:#719e07">+</span> helloRequest.getName()) |
| </span></span><span style="display:flex;"><span> .build()); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onError</span>(Throwable cause) { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onError&#34;</span>); |
| </span></span><span style="display:flex;"><span> replyObserver.onError(cause); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onCompleted</span>() { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onComplete receive request size:&#34;</span> <span style="color:#719e07">+</span> replyList.size()); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">for</span> (HelloReply reply : replyList) { |
| </span></span><span style="display:flex;"><span> replyObserver.onNext(reply); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> replyObserver.onCompleted(); |
| </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></code></pre></div></li> |
| <li> |
| <p>创建 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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">StreamProvider</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">main</span>(String<span style="color:#719e07">[]</span> args) <span style="color:#268bd2">throws</span> InterruptedException { |
| </span></span><span style="display:flex;"><span> ServiceConfig<span style="color:#719e07">&lt;</span>IStreamGreeter<span style="color:#719e07">&gt;</span> service <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ServiceConfig<span style="color:#719e07">&lt;&gt;</span>(); |
| </span></span><span style="display:flex;"><span> service.setInterface(IStreamGreeter.class); |
| </span></span><span style="display:flex;"><span> service.setRef(<span style="color:#719e07">new</span> IStreamGreeterImpl()); |
| </span></span><span style="display:flex;"><span> service.setProtocol(<span style="color:#719e07">new</span> ProtocolConfig(CommonConstants.TRIPLE, 50051)); |
| </span></span><span style="display:flex;"><span> service.setApplication(<span style="color:#719e07">new</span> ApplicationConfig(<span style="color:#2aa198">&#34;stream-provider&#34;</span>)); |
| </span></span><span style="display:flex;"><span> service.setRegistry(<span style="color:#719e07">new</span> RegistryConfig(<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span>)); |
| </span></span><span style="display:flex;"><span> service.export(); |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;dubbo service started&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">new</span> CountDownLatch(1).await(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></li> |
| <li> |
| <p>创建 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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">StreamConsumer</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">main</span>(String<span style="color:#719e07">[]</span> args) <span style="color:#268bd2">throws</span> InterruptedException, IOException { |
| </span></span><span style="display:flex;"><span> ReferenceConfig<span style="color:#719e07">&lt;</span>IStreamGreeter<span style="color:#719e07">&gt;</span> ref <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ReferenceConfig<span style="color:#719e07">&lt;&gt;</span>(); |
| </span></span><span style="display:flex;"><span> ref.setInterface(IStreamGreeter.class); |
| </span></span><span style="display:flex;"><span> ref.setCheck(<span style="color:#cb4b16">false</span>); |
| </span></span><span style="display:flex;"><span> ref.setProtocol(CommonConstants.TRIPLE); |
| </span></span><span style="display:flex;"><span> ref.setLazy(<span style="color:#cb4b16">true</span>); |
| </span></span><span style="display:flex;"><span> ref.setTimeout(100000); |
| </span></span><span style="display:flex;"><span> ref.setApplication(<span style="color:#719e07">new</span> ApplicationConfig(<span style="color:#2aa198">&#34;stream-consumer&#34;</span>)); |
| </span></span><span style="display:flex;"><span> ref.setRegistry(<span style="color:#719e07">new</span> RegistryConfig(<span style="color:#2aa198">&#34;zookeeper://mse-6e9fda00-p.zk.mse.aliyuncs.com:2181&#34;</span>)); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">final</span> IStreamGreeter iStreamGreeter <span style="color:#719e07">=</span> ref.get(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;dubbo ref started&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> StreamObserver<span style="color:#719e07">&lt;</span>HelloRequest<span style="color:#719e07">&gt;</span> streamObserver <span style="color:#719e07">=</span> iStreamGreeter.sayHello(<span style="color:#719e07">new</span> StreamObserver<span style="color:#719e07">&lt;</span>HelloReply<span style="color:#719e07">&gt;</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onNext</span>(HelloReply reply) { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onNext&#34;</span>); |
| </span></span><span style="display:flex;"><span> System.out.println(reply.getMessage()); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onError</span>(Throwable throwable) { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onError:&#34;</span> <span style="color:#719e07">+</span> throwable.getMessage()); |
| </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">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onCompleted</span>() { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onCompleted&#34;</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> streamObserver.onNext(HelloRequest.newBuilder() |
| </span></span><span style="display:flex;"><span> .setName(<span style="color:#2aa198">&#34;tony&#34;</span>) |
| </span></span><span style="display:flex;"><span> .build()); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> streamObserver.onNext(HelloRequest.newBuilder() |
| </span></span><span style="display:flex;"><span> .setName(<span style="color:#2aa198">&#34;nick&#34;</span>) |
| </span></span><span style="display:flex;"><span> .build()); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> streamObserver.onCompleted(); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">catch</span> (Throwable t) { |
| </span></span><span style="display:flex;"><span> t.printStackTrace(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> System.in.read(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></li> |
| <li> |
| <p>运行 Provider 和 Consumer ,可以看到请求正常返回了</p> |
| <blockquote> |
| <p>onNext<br> |
| receive name:tony<br> |
| onNext<br> |
| receive name:nick<br> |
| onCompleted</p> |
| </blockquote> |
| </li> |
| </ol> |
| <h3 id="常见问题">常见问题</h3> |
| <ol> |
| <li>protobuf 类找不到</li> |
| </ol> |
| <p>由于 Triple 协议底层需要依赖 protobuf 协议进行传输,即使定义的服务接口不使用 protobuf 也需要在环境中引入 protobuf 的依赖。</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-xml" data-lang="xml"><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>com.google.protobuf<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>protobuf-java<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>3.19.4<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span></code></pre></div></description></item></channel></rss> |