| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – 开发服务</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/</link><description>Recent content in 开发服务 on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="https://dubbo.apache.org/zh-cn/overview/tasks/develop/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview: 通过模板生成项目脚手架</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/template/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/develop/template/</guid><description> |
| <p><a href="https://start.dubbo.apache.org/bootstrap.html" target="_blank">Dubbo Initializer</a> 可用来快速生成 Java 项目脚手架,帮助简化微服务项目搭建、基本配置、组件依赖管理等。</p> |
| <blockquote> |
| <p>Initializer 仍在持续更新中,更多 Dubbo Feature 的支持将会陆续发布。</p> |
| </blockquote> |
| <h2 id="选择-dubbo-版本">选择 Dubbo 版本</h2> |
| <p>Initializer 将使用 <code>dubbo-spring-boot-starter</code> 创建 Spring Boot 项目,因此我们首先需要选择 Dubbo 与 Spring Boot 的版本。</p> |
| <p><img src="https://dubbo.apache.org/imgs/v3/tasks/develop/initializer-choose-version.png" alt="initializer-choose-version"></p> |
| <h2 id="录入项目基本信息">录入项目基本信息</h2> |
| <p>接下来,填入项目基本信息,包括项目坐标、项目名称、包名、JDK 版本等。</p> |
| <p><img src="https://dubbo.apache.org/imgs/v3/tasks/develop/initializer-project-info.png" alt="initializer-project-info"></p> |
| <h2 id="选择项目结构">选择项目结构</h2> |
| <p>有两种项目结构可共选择,分别是 <code>单模块</code> 和 <code>多模块</code>,在这个示例中我们选择 <code>单模块</code>。</p> |
| <p><img src="https://dubbo.apache.org/imgs/v3/tasks/develop/initializer-project-architecture.png" alt="initializer-project-architecture"></p> |
| <ul> |
| <li>单模块,所有组件代码存放在一个 module 中,特点是结构简单。</li> |
| <li>多模块,生成的项目有 <code>API</code>、<code>Service</code> 两个模块,其中 <code>API</code> 用于存放 Dubbo 服务定义,<code>Service</code> 用于存放服务实现或调用逻辑。通常多模块更有利于服务定义的单独管理与发布。</li> |
| </ul> |
| <h2 id="选择依赖组件">选择依赖组件</h2> |
| <p>我们为模板默认选择如下几个依赖组件:</p> |
| <ul> |
| <li>Dubbo 组件 |
| <ul> |
| <li>Java Interface</li> |
| <li>注册中心,zookeeper</li> |
| <li>协议 TCP</li> |
| </ul> |
| </li> |
| <li>常用微服务组件 |
| <ul> |
| <li>Web</li> |
| <li>Mybatis</li> |
| <li>模版引擎</li> |
| </ul> |
| </li> |
| </ul> |
| <p><img src="https://dubbo.apache.org/imgs/v3/tasks/develop/initializer-dependencies.png" alt="initializer-dependencies"></p> |
| <p>基于以上选项,生成的项目将以 Zookeeper 为注册中心,以高性能 Dubbo2 TCP 协议为 RPC 通信协议,并且增加了 Web、Mybatis 等组件依赖和示例。</p> |
| <blockquote> |
| <p>注意:上面选中的 Dubbo 组件也都是默认选项,即在不手动添加任何依赖的情况下,打开页面后直接点击代码生成,生成的代码即包含以上 Dubbo 组件。</p> |
| <p>如手动添加依赖组件,请注意 Dubbo 各个依赖组件之间的隐含组合关系限制,比如</p> |
| <ul> |
| <li>如果选择了【Dubbo Service API】-【IDL】,则目前仅支持选择 【Dubbo Protocol】中的 【HTTP/2】或 【gRPC】 协议。</li> |
| <li>同一个依赖分组下,相同类型的依赖只能选择一个,比如 【Dubbo Registry&amp;Config&amp;Metadata】分组下,从注册中心视角【Zookeeper】、【Nacos】只能选一个,如果要设置多注册中心,请在生成的代码中手动修改配置。但注册中心、配置中心可以分别选一个,比如 Zookeeper 和 Apollo 可同时选中。</li> |
| </ul> |
| </blockquote> |
| <h2 id="生成项目模板">生成项目模板</h2> |
| <ul> |
| <li>点击 “浏览代码” 可在线浏览项目结构与代码</li> |
| <li>点击 “获取代码” 生成项目下载地址</li> |
| </ul> |
| <p><img src="https://dubbo.apache.org/imgs/v3/tasks/develop/initializer-preview.png" alt="initializer-preview"></p> |
| <p>项目下载到本地后,解压并导入 IDE 后即可根据需要开发定制 Dubbo 应用。</p></description></item><item><title>Overview: 开发服务</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/service_reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/develop/service_reference/</guid><description> |
| <h2 id="发布和调用">发布和调用</h2> |
| <p>通过一个简单的Springboot实例代码,展示Dubbo服务的发布和调用</p> |
| <p>本文将基于 Dubbo Samples 示例演示如何快速搭建并部署一个微服务应用。 |
| 代码地址:<a href="https://github.com/apache/dubbo-samples/tree/master/10-task/dubbo-samples-develop">dubbo-samples-develop</a> |
| 代码分为三个模块</p> |
| <ul> |
| <li>api</li> |
| <li>develop-provider</li> |
| <li>develop-consumer</li> |
| </ul> |
| <h2 id="准备">准备</h2> |
| <p>本示例代码基于Springboot 3.0</p> |
| <p>1、首先需要一个可用的注册中心 Zookeeper,Nacos,Redis 均可。</p> |
| <p>2、新建一个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-xml" data-lang="xml"><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- registry 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.alibaba.nacos<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>nacos-client<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>${nacos.version}<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></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- dubbo 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-spring-boot-starter<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>${dubbo.version}<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></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.springframework.boot<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>spring-boot-starter<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span></code></pre></div><p>本示例使用的注册中心为Nacos,使用ZK请将nacos-client包替换为对应版本zk客户端包。</p> |
| <h2 id="发布服务">发布服务</h2> |
| <p>1、定义服务接口</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">DevelopService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>2、服务接口实现</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">@DubboService</span><span style="color:#719e07">(</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;group1&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">DevelopProviderServiceV1</span> <span style="color:#268bd2">implements</span> DevelopService<span style="color:#719e07">{</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> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> StringBuilder s <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> StringBuilder<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> s<span style="color:#719e07">.</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ServiceV1 param:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> s<span style="color:#719e07">.</span>toString<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>使用@DubboService 注解,Dubbo会将对应的服务注册到spring, |
| 在spring启动后调用对应的服务导出方法,将服务注册到注册中心, |
| 这样Consumer端才能发现我们发布的服务并调用</p> |
| <p>3、添加Dubbo配置</p> |
| <p>添加application.properties相关配置,也可新建dubbo.properties保存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-properties" data-lang="properties"><span style="display:flex;"><span>dubbo.application.name<span style="color:#719e07">=</span><span style="color:#2aa198">provider</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># Enable token verification for each invocation</span> |
| </span></span><span style="display:flex;"><span>dubbo.provider.token<span style="color:#719e07">=</span><span style="color:#2aa198">false</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># Specify the registry address</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># dubbo.registry.address=nacos://localhost:8848?username=nacos&amp;password=nacos</span> |
| </span></span><span style="display:flex;"><span>dubbo.registry.address<span style="color:#719e07">=</span><span style="color:#2aa198">nacos://${nacos.address:localhost}:8848?username=nacos&amp;password=nacos</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>dubbo.protocol.name<span style="color:#719e07">=</span><span style="color:#2aa198">dubbo</span> |
| </span></span><span style="display:flex;"><span>dubbo.protocol.port<span style="color:#719e07">=</span><span style="color:#2aa198">20881</span> |
| </span></span></code></pre></div><p>4、启动服务</p> |
| <p>创建Springboot启动类,需添加@EnableDubbo注解,开启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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@EnableDubbo</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">@SpringBootApplication</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">DevelopApplication</span> <span style="color:#719e07">{</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><span style="color:#719e07">(</span>String<span style="color:#719e07">[]</span> args<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> SpringApplication<span style="color:#719e07">.</span>run<span style="color:#719e07">(</span>DevelopApplication<span style="color:#719e07">.</span>class<span style="color:#719e07">,</span> args<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>启动成功后,在注册中心可以看到对应的服务列表,如图: |
| <code>![serviceList](/imgs/v3/develop/develop-service-list.png)</code></p> |
| <h2 id="调用服务">调用服务</h2> |
| <p>创建DemoTask类,通过@DubboReference注解对需要调用的服务进行引入。即可像调用本地方法一样调用远程服务了。</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:#586e75">//实现CommandLineRunner 让Springboot启动后调用run方法 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span><span style="color:#268bd2">@Component</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">DemoTask</span> <span style="color:#268bd2">implements</span> CommandLineRunner <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@DubboReference</span><span style="color:#719e07">(</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;group1&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> DevelopService developService<span style="color:#719e07">;</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">run</span><span style="color:#719e07">(</span>String<span style="color:#719e07">...</span> args<span style="color:#719e07">)</span> <span style="color:#268bd2">throws</span> Exception <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//调用DevelopService的group1分组实现 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Dubbo Remote Return ======&gt; &#34;</span> <span style="color:#719e07">+</span> developService<span style="color:#719e07">.</span>invoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;1&#34;</span><span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>启动服务 打印</p> |
| <p><code>Dubbo Remote Return ======&gt; ServiceV1 param:1</code></p> |
| <p>说明服务调用成功</p></description></item><item><title>Overview: 异步调用</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/async/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/develop/async/</guid><description> |
| <p>文档完整的示例地址请参见</p> |
| <ul> |
| <li><a href="https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-async/dubbo-samples-async-simple-boot">服务调用异步</a></li> |
| <li><a href="https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-async/dubbo-samples-async-provider">服务执行异步</a></li> |
| <li><a href="https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-async/dubbo-samples-async-original-future">定义 CompletableFuture 方法签名的服务</a></li> |
| </ul> |
| <h2 id="异步调用">异步调用</h2> |
| <p>Dubbo异步调用分为Provider端异步调用和Consumer端异步调用。 |
| Provider端异步执行将阻塞的业务从Dubbo内部线程池切换到业务自定义线程, |
| 避免Dubbo线程池的过度占用,有助于避免不同服务间的互相影响。异步执行无异于节省资源或提升RPC响应性能。</p> |
| <p><em><font color='#FF7D00' size=4 > 注意 </font></em></p> |
| <blockquote> |
| <p>Provider 端异步执行和 Consumer 端异步调用是相互独立的,你可以任意正交组合两端配置</p> |
| <ul> |
| <li>Consumer同步 - Provider同步</li> |
| <li>Consumer异步 - Provider同步</li> |
| <li>Consumer同步 - Provider异步</li> |
| <li>Consumer异步 - Provider异步</li> |
| </ul> |
| </blockquote> |
| <h2 id="使用场景">使用场景</h2> |
| <ul> |
| <li>对于Provider端来说,如果接口比较耗时,避免dubbo线程被阻塞,可以使用异步将线程切换到业务线程。</li> |
| <li>对于Consumer端来说,调用Dubbo接口没有严格时序上的关系、不是原子操作、不影响逻辑情况下可以使用异步调用。</li> |
| </ul> |
| <h2 id="provider异步">Provider异步</h2> |
| <h3 id="1使用completablefuture实现异步">1、使用CompletableFuture实现异步</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">interface</span> <span style="color:#268bd2">AsyncService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">/** |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * 同步调用方法 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> */</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">/** |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * 异步调用方法 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> */</span> |
| </span></span><span style="display:flex;"><span> CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">asyncInvoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboService</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">AsyncServiceImpl</span> <span style="color:#268bd2">implements</span> AsyncService <span style="color:#719e07">{</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> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> time <span style="color:#719e07">=</span> ThreadLocalRandom<span style="color:#719e07">.</span>current<span style="color:#719e07">().</span>nextLong<span style="color:#719e07">(</span>1000<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> Thread<span style="color:#719e07">.</span>sleep<span style="color:#719e07">(</span>time<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> StringBuilder s <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> StringBuilder<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> s<span style="color:#719e07">.</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;AsyncService invoke param:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>param<span style="color:#719e07">).</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;,sleep:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>time<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> s<span style="color:#719e07">.</span>toString<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">catch</span> <span style="color:#719e07">(</span>InterruptedException e<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> Thread<span style="color:#719e07">.</span>currentThread<span style="color:#719e07">().</span>interrupt<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#cb4b16">null</span><span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</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>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">asyncInvoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 建议为supplyAsync提供自定义线程池 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">return</span> CompletableFuture<span style="color:#719e07">.</span>supplyAsync<span style="color:#719e07">(()</span> <span style="color:#719e07">-&gt;</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// Do something |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#dc322f">long</span> time <span style="color:#719e07">=</span> ThreadLocalRandom<span style="color:#719e07">.</span>current<span style="color:#719e07">().</span>nextLong<span style="color:#719e07">(</span>1000<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> Thread<span style="color:#719e07">.</span>sleep<span style="color:#719e07">(</span>time<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> StringBuilder s <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> StringBuilder<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> s<span style="color:#719e07">.</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;AsyncService asyncInvoke param:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>param<span style="color:#719e07">).</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;,sleep:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>time<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> s<span style="color:#719e07">.</span>toString<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">catch</span> <span style="color:#719e07">(</span>InterruptedException e<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> Thread<span style="color:#719e07">.</span>currentThread<span style="color:#719e07">().</span>interrupt<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#cb4b16">null</span><span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">});</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>通过 return CompletableFuture.supplyAsync() ,业务执行已从 Dubbo 线程切换到业务线程,避免了对 Dubbo 线程池的阻塞。</p> |
| <h3 id="2使用asynccontext实现异步">2、使用AsyncContext实现异步</h3> |
| <p>Dubbo 提供了一个类似 Servlet 3.0 的异步接口AsyncContext,在没有 CompletableFuture 签名接口的情况下,也可以实现 Provider 端的异步执行。</p> |
| <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">interface</span> <span style="color:#268bd2">AsyncService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</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-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">AsyncServiceImpl</span> <span style="color:#268bd2">implements</span> AsyncService <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">final</span> AsyncContext asyncContext <span style="color:#719e07">=</span> RpcContext<span style="color:#719e07">.</span>startAsync<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">new</span> Thread<span style="color:#719e07">(()</span> <span style="color:#719e07">-&gt;</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 如果要使用上下文,则必须要放在第一句执行 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> asyncContext<span style="color:#719e07">.</span>signalContextSwitch<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> Thread<span style="color:#719e07">.</span>sleep<span style="color:#719e07">(</span>500<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">catch</span> <span style="color:#719e07">(</span>InterruptedException e<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> e<span style="color:#719e07">.</span>printStackTrace<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 写回响应 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> asyncContext<span style="color:#719e07">.</span>write<span style="color:#719e07">(</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;, response from provider.&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}).</span>start<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#cb4b16">null</span><span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><h2 id="consumer异步">Consumer异步</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboReference</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> AsyncService asyncService<span style="color:#719e07">;</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">run</span><span style="color:#719e07">(</span>String<span style="color:#719e07">...</span> args<span style="color:#719e07">)</span> <span style="color:#268bd2">throws</span> Exception <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//调用异步接口 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> future1 <span style="color:#719e07">=</span> asyncService<span style="color:#719e07">.</span>asyncInvoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;async call request1&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> future1<span style="color:#719e07">.</span>whenComplete<span style="color:#719e07">((</span>v<span style="color:#719e07">,</span> t<span style="color:#719e07">)</span> <span style="color:#719e07">-&gt;</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#719e07">(</span>t <span style="color:#719e07">!=</span> <span style="color:#cb4b16">null</span><span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> t<span style="color:#719e07">.</span>printStackTrace<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">else</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;AsyncTask Response-1: &#34;</span> <span style="color:#719e07">+</span> v<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">});</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//两次调用并非顺序返回 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> future2 <span style="color:#719e07">=</span> asyncService<span style="color:#719e07">.</span>asyncInvoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;async call request2&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> future2<span style="color:#719e07">.</span>whenComplete<span style="color:#719e07">((</span>v<span style="color:#719e07">,</span> t<span style="color:#719e07">)</span> <span style="color:#719e07">-&gt;</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#719e07">(</span>t <span style="color:#719e07">!=</span> <span style="color:#cb4b16">null</span><span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> t<span style="color:#719e07">.</span>printStackTrace<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">else</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;AsyncTask Response-2: &#34;</span> <span style="color:#719e07">+</span> v<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">});</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//consumer异步调用 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> future3 <span style="color:#719e07">=</span> CompletableFuture<span style="color:#719e07">.</span>supplyAsync<span style="color:#719e07">(()</span> <span style="color:#719e07">-&gt;</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> asyncService<span style="color:#719e07">.</span>invoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;invoke call request3&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">});</span> |
| </span></span><span style="display:flex;"><span> future3<span style="color:#719e07">.</span>whenComplete<span style="color:#719e07">((</span>v<span style="color:#719e07">,</span> t<span style="color:#719e07">)</span> <span style="color:#719e07">-&gt;</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#719e07">(</span>t <span style="color:#719e07">!=</span> <span style="color:#cb4b16">null</span><span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> t<span style="color:#719e07">.</span>printStackTrace<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">else</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;AsyncTask Response-3: &#34;</span> <span style="color:#719e07">+</span> v<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">});</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;AsyncTask Executed before response return.&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div></description></item><item><title>Overview: 版本与分组</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/version_group/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/develop/version_group/</guid><description> |
| <h2 id="版本与分组">版本与分组</h2> |
| <p>Dubbo服务中,接口并不能唯一确定一个服务,只有接口+分组+版本号才能唯一确定一个服务。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <ul> |
| <li>当同一个接口针对不同的业务场景、不同的使用需求或者不同的功能模块等场景,可使用服务分组来区分不同的实现方式。同时,这些不同实现所提供的服务是可并存的,也支持互相调用。</li> |
| <li>当接口实现需要升级又要保留原有实现的情况下,即出现不兼容升级时,我们可以使用不同版本号进行区分。</li> |
| </ul> |
| <h2 id="使用方式">使用方式</h2> |
| <p>使用 @DubboService 注解,添加 group 参数和 version 参数 |
| 本示例中使用&quot;发布和调用&quot; 中示例代码</p> |
| <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">interface</span> <span style="color:#268bd2">DevelopService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>接口实现1:</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">@DubboService</span><span style="color:#719e07">(</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;group1&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">DevelopProviderServiceV1</span> <span style="color:#268bd2">implements</span> DevelopService<span style="color:#719e07">{</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> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> StringBuilder s <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> StringBuilder<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> s<span style="color:#719e07">.</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ServiceV1 param:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> s<span style="color:#719e07">.</span>toString<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>接口实现2:</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">@DubboService</span><span style="color:#719e07">(</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;group2&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;2.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">DevelopProviderServiceV2</span> <span style="color:#268bd2">implements</span> DevelopService<span style="color:#719e07">{</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> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> StringBuilder s <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> StringBuilder<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> s<span style="color:#719e07">.</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ServiceV2 param:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> s<span style="color:#719e07">.</span>toString<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>启动服务后,可以在注册中心看到对应的服务列表,如下: |
| <code>![serviceList](/imgs/v3/develop/develop-service-list.png)</code></p> |
| <p>客户端接口调用:</p> |
| <blockquote> |
| <p>使用 @DubboReference 注解,添加 group 参数和 version 参数</p> |
| </blockquote> |
| <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">@DubboReference</span><span style="color:#719e07">(</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;group1&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> DevelopService developService<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">@DubboReference</span><span style="color:#719e07">(</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;group2&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;2.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> DevelopService developServiceV2<span style="color:#719e07">;</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">run</span><span style="color:#719e07">(</span>String<span style="color:#719e07">...</span> args<span style="color:#719e07">)</span> <span style="color:#268bd2">throws</span> Exception <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//调用DevelopService的group1分组实现 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Dubbo Remote Return ======&gt; &#34;</span> <span style="color:#719e07">+</span> developService<span style="color:#719e07">.</span>invoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;1&#34;</span><span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//调用DevelopService的另一个实现 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Dubbo Remote Return ======&gt; &#34;</span> <span style="color:#719e07">+</span> developServiceV2<span style="color:#719e07">.</span>invoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;2&#34;</span><span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div></description></item><item><title>Overview: 上下文参数传递</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/context/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/develop/context/</guid><description> |
| <h2 id="上下文参数传递">上下文参数传递</h2> |
| <p>在 Dubbo 3 中,RpcContext 被拆分为四大模块(ServerContext、ClientAttachment、ServerAttachment 和 ServiceContext)。</p> |
| <p>它们分别承担了不同的职责:</p> |
| <ul> |
| <li>ServiceContext:在 Dubbo 内部使用,用于传递调用链路上的参数信息,如 invoker 对象等</li> |
| <li>ClientAttachment:在 Client 端使用,往 ClientAttachment 中写入的参数将被传递到 Server 端</li> |
| <li>ServerAttachment:在 Server 端使用,从 ServerAttachment 中读取的参数是从 Client 中传递过来的</li> |
| <li>ServerContext:在 Client 端和 Server 端使用,用于从 Server 端回传 Client 端使用,Server 端写入到 ServerContext 的参数在调用结束后可以在 Client 端的 ServerContext 获取到</li> |
| </ul> |
| <h2 id="使用场景">使用场景</h2> |
| <p>1、Dubbo系统间调用时,想传递一些通用参数,可通过Dubbo提供的扩展如Filter等实现统一的参数传递</p> |
| <p>2、Dubbo系统间调用时,想传递接口定义之外的参数,可在调用接口前使用setAttachment传递参数。</p> |
| <h2 id="使用方式">使用方式</h2> |
| <p>setAttachment 设置的 KV 对,在完成下面一次远程调用会被清空,即多次远程调用要多次设置。</p> |
| <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">interface</span> <span style="color:#268bd2">ContextService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboService</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">ContextServiceImpl</span> <span style="color:#268bd2">implements</span> ContextService<span style="color:#719e07">{</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> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//ServerAttachment接收客户端传递过来的参数 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> Object<span style="color:#719e07">&gt;</span> serverAttachments <span style="color:#719e07">=</span> RpcContext<span style="color:#719e07">.</span>getServerAttachment<span style="color:#719e07">().</span>getObjectAttachments<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ContextService serverAttachments:&#34;</span> <span style="color:#719e07">+</span> JSON<span style="color:#719e07">.</span>toJSONString<span style="color:#719e07">(</span>serverAttachments<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//往客户端传递参数 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> RpcContext<span style="color:#719e07">.</span>getServerContext<span style="color:#719e07">().</span>setAttachment<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;serverKey&#34;</span><span style="color:#719e07">,</span><span style="color:#2aa198">&#34;serverValue&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> StringBuilder s <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> StringBuilder<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> s<span style="color:#719e07">.</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ContextService param:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> s<span style="color:#719e07">.</span>toString<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</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-java" data-lang="java"><span style="display:flex;"><span> <span style="color:#586e75">//往服务端传递参数 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> RpcContext<span style="color:#719e07">.</span>getClientAttachment<span style="color:#719e07">().</span>setAttachment<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;clientKey1&#34;</span><span style="color:#719e07">,</span><span style="color:#2aa198">&#34;clientValue1&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> String res <span style="color:#719e07">=</span> contextService<span style="color:#719e07">.</span>invoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;context1&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//接收传递回来参数 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> Object<span style="color:#719e07">&gt;</span> clientAttachment <span style="color:#719e07">=</span> RpcContext<span style="color:#719e07">.</span>getServerContext<span style="color:#719e07">().</span>getObjectAttachments<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ContextTask clientAttachment:&#34;</span> <span style="color:#719e07">+</span> JSON<span style="color:#719e07">.</span>toJSONString<span style="color:#719e07">(</span>clientAttachment<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ContextService Return : &#34;</span> <span style="color:#719e07">+</span> res<span style="color:#719e07">);</span> |
| </span></span></code></pre></div><p><em><font color='#FF7D00' size=4 > 注意 </font></em></p> |
| <blockquote> |
| <p>path, group, version, dubbo, token, timeout 几个 key 是保留字段,请使用其它值。</p> |
| </blockquote></description></item><item><title>Overview: 开发服务</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/generic/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/develop/generic/</guid><description> |
| <h2 id="泛化调用">泛化调用</h2> |
| <p>泛化调用(客户端泛化调用)是指在调用方没有服务方提供的 API(SDK)的情况下,对服务方进行调用,并且可以正常拿到调用结果。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>调用方没有接口及模型类元,知道服务的接口的全限定类名和方法名的情况下,可以通过泛化调用调用对应接口。 |
| 比如:实现一个通用的服务测试框架</p> |
| <h2 id="使用方式">使用方式</h2> |
| <p>本示例中使用&quot;发布和调用&quot; 中示例代码</p> |
| <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">interface</span> <span style="color:#268bd2">DevelopService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>接口实现1:</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">@DubboService</span><span style="color:#719e07">(</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;group1&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">DevelopProviderServiceV1</span> <span style="color:#268bd2">implements</span> DevelopService<span style="color:#719e07">{</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> String <span style="color:#268bd2">invoke</span><span style="color:#719e07">(</span>String param<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> StringBuilder s <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> StringBuilder<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> s<span style="color:#719e07">.</span>append<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;ServiceV1 param:&#34;</span><span style="color:#719e07">).</span>append<span style="color:#719e07">(</span>param<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> s<span style="color:#719e07">.</span>toString<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><h2 id="客户端调用">客户端调用</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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Component</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">GenericTask</span> <span style="color:#268bd2">implements</span> CommandLineRunner <span style="color:#719e07">{</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">run</span><span style="color:#719e07">(</span>String<span style="color:#719e07">...</span> args<span style="color:#719e07">)</span> <span style="color:#268bd2">throws</span> Exception <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> GenericService genericService <span style="color:#719e07">=</span> buildGenericService<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;org.apache.dubbo.samples.develop.DevelopService&#34;</span><span style="color:#719e07">,</span><span style="color:#2aa198">&#34;group2&#34;</span><span style="color:#719e07">,</span><span style="color:#2aa198">&#34;2.0&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//传入需要调用的方法,参数类型列表,参数列表 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> Object result <span style="color:#719e07">=</span> genericService<span style="color:#719e07">.</span>$invoke<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;invoke&#34;</span><span style="color:#719e07">,</span> <span style="color:#719e07">new</span> String<span style="color:#719e07">[]{</span><span style="color:#2aa198">&#34;java.lang.String&#34;</span><span style="color:#719e07">},</span> <span style="color:#719e07">new</span> Object<span style="color:#719e07">[]{</span><span style="color:#2aa198">&#34;g1&#34;</span><span style="color:#719e07">});</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;GenericTask Response: &#34;</span> <span style="color:#719e07">+</span> JSON<span style="color:#719e07">.</span>toJSONString<span style="color:#719e07">(</span>result<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> GenericService <span style="color:#268bd2">buildGenericService</span><span style="color:#719e07">(</span>String interfaceClass<span style="color:#719e07">,</span> String group<span style="color:#719e07">,</span> String version<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> ReferenceConfig<span style="color:#719e07">&lt;</span>GenericService<span style="color:#719e07">&gt;</span> reference <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> reference<span style="color:#719e07">.</span>setInterface<span style="color:#719e07">(</span>interfaceClass<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> reference<span style="color:#719e07">.</span>setVersion<span style="color:#719e07">(</span>version<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//开启泛化调用 |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> reference<span style="color:#719e07">.</span>setGeneric<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;true&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> reference<span style="color:#719e07">.</span>setTimeout<span style="color:#719e07">(</span>30000<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> reference<span style="color:#719e07">.</span>setGroup<span style="color:#719e07">(</span>group<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> ReferenceCache cache <span style="color:#719e07">=</span> SimpleReferenceCache<span style="color:#719e07">.</span>getCache<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> cache<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span>reference<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">catch</span> <span style="color:#719e07">(</span>Exception e<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">throw</span> <span style="color:#719e07">new</span> RuntimeException<span style="color:#719e07">(</span>e<span style="color:#719e07">.</span>getMessage<span style="color:#719e07">());</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div></description></item><item><title>Overview: 使用 IDL 定义与开发服务</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/develop/idl/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/develop/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 style="color:#719e07">(</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 style="color:#719e07">,</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 style="color:#719e07">)</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 style="color:#719e07">{</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 style="color:#719e07">;</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 style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> org<span style="color:#719e07">.</span>apache<span style="color:#719e07">.</span>dubbo<span style="color:#719e07">.</span>demo<span style="color:#719e07">.</span>HelloReply <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>org<span style="color:#719e07">.</span>apache<span style="color:#719e07">.</span>dubbo<span style="color:#719e07">.</span>demo<span style="color:#719e07">.</span>HelloRequest request<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> CompletableFuture<span style="color:#719e07">&lt;</span>org<span style="color:#719e07">.</span>apache<span style="color:#719e07">.</span>dubbo<span style="color:#719e07">.</span>demo<span style="color:#719e07">.</span>HelloReply<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHelloAsync</span><span style="color:#719e07">(</span>org<span style="color:#719e07">.</span>apache<span style="color:#719e07">.</span>dubbo<span style="color:#719e07">.</span>demo<span style="color:#719e07">.</span>HelloRequest request<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</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 style="color:#719e07">{</span> |
| </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<span style="color:#719e07">.</span>getLogger<span style="color:#719e07">(</span>DemoServiceImpl<span style="color:#719e07">.</span>class<span style="color:#719e07">);</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> HelloReply <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>HelloRequest request<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> logger<span style="color:#719e07">.</span>info<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Hello &#34;</span> <span style="color:#719e07">+</span> request<span style="color:#719e07">.</span>getName<span style="color:#719e07">()</span> <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;, request from consumer: &#34;</span> <span style="color:#719e07">+</span> RpcContext<span style="color:#719e07">.</span>getContext<span style="color:#719e07">().</span>getRemoteAddress<span style="color:#719e07">());</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> HelloReply<span style="color:#719e07">.</span>newBuilder<span style="color:#719e07">()</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">.</span>setMessage<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Hello &#34;</span> <span style="color:#719e07">+</span> request<span style="color:#719e07">.</span>getName<span style="color:#719e07">()</span> <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<span style="color:#719e07">.</span>getContext<span style="color:#719e07">().</span>getLocalAddress<span style="color:#719e07">())</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">.</span>build<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</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><span style="color:#719e07">(</span>HelloRequest request<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> CompletableFuture<span style="color:#719e07">.</span>completedFuture<span style="color:#719e07">(</span>sayHello<span style="color:#719e07">(</span>request<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</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:#719e07">()</span> <span style="color:#268bd2">throws</span> Exception <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">...</span> |
| </span></span><span style="display:flex;"><span> DemoService demoService <span style="color:#719e07">=</span> context<span style="color:#719e07">.</span>getBean<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;demoService&#34;</span><span style="color:#719e07">,</span> DemoService<span style="color:#719e07">.</span>class<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> HelloRequest request <span style="color:#719e07">=</span> HelloRequest<span style="color:#719e07">.</span>newBuilder<span style="color:#719e07">().</span>setName<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Hello&#34;</span><span style="color:#719e07">).</span>build<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> HelloReply reply <span style="color:#719e07">=</span> demoService<span style="color:#719e07">.</span>sayHello<span style="color:#719e07">(</span>request<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;result: &#34;</span> <span style="color:#719e07">+</span> reply<span style="color:#719e07">.</span>getMessage<span style="color:#719e07">());</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</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></channel></rss> |