| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – 高级用法</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/</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/docs/advanced/index.xml" rel="self" type="application/rss+xml"/><item><title>Docs: 启动时检查</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/preflight-check/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/preflight-check/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/preflight-check/">最新版本</a>。</p> |
| </div> |
| <p>Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 <code>check=&quot;true&quot;</code>。</p> |
| <p>可以通过 <code>check=&quot;false&quot;</code> 关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。</p> |
| <p>另外,如果你的 Spring 容器是懒加载的,或者通过 API 编程延迟引用服务,请关闭 check,否则服务临时不可用时,会抛出异常,拿到 null 引用,如果 <code>check=&quot;false&quot;</code>,总是会返回引用,当服务恢复时,能自动连上。</p> |
| <h2 id="示例">示例</h2> |
| <h3 id="通过-spring-配置文件">通过 spring 配置文件</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> check=<span style="color:#2aa198">&#34;false&#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:consumer</span> check=<span style="color:#2aa198">&#34;false&#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:registry</span> check=<span style="color:#2aa198">&#34;false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="通过-dubboproperties">通过 dubbo.properties</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-properties" data-lang="properties"><span style="display:flex;"><span>dubbo.reference.com.foo.BarService.check<span style="color:#719e07">=</span><span style="color:#2aa198">false</span> |
| </span></span><span style="display:flex;"><span>dubbo.consumer.check<span style="color:#719e07">=</span><span style="color:#2aa198">false</span> |
| </span></span><span style="display:flex;"><span>dubbo.registry.check<span style="color:#719e07">=</span><span style="color:#2aa198">false</span> |
| </span></span></code></pre></div><h3 id="通过--d-参数">通过 -D 参数</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>java -Ddubbo.reference.com.foo.BarService.check<span style="color:#719e07">=</span><span style="color:#b58900">false</span> |
| </span></span><span style="display:flex;"><span>java -Ddubbo.consumer.check<span style="color:#719e07">=</span><span style="color:#b58900">false</span> |
| </span></span><span style="display:flex;"><span>java -Ddubbo.registry.check<span style="color:#719e07">=</span><span style="color:#b58900">false</span> |
| </span></span></code></pre></div><h2 id="配置的含义">配置的含义</h2> |
| <p><code>dubbo.reference.com.foo.BarService.check</code>,覆盖 <code>com.foo.BarService</code>的 reference 的 check 值,就算配置中有声明,也会被覆盖。</p> |
| <p><code>dubbo.consumer.check=false</code>,是设置reference的 <code>check</code> 的缺省值,如果配置中有显式的声明,如:<code>&lt;dubbo:reference check=&quot;true&quot;/&gt;</code>,不会受影响。</p> |
| <p><code>dubbo.registry.check=false</code>,前面两个都是指订阅成功,但提供者列表是否为空是否报错,如果注册订阅失败时,也允许启动,需使用此选项,将在后台定时重试。</p></description></item><item><title>Docs: 序列化协议安全</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/serialization-security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/serialization-security/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/blog/1/01/01/%E5%BA%8F%E5%88%97%E5%8C%96%E5%8D%8F%E8%AE%AE%E5%AE%89%E5%85%A8/">最新版本</a>。</p> |
| </div> |
| <p>Dubbo3.0在序列化协议安全方面进行了升级加固,推荐使用Tripe协议非Wrapper模式。 |
| 该协议默认安全,但需要开发人员编写IDL文件。</p> |
| <p>Triple协议Wrapper模式下,允许兼容其它序列化数据,提供了良好的兼容性。但其它协议可能存在反序列化安全缺陷,对于Hession2协议,高安全属性用户应当按照samples代码指示,开启白名单模式,框架默认会开启黑名单模式,拦截恶意调用。</p> |
| <p>不建议使用其它序列化协议,当攻击者可访问Provider接口时,其它序列化协议的安全缺陷,可能导致 Povider 接口命令执行。</p> |
| <p>若必须使用其它序列化协议,同时希望具备一定安全性。应当开启Token鉴权机制,防止未鉴权的不可信请求来源威胁Provider的安全性。开启Token鉴权机制时,应当同步开启注册中心的鉴权功能。</p></description></item><item><title>Docs: 集群容错</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/fault-tolerent-strategy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/fault-tolerent-strategy/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/fault-tolerent-strategy/">最新版本</a>。</p> |
| </div> |
| <p>在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/cluster.jpg" alt="cluster"></p> |
| <p>各节点关系:</p> |
| <ul> |
| <li>这里的 <code>Invoker</code> 是 <code>Provider</code> 的一个可调用 <code>Service</code> 的抽象,<code>Invoker</code> 封装了 <code>Provider</code> 地址及 <code>Service</code> 接口信息</li> |
| <li><code>Directory</code> 代表多个 <code>Invoker</code>,可以把它看成 <code>List&lt;Invoker&gt;</code> ,但与 <code>List</code> 不同的是,它的值可能是动态变化的,比如注册中心推送变更</li> |
| <li><code>Cluster</code> 将 <code>Directory</code> 中的多个 <code>Invoker</code> 伪装成一个 <code>Invoker</code>,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个</li> |
| <li><code>Router</code> 负责从多个 <code>Invoker</code> 中按路由规则选出子集,比如读写分离,应用隔离等</li> |
| <li><code>LoadBalance</code> 负责从多个 <code>Invoker</code> 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选</li> |
| </ul> |
| <h2 id="集群容错模式">集群容错模式</h2> |
| <p>可以自行扩展集群容错策略,参见:<a href="../../references/spis/cluster">集群扩展</a></p> |
| <h3 id="failover-cluster">Failover Cluster</h3> |
| <p>失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 <code>retries=&quot;2&quot;</code> 来设置重试次数(不含第一次)。</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> retries=<span style="color:#2aa198">&#34;2&#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> retries=<span style="color:#2aa198">&#34;2&#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&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;findFoo&#34;</span> retries=<span style="color:#2aa198">&#34;2&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| 该配置为缺省配置 |
| </div> |
| <h3 id="failfast-cluster">Failfast Cluster</h3> |
| <p>快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。</p> |
| <h3 id="failsafe-cluster">Failsafe Cluster</h3> |
| <p>失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。</p> |
| <h3 id="failback-cluster">Failback Cluster</h3> |
| <p>失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。</p> |
| <h3 id="forking-cluster">Forking Cluster</h3> |
| <p>并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 <code>forks=&quot;2&quot;</code> 来设置最大并行数。</p> |
| <h3 id="broadcast-cluster">Broadcast Cluster</h3> |
| <p>广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。</p> |
| <p>现在广播调用中,可以通过 broadcast.fail.percent 配置节点调用失败的比例,当达到这个比例后,BroadcastClusterInvoker |
| 将不再调用其他节点,直接抛出异常。 broadcast.fail.percent 取值在 0~100 范围内。默认情况下当全部调用失败后,才会抛出异常。 |
| broadcast.fail.percent 只是控制的当失败后是否继续调用其他节点,并不改变结果(任意一台报错则报错)。broadcast.fail.percent 参数 |
| 在 dubbo2.7.10 及以上版本生效。</p> |
| <p>Broadcast Cluster 配置 broadcast.fail.percent。</p> |
| <p>broadcast.fail.percent=20 代表了当 20% 的节点调用失败就抛出异常,不再调用其他节点。</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>@reference(cluster = &#34;broadcast&#34;, parameters = {&#34;broadcast.fail.percent&#34;, &#34;20&#34;}) |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>2.1.0</code> 开始支持 |
| </div> |
| <h3 id="available-cluster">Available Cluster</h3> |
| <p>调用目前可用的实例(只调用一个),如果当前没有可用的实例,则抛出异常。通常用于不需要负载均衡的场景。</p> |
| <h3 id="mergeable-cluster">Mergeable Cluster</h3> |
| <p>将集群中的调用结果聚合起来返回结果,通常和group一起配合使用。通过分组对结果进行聚合并返回聚合后的结果,比如菜单服务,用group区分同一接口的多种实现,现在消费方需从每种group中调用一次并返回结果,对结果进行合并之后返回,这样就可以实现聚合菜单项。</p> |
| <h3 id="zoneaware-cluster">ZoneAware Cluster</h3> |
| <p>多注册中心订阅的场景,注册中心集群间的负载均衡。对于多注册中心间的选址策略有如下四种</p> |
| <ol> |
| <li>指定优先级:<code>preferred=&quot;true&quot;</code>注册中心的地址将被优先选择</li> |
| </ol> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:registry</span> address=<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span> preferred=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><ol start="2"> |
| <li>同中心优先:检查当前请求所属的区域,优先选择具有相同区域的注册中心</li> |
| </ol> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:registry</span> address=<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span> zone=<span style="color:#2aa198">&#34;beijing&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><ol start="3"> |
| <li>权重轮询:根据每个注册中心的权重分配流量</li> |
| </ol> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;beijing&#34;</span> address=<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span> weight=<span style="color:#2aa198">&#34;100&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;shanghai&#34;</span> address=<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2182&#34;</span> weight=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><ol start="4"> |
| <li>缺省值:选择一个可用的注册中心</li> |
| </ol> |
| <h2 id="集群模式配置">集群模式配置</h2> |
| <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:service</span> cluster=<span style="color:#2aa198">&#34;failsafe&#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> cluster=<span style="color:#2aa198">&#34;failsafe&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 负载均衡</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/loadbalance/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/loadbalance/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/loadbalance/">最新版本</a>。</p> |
| </div> |
| <p>在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 <code>random</code> 随机调用。</p> |
| <p>具体实现上,Dubbo 提供的是客户端负载均衡,即由 Consumer 通过负载均衡算法得出需要将请求提交到哪个 Provider 实例。</p> |
| <p>可以自行扩展负载均衡策略,参见:<a href="../../references/spis/load-balance">负载均衡扩展</a></p> |
| <h2 id="负载均衡策略">负载均衡策略</h2> |
| <p>目前 Dubbo 内置了如下负载均衡算法,用户可直接配置使用:</p> |
| <table> |
| <thead> |
| <tr> |
| <th style="text-align:left">算法</th> |
| <th style="text-align:left">特性</th> |
| <th style="text-align:left">备注</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td style="text-align:left">RandomLoadBalance</td> |
| <td style="text-align:left">加权随机</td> |
| <td style="text-align:left">默认算法,默认权重相同</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">RoundRobinLoadBalance</td> |
| <td style="text-align:left">加权轮询</td> |
| <td style="text-align:left">借鉴于 Nginx 的平滑加权轮询算法,默认权重相同,</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">LeastActiveLoadBalance</td> |
| <td style="text-align:left">最少活跃优先 + 加权随机</td> |
| <td style="text-align:left">背后是能者多劳的思想</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">ShortestResponseLoadBalance</td> |
| <td style="text-align:left">最短响应优先 + 加权随机</td> |
| <td style="text-align:left">更加关注响应速度</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">ConsistentHashLoadBalance</td> |
| <td style="text-align:left">一致性 Hash</td> |
| <td style="text-align:left">确定的入参,确定的提供者,适用于有状态请求</td> |
| </tr> |
| </tbody> |
| </table> |
| <h3 id="random">Random</h3> |
| <ul> |
| <li><strong>加权随机</strong>,按权重设置随机概率。</li> |
| <li>在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。</li> |
| <li>缺点:存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。</li> |
| </ul> |
| <h3 id="roundrobin">RoundRobin</h3> |
| <ul> |
| <li><strong>加权轮询</strong>,按公约后的权重设置轮询比率,循环调用节点</li> |
| <li>缺点:同样存在慢的提供者累积请求的问题。</li> |
| </ul> |
| <p>加权轮询过程过程中,如果某节点权重过大,会存在某段时间内调用过于集中的问题。<br> |
| 例如 ABC 三节点有如下权重:<code>{A: 3, B: 2, C: 1}</code><br> |
| 那么按照最原始的轮询算法,调用过程将变成:<code>A A A B B C</code></p> |
| <p>对此,Dubbo 借鉴 Nginx 的平滑加权轮询算法,对此做了优化,调用过程可抽象成下表:</p> |
| <table> |
| <thead> |
| <tr> |
| <th style="text-align:left">轮前加和权重</th> |
| <th style="text-align:left">本轮胜者</th> |
| <th style="text-align:left">合计权重</th> |
| <th style="text-align:left">轮后权重(胜者减去合计权重)</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td style="text-align:left">起始轮</td> |
| <td style="text-align:left">\</td> |
| <td style="text-align:left">\</td> |
| <td style="text-align:left"><code>A(0), B(0), C(0)</code></td> |
| </tr> |
| <tr> |
| <td style="text-align:left"><code>A(3), B(2), C(1)</code></td> |
| <td style="text-align:left">A</td> |
| <td style="text-align:left">6</td> |
| <td style="text-align:left"><code>A(-3), B(2), C(1)</code></td> |
| </tr> |
| <tr> |
| <td style="text-align:left"><code>A(0), B(4), C(2)</code></td> |
| <td style="text-align:left">B</td> |
| <td style="text-align:left">6</td> |
| <td style="text-align:left"><code>A(0), B(-2), C(2)</code></td> |
| </tr> |
| <tr> |
| <td style="text-align:left"><code>A(3), B(0), C(3)</code></td> |
| <td style="text-align:left">A</td> |
| <td style="text-align:left">6</td> |
| <td style="text-align:left"><code>A(-3), B(0), C(3)</code></td> |
| </tr> |
| <tr> |
| <td style="text-align:left"><code>A(0), B(2), C(4)</code></td> |
| <td style="text-align:left">C</td> |
| <td style="text-align:left">6</td> |
| <td style="text-align:left"><code>A(0), B(2), C(-2)</code></td> |
| </tr> |
| <tr> |
| <td style="text-align:left"><code>A(3), B(4), C(-1)</code></td> |
| <td style="text-align:left">B</td> |
| <td style="text-align:left">6</td> |
| <td style="text-align:left"><code>A(3), B(-2), C(-1)</code></td> |
| </tr> |
| <tr> |
| <td style="text-align:left"><code>A(6), B(0), C(0)</code></td> |
| <td style="text-align:left">A</td> |
| <td style="text-align:left">6</td> |
| <td style="text-align:left"><code>A(0), B(0), C(0)</code></td> |
| </tr> |
| </tbody> |
| </table> |
| <p>我们发现经过合计权重(3+2+1)轮次后,循环又回到了起点,整个过程中节点流量是平滑的,且哪怕在很短的时间周期内,概率都是按期望分布的。</p> |
| <p>如果用户有加权轮询的需求,可放心使用该算法。</p> |
| <h3 id="leastactive">LeastActive</h3> |
| <ul> |
| <li><strong>加权最少活跃调用优先</strong>,活跃数越低,越优先调用,相同活跃数的进行加权随机。活跃数指调用前后计数差(针对特定提供者:请求发送数 - 响应返回数),表示特定提供者的任务堆积量,活跃数越低,代表该提供者处理能力越强。</li> |
| <li>使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大;相对的,处理能力越强的节点,处理更多的请求。</li> |
| </ul> |
| <h3 id="shortestresponse">ShortestResponse</h3> |
| <ul> |
| <li><strong>加权最短响应优先</strong>,在最近一个滑动窗口中,响应时间越短,越优先调用。相同响应时间的进行加权随机。</li> |
| <li>使得响应时间越快的提供者,处理更多的请求。</li> |
| <li>缺点:可能会造成流量过于集中于高性能节点的问题。</li> |
| </ul> |
| <p>这里的响应时间 = 某个提供者在窗口时间内的平均响应时间,窗口时间默认是 30s。</p> |
| <h3 id="consistenthash">ConsistentHash</h3> |
| <ul> |
| <li><strong>一致性 Hash</strong>,相同参数的请求总是发到同一提供者。</li> |
| <li>当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。</li> |
| <li>算法参见:<a href="http://en.wikipedia.org/wiki/Consistent_hashing">Consistent Hashing | WIKIPEDIA</a></li> |
| <li>缺省只对第一个参数 Hash,如果要修改,请配置 <code>&lt;dubbo:parameter key=&quot;hash.arguments&quot; value=&quot;0,1&quot; /&gt;</code></li> |
| <li>缺省用 160 份虚拟节点,如果要修改,请配置 <code>&lt;dubbo:parameter key=&quot;hash.nodes&quot; value=&quot;320&quot; /&gt;</code></li> |
| </ul> |
| <h2 id="配置">配置</h2> |
| <h3 id="服务端服务级别">服务端服务级别</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;...&#34;</span> loadbalance=<span style="color:#2aa198">&#34;roundrobin&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="客户端服务级别">客户端服务级别</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> interface=<span style="color:#2aa198">&#34;...&#34;</span> loadbalance=<span style="color:#2aa198">&#34;roundrobin&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="服务端方法级别">服务端方法级别</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;...&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;...&#34;</span> loadbalance=<span style="color:#2aa198">&#34;roundrobin&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:service&gt;</span> |
| </span></span></code></pre></div><h3 id="客户端方法级别">客户端方法级别</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> interface=<span style="color:#2aa198">&#34;...&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;...&#34;</span> loadbalance=<span style="color:#2aa198">&#34;roundrobin&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 线程模型</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/thread-model/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/thread-model/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/threading-model/">最新版本</a>。</p> |
| </div> |
| <p>如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO 线程上处理更快,因为减少了线程池调度。</p> |
| <p>但如果事件处理逻辑较慢,或者需要发起新的 IO 请求,比如需要查询数据库,则必须派发到线程池,否则 IO 线程阻塞,将导致不能接收其它请求。</p> |
| <p>如果用 IO 线程处理事件,又在事件处理过程中发起新的 IO 请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/dubbo-protocol.jpg" alt="dubbo-protocol"></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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> dispatcher=<span style="color:#2aa198">&#34;all&#34;</span> threadpool=<span style="color:#2aa198">&#34;fixed&#34;</span> threads=<span style="color:#2aa198">&#34;100&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>Dispatcher</p> |
| <ul> |
| <li><code>all</code> 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。</li> |
| <li><code>direct</code> 所有消息都不派发到线程池,全部在 IO 线程上直接执行。</li> |
| <li><code>message</code> 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO 线程上执行。</li> |
| <li><code>execution</code> 只有请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在 IO 线程上执行。</li> |
| <li><code>connection</code> 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。</li> |
| </ul> |
| <p>ThreadPool</p> |
| <ul> |
| <li><code>fixed</code> 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)</li> |
| <li><code>cached</code> 缓存线程池,空闲一分钟自动删除,需要时重建。</li> |
| <li><code>limited</code> 可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。</li> |
| <li><code>eager</code> 优先创建<code>Worker</code>线程池。在任务数量大于<code>corePoolSize</code>但是小于<code>maximumPoolSize</code>时,优先创建<code>Worker</code>来处理任务。当任务数量大于<code>maximumPoolSize</code>时,将任务放入阻塞队列中。阻塞队列充满时抛出<code>RejectedExecutionException</code>。(相比于<code>cached</code>:<code>cached</code>在任务数量超过<code>maximumPoolSize</code>时直接抛出异常而不是将任务放入阻塞队列)</li> |
| </ul></description></item><item><title>Docs: 直连提供者</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/explicit-target/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/explicit-target/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/explicit-target/">最新版本</a>。</p> |
| </div> |
| <p>在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直连方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/dubbo-directly.jpg" alt="/user-guide/images/dubbo-directly.jpg"></p> |
| <h2 id="通过-xml-配置">通过 XML 配置</h2> |
| <p>如果是线上需求需要点对点,可在 <code>&lt;dubbo:reference&gt;</code> 中配置 url 指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下:</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> id=<span style="color:#2aa198">&#34;xxxService&#34;</span> interface=<span style="color:#2aa198">&#34;com.alibaba.xxx.XxxService&#34;</span> url=<span style="color:#2aa198">&#34;dubbo://localhost:20890&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>1.0.6</code> 及以上版本支持 |
| </div> |
| <h2 id="通过--d-参数指定">通过 -D 参数指定</h2> |
| <p>在 JVM 启动参数中加入-D参数映射服务地址,如:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>java -Dcom.alibaba.xxx.XxxService<span style="color:#719e07">=</span>dubbo://localhost:20890 |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| key 为服务名,value 为服务提供者 url,此配置优先级最高,<code>1.0.15</code> 及以上版本支持 |
| </div> |
| <h2 id="通过文件映射">通过文件映射</h2> |
| <p>如果服务比较多,也可以用文件映射,用 <code>-Ddubbo.resolve.file</code> 指定映射文件路径,此配置优先级高于 <code>&lt;dubbo:reference&gt;</code> 中的配置 [^3],如:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>java -Ddubbo.resolve.file<span style="color:#719e07">=</span>xxx.properties |
| </span></span></code></pre></div><p>然后在映射文件 <code>xxx.properties</code> 中加入配置,其中 key 为服务名,value 为服务提供者 URL:</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>com.alibaba.xxx.XxxService<span style="color:#719e07">=</span><span style="color:#2aa198">dubbo://localhost:20890</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>1.0.15</code> 及以上版本支持,<code>2.0</code> 以上版本自动加载 ${user.home}/dubbo-resolve.properties文件,不需要配置 |
| </div> |
| <div class="alert alert-warning" role="alert"> |
| <h4 class="alert-heading">注意</h4> |
| 为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。 |
| </div></description></item><item><title>Docs: 只订阅</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/subscribe-only/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/subscribe-only/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/subscribe-only/">最新版本</a>。</p> |
| </div> |
| <p>为方便开发测试,经常会在线下共用一个所有服务可用的注册中心,这时,如果一个正在开发中的服务提供者注册,可能会影响消费者不能正常运行。</p> |
| <p>可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其它服务),而不注册正在开发的服务,通过直连测试正在开发的服务。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/subscribe-only.jpg" alt="/user-guide/images/subscribe-only.jpg"></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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:registry</span> address=<span style="color:#2aa198">&#34;10.20.153.10:9090&#34;</span> register=<span style="color:#2aa198">&#34;false&#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:registry</span> address=<span style="color:#2aa198">&#34;10.20.153.10:9090?register=false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 多协议</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/multi-protocols/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/multi-protocols/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/multi-protocols/">最新版本</a>。</p> |
| </div> |
| <p>Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。</p> |
| <h2 id="不同服务不同协议">不同服务不同协议</h2> |
| <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:#719e07">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;world&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;registry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090&#34;</span> username=<span style="color:#2aa198">&#34;admin&#34;</span> password=<span style="color:#2aa198">&#34;hello1234&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 多协议配置 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> port=<span style="color:#2aa198">&#34;20880&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;rmi&#34;</span> port=<span style="color:#2aa198">&#34;1099&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 使用dubbo协议暴露服务 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.HelloService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> ref=<span style="color:#2aa198">&#34;helloService&#34;</span> protocol=<span style="color:#2aa198">&#34;dubbo&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 使用rmi协议暴露服务 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.DemoService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> ref=<span style="color:#2aa198">&#34;demoService&#34;</span> protocol=<span style="color:#2aa198">&#34;rmi&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&gt;</span> |
| </span></span></code></pre></div><h2 id="多协议暴露服务">多协议暴露服务</h2> |
| <p>需要与 http 客户端相互操作</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:#719e07">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;world&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;registry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090&#34;</span> username=<span style="color:#2aa198">&#34;admin&#34;</span> password=<span style="color:#2aa198">&#34;hello1234&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 多协议配置 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> port=<span style="color:#2aa198">&#34;20880&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;hessian&#34;</span> port=<span style="color:#2aa198">&#34;8080&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 使用多个协议暴露服务 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:service</span> id=<span style="color:#2aa198">&#34;helloService&#34;</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.HelloService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> protocol=<span style="color:#2aa198">&#34;dubbo,hessian&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 多注册中心</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/multi-registry/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/multi-registry/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/multi-registry/">最新版本</a>。</p> |
| </div> |
| <p>Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。另外,注册中心是支持自定义扩展的 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。</p> |
| <h2 id="多注册中心注册">多注册中心注册</h2> |
| <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:#719e07">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;world&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 多注册中心配置 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;hangzhouRegistry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;qingdaoRegistry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.141.151:9010&#34;</span> default=<span style="color:#2aa198">&#34;false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 向多个注册中心注册 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.HelloService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> ref=<span style="color:#2aa198">&#34;helloService&#34;</span> registry=<span style="color:#2aa198">&#34;hangzhouRegistry,qingdaoRegistry&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&gt;</span> |
| </span></span></code></pre></div><h2 id="不同服务使用不同注册中心">不同服务使用不同注册中心</h2> |
| <p>比如:CRM 有些服务是专门为国际站设计的,有些服务是专门为中文站设计的。</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:#719e07">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;world&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 多注册中心配置 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;chinaRegistry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;intlRegistry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.154.177:9010&#34;</span> default=<span style="color:#2aa198">&#34;false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 向中文站注册中心注册 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.HelloService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> ref=<span style="color:#2aa198">&#34;helloService&#34;</span> registry=<span style="color:#2aa198">&#34;chinaRegistry&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 向国际站注册中心注册 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.DemoService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> ref=<span style="color:#2aa198">&#34;demoService&#34;</span> registry=<span style="color:#2aa198">&#34;intlRegistry&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&gt;</span> |
| </span></span></code></pre></div><h2 id="多注册中心引用">多注册中心引用</h2> |
| <p>比如:CRM 需同时调用中文站和国际站的 PC2 服务,PC2 在中文站和国际站均有部署,接口及版本号都一样,但连的数据库不一样。</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:#719e07">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;world&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 多注册中心配置 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;chinaRegistry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> id=<span style="color:#2aa198">&#34;intlRegistry&#34;</span> address=<span style="color:#2aa198">&#34;10.20.154.177:9010&#34;</span> default=<span style="color:#2aa198">&#34;false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 引用中文站服务 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;chinaHelloService&#34;</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.HelloService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> registry=<span style="color:#2aa198">&#34;chinaRegistry&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 引用国际站站服务 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;intlHelloService&#34;</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.HelloService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> registry=<span style="color:#2aa198">&#34;intlRegistry&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&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:#719e07">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;world&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 多注册中心配置,竖号分隔表示同时连接多个不同注册中心,同一注册中心的多个集群地址用逗号分隔 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090|10.20.154.177:9010&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- 引用服务 --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;helloService&#34;</span> interface=<span style="color:#2aa198">&#34;com.alibaba.hello.api.HelloService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&gt;</span> |
| </span></span></code></pre></div><div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p>可以自行扩展注册中心,参见:<a href="../../references/spis/registry">注册中心扩展</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 服务分组</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/service-group/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/service-group/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/service-group/">最新版本</a>。</p> |
| </div> |
| <p>当一个接口有多种实现时,可以用 group 区分。</p> |
| <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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> group=<span style="color:#2aa198">&#34;feedback&#34;</span> interface=<span style="color:#2aa198">&#34;com.xxx.IndexService&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> group=<span style="color:#2aa198">&#34;member&#34;</span> interface=<span style="color:#2aa198">&#34;com.xxx.IndexService&#34;</span> <span style="color:#268bd2">/&gt;</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;feedbackIndexService&#34;</span> group=<span style="color:#2aa198">&#34;feedback&#34;</span> interface=<span style="color:#2aa198">&#34;com.xxx.IndexService&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;memberIndexService&#34;</span> group=<span style="color:#2aa198">&#34;member&#34;</span> interface=<span style="color:#2aa198">&#34;com.xxx.IndexService&#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> id=<span style="color:#2aa198">&#34;barService&#34;</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> group=<span style="color:#2aa198">&#34;*&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>2.2.0</code> 以上版本支持,总是只调一个可用组的实现 |
| </div></description></item><item><title>Docs: 静态服务</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/static-service/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/static-service/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/registry/simple/">最新版本</a>。</p> |
| </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:registry</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090&#34;</span> dynamic=<span style="color:#2aa198">&#34;false&#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:registry</span> address=<span style="color:#2aa198">&#34;10.20.141.150:9090?dynamic=false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>服务提供者初次注册时为禁用状态,需人工启用。断线时,将不会被自动删除,需人工禁用。</p> |
| <p>如果是一个第三方服务提供者,比如 memcached,可以直接向注册中心写入提供者地址信息,消费者正常使用 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</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>RegistryFactory registryFactory <span style="color:#719e07">=</span> ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); |
| </span></span><span style="display:flex;"><span>Registry registry <span style="color:#719e07">=</span> registryFactory.getRegistry(URL.valueOf(<span style="color:#2aa198">&#34;zookeeper://10.20.153.10:2181&#34;</span>)); |
| </span></span><span style="display:flex;"><span>registry.register(URL.valueOf(<span style="color:#2aa198">&#34;memcached://10.20.153.11/com.foo.BarService?category=providers&amp;dynamic=false&amp;application=foo&#34;</span>)); |
| </span></span></code></pre></div><div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p>通常由脚本监控中心页面等调用&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 多版本</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/multi-versions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/multi-versions/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/multi-versions/">最新版本</a>。</p> |
| </div> |
| <p>当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。</p> |
| <p>可以按照以下的步骤进行版本迁移:</p> |
| <ol> |
| <li>在低压力时间段,先升级一半提供者为新版本</li> |
| <li>再将所有消费者升级为新版本</li> |
| <li>然后将剩下的一半提供者升级为新版本</li> |
| </ol> |
| <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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> version=<span style="color:#2aa198">&#34;2.0.0&#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> id=<span style="color:#2aa198">&#34;barService&#34;</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#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> id=<span style="color:#2aa198">&#34;barService&#34;</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> version=<span style="color:#2aa198">&#34;2.0.0&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>如果不需要区分版本,可以按照以下的方式配置 [^1]:</p> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>2.2.0</code> 以上版本支持 |
| </div> |
| <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> id=<span style="color:#2aa198">&#34;barService&#34;</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> version=<span style="color:#2aa198">&#34;*&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 分组聚合</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/group-merger/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/group-merger/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/group-merger/">最新版本</a>。</p> |
| </div> |
| <p>通过分组对结果进行聚合并返回聚合后的结果,比如菜单服务,用group区分同一接口的多种实现,现在消费方需从每种group中调用一次并返回结果,对结果进行合并之后返回,这样就可以实现聚合菜单项。</p> |
| <p>相关代码可以参考 <a href="https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-merge">dubbo 项目中的示例</a></p> |
| <h2 id="配置">配置</h2> |
| <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> interface=<span style="color:#2aa198">&#34;com.xxx.MenuService&#34;</span> group=<span style="color:#2aa198">&#34;*&#34;</span> merger=<span style="color:#2aa198">&#34;true&#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> interface=<span style="color:#2aa198">&#34;com.xxx.MenuService&#34;</span> group=<span style="color:#2aa198">&#34;aaa,bbb&#34;</span> merger=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>指定方法合并结果,其它未指定的方法,将只调用一个 Group</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> interface=<span style="color:#2aa198">&#34;com.xxx.MenuService&#34;</span> group=<span style="color:#2aa198">&#34;*&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;getMenuItems&#34;</span> merger=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&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> interface=<span style="color:#2aa198">&#34;com.xxx.MenuService&#34;</span> group=<span style="color:#2aa198">&#34;*&#34;</span> merger=<span style="color:#2aa198">&#34;true&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;getMenuItems&#34;</span> merger=<span style="color:#2aa198">&#34;false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div><p>指定合并策略,缺省根据返回值类型自动匹配,如果同一类型有两个合并器时,需指定合并器的名称</p> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| 参见:<a href="../../../docsv2.7/dev/impls/merger/">合并结果扩展</a> |
| </div> |
| <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> interface=<span style="color:#2aa198">&#34;com.xxx.MenuService&#34;</span> group=<span style="color:#2aa198">&#34;*&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;getMenuItems&#34;</span> merger=<span style="color:#2aa198">&#34;mymerge&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&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> interface=<span style="color:#2aa198">&#34;com.xxx.MenuService&#34;</span> group=<span style="color:#2aa198">&#34;*&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;getMenuItems&#34;</span> merger=<span style="color:#2aa198">&#34;.addAll&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| 从 <code>2.1.0</code> 版本开始支持 |
| </div></description></item><item><title>Docs: 参数验证</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/parameter-validation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/parameter-validation/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/parameter-validation/">最新版本</a>。</p> |
| </div> |
| <p>参数验证功能是基于 <a href="https://jcp.org/en/jsr/detail?id=303">JSR303</a> 实现的,用户只需标识 JSR303 标准的验证 annotation,并通过声明 filter 来实现验证。</p> |
| <h2 id="maven-依赖">Maven 依赖</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>javax.validation<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>validation-api<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>1.0.0.GA<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.hibernate<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>hibernate-validator<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>4.2.0.Final<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span></code></pre></div><h2 id="示例">示例</h2> |
| <h3 id="参数标注示例">参数标注示例</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">import</span> java.io.Serializable; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> java.util.Date; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.Future; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.Max; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.Min; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.NotNull; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.Past; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.Pattern; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.Size; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">ValidationParameter</span> <span style="color:#268bd2">implements</span> Serializable { |
| </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> <span style="color:#dc322f">long</span> serialVersionUID <span style="color:#719e07">=</span> 7158911668568000392L; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@NotNull</span> <span style="color:#586e75">// 不允许为空</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Size</span>(min <span style="color:#719e07">=</span> 1, max <span style="color:#719e07">=</span> 20) <span style="color:#586e75">// 长度或大小范围</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> String name; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@NotNull</span>(groups <span style="color:#719e07">=</span> ValidationService.Save.class) <span style="color:#586e75">// 保存时不允许为空,更新时允许为空 ,表示不更新该字段</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Pattern</span>(regexp <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$&#34;</span>) |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> String email; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Min</span>(18) <span style="color:#586e75">// 最小值</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Max</span>(100) <span style="color:#586e75">// 最大值</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#dc322f">int</span> age; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Past</span> <span style="color:#586e75">// 必须为一个过去的时间</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> Date loginDate; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Future</span> <span style="color:#586e75">// 必须为一个未来的时间</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> Date expiryDate; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">getName</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> name; |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">setName</span>(String name) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.name <span style="color:#719e07">=</span> name; |
| </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">public</span> String <span style="color:#268bd2">getEmail</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> email; |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">setEmail</span>(String email) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.email <span style="color:#719e07">=</span> email; |
| </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">public</span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">getAge</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> age; |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">setAge</span>(<span style="color:#dc322f">int</span> age) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.age <span style="color:#719e07">=</span> age; |
| </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">public</span> Date <span style="color:#268bd2">getLoginDate</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> loginDate; |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">setLoginDate</span>(Date loginDate) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.loginDate <span style="color:#719e07">=</span> loginDate; |
| </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">public</span> Date <span style="color:#268bd2">getExpiryDate</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> expiryDate; |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">setExpiryDate</span>(Date expiryDate) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.expiryDate <span style="color:#719e07">=</span> expiryDate; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h3 id="分组验证示例">分组验证示例</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-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">ValidationService</span> { <span style="color:#586e75">// 缺省可按服务接口区分验证场景,如:@NotNull(groups = ValidationService.class) </span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@interface</span> Save{} <span style="color:#586e75">// 与方法同名接口,首字母大写,用于区分验证场景,如:@NotNull(groups = ValidationService.Save.class),可选</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">save</span>(ValidationParameter parameter); |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">update</span>(ValidationParameter parameter); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h3 id="关联验证示例">关联验证示例</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.GroupSequence; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">ValidationService</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GroupSequence</span>(Update.class) <span style="color:#586e75">// 同时验证Update组规则</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@interface</span> Save{} |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">save</span>(ValidationParameter parameter); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@interface</span> Update{} |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">update</span>(ValidationParameter parameter); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h3 id="参数验证示例">参数验证示例</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.Min; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.constraints.NotNull; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">ValidationService</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">save</span>(<span style="color:#268bd2">@NotNull</span> ValidationParameter parameter); <span style="color:#586e75">// 验证参数不为空</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">delete</span>(<span style="color:#268bd2">@Min</span>(1) <span style="color:#dc322f">int</span> id); <span style="color:#586e75">// 直接对基本类型参数验证</span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h2 id="配置">配置</h2> |
| <h3 id="在客户端验证参数">在客户端验证参数</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;validationService&#34;</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.examples.validation.api.ValidationService&#34;</span> validation=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="在服务器端验证参数">在服务器端验证参数</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.examples.validation.api.ValidationService&#34;</span> ref=<span style="color:#2aa198">&#34;validationService&#34;</span> validation=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| Dubbo 默认支持 hibernate-validator 版本 &lt;=6.x,若使用 hibernate-validator 7.x 版本,请将 validation 参数声明为 jvalidatorNew |
| </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:#719e07">import</span> javax.validation.ConstraintViolationException; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> javax.validation.ConstraintViolationException; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.springframework.context.support.ClassPathXmlApplicationContext; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.examples.validation.api.ValidationParameter; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.examples.validation.api.ValidationService; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> org.apache.dubbo.rpc.RpcException; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">ValidationConsumer</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#268bd2">static</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">main</span>(String<span style="color:#719e07">[]</span> args) <span style="color:#268bd2">throws</span> Exception { |
| </span></span><span style="display:flex;"><span> String config <span style="color:#719e07">=</span> ValidationConsumer.class.getPackage().getName().replace(<span style="color:#2aa198">&#39;.&#39;</span>, <span style="color:#2aa198">&#39;/&#39;</span>) <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;/validation-consumer.xml&#34;</span>; |
| </span></span><span style="display:flex;"><span> ClassPathXmlApplicationContext context <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ClassPathXmlApplicationContext(config); |
| </span></span><span style="display:flex;"><span> context.start(); |
| </span></span><span style="display:flex;"><span> ValidationService validationService <span style="color:#719e07">=</span> (ValidationService)context.getBean(<span style="color:#2aa198">&#34;validationService&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// Error</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> parameter <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ValidationParameter(); |
| </span></span><span style="display:flex;"><span> validationService.save(parameter); |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;Validation ERROR&#34;</span>); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">catch</span> (RpcException e) { <span style="color:#586e75">// 抛出的是RpcException</span> |
| </span></span><span style="display:flex;"><span> ConstraintViolationException ve <span style="color:#719e07">=</span> (ConstraintViolationException) e.getCause(); <span style="color:#586e75">// 里面嵌了一个ConstraintViolationException</span> |
| </span></span><span style="display:flex;"><span> Set<span style="color:#719e07">&lt;</span>ConstraintViolation<span style="color:#719e07">&lt;?&gt;&gt;</span> violations <span style="color:#719e07">=</span> ve.getConstraintViolations(); <span style="color:#586e75">// 可以拿到一个验证错误详细信息的集合</span> |
| </span></span><span style="display:flex;"><span> System.out.println(violations); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <p>自 <code>2.1.0</code> 版本开始支持, 如何使用可以参考 <a href="https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-validation">dubbo 项目中的示例代码</a></p> |
| <p>验证方式可扩展,扩展方式参见开发者手册中的<a href="../../references/spis/validation">验证扩展</a></p> |
| </div></description></item><item><title>Docs: 结果缓存</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/result-cache/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/result-cache/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/result-cache/">最新版本</a>。</p> |
| </div> |
| <p>结果缓存,用于加速热门数据的访问速度,Dubbo 提供声明式缓存,以减少用户加缓存的工作量。</p> |
| <h2 id="缓存类型">缓存类型</h2> |
| <ul> |
| <li><code>lru</code> 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。</li> |
| <li><code>threadlocal</code> 当前线程缓存,比如一个页面渲染,用到很多 portal,每个 portal 都要去查用户信息,通过线程缓存,可以减少这种多余访问。</li> |
| <li><code>jcache</code> 与 <a href="http://jcp.org/en/jsr/detail?id=107%27">JSR107</a> 集成,可以桥接各种缓存实现。</li> |
| </ul> |
| <p>缓存类型可扩展,参见:<a href="../../references/spis/cache">缓存扩展</a></p> |
| <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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> cache=<span style="color:#2aa198">&#34;lru&#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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;findBar&#34;</span> cache=<span style="color:#2aa198">&#34;lru&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <p><code>2.1.0</code> 以上版本支持。</p> |
| <p><a href="https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-cache">示例代码</a></p> |
| </div></description></item><item><title>Docs: 使用泛化调用</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/generic-reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/generic-reference/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/generic-reference/">最新版本</a>。</p> |
| </div> |
| <p>泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 <code>Map</code> 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 <code>GenericService</code> 调用所有服务实现。</p> |
| <h2 id="通过-spring-使用泛化调用">通过 Spring 使用泛化调用</h2> |
| <p>在 Spring 配置申明 <code>generic=&quot;true&quot;</code>:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;barService&#34;</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> generic=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>在 Java 代码获取 barService 并开始泛化调用:</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>GenericService barService <span style="color:#719e07">=</span> (GenericService) applicationContext.getBean(<span style="color:#2aa198">&#34;barService&#34;</span>); |
| </span></span><span style="display:flex;"><span>Object result <span style="color:#719e07">=</span> barService.$invoke(<span style="color:#2aa198">&#34;sayHello&#34;</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">new</span> Object<span style="color:#719e07">[]</span> { <span style="color:#2aa198">&#34;World&#34;</span> }); |
| </span></span></code></pre></div><h2 id="通过-api-方式使用泛化调用">通过 API 方式使用泛化调用</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:#719e07">import</span> org.apache.dubbo.rpc.service.GenericService; |
| </span></span><span style="display:flex;"><span>... |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 引用远程服务 </span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存</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;</span>GenericService<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 弱类型接口名</span> |
| </span></span><span style="display:flex;"><span>reference.setInterface(<span style="color:#2aa198">&#34;com.xxx.XxxService&#34;</span>); |
| </span></span><span style="display:flex;"><span>reference.setVersion(<span style="color:#2aa198">&#34;1.0.0&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 声明为泛化接口 </span> |
| </span></span><span style="display:flex;"><span>reference.setGeneric(<span style="color:#cb4b16">true</span>); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用 </span> |
| </span></span><span style="display:flex;"><span>GenericService genericService <span style="color:#719e07">=</span> reference.get(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 基本类型以及Date,List,Map等不需要转换,直接调用 </span> |
| </span></span><span style="display:flex;"><span>Object result <span style="color:#719e07">=</span> genericService.$invoke(<span style="color:#2aa198">&#34;sayHello&#34;</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">new</span> Object<span style="color:#719e07">[]</span> {<span style="color:#2aa198">&#34;world&#34;</span>}); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 用Map表示POJO参数,如果返回值为POJO也将自动转成Map </span> |
| </span></span><span style="display:flex;"><span>Map<span style="color:#719e07">&lt;</span>String, Object<span style="color:#719e07">&gt;</span> person <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HashMap<span style="color:#719e07">&lt;</span>String, Object<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;name&#34;</span>, <span style="color:#2aa198">&#34;xxx&#34;</span>); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;password&#34;</span>, <span style="color:#2aa198">&#34;yyy&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 如果返回POJO将自动转成Map </span> |
| </span></span><span style="display:flex;"><span>Object result <span style="color:#719e07">=</span> genericService.$invoke(<span style="color:#2aa198">&#34;findPerson&#34;</span>, <span style="color:#719e07">new</span> String<span style="color:#719e07">[]</span> |
| </span></span><span style="display:flex;"><span>{<span style="color:#2aa198">&#34;com.xxx.Person&#34;</span>}, <span style="color:#719e07">new</span> Object<span style="color:#719e07">[]</span>{person}); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div><h2 id="有关泛化类型的进一步解释">有关泛化类型的进一步解释</h2> |
| <p>假设存在 POJO 如:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> com.xxx; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">PersonImpl</span> <span style="color:#268bd2">implements</span> Person { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> String name; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> String password; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">getName</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> name; |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">setName</span>(String name) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.name <span style="color:#719e07">=</span> name; |
| </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">public</span> String <span style="color:#268bd2">getPassword</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> password; |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">setPassword</span>(String password) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.password <span style="color:#719e07">=</span> password; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>则 POJO 数据:</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>Person person <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> PersonImpl(); |
| </span></span><span style="display:flex;"><span>person.setName(<span style="color:#2aa198">&#34;xxx&#34;</span>); |
| </span></span><span style="display:flex;"><span>person.setPassword(<span style="color:#2aa198">&#34;yyy&#34;</span>); |
| </span></span></code></pre></div><p>可用下面 Map 表示:</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>Map<span style="color:#719e07">&lt;</span>String, Object<span style="color:#719e07">&gt;</span> map <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HashMap<span style="color:#719e07">&lt;</span>String, Object<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 注意:如果参数类型是接口,或者List等丢失泛型,可通过class属性指定类型。</span> |
| </span></span><span style="display:flex;"><span>map.put(<span style="color:#2aa198">&#34;class&#34;</span>, <span style="color:#2aa198">&#34;com.xxx.PersonImpl&#34;</span>); |
| </span></span><span style="display:flex;"><span>map.put(<span style="color:#2aa198">&#34;name&#34;</span>, <span style="color:#2aa198">&#34;xxx&#34;</span>); |
| </span></span><span style="display:flex;"><span>map.put(<span style="color:#2aa198">&#34;password&#34;</span>, <span style="color:#2aa198">&#34;yyy&#34;</span>); |
| </span></span></code></pre></div></description></item><item><title>Docs: Protobuf</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/protobuf-idl/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/protobuf-idl/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/upgrades-and-compatibility/migration-triple/#%E5%A4%9A%E8%AF%AD%E8%A8%80%E7%94%A8%E6%88%B7">最新版本</a>。</p> |
| </div> |
| <p>当前 Dubbo 的服务定义和具体的编程语言绑定,没有提供一种语言中立的服务描述格式,比如 Java 就是定义 Interface 接口,到了其他语言又得重新以另外的格式定义一遍。 |
| 2.7.5 版本通过支持 Protobuf IDL 实现了语言中立的服务定义。</p> |
| <p>日后,不论我们使用什么语言版本来开发 Dubbo 服务,都可以直接使用 IDL 定义如下服务,具体请<a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/serialization/dubbo-samples-protobuf">参见示例</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-go" data-lang="go"><span style="display:flex;"><span>syntax = <span style="color:#2aa198">&#34;proto3&#34;</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>option java_multiple_files = <span style="color:#cb4b16">true</span>; |
| </span></span><span style="display:flex;"><span>option java_package = <span style="color:#2aa198">&#34;org.apache.dubbo.demo&#34;</span>; |
| </span></span><span style="display:flex;"><span>option java_outer_classname = <span style="color:#2aa198">&#34;DemoServiceProto&#34;</span>; |
| </span></span><span style="display:flex;"><span>option objc_class_prefix = <span style="color:#2aa198">&#34;DEMOSRV&#34;</span>; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> demoservice; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The demo service definition. |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>service DemoService { |
| </span></span><span style="display:flex;"><span> rpc <span style="color:#268bd2">SayHello</span> (HelloRequest) <span style="color:#268bd2">returns</span> (HelloReply) {} |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The request message containing the user&#39;s name. |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>message HelloRequest { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> name = <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// The response message containing the greetings |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span>message HelloReply { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> message = <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></description></item><item><title>Docs: GoogleProtobuf 对象泛化调用</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/pb-generic-reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/pb-generic-reference/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/generic-reference/#protobuf-%E5%AF%B9%E8%B1%A1%E6%B3%9B%E5%8C%96%E8%B0%83%E7%94%A8">最新版本</a>。</p> |
| </div> |
| <p>泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参考 <a href="../generic-reference">泛化调用</a>。 |
| 一般泛化调用只能用于生成的服务参数为POJO的情况,而 GoogleProtobuf 的对象是基于 Builder 生成的非正常POJO,可以通过 protobuf-json 泛化调用。</p> |
| <p>GoogleProtobuf 序列化相关的Demo可以参考 <a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/serialization/dubbo-samples-protobuf">protobuf-demo</a></p> |
| <h2 id="通过spring对google-protobuf对象泛化调用">通过Spring对Google Protobuf对象泛化调用</h2> |
| <p>在 Spring 中配置声明 generic = &ldquo;protobuf-json&rdquo;</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> id=<span style="color:#2aa198">&#34;barService&#34;</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> generic=<span style="color:#2aa198">&#34;protobuf-json&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>在 Java 代码获取 barService 并开始泛化调用:</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>GenericService barService <span style="color:#719e07">=</span> (GenericService) applicationContext.getBean(<span style="color:#2aa198">&#34;barService&#34;</span>); |
| </span></span><span style="display:flex;"><span>Object result <span style="color:#719e07">=</span> barService.$invoke(<span style="color:#2aa198">&#34;sayHello&#34;</span>,<span style="color:#719e07">new</span> String<span style="color:#719e07">[]</span>{<span style="color:#2aa198">&#34;org.apache.dubbo.protobuf.GooglePbBasic$CDubboGooglePBRequestType&#34;</span>}, <span style="color:#719e07">new</span> Object<span style="color:#719e07">[]</span>{<span style="color:#2aa198">&#34;{\&#34;double\&#34;:0.0,\&#34;float\&#34;:0.0,\&#34;bytesType\&#34;:\&#34;Base64String\&#34;,\&#34;int32\&#34;:0}&#34;</span>}); |
| </span></span></code></pre></div><h2 id="通过-api-方式对-google-protobuf-对象泛化调用">通过 API 方式对 Google Protobuf 对象泛化调用</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>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;</span>GenericService<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 弱类型接口名</span> |
| </span></span><span style="display:flex;"><span>reference.setInterface(GenericService.class.getName()); |
| </span></span><span style="display:flex;"><span>reference.setInterface(<span style="color:#2aa198">&#34;com.xxx.XxxService&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 声明为Protobuf-json</span> |
| </span></span><span style="display:flex;"><span>reference.setGeneric(Constants.GENERIC_SERIALIZATION_PROTOBUF); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>GenericService genericService <span style="color:#719e07">=</span> reference.get(); |
| </span></span><span style="display:flex;"><span>Map<span style="color:#719e07">&lt;</span>String, Object<span style="color:#719e07">&gt;</span> person <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HashMap<span style="color:#719e07">&lt;</span>String, Object<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;fixed64&#34;</span>, <span style="color:#2aa198">&#34;0&#34;</span>); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;int64&#34;</span>, <span style="color:#2aa198">&#34;0&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 参考google官方的protobuf 3 的语法,服务的每个方法中只传输一个POJO对象</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// protobuf的泛化调用只允许传递一个类型为String的json对象来代表请求参数</span> |
| </span></span><span style="display:flex;"><span>String requestString <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> Gson().toJson(person); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 返回对象是GoolgeProtobuf响应对象的json字符串。</span> |
| </span></span><span style="display:flex;"><span>Object result <span style="color:#719e07">=</span> genericService.$invoke(<span style="color:#2aa198">&#34;sayHello&#34;</span>, <span style="color:#719e07">new</span> String<span style="color:#719e07">[]</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;com.xxx.XxxService.GooglePbBasic$CDubboGooglePBRequestType&#34;</span>}, |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">new</span> Object<span style="color:#719e07">[]</span> {requestString}); |
| </span></span></code></pre></div><h2 id="googleprotobuf-对象的处理">GoogleProtobuf 对象的处理</h2> |
| <p>GoogleProtobuf 对象是由 Protocol 契约生成,相关知识请参考 <a href="https://developers.google.com/protocol-buffers/?hl=zh-CN">ProtocolBuffers 文档</a>。假如有如下Protobuf 契约</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-proto" data-lang="proto"><span style="display:flex;"><span>syntax <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;proto3&#34;</span>; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">package</span> com<span style="color:#719e07">.</span>xxx.XxxService.GooglePbBasic.basic; |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">message</span> <span style="color:#268bd2">CDubboGooglePBRequestType</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">double</span> <span style="color:#dc322f">double</span> <span style="color:#719e07">=</span> <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">float</span> <span style="color:#dc322f">float</span> <span style="color:#719e07">=</span> <span style="color:#2aa198">2</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">int32</span> <span style="color:#dc322f">int32</span> <span style="color:#719e07">=</span> <span style="color:#2aa198">3</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">bool</span> <span style="color:#dc322f">bool</span> <span style="color:#719e07">=</span> <span style="color:#2aa198">13</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> <span style="color:#dc322f">string</span> <span style="color:#719e07">=</span> <span style="color:#2aa198">14</span>; |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">bytes</span> bytesType <span style="color:#719e07">=</span> <span style="color:#2aa198">15</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">message</span> <span style="color:#268bd2">CDubboGooglePBResponseType</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">string</span> msg <span style="color:#719e07">=</span> <span style="color:#2aa198">1</span>; |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">service</span> CDubboGooglePBService { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">rpc</span> sayHello (CDubboGooglePBRequestType) <span style="color:#719e07">returns</span> (CDubboGooglePBResponseType); |
| </span></span><span style="display:flex;"><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>Map<span style="color:#719e07">&lt;</span>String, Object<span style="color:#719e07">&gt;</span> person <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HashMap<span style="color:#719e07">&lt;&gt;</span>(); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;double&#34;</span>, <span style="color:#2aa198">&#34;1.000&#34;</span>); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;float&#34;</span>, <span style="color:#2aa198">&#34;1.00&#34;</span>); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;int32&#34;</span>,<span style="color:#2aa198">&#34;1&#34;</span> ); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;bool&#34;</span>,<span style="color:#2aa198">&#34;false&#34;</span> ); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">//String 的对象需要经过base64编码</span> |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;string&#34;</span>,<span style="color:#2aa198">&#34;someBaseString&#34;</span>); |
| </span></span><span style="display:flex;"><span>person.put(<span style="color:#2aa198">&#34;bytesType&#34;</span>,<span style="color:#2aa198">&#34;150&#34;</span>); |
| </span></span></code></pre></div><h2 id="googleprotobuf-服务元数据解析">GoogleProtobuf 服务元数据解析</h2> |
| <p>Google Protobuf 对象缺少标准的 JSON 格式,生成的服务元数据信息存在错误。请添加如下依赖元数据解析的依赖。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>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-metadata-definition-protobuf<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></code></pre></div><p>从服务元数据中也可以比较容易构建泛化调用对象。</p></description></item><item><title>Docs: 实现泛化调用</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/generic-service/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/generic-service/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/generic-service/">最新版本</a>。</p> |
| </div> |
| <p>泛接口实现方式主要用于服务器端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的远程服务 Mock 框架,可通过实现 GenericService 接口处理所有服务请求。</p> |
| <p>在 Java 代码中实现 <code>GenericService</code> 接口:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> com.foo; |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">MyGenericService</span> <span style="color:#268bd2">implements</span> GenericService { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Object <span style="color:#268bd2">$invoke</span>(String methodName, String<span style="color:#719e07">[]</span> parameterTypes, Object<span style="color:#719e07">[]</span> args) <span style="color:#268bd2">throws</span> GenericException { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> (<span style="color:#2aa198">&#34;sayHello&#34;</span>.equals(methodName)) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;Welcome &#34;</span> <span style="color:#719e07">+</span> args<span style="color:#719e07">[</span>0<span style="color:#719e07">]</span>; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h2 id="通过-spring-暴露泛化实现">通过 Spring 暴露泛化实现</h2> |
| <p>在 Spring 配置申明服务的实现:</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;genericService&#34;</span> class=<span style="color:#2aa198">&#34;com.foo.MyGenericService&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> ref=<span style="color:#2aa198">&#34;genericService&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h2 id="通过-api-方式暴露泛化实现">通过 API 方式暴露泛化实现</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></span><span style="display:flex;"><span><span style="color:#586e75">// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口实现 </span> |
| </span></span><span style="display:flex;"><span>GenericService xxxService <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> XxxGenericService(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存 </span> |
| </span></span><span style="display:flex;"><span>ServiceConfig<span style="color:#719e07">&lt;</span>GenericService<span style="color:#719e07">&gt;</span> service <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ServiceConfig<span style="color:#719e07">&lt;</span>GenericService<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 弱类型接口名 </span> |
| </span></span><span style="display:flex;"><span>service.setInterface(<span style="color:#2aa198">&#34;com.xxx.XxxService&#34;</span>); |
| </span></span><span style="display:flex;"><span>service.setVersion(<span style="color:#2aa198">&#34;1.0.0&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 指向一个通用服务实现 </span> |
| </span></span><span style="display:flex;"><span>service.setRef(xxxService); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 暴露及注册服务 </span> |
| </span></span><span style="display:flex;"><span>service.export(); |
| </span></span></code></pre></div></description></item><item><title>Docs: 回声测试</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/echo-service/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/echo-service/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/echo-service/">最新版本</a>。</p> |
| </div> |
| <p>回声测试用于检测服务是否可用,回声测试按照正常请求流程执行,能够测试整个调用是否通畅,可用于监控。</p> |
| <p>所有服务自动实现 <code>EchoService</code> 接口,只需将任意服务引用强制转型为 <code>EchoService</code>,即可使用。</p> |
| <p>Spring 配置:</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> id=<span style="color:#2aa198">&#34;memberService&#34;</span> interface=<span style="color:#2aa198">&#34;com.xxx.MemberService&#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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// 远程服务引用</span> |
| </span></span><span style="display:flex;"><span>MemberService memberService <span style="color:#719e07">=</span> ctx.getBean(<span style="color:#2aa198">&#34;memberService&#34;</span>); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>EchoService echoService <span style="color:#719e07">=</span> (EchoService) memberService; <span style="color:#586e75">// 强制转型为EchoService</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 回声测试可用性</span> |
| </span></span><span style="display:flex;"><span>String status <span style="color:#719e07">=</span> echoService.$echo(<span style="color:#2aa198">&#34;OK&#34;</span>); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">assert</span>(status.equals(<span style="color:#2aa198">&#34;OK&#34;</span>)); |
| </span></span></code></pre></div></description></item><item><title>Docs: 上下文信息</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/context/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/context/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/context/">最新版本</a>。</p> |
| </div> |
| <p>上下文中存放的是当前调用过程中所需的环境信息。所有配置信息都将转换为 URL 的参数,参见 <a href="../../references/xml">schema 配置参考手册</a> 中的<strong>对应URL参数</strong>一列。</p> |
| <p>RpcContext 是一个 ThreadLocal 的临时状态记录器,当接收到 RPC 请求,或发起 RPC 请求时,RpcContext 的状态都会变化。比如:A 调 B,B 再调 C,则 B 机器上,在 B 调 C 之前,RpcContext 记录的是 A 调 B 的信息,在 B 调 C 之后,RpcContext 记录的是 B 调 C 的信息。</p> |
| <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:#586e75">// 远程调用</span> |
| </span></span><span style="display:flex;"><span>xxxService.xxx(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 本端是否为消费端,这里会返回true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#dc322f">boolean</span> isConsumerSide <span style="color:#719e07">=</span> RpcContext.getContext().isConsumerSide(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 获取最后一次调用的提供方IP地址</span> |
| </span></span><span style="display:flex;"><span>String serverIP <span style="color:#719e07">=</span> RpcContext.getContext().getRemoteHost(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 获取当前服务配置信息,所有配置信息都将转换为URL的参数</span> |
| </span></span><span style="display:flex;"><span>String application <span style="color:#719e07">=</span> RpcContext.getContext().getUrl().getParameter(<span style="color:#2aa198">&#34;application&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 注意:每发起RPC调用,上下文状态会变化</span> |
| </span></span><span style="display:flex;"><span>yyyService.yyy(); |
| </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">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">XxxServiceImpl</span> <span style="color:#268bd2">implements</span> XxxService { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">xxx</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 本端是否为提供端,这里会返回true</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">boolean</span> isProviderSide <span style="color:#719e07">=</span> RpcContext.getContext().isProviderSide(); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 获取调用方IP地址</span> |
| </span></span><span style="display:flex;"><span> String clientIP <span style="color:#719e07">=</span> RpcContext.getContext().getRemoteHost(); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 获取当前服务配置信息,所有配置信息都将转换为URL的参数</span> |
| </span></span><span style="display:flex;"><span> String application <span style="color:#719e07">=</span> RpcContext.getContext().getUrl().getParameter(<span style="color:#2aa198">&#34;application&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 注意:每发起RPC调用,上下文状态会变化</span> |
| </span></span><span style="display:flex;"><span> yyyService.yyy(); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 此时本端变成消费端,这里会返回false</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">boolean</span> isProviderSide <span style="color:#719e07">=</span> RpcContext.getContext().isProviderSide(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></description></item><item><title>Docs: 隐式参数</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/attachment/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/attachment/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/attachment/">最新版本</a>。</p> |
| </div> |
| <p>可以通过 <code>RpcContext</code> 上的 <code>setAttachment</code> 和 <code>getAttachment</code> 在服务消费方和提供方之间进行参数的隐式传递。</p> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">注意</h4> |
| path, group, version, dubbo, token, timeout 几个 key 是保留字段,请使用其它值。 |
| </div> |
| <p><img src="https://dubbo.apache.org/imgs/user/context.png" alt="/user-guide/images/context.png"></p> |
| <h4 id="在服务消费方端设置隐式参数">在服务消费方端设置隐式参数</h4> |
| <p><code>setAttachment</code> 设置的 KV 对,在完成下面一次远程调用会被清空,即多次远程调用要多次设置。</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>RpcContext.getContext().setAttachment(&#34;index&#34;, &#34;1&#34;); // 隐式传参,后面的远程调用都会隐式将这些参数发送到服务器端,类似cookie,用于框架集成,不建议常规业务使用 |
| </span></span><span style="display:flex;"><span>xxxService.xxx(); // 远程调用 |
| </span></span><span style="display:flex;"><span>// ... |
| </span></span></code></pre></div><h4 id="在服务提供方端获取隐式参数">在服务提供方端获取隐式参数</h4> |
| <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">XxxServiceImpl</span> <span style="color:#268bd2">implements</span> XxxService { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">xxx</span>() { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 获取客户端隐式传入的参数,用于框架集成,不建议常规业务使用</span> |
| </span></span><span style="display:flex;"><span> String index <span style="color:#719e07">=</span> RpcContext.getContext().getAttachment(<span style="color:#2aa198">&#34;index&#34;</span>); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></description></item><item><title>Docs: 异步调用</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/async-call/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/async-call/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/async-call/">最新版本</a>。</p> |
| </div> |
| <p>从 2.7.0 开始,Dubbo 的所有异步编程接口开始以 <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html">CompletableFuture</a> 为基础</p> |
| <p>基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/future.jpg" alt="/user-guide/images/future.jpg"></p> |
| <h2 id="使用-completablefuture-签名的接口">使用 CompletableFuture 签名的接口</h2> |
| <p>需要服务提供者事先定义 CompletableFuture 签名的服务,具体参见<a href="../async-execute-on-provider">服务端异步执行</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-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></span><span style="display:flex;"><span> CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHello</span>(String name); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>注意接口的返回类型是 <code>CompletableFuture&lt;String&gt;</code>。</p> |
| <p>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;dubbo:reference</span> id=<span style="color:#2aa198">&#34;asyncService&#34;</span> timeout=<span style="color:#2aa198">&#34;10000&#34;</span> interface=<span style="color:#2aa198">&#34;com.alibaba.dubbo.samples.async.api.AsyncService&#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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// 调用直接返回CompletableFuture</span> |
| </span></span><span style="display:flex;"><span>CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> future <span style="color:#719e07">=</span> asyncService.sayHello(<span style="color:#2aa198">&#34;async call request&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 增加回调</span> |
| </span></span><span style="display:flex;"><span>future.whenComplete((v, t) <span style="color:#719e07">-&gt;</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> (t <span style="color:#719e07">!=</span> <span style="color:#cb4b16">null</span>) { |
| </span></span><span style="display:flex;"><span> t.printStackTrace(); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">else</span> { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;Response: &#34;</span> <span style="color:#719e07">+</span> v); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>}); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 早于结果输出</span> |
| </span></span><span style="display:flex;"><span>System.out.println(<span style="color:#2aa198">&#34;Executed before response return.&#34;</span>); |
| </span></span></code></pre></div><h2 id="使用-rpccontext">使用 RpcContext</h2> |
| <p>在 consumer.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;dubbo:reference</span> id=<span style="color:#2aa198">&#34;asyncService&#34;</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.samples.governance.api.AsyncService&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;sayHello&#34;</span> async=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#586e75">// 此调用会立即返回null</span> |
| </span></span><span style="display:flex;"><span>asyncService.sayHello(<span style="color:#2aa198">&#34;world&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future</span> |
| </span></span><span style="display:flex;"><span>CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> helloFuture <span style="color:#719e07">=</span> RpcContext.getContext().getCompletableFuture(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 为Future添加回调</span> |
| </span></span><span style="display:flex;"><span>helloFuture.whenComplete((retValue, exception) <span style="color:#719e07">-&gt;</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> (exception <span style="color:#719e07">==</span> <span style="color:#cb4b16">null</span>) { |
| </span></span><span style="display:flex;"><span> System.out.println(retValue); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">else</span> { |
| </span></span><span style="display:flex;"><span> exception.printStackTrace(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><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>CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> future <span style="color:#719e07">=</span> RpcContext.getContext().asyncCall( |
| </span></span><span style="display:flex;"><span> () <span style="color:#719e07">-&gt;</span> { |
| </span></span><span style="display:flex;"><span> asyncService.sayHello(<span style="color:#2aa198">&#34;oneway call request1&#34;</span>); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>future.get(); |
| </span></span></code></pre></div><h2 id="重载服务接口">重载服务接口</h2> |
| <p>如果你只有这样的同步服务定义,而又不喜欢 RpcContext 的异步使用方式。</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">GreetingsService</span> { |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHi</span>(String name); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>那还有一种方式,就是利用 Java 8 提供的 default 接口实现,重载一个带有 CompletableFuture 签名的方法。</p> |
| <blockquote> |
| <p>CompletableFuture 签名的方法目前只支持 Dubbo 协议,其他协议由于第三方实现问题,需要视具体情况而定。</p> |
| </blockquote> |
| <p>有两种方式来实现:</p> |
| <ol> |
| <li>提供方或消费方自己修改接口签名</li> |
| </ol> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">GreetingsService</span> { |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHi</span>(String name); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// AsyncSignal is totally optional, you can use any parameter type as long as java allows your to do that.</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">default</span> CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHi</span>(String name, AsyncSignal signal) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> CompletableFuture.completedFuture(sayHi(name)); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><ol> |
| <li>Dubbo 官方提供 compiler hacker,编译期自动重写同步方法,请<a href="https://github.com/dubbo/dubbo-async-processor#compiler-hacker-processer">在此</a>讨论和跟进具体进展。</li> |
| </ol> |
| <p>你也可以设置是否等待消息发出: <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p> |
| <ul> |
| <li><code>sent=&quot;true&quot;</code> 等待消息发出,消息发送失败将抛出异常。</li> |
| <li><code>sent=&quot;false&quot;</code> 不等待消息发出,将消息放入 IO 队列,即刻返回。</li> |
| </ul> |
| <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:method</span> name=<span style="color:#2aa198">&#34;findFoo&#34;</span> async=<span style="color:#2aa198">&#34;true&#34;</span> sent=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>如果你只是想异步,完全忽略返回值,可以配置 <code>return=&quot;false&quot;</code>,以减少 Future 对象的创建和管理成本:</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:method</span> name=<span style="color:#2aa198">&#34;findFoo&#34;</span> async=<span style="color:#2aa198">&#34;true&#34;</span> return=<span style="color:#2aa198">&#34;false&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p>异步总是不等待返回&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 异步执行</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/async-execute-on-provider/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/async-execute-on-provider/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/async-execute-on-provider/">最新版本</a>。</p> |
| </div> |
| <p>Provider端异步执行将阻塞的业务从Dubbo内部线程池切换到业务自定义线程,避免Dubbo线程池的过度占用,有助于避免不同服务间的互相影响。异步执行无异于节省资源或提升RPC响应性能,因为如果业务执行需要阻塞,则始终还是要有线程来负责执行。</p> |
| <div class="alert alert-warning" role="alert"> |
| <h4 class="alert-heading">注意</h4> |
| <p>Provider 端异步执行和 Consumer 端异步调用是相互独立的,你可以任意正交组合两端配置</p> |
| <ul> |
| <li>Consumer同步 - Provider同步</li> |
| <li>Consumer异步 - Provider同步</li> |
| <li>Consumer同步 - Provider异步</li> |
| <li>Consumer异步 - Provider异步</li> |
| </ul> |
| </div> |
| <h2 id="定义-completablefuture-签名的接口">定义 CompletableFuture 签名的接口</h2> |
| <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></span><span style="display:flex;"><span> CompletableFuture<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">sayHello</span>(String name); |
| </span></span><span style="display:flex;"><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></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">sayHello</span>(String name) { |
| </span></span><span style="display:flex;"><span> RpcContext savedContext <span style="color:#719e07">=</span> RpcContext.getContext(); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 建议为supplyAsync提供自定义线程池,避免使用JDK公用线程池</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> CompletableFuture.supplyAsync(() <span style="color:#719e07">-&gt;</span> { |
| </span></span><span style="display:flex;"><span> System.out.println(savedContext.getAttachment(<span style="color:#2aa198">&#34;consumer-key1&#34;</span>)); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> Thread.sleep(5000); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">catch</span> (InterruptedException e) { |
| </span></span><span style="display:flex;"><span> e.printStackTrace(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;async response from provider.&#34;</span>; |
| </span></span><span style="display:flex;"><span> }); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>通过 <code>return CompletableFuture.supplyAsync() </code>,业务执行已从 Dubbo 线程切换到业务线程,避免了对 Dubbo 线程池的阻塞。</p> |
| <h2 id="使用asynccontext">使用AsyncContext</h2> |
| <p>Dubbo 提供了一个类似 Servlet 3.0 的异步接口<code>AsyncContext</code>,在没有 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></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHello</span>(String name); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><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;bean</span> id=<span style="color:#2aa198">&#34;asyncService&#34;</span> class=<span style="color:#2aa198">&#34;org.apache.dubbo.samples.governance.impl.AsyncServiceImpl&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.samples.governance.api.AsyncService&#34;</span> ref=<span style="color:#2aa198">&#34;asyncService&#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-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></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span>(String name) { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">final</span> AsyncContext asyncContext <span style="color:#719e07">=</span> RpcContext.startAsync(); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">new</span> Thread(() <span style="color:#719e07">-&gt;</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 如果要使用上下文,则必须要放在第一句执行</span> |
| </span></span><span style="display:flex;"><span> asyncContext.signalContextSwitch(); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> Thread.sleep(500); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">catch</span> (InterruptedException e) { |
| </span></span><span style="display:flex;"><span> e.printStackTrace(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 写回响应</span> |
| </span></span><span style="display:flex;"><span> asyncContext.write(<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></span><span style="display:flex;"><span> }).start(); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#cb4b16">null</span>; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></description></item><item><title>Docs: 本地调用</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/local-call/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/local-call/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/local-call/">最新版本</a>。</p> |
| </div> |
| <p>本地调用使用了 injvm 协议,是一个伪协议,它不开启端口,不发起远程调用,只在 JVM 内直接关联,但执行 Dubbo 的 Filter 链。</p> |
| <h2 id="配置">配置</h2> |
| <p>定义 injvm 协议</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:protocol</span> name=<span style="color:#2aa198">&#34;injvm&#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:provider</span> protocol=<span style="color:#2aa198">&#34;injvm&#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:service</span> protocol=<span style="color:#2aa198">&#34;injvm&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>优先使用 injvm</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:consumer</span> injvm=<span style="color:#2aa198">&#34;true&#34;</span> ...<span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:provider</span> injvm=<span style="color:#2aa198">&#34;true&#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> injvm=<span style="color:#2aa198">&#34;true&#34;</span> ...<span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> injvm=<span style="color:#2aa198">&#34;true&#34;</span> ...<span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">注意</h4> |
| Dubbo 从 <code>2.2.0</code> 每个服务默认都会在本地暴露,无需进行任何配置即可进行本地引用,如果不希望服务进行远程暴露,只需要在 provider 将 protocol 设置成 injvm 即可 |
| </div> |
| <h2 id="自动暴露引用本地服务">自动暴露、引用本地服务</h2> |
| <p>从 <code>2.2.0</code> 开始,每个服务默认都会在本地暴露。在引用服务的时候,默认优先引用本地服务。如果希望引用远程服务可以使用一下配置强制引用远程服务。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-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> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 参数回调</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/callback-parameter/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/callback-parameter/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/callback-parameter/">最新版本</a>。</p> |
| </div> |
| <p>参数回调方式与调用本地 callback 或 listener 相同,只需要在 Spring 的配置文件中声明哪个参数是 callback 类型即可。Dubbo 将基于长连接生成反向代理,这样就可以从服务器端调用客户端逻辑。可以参考 <a href="https://github.com/dubbo/dubbo-samples/tree/master/2-advanced/dubbo-samples-callback">dubbo 项目中的示例代码</a>。</p> |
| <h4 id="服务接口示例">服务接口示例</h4> |
| <h6 id="callbackservicejava">CallbackService.java</h6> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> com.callback; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">CallbackService</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">addListener</span>(String key, CallbackListener listener); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h6 id="callbacklistenerjava">CallbackListener.java</h6> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> com.callback; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">CallbackListener</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">changed</span>(String msg); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h4 id="服务提供者接口实现示例">服务提供者接口实现示例</h4> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> com.callback.impl; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> java.text.SimpleDateFormat; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> java.util.Date; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> java.util.Map; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> java.util.concurrent.ConcurrentHashMap; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> com.callback.CallbackListener; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">import</span> com.callback.CallbackService; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">CallbackServiceImpl</span> <span style="color:#268bd2">implements</span> CallbackService { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> Map<span style="color:#719e07">&lt;</span>String, CallbackListener<span style="color:#719e07">&gt;</span> listeners <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ConcurrentHashMap<span style="color:#719e07">&lt;</span>String, CallbackListener<span style="color:#719e07">&gt;</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">CallbackServiceImpl</span>() { |
| </span></span><span style="display:flex;"><span> Thread t <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> Thread(<span style="color:#719e07">new</span> Runnable() { |
| </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></span><span style="display:flex;"><span> <span style="color:#719e07">while</span>(<span style="color:#cb4b16">true</span>) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">for</span>(Map.Entry<span style="color:#719e07">&lt;</span>String, CallbackListener<span style="color:#719e07">&gt;</span> entry : listeners.entrySet()){ |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> entry.getValue().changed(getChanged(entry.getKey())); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">catch</span> (Throwable t) { |
| </span></span><span style="display:flex;"><span> listeners.remove(entry.getKey()); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> Thread.sleep(5000); <span style="color:#586e75">// 定时触发变更通知</span> |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">catch</span> (Throwable t) { <span style="color:#586e75">// 防御容错</span> |
| </span></span><span style="display:flex;"><span> t.printStackTrace(); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> }); |
| </span></span><span style="display:flex;"><span> t.setDaemon(<span style="color:#cb4b16">true</span>); |
| </span></span><span style="display:flex;"><span> t.start(); |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">addListener</span>(String key, CallbackListener listener) { |
| </span></span><span style="display:flex;"><span> listeners.put(key, listener); |
| </span></span><span style="display:flex;"><span> listener.changed(getChanged(key)); <span style="color:#586e75">// 发送变更通知</span> |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> String <span style="color:#268bd2">getChanged</span>(String key) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;Changed: &#34;</span> <span style="color:#719e07">+</span> <span style="color:#719e07">new</span> SimpleDateFormat(<span style="color:#2aa198">&#34;yyyy-MM-dd HH:mm:ss&#34;</span>).format(<span style="color:#719e07">new</span> Date()); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h4 id="服务提供者配置示例">服务提供者配置示例</h4> |
| <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;callbackService&#34;</span> class=<span style="color:#2aa198">&#34;com.callback.impl.CallbackServiceImpl&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.callback.CallbackService&#34;</span> ref=<span style="color:#2aa198">&#34;callbackService&#34;</span> connections=<span style="color:#2aa198">&#34;1&#34;</span> callbacks=<span style="color:#2aa198">&#34;1000&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;addListener&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:argument</span> index=<span style="color:#2aa198">&#34;1&#34;</span> callback=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!--也可以通过指定类型的方式--&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!--&lt;dubbo:argument type=&#34;com.demo.CallbackListener&#34; callback=&#34;true&#34; /&gt;--&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dubbo:method&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:service&gt;</span> |
| </span></span></code></pre></div><h4 id="服务消费者配置示例">服务消费者配置示例</h4> |
| <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> id=<span style="color:#2aa198">&#34;callbackService&#34;</span> interface=<span style="color:#2aa198">&#34;com.callback.CallbackService&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h4 id="服务消费者调用示例">服务消费者调用示例</h4> |
| <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>ClassPathXmlApplicationContext context <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ClassPathXmlApplicationContext(<span style="color:#2aa198">&#34;classpath:consumer.xml&#34;</span>); |
| </span></span><span style="display:flex;"><span>context.start(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>CallbackService callbackService <span style="color:#719e07">=</span> (CallbackService) context.getBean(<span style="color:#2aa198">&#34;callbackService&#34;</span>); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>callbackService.addListener(<span style="color:#2aa198">&#34;foo.bar&#34;</span>, <span style="color:#719e07">new</span> CallbackListener(){ |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">changed</span>(String msg) { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;callback1:&#34;</span> <span style="color:#719e07">+</span> msg); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>}); |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>2.0.6</code> 及其以上版本支持 |
| </div></description></item><item><title>Docs: 服务鉴权</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/auth/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/auth/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/security/auth/">最新版本</a>。</p> |
| </div> |
| <h1 id="服务鉴权">服务鉴权</h1> |
| <p>类似支付之类的对安全性敏感的业务可能会有限制匿名调用的需求。在加固安全性方面,2.7.5 引入了基于AK/SK机制的认证鉴权机制,并且引入了鉴权服务中心,主要原理是消费端在请求需要鉴权的服务时,会通过SK、请求元数据、时间戳、参数等信息来生成对应的请求签名,通过Dubbo的Attahcment机制携带到对端进行验签,验签通过才进行业务逻辑处理。如下图所示:</p> |
| <p><img src="https://dubbo.apache.org/imgs/docsv2.7/user/examples/auth/auth.png" alt="img"></p> |
| <p>具体的接入方式也并不复杂:</p> |
| <ol> |
| <li> |
| <p>使用者需要在微服务站点上填写自己的应用信息,并为该应用生成唯一的证书凭证。</p> |
| </li> |
| <li> |
| <p>之后在管理站点上提交工单,申请某个敏感业务服务的使用权限,并由对应业务管理者进行审批,审批通过之后,会生成对应的AK/SK到鉴权服务中心。</p> |
| </li> |
| <li> |
| <p>导入该证书到对应的应用下,并且进行配置。配置方式也十分简单,以注解方式为例:</p> |
| <p>服务提供端,只需要设置<code>service.auth</code>为true,表示该服务的调用需要鉴权认证通过。<code>param.sign</code>为<code>true</code>表示需要对参数也进行校验。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Service</span>(parameters <span style="color:#719e07">=</span> {<span style="color:#2aa198">&#34;service.auth&#34;</span>,<span style="color:#2aa198">&#34;true&#34;</span>,<span style="color:#2aa198">&#34;param.sign&#34;</span>,<span style="color:#2aa198">&#34;true&#34;</span>}) |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">AuthDemoServiceImpl</span> <span style="color:#268bd2">implements</span> AuthService { |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>服务消费端,只需要配置好对应的证书等信息即可,之后会自动地在对这些需要认证的接口发起调用前进行签名操作,通过与鉴权服务的交互,用户无需在代码中配置AK/SK这些敏感信息,并且在不重启应用的情况下刷新AK/SK,达到权限动态下发的目的。</p> |
| </li> |
| </ol> |
| <p>该方案目前已经提交给Dubbo开源社区,并且完成了基本框架的合并,除了AK/SK的鉴权方式之外,通过SPI机制支持用户可定制化的鉴权认证以及适配公司内部基础设施的密钥存储。</p></description></item><item><title>Docs: 事件通知</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/events-notify/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/events-notify/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/events-notify/">最新版本</a>。</p> |
| </div> |
| <p>在调用之前、调用之后、出现异常时,会触发 <code>oninvoke</code>、<code>onreturn</code>、<code>onthrow</code> 三个事件,可以配置当事件发生时,通知哪个类的哪个方法。</p> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| 支持版本:<code>2.0.7</code> 之后 |
| </div> |
| <h4 id="服务提供者与消费者共享服务接口">服务提供者与消费者共享服务接口</h4> |
| <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">interface</span> <span style="color:#268bd2">IDemoService</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Person <span style="color:#268bd2">get</span>(<span style="color:#dc322f">int</span> id); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h4 id="服务提供者实现">服务提供者实现</h4> |
| <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">class</span> <span style="color:#268bd2">NormalDemoService</span> <span style="color:#268bd2">implements</span> IDemoService { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Person <span style="color:#268bd2">get</span>(<span style="color:#dc322f">int</span> id) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> Person(id, <span style="color:#2aa198">&#34;charles`son&#34;</span>, 4); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h4 id="服务提供者配置">服务提供者配置</h4> |
| <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:application</span> name=<span style="color:#2aa198">&#34;rpc-callback-demo&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:registry</span> address=<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;bean</span> id=<span style="color:#2aa198">&#34;demoService&#34;</span> class=<span style="color:#2aa198">&#34;org.apache.dubbo.callback.implicit.NormalDemoService&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.callback.implicit.IDemoService&#34;</span> ref=<span style="color:#2aa198">&#34;demoService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> group=<span style="color:#2aa198">&#34;cn&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h4 id="服务消费者-callback-接口">服务消费者 Callback 接口</h4> |
| <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">interface</span> <span style="color:#268bd2">Notify</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onreturn</span>(Person msg, Integer id); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onthrow</span>(Throwable ex, Integer id); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h4 id="服务消费者-callback-实现">服务消费者 Callback 实现</h4> |
| <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">class</span> <span style="color:#268bd2">NotifyImpl</span> <span style="color:#268bd2">implements</span> Notify { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Map<span style="color:#719e07">&lt;</span>Integer, Person<span style="color:#719e07">&gt;</span> ret <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HashMap<span style="color:#719e07">&lt;</span>Integer, Person<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Map<span style="color:#719e07">&lt;</span>Integer, Throwable<span style="color:#719e07">&gt;</span> errors <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HashMap<span style="color:#719e07">&lt;</span>Integer, Throwable<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onreturn</span>(Person msg, Integer id) { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;onreturn:&#34;</span> <span style="color:#719e07">+</span> msg); |
| </span></span><span style="display:flex;"><span> ret.put(id, msg); |
| </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">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">onthrow</span>(Throwable ex, Integer id) { |
| </span></span><span style="display:flex;"><span> errors.put(id, ex); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h4 id="服务消费者-callback-配置">服务消费者 Callback 配置</h4> |
| <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;demoCallback&#34;</span> class = <span style="color:#2aa198">&#34;org.apache.dubbo.callback.implicit.NotifyImpl&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;demoService&#34;</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.callback.implicit.IDemoService&#34;</span> version=<span style="color:#2aa198">&#34;1.0.0&#34;</span> group=<span style="color:#2aa198">&#34;cn&#34;</span> <span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;get&#34;</span> async=<span style="color:#2aa198">&#34;true&#34;</span> onreturn = <span style="color:#2aa198">&#34;demoCallback.onreturn&#34;</span> onthrow=<span style="color:#2aa198">&#34;demoCallback.onthrow&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div><p><code>callback</code> 与 <code>async</code> 功能正交分解,<code>async=true</code> 表示结果是否马上返回,<code>onreturn</code> 表示是否需要回调。</p> |
| <p>两者叠加存在以下几种组合情况:</p> |
| <ul> |
| <li>异步回调模式:<code>async=true onreturn=&quot;xxx&quot;</code></li> |
| <li>同步回调模式:<code>async=false onreturn=&quot;xxx&quot;</code></li> |
| <li>异步无回调 :<code>async=true</code></li> |
| <li>同步无回调 :<code>async=false</code></li> |
| </ul> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>async=false</code> 默认 |
| </div> |
| <h4 id="测试代码">测试代码</h4> |
| <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>IDemoService demoService <span style="color:#719e07">=</span> (IDemoService) context.getBean(<span style="color:#2aa198">&#34;demoService&#34;</span>); |
| </span></span><span style="display:flex;"><span>NotifyImpl notify <span style="color:#719e07">=</span> (NotifyImpl) context.getBean(<span style="color:#2aa198">&#34;demoCallback&#34;</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#dc322f">int</span> requestId <span style="color:#719e07">=</span> 2; |
| </span></span><span style="display:flex;"><span>Person ret <span style="color:#719e07">=</span> demoService.get(requestId); |
| </span></span><span style="display:flex;"><span>Assert.assertEquals(<span style="color:#cb4b16">null</span>, ret); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">//for Test:只是用来说明callback正常被调用,业务具体实现自行决定.</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">for</span> (<span style="color:#dc322f">int</span> i <span style="color:#719e07">=</span> 0; i <span style="color:#719e07">&lt;</span> 10; i<span style="color:#719e07">++</span>) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> (<span style="color:#719e07">!</span>notify.ret.containsKey(requestId)) { |
| </span></span><span style="display:flex;"><span> Thread.sleep(200); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">else</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">break</span>; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span>Assert.assertEquals(requestId, notify.ret.get(requestId).getId()); |
| </span></span></code></pre></div></description></item><item><title>Docs: 本地存根</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/local-stub/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/local-stub/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/local-stub/">最新版本</a>。</p> |
| </div> |
| <p>远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>,然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/stub.jpg" alt="/user-guide/images/stub.jpg"></p> |
| <p>在 spring 配置文件中按以下方式配置:</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:consumer</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> stub=<span style="color:#2aa198">&#34;true&#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:consumer</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> stub=<span style="color:#2aa198">&#34;com.foo.BarServiceStub&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>提供 Stub 的实现 <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> com.foo; |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">BarServiceStub</span> <span style="color:#268bd2">implements</span> BarService { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> BarService barService; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 构造函数传入真正的远程代理对象</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#268bd2">BarServiceStub</span>(BarService barService){ |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">this</span>.barService <span style="color:#719e07">=</span> barService; |
| </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">public</span> String <span style="color:#268bd2">sayHello</span>(String name) { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 此代码在客户端执行, 你可以在客户端做ThreadLocal本地缓存,或预先验证参数是否合法,等等</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> barService.sayHello(name); |
| </span></span><span style="display:flex;"><span> } <span style="color:#719e07">catch</span> (Exception e) { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 你可以容错,可以做任何AOP拦截事项</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;容错数据&#34;</span>; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p>Stub 必须有可传入 Proxy 的构造函数。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| <li id="fn:2"> |
| <p>在 interface 旁边放一个 Stub 实现,它实现 BarService 接口,并有一个传入远程 BarService 实例的构造函数&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 本地伪装</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/local-mock/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/local-mock/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/local-mock/">最新版本</a>。</p> |
| </div> |
| <p>本地伪装 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> 通常用于服务降级,比如某验权服务,当服务提供方全部挂掉后,客户端不抛出异常,而是通过 Mock 数据返回授权失败。</p> |
| <p>在 spring 配置文件中按以下方式配置:</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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> mock=<span style="color:#2aa198">&#34;true&#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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> mock=<span style="color:#2aa198">&#34;com.foo.BarServiceMock&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>在工程中提供 Mock 实现 <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">package</span> com.foo; |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">BarServiceMock</span> <span style="color:#268bd2">implements</span> BarService { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span>(String name) { |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// 你可以伪造容错数据,此方法只在出现RpcException时被执行</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;容错数据&#34;</span>; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>如果服务的消费方经常需要 try-catch 捕获异常,如:</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>Offer offer <span style="color:#719e07">=</span> <span style="color:#cb4b16">null</span>; |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">try</span> { |
| </span></span><span style="display:flex;"><span> offer <span style="color:#719e07">=</span> offerService.findOffer(offerId); |
| </span></span><span style="display:flex;"><span>} <span style="color:#719e07">catch</span> (RpcException e) { |
| </span></span><span style="display:flex;"><span> logger.error(e); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>请考虑改为 Mock 实现,并在 Mock 实现中 return null。如果只是想简单的忽略异常,在 <code>2.0.11</code> 以上版本可用:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> mock=<span style="color:#2aa198">&#34;return null&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h2 id="进阶用法">进阶用法</h2> |
| <h3 id="return">return</h3> |
| <p>使用 <code>return</code> 来返回一个字符串表示的对象,作为 Mock 的返回值。合法的字符串可以是:</p> |
| <ul> |
| <li><em>empty</em>: 代表空,基本类型的默认值,或者集合类的空值</li> |
| <li><em>null</em>: <code>null</code></li> |
| <li><em>true</em>: <code>true</code></li> |
| <li><em>false</em>: <code>false</code></li> |
| <li><em>JSON 格式</em>: 反序列化 JSON 所得到的对象</li> |
| </ul> |
| <h3 id="throw">throw</h3> |
| <p>使用 <code>throw</code> 来返回一个 Exception 对象,作为 Mock 的返回值。</p> |
| <p>当调用出错时,抛出一个默认的 RPCException:</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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> mock=<span style="color:#2aa198">&#34;throw&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>当调用出错时,抛出指定的 Exception:</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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> mock=<span style="color:#2aa198">&#34;throw com.foo.MockException&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="force-和-fail">force 和 fail</h3> |
| <p>在 <code>2.6.6</code> 以上的版本,可以开始在 Spring XML 配置文件中使用 <code>fail:</code> 和 <code>force:</code>。<code>force:</code> 代表强制使用 Mock 行为,在这种情况下不会走远程调用。<code>fail:</code> 与默认行为一致,只有当远程调用发生错误时才使用 Mock 行为。<code>force:</code> 和 <code>fail:</code> 都支持与 <code>throw</code> 或者 <code>return</code> 组合使用。</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> mock=<span style="color:#2aa198">&#34;force:return fake&#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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> mock=<span style="color:#2aa198">&#34;force:throw com.foo.MockException&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="在方法级别配置-mock">在方法级别配置 Mock</h3> |
| <p>Mock 可以在方法级别上指定,假定 <code>com.foo.BarService</code> 上有好几个方法,我们可以单独为 <code>sayHello()</code> 方法指定 Mock 行为。具体配置如下所示,在本例中,只要 <code>sayHello()</code> 被调用到时,强制返回 &ldquo;fake&rdquo;:</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> id=<span style="color:#2aa198">&#34;demoService&#34;</span> check=<span style="color:#2aa198">&#34;false&#34;</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:parameter</span> key=<span style="color:#2aa198">&#34;sayHello.mock&#34;</span> value=<span style="color:#2aa198">&#34;force:return fake&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div><div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p>Mock 是 Stub 的一个子集,便于服务提供方在客户端执行容错逻辑,因经常需要在出现 RpcException (比如网络失败,超时等)时进行容错,而在出现业务异常(比如登录用户名密码错误)时不需要容错,如果用 Stub,可能就需要捕获并依赖 RpcException 类,而用 Mock 就可以不依赖 RpcException,因为它的约定就是只有出现 RpcException 时才执行。&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| <li id="fn:2"> |
| <p>在 interface 旁放一个 Mock 实现,它实现 BarService 接口,并有一个无参构造函数&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 延迟暴露</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/delay-publish/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/delay-publish/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/delay-publish/">最新版本</a>。</p> |
| </div> |
| <p>如果你的服务需要预热时间,比如初始化缓存,等待相关资源就位等,可以使用 delay 进行延迟暴露。我们在 Dubbo 2.6.5 版本中对服务延迟暴露逻辑进行了细微的调整,将需要延迟暴露(delay &gt; 0)服务的倒计时动作推迟到了 Spring 初始化完成后进行。你在使用 Dubbo 的过程中,并不会感知到此变化,因此请放心使用。</p> |
| <h2 id="dubbo-265-之前版本">Dubbo 2.6.5 之前版本</h2> |
| <p>延迟到 Spring 初始化完成后,再暴露服务<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></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:service</span> delay=<span style="color:#2aa198">&#34;-1&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>延迟 5 秒暴露服务</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:service</span> delay=<span style="color:#2aa198">&#34;5000&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h2 id="dubbo-265-及以后版本">Dubbo 2.6.5 及以后版本</h2> |
| <p>所有服务都将在 Spring 初始化完成后进行暴露,如果你不需要延迟暴露服务,无需配置 delay。</p> |
| <p>延迟 5 秒暴露服务</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:service</span> delay=<span style="color:#2aa198">&#34;5000&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h2 id="spring-2x-初始化死锁问题">Spring 2.x 初始化死锁问题</h2> |
| <h3 id="触发条件">触发条件</h3> |
| <p>在 Spring 解析到 <code>&lt;dubbo:service /&gt;</code> 时,就已经向外暴露了服务,而 Spring 还在接着初始化其它 Bean。如果这时有请求进来,并且服务的实现类里有调用 <code>applicationContext.getBean()</code> 的用法。</p> |
| <ol> |
| <li> |
| <p>请求线程的 applicationContext.getBean() 调用,先同步 singletonObjects 判断 Bean 是否存在,不存在就同步 beanDefinitionMap 进行初始化,并再次同步 singletonObjects 写入 Bean 实例缓存。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/lock-get-bean.jpg" alt="deadlock"></p> |
| </li> |
| <li> |
| <p>而 Spring 初始化线程,因不需要判断 Bean 的存在,直接同步 beanDefinitionMap 进行初始化,并同步 singletonObjects 写入 Bean 实例缓存。</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/lock-init-context.jpg" alt="/user-guide/images/lock-init-context.jpg"></p> |
| <p>这样就导致 getBean 线程,先锁 singletonObjects,再锁 beanDefinitionMap,再次锁 singletonObjects。<br> |
| 而 Spring 初始化线程,先锁 beanDefinitionMap,再锁 singletonObjects。反向锁导致线程死锁,不能提供服务,启动不了。</p> |
| </li> |
| </ol> |
| <h3 id="规避办法">规避办法</h3> |
| <ol> |
| <li>强烈建议不要在服务的实现类中有 applicationContext.getBean() 的调用,全部采用 IoC 注入的方式使用 Spring的Bean。</li> |
| <li>如果实在要调 getBean(),可以将 Dubbo 的配置放在 Spring 的最后加载。</li> |
| <li>如果不想依赖配置顺序,可以使用 <code>&lt;dubbo:provider delay=”-1” /&gt;</code>,使 Dubbo 在 Spring 容器初始化完后,再暴露服务。</li> |
| <li>如果大量使用 getBean(),相当于已经把 Spring 退化为工厂模式在用,可以将 Dubbo 的服务隔离单独的 Spring 容器。</li> |
| </ol> |
| <div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p>基于 Spring 的 ContextRefreshedEvent 事件触发暴露&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 并发控制</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/concurrency-control/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/concurrency-control/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/concurrency-control/">最新版本</a>。</p> |
| </div> |
| <h2 id="配置样例">配置样例</h2> |
| <h3 id="样例-1">样例 1</h3> |
| <p>限制 <code>com.foo.BarService</code> 的每个方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个:</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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> executes=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="样例-2">样例 2</h3> |
| <p>限制 <code>com.foo.BarService</code> 的 <code>sayHello</code> 方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个:</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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;sayHello&#34;</span> executes=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:service&gt;</span> |
| </span></span></code></pre></div><h3 id="样例-3">样例 3</h3> |
| <p>限制 <code>com.foo.BarService</code> 的每个方法,每客户端并发执行(或占用连接的请求数)不能超过 10 个:</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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> actives=<span style="color:#2aa198">&#34;10&#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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> actives=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="样例-4">样例 4</h3> |
| <p>限制 <code>com.foo.BarService</code> 的 <code>sayHello</code> 方法,每客户端并发执行(或占用连接的请求数)不能超过 10 个:</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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;sayHello&#34;</span> actives=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:service&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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;sayHello&#34;</span> actives=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:service&gt;</span> |
| </span></span></code></pre></div><p>如果 <code>&lt;dubbo:service&gt;</code> 和 <code>&lt;dubbo:reference&gt;</code> 都配了actives,<code>&lt;dubbo:reference&gt;</code> 优先,参见:<a href="../../references/configuration/xml">配置的覆盖策略</a>。</p> |
| <h2 id="load-balance-均衡">Load Balance 均衡</h2> |
| <p>配置服务的客户端的 <code>loadbalance</code> 属性为 <code>leastactive</code>,此 Loadbalance 会调用并发数最小的 Provider(Consumer端并发数)。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> loadbalance=<span style="color:#2aa198">&#34;leastactive&#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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> loadbalance=<span style="color:#2aa198">&#34;leastactive&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 连接控制</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/config-connections/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/config-connections/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/config-connections/">最新版本</a>。</p> |
| </div> |
| <h2 id="服务端连接控制">服务端连接控制</h2> |
| <p>限制服务器端接受的连接不能超过 10 个 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</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:provider</span> protocol=<span style="color:#2aa198">&#34;dubbo&#34;</span> accepts=<span style="color:#2aa198">&#34;10&#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:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> accepts=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h2 id="客户端连接控制">客户端连接控制</h2> |
| <p>限制客户端服务使用连接不能超过 10 个 <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>:</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> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> connections=<span style="color:#2aa198">&#34;10&#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:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> connections=<span style="color:#2aa198">&#34;10&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>如果 <code>&lt;dubbo:service&gt;</code> 和 <code>&lt;dubbo:reference&gt;</code> 都配了 connections,<code>&lt;dubbo:reference&gt;</code> 优先,参见:<a href="../../references/configuration/xml/">配置的覆盖策略</a></p> |
| <div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p>因为连接在 Server上,所以配置在 Provider 上&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| <li id="fn:2"> |
| <p>如果是长连接,比如 Dubbo 协议,connections 表示该服务对每个提供者建立的长连接数&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 延迟连接</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/lazy-connect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/lazy-connect/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/lazy-connect/">最新版本</a>。</p> |
| </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:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> lazy=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| 该配置只对使用长连接的 dubbo 协议生效。 |
| </div></description></item><item><title>Docs: 粘滞连接</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/stickiness/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/stickiness/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/stickiness/">最新版本</a>。</p> |
| </div> |
| <p>粘滞连接用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非该提供者挂了,再连另一台。</p> |
| <p>粘滞连接将自动开启<a href="../lazy-connect">延迟连接</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;xxxService&#34;</span> interface=<span style="color:#2aa198">&#34;com.xxx.XxxService&#34;</span> sticky=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>Dubbo 支持方法级别的粘滞连接,如果你想进行更细粒度的控制,还可以这样配置。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;xxxService&#34;</span> interface=<span style="color:#2aa198">&#34;com.xxx.XxxService&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:method</span> name=<span style="color:#2aa198">&#34;sayHello&#34;</span> sticky=<span style="color:#2aa198">&#34;true&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dubbo:reference&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: TLS</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/tls/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/tls/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/security/tls/">最新版本</a>。</p> |
| </div> |
| <p>2.7.5 版本在传输链路的安全性上做了很多工作,对于内置的 Dubbo Netty Server 和新引入的 gRPC 协议都提供了基于 TLS 的安全链路传输机制。</p> |
| <p>TLS 的配置都有统一的入口,如下所示:</p> |
| <h5 id="provider-端">Provider 端</h5> |
| <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>SslConfig sslConfig <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> SslConfig(); |
| </span></span><span style="display:flex;"><span>sslConfig.setServerKeyCertChainPath(<span style="color:#2aa198">&#34;path to cert&#34;</span>); |
| </span></span><span style="display:flex;"><span>sslConfig.setServerPrivateKeyPath(args<span style="color:#719e07">[</span>1<span style="color:#719e07">]</span>); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 如果开启双向 cert 认证</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">if</span> (mutualTls) { |
| </span></span><span style="display:flex;"><span> sslConfig.setServerTrustCertCollectionPath(args<span style="color:#719e07">[</span>2<span style="color:#719e07">]</span>); |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>ProtocolConfig protocolConfig <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ProtocolConfig(<span style="color:#2aa198">&#34;dubbo/grpc&#34;</span>); |
| </span></span><span style="display:flex;"><span>protocolConfig.setSslEnabled(<span style="color:#cb4b16">true</span>); |
| </span></span></code></pre></div><h5 id="consumer-端">Consumer 端</h5> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#719e07">if</span> (<span style="color:#719e07">!</span>mutualTls) {} |
| </span></span><span style="display:flex;"><span> sslConfig.setClientTrustCertCollectionPath(args<span style="color:#719e07">[</span>0<span style="color:#719e07">]</span>); |
| </span></span><span style="display:flex;"><span>} <span style="color:#719e07">else</span> { |
| </span></span><span style="display:flex;"><span> sslConfig.setClientTrustCertCollectionPath(args<span style="color:#719e07">[</span>0<span style="color:#719e07">]</span>); |
| </span></span><span style="display:flex;"><span> sslConfig.setClientKeyCertChainPath(args<span style="color:#719e07">[</span>1<span style="color:#719e07">]</span>); |
| </span></span><span style="display:flex;"><span> sslConfig.setClientPrivateKeyPath(args<span style="color:#719e07">[</span>2<span style="color:#719e07">]</span>); |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>为尽可能保证应用启动的灵活性,TLS Cert 的指定还能通过 -D 参数或环境变量等方式来在启动阶段根据部署环境动态指定,具体请参见 Dubbo 配置读取规则与 TLS 示例</p> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <p>参考 Dubbo <a href="https://dubbo.apache.org/zh-cn/docsv2.7/user/configuration/configuration-load-process/">配置读取规则</a>,TLS <a href="https://github.com/apache/dubbo-samples/tree/master/4-governance/dubbo-samples-ssl">示例</a></p> |
| <p>如果要使用的是 gRPC 协议,在开启 TLS 时会使用到协议协商机制,因此必须使用支持 ALPN 机制的 Provider,推荐使用的是 netty-tcnative,具体可参见 gRPC Java 社区的<a href="https://github.com/grpc/grpc-java/blob/master/SECURITY.md">总结</a></p> |
| </div> |
| <p>在服务调用的安全性上,Dubbo 在后续的版本中会持续投入,其中服务发现/调用的鉴权机制预计在接下来的版本中就会和大家见面。</p></description></item><item><title>Docs: 令牌验证</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/token-authorization/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/token-authorization/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/security/token-authorization/">最新版本</a>。</p> |
| </div> |
| <p>通过令牌验证在注册中心控制权限,以决定要不要下发令牌给消费者,可以防止消费者绕过注册中心访问提供者,另外通过注册中心可灵活改变授权方式,而不需修改或升级提供者</p> |
| <p><img src="https://dubbo.apache.org/imgs/user/dubbo-token.jpg" alt="/user-guide/images/dubbo-token.jpg"></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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#586e75">&lt;!--随机token令牌,使用UUID生成--&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:provider</span> token=<span style="color:#2aa198">&#34;true&#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:#586e75">&lt;!--固定token令牌,相当于密码--&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:provider</span> token=<span style="color:#2aa198">&#34;123456&#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:#586e75">&lt;!--随机token令牌,使用UUID生成--&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> token=<span style="color:#2aa198">&#34;true&#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:#586e75">&lt;!--固定token令牌,相当于密码--&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.foo.BarService&#34;</span> token=<span style="color:#2aa198">&#34;123456&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 路由规则</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/routing-rule/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/routing-rule/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/core-features/traffic/">最新版本</a>。</p> |
| </div> |
| <p>路由规则在发起一次RPC调用前起到过滤目标服务器地址的作用,过滤后的地址列表,将作为消费端最终发起RPC调用的备选地址。</p> |
| <ul> |
| <li>条件路由。支持以服务或 Consumer 应用为粒度配置路由规则。</li> |
| <li>标签路由。以 Provider 应用为粒度配置路由规则。</li> |
| </ul> |
| <p>后续我们计划在 2.6.x 版本的基础上继续增强脚本路由功能。</p> |
| <h2 id="条件路由">条件路由</h2> |
| <p>您可以随时在服务治理控制台 <a href="https://github.com/apache/dubbo-admin">Dubbo-Admin</a> 写入路由规则</p> |
| <h3 id="简介">简介</h3> |
| <ul> |
| <li> |
| <p>应用粒度</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># app1的消费者只能消费所有端口为20880的服务实例</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># app2的消费者只能消费所有端口为20881的服务实例</span> |
| </span></span><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: application |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">force</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">runtime</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: governance-conditionrouter-consumer |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">conditions</span>: |
| </span></span><span style="display:flex;"><span> - application=app1 =&gt; address=*:20880 |
| </span></span><span style="display:flex;"><span> - application=app2 =&gt; address=*:20881 |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div></li> |
| <li> |
| <p>服务粒度</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># DemoService的sayHello方法只能消费所有端口为20880的服务实例</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># DemoService的sayHi方法只能消费所有端口为20881的服务实例</span> |
| </span></span><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: service |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">force</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">runtime</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: org.apache.dubbo.samples.governance.api.DemoService |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">conditions</span>: |
| </span></span><span style="display:flex;"><span> - method=sayHello =&gt; address=*:20880 |
| </span></span><span style="display:flex;"><span> - method=sayHi =&gt; address=*:20881 |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div></li> |
| </ul> |
| <h3 id="规则详解">规则详解</h3> |
| <h4 id="各字段含义">各字段含义</h4> |
| <ul> |
| <li><code>scope</code>表示路由规则的作用粒度,scope的取值会决定key的取值。<strong>必填</strong>。 |
| <ul> |
| <li>service 服务粒度</li> |
| <li>application 应用粒度</li> |
| </ul> |
| </li> |
| <li><code>Key</code>明确规则体作用在哪个服务或应用。<strong>必填</strong>。 |
| <ul> |
| <li>scope=service时,key取值为[{group}:]{service}[:{version}]的组合</li> |
| <li>scope=application时,key取值为application名称</li> |
| </ul> |
| </li> |
| <li><code>enabled=true</code> 当前路由规则是否生效,可不填,缺省生效。</li> |
| <li><code>force=false</code> 当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,可不填,缺省为 <code>false</code>。</li> |
| <li><code>runtime=false</code> 是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设为 <code>true</code>,需要注意设置会影响调用的性能,可不填,缺省为 <code>false</code>。</li> |
| <li><code>priority=1</code> 路由规则的优先级,用于排序,优先级越大越靠前执行,可不填,缺省为 <code>0</code>。</li> |
| <li><code>conditions</code> 定义具体的路由规则内容。<strong>必填</strong>。</li> |
| </ul> |
| <h4 id="conditions规则体">Conditions规则体</h4> |
| <pre><code>`conditions`部分是规则的主体,由1到任意多条规则组成,下面我们就每个规则的配置语法做详细说明: |
| </code></pre> |
| <ol> |
| <li><strong>格式</strong></li> |
| </ol> |
| <ul> |
| <li><code>=&gt;</code> 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则。</li> |
| <li><code>=&gt;</code> 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表。</li> |
| <li>如果匹配条件为空,表示对所有消费方应用,如:<code>=&gt; host != 10.20.153.11</code></li> |
| <li>如果过滤条件为空,表示禁止访问,如:<code>host = 10.20.153.10 =&gt;</code></li> |
| </ul> |
| <ol start="2"> |
| <li><strong>表达式</strong></li> |
| </ol> |
| <p>参数支持:</p> |
| <ul> |
| <li>服务调用信息,如:method, argument 等,暂不支持参数路由</li> |
| <li>URL 本身的字段,如:protocol, host, port 等</li> |
| <li>以及 URL 上的所有参数,如:application, organization 等</li> |
| </ul> |
| <p>条件支持:</p> |
| <ul> |
| <li>等号 <code>=</code> 表示&quot;匹配&quot;,如:<code>host = 10.20.153.10</code></li> |
| <li>不等号 <code>!=</code> 表示&quot;不匹配&quot;,如:<code>host != 10.20.153.10</code></li> |
| </ul> |
| <p>值支持:</p> |
| <ul> |
| <li>以逗号 <code>,</code> 分隔多个值,如:<code>host != 10.20.153.10,10.20.153.11</code></li> |
| <li>以星号 <code>*</code> 结尾,表示通配,如:<code>host != 10.20.*</code></li> |
| <li>以美元符 <code>$</code> 开头,表示引用消费者参数,如:<code>host = $host</code></li> |
| </ul> |
| <ol start="3"> |
| <li><strong>Condition示例</strong></li> |
| </ol> |
| <ul> |
| <li>排除预发布机:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>=&gt; host != 172.22.3.91 |
| </span></span></code></pre></div><ul> |
| <li>白名单:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>register.ip != 10.20.153.10,10.20.153.11 =&gt; |
| </span></span></code></pre></div> |
| <div class="alert alert-warning" role="alert"> |
| <h4 class="alert-heading">注意</h4> |
| 一个服务只能有一条白名单规则,否则两条规则交叉,就都被筛选掉了 |
| </div> |
| <ul> |
| <li>黑名单:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>register.ip = 10.20.153.10,10.20.153.11 =&gt; |
| </span></span></code></pre></div><ul> |
| <li>服务寄宿在应用上,只暴露一部分的机器,防止整个集群挂掉:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>=&gt; host = 172.22.3.1*,172.22.3.2* |
| </span></span></code></pre></div><ul> |
| <li>为重要应用提供额外的机器:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>application != kylin =&gt; host != 172.22.3.95,172.22.3.96 |
| </span></span></code></pre></div><ul> |
| <li>读写分离:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>method = find*,list*,get*,is* =&gt; host = 172.22.3.94,172.22.3.95,172.22.3.96 |
| </span></span><span style="display:flex;"><span>method != find*,list*,get*,is* =&gt; host = 172.22.3.97,172.22.3.98 |
| </span></span></code></pre></div><ul> |
| <li>前后台分离:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>application = bops =&gt; host = 172.22.3.91,172.22.3.92,172.22.3.93 |
| </span></span><span style="display:flex;"><span>application != bops =&gt; host = 172.22.3.94,172.22.3.95,172.22.3.96 |
| </span></span></code></pre></div><ul> |
| <li>隔离不同机房网段:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>host != 172.22.3.* =&gt; host != 172.22.3.* |
| </span></span></code></pre></div><ul> |
| <li>提供者与消费者部署在同集群内,本机只访问本机的服务:</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>=&gt; host = $host |
| </span></span></code></pre></div><h2 id="标签路由规则">标签路由规则</h2> |
| <h3 id="简介-1">简介</h3> |
| <p>标签路由通过将某一个或多个服务的提供者划分到同一个分组,约束流量只在指定分组中流转,从而实现流量隔离的目的,可以作为蓝绿发布、灰度发布等场景的能力基础。</p> |
| <h4 id="provider">Provider</h4> |
| <p>标签主要是指对Provider端应用实例的分组,目前有两种方式可以完成实例分组,分别是<code>动态规则打标</code>和<code>静态规则打标</code>,其中动态规则相较于静态规则优先级更高,而当两种规则同时存在且出现冲突时,将以动态规则为准。</p> |
| <ul> |
| <li> |
| <p>动态规则打标,可随时在<strong>服务治理控制台</strong>下发标签归组规则</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># governance-tagrouter-provider应用增加了两个标签分组tag1和tag2</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># tag1包含一个实例 127.0.0.1:20880</span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75"># tag2包含一个实例 127.0.0.1:20881</span> |
| </span></span><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">force</span>: <span style="color:#cb4b16">false</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">runtime</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">key</span>: governance-tagrouter-provider |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">tags</span>: |
| </span></span><span style="display:flex;"><span> - <span style="color:#268bd2">name</span>: tag1 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">&#34;127.0.0.1:20880&#34;</span>] |
| </span></span><span style="display:flex;"><span> - <span style="color:#268bd2">name</span>: tag2 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">&#34;127.0.0.1:20881&#34;</span>] |
| </span></span><span style="display:flex;"><span> ... |
| </span></span></code></pre></div></li> |
| <li> |
| <p>静态打标</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:provider</span> tag=<span style="color:#2aa198">&#34;tag1&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>or</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:service</span> tag=<span style="color:#2aa198">&#34;tag1&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>or</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>java <span style="color:#2aa198">-jar xxx-provider.jar -Ddubbo.provider.tag={the tag you want, may come from OS ENV}</span> |
| </span></span></code></pre></div></li> |
| </ul> |
| <h4 id="consumer">Consumer</h4> |
| <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>RpcContext.getContext().setAttachment(Constants.TAG_KEY,<span style="color:#2aa198">&#34;tag1&#34;</span>); |
| </span></span></code></pre></div><p>请求标签的作用域为每一次 invocation,使用 attachment 来传递请求标签,注意保存在 attachment 中的值将会在一次完整的远程调用中持续传递,得益于这样的特性,我们只需要在起始调用时,通过一行代码的设置,达到标签的持续传递。</p> |
| <blockquote> |
| <p>目前仅仅支持 hardcoding 的方式设置 dubboTag。注意到 RpcContext 是线程绑定的,优雅的使用 TagRouter 特性,建议通过 servlet 过滤器(在 web 环境下),或者定制的 SPI 过滤器设置 dubboTag。</p> |
| </blockquote> |
| <h3 id="规则详解-1">规则详解</h3> |
| <h4 id="格式">格式</h4> |
| <ul> |
| <li><code>Key</code>明确规则体作用到哪个应用。<strong>必填</strong>。</li> |
| <li><code>enabled=true</code> 当前路由规则是否生效,可不填,缺省生效。</li> |
| <li><code>force=false</code> 当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,可不填,缺省为 <code>false</code>。</li> |
| <li><code>runtime=false</code> 是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设为 <code>true</code>,需要注意设置会影响调用的性能,可不填,缺省为 <code>false</code>。</li> |
| <li><code>priority=1</code> 路由规则的优先级,用于排序,优先级越大越靠前执行,可不填,缺省为 <code>0</code>。</li> |
| <li><code>tags</code> 定义具体的标签分组内容,可定义任意n(n&gt;=1)个标签并为每个标签指定实例列表。<strong>必填</strong>。 |
| <ul> |
| <li>name, 标签名称</li> |
| </ul> |
| </li> |
| <li>addresses, 当前标签包含的实例列表</li> |
| </ul> |
| <h4 id="降级约定">降级约定</h4> |
| <ol> |
| <li> |
| <p><code>dubbo.tag=tag1</code> 时优先选择 标记了<code>tag=tag1</code> 的 provider。若集群中不存在与请求标记对应的服务,默认将降级请求 tag为空的provider;如果要改变这种默认行为,即找不到匹配tag1的provider返回异常,需设置<code>dubbo.force.tag=true</code>。</p> |
| </li> |
| <li> |
| <p><code>dubbo.tag</code>未设置时,只会匹配tag为空的provider。即使集群中存在可用的服务,若 tag 不匹配也就无法调用,这与约定1不同,携带标签的请求可以降级访问到无标签的服务,但不携带标签/携带其他种类标签的请求永远无法访问到其他标签的服务。</p> |
| </li> |
| </ol> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <p><code>2.6.x</code> 版本以及更早的版本请使用<a href="../routing-rule-deprecated">老版本路由规则</a></p> |
| <p>自定义路由参考<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/spi/description/router/">路由扩展</a></p> |
| </div></description></item><item><title>Docs: 旧路由规则</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/routing-rule-deprecated/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/routing-rule-deprecated/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/core-features/traffic/">最新版本</a>。</p> |
| </div> |
| <p>路由规则 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> 决定一次 dubbo 服务调用的目标服务器,分为条件路由规则和脚本路由规则,并且支持可扩展 <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p> |
| <h2 id="写入路由规则">写入路由规则</h2> |
| <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>RegistryFactory registryFactory <span style="color:#719e07">=</span> ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); |
| </span></span><span style="display:flex;"><span>Registry registry <span style="color:#719e07">=</span> registryFactory.getRegistry(URL.valueOf(<span style="color:#2aa198">&#34;zookeeper://10.20.153.10:2181&#34;</span>)); |
| </span></span><span style="display:flex;"><span>registry.register(URL.valueOf(<span style="color:#2aa198">&#34;route://0.0.0.0/com.foo.BarService?category=routers&amp;dynamic=false&amp;rule=&#34;</span> <span style="color:#719e07">+</span> URL.encode(<span style="color:#2aa198">&#34;host = 10.20.153.10 =&gt; host = 10.20.153.11&#34;</span>))); |
| </span></span></code></pre></div><p>其中:</p> |
| <ul> |
| <li><code>route://</code> 表示路由规则的类型,支持条件路由规则和脚本路由规则,可扩展,<strong>必填</strong>。</li> |
| <li><code>0.0.0.0</code> 表示对所有 IP 地址生效,如果只想对某个 IP 的生效,请填入具体 IP,<strong>必填</strong>。</li> |
| <li><code>com.foo.BarService</code> 表示只对指定服务生效,<strong>必填</strong>。</li> |
| <li><code>group=foo</code> 对指定服务的指定group生效,不填表示对未配置group的指定服务生效</li> |
| <li><code>version=1.0</code>对指定服务的指定version生效,不填表示对未配置version的指定服务生效</li> |
| <li><code>category=routers</code> 表示该数据为动态配置类型,<strong>必填</strong>。</li> |
| <li><code>dynamic=false</code> 表示该数据为持久数据,当注册方退出时,数据依然保存在注册中心,<strong>必填</strong>。</li> |
| <li><code>enabled=true</code> 覆盖规则是否生效,可不填,缺省生效。</li> |
| <li><code>force=false</code> 当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,可不填,缺省为 <code>false</code>。</li> |
| <li><code>runtime=false</code> 是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设为 <code>true</code>,需要注意设置会影响调用的性能,可不填,缺省为 <code>false</code>。</li> |
| <li><code>priority=1</code> 路由规则的优先级,用于排序,优先级越大越靠前执行,可不填,缺省为 <code>0</code>。</li> |
| <li><code>rule=URL.encode(&quot;host = 10.20.153.10 =&gt; host = 10.20.153.11&quot;)</code> 表示路由规则的内容,<strong>必填</strong>。</li> |
| </ul> |
| <h2 id="条件路由规则">条件路由规则</h2> |
| <p>基于条件表达式的路由规则,如:<code>host = 10.20.153.10 =&gt; host = 10.20.153.11</code></p> |
| <h3 id="规则">规则:</h3> |
| <ul> |
| <li><code>=&gt;</code> 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则。</li> |
| <li><code>=&gt;</code> 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表。</li> |
| <li>如果匹配条件为空,表示对所有消费方应用,如:<code>=&gt; host != 10.20.153.11</code></li> |
| <li>如果过滤条件为空,表示禁止访问,如:<code>host = 10.20.153.10 =&gt;</code></li> |
| </ul> |
| <h3 id="表达式">表达式:</h3> |
| <p>参数支持:</p> |
| <ul> |
| <li>服务调用信息,如:method, argument 等,暂不支持参数路由</li> |
| <li>URL 本身的字段,如:protocol, host, port 等</li> |
| <li>以及 URL 上的所有参数,如:application, organization 等</li> |
| </ul> |
| <p>条件支持:</p> |
| <ul> |
| <li>等号 <code>=</code> 表示&quot;匹配&quot;,如:<code>host = 10.20.153.10</code></li> |
| <li>不等号 <code>!=</code> 表示&quot;不匹配&quot;,如:<code>host != 10.20.153.10</code></li> |
| </ul> |
| <p>值支持:</p> |
| <ul> |
| <li>以逗号 <code>,</code> 分隔多个值,如:<code>host != 10.20.153.10,10.20.153.11</code></li> |
| <li>以星号 <code>*</code> 结尾,表示通配,如:<code>host != 10.20.*</code></li> |
| <li>以美元符 <code>$</code> 开头,表示引用消费者参数,如:<code>host = $host</code></li> |
| </ul> |
| <h3 id="示例">示例:</h3> |
| <ol start="0"> |
| <li> |
| <p>排除预发布机:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>=&gt; host != 172.22.3.91 |
| </span></span></code></pre></div></li> |
| <li> |
| <p>白名单 <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>host != 10.20.153.10,10.20.153.11 =&gt; |
| </span></span></code></pre></div></li> |
| <li> |
| <p>黑名单:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>host = 10.20.153.10,10.20.153.11 =&gt; |
| </span></span></code></pre></div></li> |
| <li> |
| <p>服务寄宿在应用上,只暴露一部分的机器,防止整个集群挂掉:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>=&gt; host = 172.22.3.1*,172.22.3.2* |
| </span></span></code></pre></div></li> |
| <li> |
| <p>为重要应用提供额外的机器:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>application != kylin =&gt; host != 172.22.3.95,172.22.3.96 |
| </span></span></code></pre></div></li> |
| <li> |
| <p>读写分离:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>method = find*,list*,get*,is* =&gt; host = 172.22.3.94,172.22.3.95,172.22.3.96 |
| </span></span><span style="display:flex;"><span>method != find*,list*,get*,is* =&gt; host = 172.22.3.97,172.22.3.98 |
| </span></span></code></pre></div></li> |
| <li> |
| <p>前后台分离:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>application = bops =&gt; host = 172.22.3.91,172.22.3.92,172.22.3.93 |
| </span></span><span style="display:flex;"><span>application != bops =&gt; host = 172.22.3.94,172.22.3.95,172.22.3.96 |
| </span></span></code></pre></div></li> |
| <li> |
| <p>隔离不同机房网段:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>host != 172.22.3.* =&gt; host != 172.22.3.* |
| </span></span></code></pre></div></li> |
| <li> |
| <p>提供者与消费者部署在同集群内,本机只访问本机的服务:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>=&gt; host = $host |
| </span></span></code></pre></div></li> |
| </ol> |
| <h2 id="脚本路由规则">脚本路由规则</h2> |
| <p>脚本路由规则 <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> 支持 JDK 脚本引擎的所有脚本,比如:javascript, jruby, groovy 等,通过 <code>type=javascript</code> 参数设置脚本类型,缺省为 javascript。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>&#34;script://0.0.0.0/com.foo.BarService?category=routers&amp;dynamic=false&amp;rule=&#34; + URL.encode(&#34;(function route(invokers) { ... } (invokers))&#34;) |
| </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-javascript" data-lang="javascript"><span style="display:flex;"><span>(<span style="color:#268bd2">function</span> route(invokers) { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">var</span> result <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> java.util.ArrayList(invokers.size()); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">for</span> (i <span style="color:#719e07">=</span> <span style="color:#2aa198">0</span>; i <span style="color:#719e07">&lt;</span> invokers.size(); i <span style="color:#719e07">++</span>) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> (<span style="color:#2aa198">&#34;10.20.153.10&#34;</span>.equals(invokers.get(i).getUrl().getHost())) { |
| </span></span><span style="display:flex;"><span> result.add(invokers.get(i)); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> result; |
| </span></span><span style="display:flex;"><span>} (invokers)); <span style="color:#586e75">// 表示立即执行方法 |
| </span></span></span></code></pre></div><h2 id="标签路由规则">标签路由规则</h2> |
| <p>标签路由规则 <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> ,当应用选择装配标签路由(TagRouter)之后,一次 dubbo 调用能够根据请求携带的 tag 标签智能地选择对应 tag 的服务提供者进行调用。</p> |
| <h3 id="服务提供者">服务提供者</h3> |
| <ol> |
| <li>给应用装配标签路由器:</li> |
| </ol> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span><span style="color:#268bd2">@Bean</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> ApplicationConfig <span style="color:#268bd2">applicationConfig</span>() { |
| </span></span><span style="display:flex;"><span> ApplicationConfig applicationConfig <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ApplicationConfig(); |
| </span></span><span style="display:flex;"><span> applicationConfig.setName(<span style="color:#2aa198">&#34;provider-book&#34;</span>); |
| </span></span><span style="display:flex;"><span> applicationConfig.setQosEnable(<span style="color:#cb4b16">false</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// instruct tag router</span> |
| </span></span><span style="display:flex;"><span> Map<span style="color:#719e07">&lt;</span>String,String<span style="color:#719e07">&gt;</span> parameters <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HashMap<span style="color:#719e07">&lt;&gt;</span>(); |
| </span></span><span style="display:flex;"><span> parameters.put(Constants.ROUTER_KEY, <span style="color:#2aa198">&#34;tag&#34;</span>); |
| </span></span><span style="display:flex;"><span> applicationConfig.setParameters(parameters); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> applicationConfig; |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><ol start="2"> |
| <li>给应用设置具体的标签:</li> |
| </ol> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Bean</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> ProviderConfig <span style="color:#268bd2">providerConfig</span>(){ |
| </span></span><span style="display:flex;"><span> ProviderConfig providerConfig <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ProviderConfig(); |
| </span></span><span style="display:flex;"><span> providerConfig.setTag(<span style="color:#2aa198">&#34;red&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> providerConfig; |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>应用未装配 tag 属性或服务提供者未设置 tag 属性,都将被认为是默认的应用,这些默认应用将会在调用无法匹配 provider 时当作降级方案。</p> |
| <h3 id="服务消费者">服务消费者</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Java" data-lang="Java"><span style="display:flex;"><span>RpcContext.getContext().setAttachment(Constants.TAG_KEY,<span style="color:#2aa198">&#34;red&#34;</span>); |
| </span></span></code></pre></div><p>请求标签的作用域为每一次 invocation,使用 attachment 来传递请求标签,注意保存在 attachment 中的值将会在一次完整的远程调用中持续传递,得益于这样的特性,我们只需要在起始调用时,通过一行代码的设置,达到标签的持续传递。</p> |
| <blockquote> |
| <p>目前仅仅支持 hardcoding 的方式设置 dubboTag。注意到 RpcContext 是线程绑定的,优雅的使用 TagRouter 特性,建议通过 servlet 过滤器(在 web 环境下),或者定制的 SPI 过滤器设置 dubboTag。</p> |
| </blockquote> |
| <h3 id="规则描述">规则描述</h3> |
| <ol> |
| <li> |
| <p>dubbo.tag=red 时优先选择 tag=red 的 provider。若集群中不存在与请求标记对应的服务,可以降级请求 tag=null 的 provider,即默认 provider。</p> |
| </li> |
| <li> |
| <p>dubbo.tag=null 时,只会匹配 tag=null 的 provider。即使集群中存在可用的服务,若 tag 不匹配就无法调用,这与规则1不同,携带标签的请求可以降级访问到无标签的服务,但不携带标签/携带其他种类标签的请求永远无法访问到其他标签的服务。</p> |
| </li> |
| </ol> |
| <div class="footnotes" role="doc-endnotes"> |
| <hr> |
| <ol> |
| <li id="fn:1"> |
| <p><code>2.2.0</code> 以上版本支持&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| <li id="fn:2"> |
| <p>路由规则扩展点:<a href="../../references/spis/router">路由扩展</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| <li id="fn:3"> |
| <p>注意:一个服务只能有一条白名单规则,否则两条规则交叉,就都被筛选掉了&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| <li id="fn:4"> |
| <p>注意:脚本没有沙箱约束,可执行任意代码,存在后门风险&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| <li id="fn:5"> |
| <p>该特性在 <code>2.7.0</code> 以上版本支持&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> |
| </li> |
| </ol> |
| </div></description></item><item><title>Docs: 配置规则</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/config-rule/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/config-rule/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/tasks/traffic-management/">最新版本</a>。</p> |
| </div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| 本文描述的是新版本规则配置,而不是<a href="../config-rule-deprecated">老版本配置规则</a> |
| </div> |
| <p>覆盖规则是 Dubbo 设计的在无需重启应用的情况下,动态调整 RPC 调用行为的一种能力。2.7.0 版本开始,支持从<strong>服务</strong>和<strong>应用</strong>两个粒度来调整动态配置。</p> |
| <h2 id="概览">概览</h2> |
| <p>请在服务治理控制台查看或修改覆盖规则。</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-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># 将应用demo(key:demo)在20880端口上提供(side:provider)的所有服务(scope:application)的权重修改为1000(weight:1000)。</span> |
| </span></span><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configVersion</span>: v2.7 |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: application |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: demo |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configs</span>: |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">&#34;0.0.0.0:20880&#34;</span>] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">side</span>: provider |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">weight</span>: <span style="color:#2aa198">1000</span> |
| </span></span><span style="display:flex;"><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-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#586e75"># 所有消费(side:consumer)DemoService服务(key:org.apache.dubbo.samples.governance.api.DemoService)的应用实例(addresses:[0.0.0.0]),超时时间修改为6000ms</span> |
| </span></span><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configVersion</span>: v2.7 |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: service |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: org.apache.dubbo.samples.governance.api.DemoService |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configs</span>: |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">0.0.0.0</span>] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">side</span>: consumer |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">timeout</span>: <span style="color:#2aa198">6000</span> |
| </span></span><span style="display:flex;"><span> ... |
| </span></span></code></pre></div><h2 id="规则详解">规则详解</h2> |
| <h4 id="配置模板">配置模板</h4> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configVersion</span>: v2.7 |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: application/service |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: app-name/group+service+version |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configs</span>: |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">&#34;0.0.0.0&#34;</span>] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">providerAddresses</span>: [<span style="color:#2aa198">&#34;1.1.1.1:20880&#34;</span>, <span style="color:#2aa198">&#34;2.2.2.2:20881&#34;</span>] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">side</span>: consumer |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">applications/services</span>: [] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">timeout</span>: <span style="color:#2aa198">1000</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">cluster</span>: failfase |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">loadbalance</span>: random |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">&#34;0.0.0.0:20880&#34;</span>] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">side</span>: provider |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">applications/services</span>: [] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">threadpool</span>: fixed |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">threads</span>: <span style="color:#2aa198">200</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">iothreads</span>: <span style="color:#2aa198">4</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">dispatcher</span>: all |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">weight</span>: <span style="color:#2aa198">200</span> |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div><p>其中:</p> |
| <ul> |
| <li><code>configVersion</code> 表示 dubbo 的版本</li> |
| <li><code>scope</code>表示配置作用范围,分别是应用(application)或服务(service)粒度。<strong>必填</strong>。</li> |
| <li><code>key</code> 指定规则体作用在哪个服务或应用。<strong>必填</strong>。 |
| <ul> |
| <li>scope=service时,key取值为[{group}:]{service}[:{version}]的组合</li> |
| </ul> |
| </li> |
| <li>scope=application时,key取值为application名称</li> |
| <li><code>enabled=true</code> 覆盖规则是否生效,可不填,缺省生效。</li> |
| <li><code>configs</code> 定义具体的覆盖规则内容,可以指定n(n&gt;=1)个规则体。<strong>必填</strong>。 |
| <ul> |
| <li>side,</li> |
| <li>applications</li> |
| <li>services</li> |
| <li>parameters</li> |
| <li>addresses</li> |
| <li>providerAddresses</li> |
| </ul> |
| </li> |
| </ul> |
| <p><strong>对于绝大多数配置场景,只需要理清楚以下问题基本就知道配置该怎么写了:</strong></p> |
| <ol> |
| <li> |
| <p>要修改整个应用的配置还是某个服务的配置。</p> |
| <ul> |
| <li>应用:<code>scope: application, key: app-name</code>(还可使用<code>services</code>指定某几个服务)。</li> |
| <li>服务:<code>scope: service, key:group+service+version </code>。</li> |
| </ul> |
| </li> |
| <li> |
| <p>修改是作用到消费者端还是提供者端。</p> |
| <ul> |
| <li>消费者:<code>side: consumer</code> ,作用到消费端时(你还可以进一步使用<code>providerAddress</code>, <code>applications</code>选定特定的提供者示例或应用)。</li> |
| <li>提供者:<code>side: provider</code>。</li> |
| </ul> |
| </li> |
| <li> |
| <p>配置是否只对某几个特定实例生效。</p> |
| <ul> |
| <li>所有实例:<code>addresses: [&quot;0.0.0.0&quot;] </code>或<code>addresses: [&quot;0.0.0.0:*&quot;] </code>具体由side值决定。</li> |
| <li>指定实例:<code>addersses[实例地址列表]</code>。</li> |
| </ul> |
| </li> |
| <li> |
| <p>要修改的属性是哪个。</p> |
| </li> |
| </ol> |
| <h4 id="示例">示例</h4> |
| <ol> |
| <li> |
| <p>禁用提供者:(通常用于临时踢除某台提供者机器,相似的,禁止消费者访问请使用路由规则)</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configVersion</span>: v2.7 |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: application |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: demo-provider |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configs</span>: |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">&#34;10.20.153.10:20880&#34;</span>] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">side</span>: provider |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">disabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div></li> |
| <li> |
| <p>调整权重:(通常用于容量评估,缺省权重为 200)</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configVersion</span>: v2.7 |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: application |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: demo-provider |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configs</span>: |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">addresses</span>: [<span style="color:#2aa198">&#34;10.20.153.10:20880&#34;</span>] |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">side</span>: provider |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">weight</span>: <span style="color:#2aa198">200</span> |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div></li> |
| <li> |
| <p>调整负载均衡策略:(缺省负载均衡策略为 random)</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configVersion</span>: v2.7 |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: application |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: demo-consumer |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configs</span>: |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">side</span>: consumer |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">loadbalance</span>: random |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div></li> |
| <li> |
| <p>服务降级:(通常用于临时屏蔽某个出错的非关键服务)</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>--- |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configVersion</span>: v2.7 |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">scope</span>: service |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">key</span>: org.apache.dubbo.samples.governance.api.DemoService |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">enabled</span>: <span style="color:#cb4b16">true</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">configs</span>: |
| </span></span><span style="display:flex;"><span>- <span style="color:#268bd2">side</span>: consumer |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">parameters</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">force</span>: return null |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div></li> |
| </ol></description></item><item><title>Docs: 服务降级</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/service-downgrade/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/service-downgrade/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/service-downgrade/">最新版本</a>。</p> |
| </div> |
| <p>可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。</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>RegistryFactory registryFactory <span style="color:#719e07">=</span> ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); |
| </span></span><span style="display:flex;"><span>Registry registry <span style="color:#719e07">=</span> registryFactory.getRegistry(URL.valueOf(<span style="color:#2aa198">&#34;zookeeper://10.20.153.10:2181&#34;</span>)); |
| </span></span><span style="display:flex;"><span>registry.register(URL.valueOf(<span style="color:#2aa198">&#34;override://0.0.0.0/com.foo.BarService?category=configurators&amp;dynamic=false&amp;application=foo&amp;mock=force:return+null&#34;</span>)); |
| </span></span></code></pre></div><p>其中:</p> |
| <ul> |
| <li><code>mock=force:return+null</code> 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。</li> |
| <li>还可以改为 <code>mock=fail:return+null</code> 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。</li> |
| </ul> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>2.2.0</code> 以上版本支持 |
| </div></description></item><item><title>Docs: 旧配置规则</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/config-rule-deprecated/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/config-rule-deprecated/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/tasks/traffic-management/">最新版本</a>。</p> |
| </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>RegistryFactory registryFactory <span style="color:#719e07">=</span> ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); |
| </span></span><span style="display:flex;"><span>Registry registry <span style="color:#719e07">=</span> registryFactory.getRegistry(URL.valueOf(<span style="color:#2aa198">&#34;zookeeper://10.20.153.10:2181&#34;</span>)); |
| </span></span><span style="display:flex;"><span>registry.register(URL.valueOf(<span style="color:#2aa198">&#34;override://0.0.0.0/com.foo.BarService?category=configurators&amp;dynamic=false&amp;application=foo&amp;timeout=1000&#34;</span>)); |
| </span></span></code></pre></div><p>其中:</p> |
| <ul> |
| <li><code>override://</code> 表示数据采用覆盖方式,支持 <code>override</code> 和 <code>absent</code>,可扩展,<strong>必填</strong>。</li> |
| <li><code>0.0.0.0</code> 表示对所有 IP 地址生效,如果只想覆盖某个 IP 的数据,请填入具体 IP,<strong>必填</strong>。</li> |
| <li><code>com.foo.BarService</code> 表示只对指定服务生效,<strong>必填</strong>。</li> |
| <li><code>category=configurators</code> 表示该数据为动态配置类型,<strong>必填</strong>。</li> |
| <li><code>dynamic=false</code> 表示该数据为持久数据,当注册方退出时,数据依然保存在注册中心,<strong>必填</strong>。</li> |
| <li><code>enabled=true</code> 覆盖规则是否生效,可不填,缺省生效。</li> |
| <li><code>application=foo</code> 表示只对指定应用生效,可不填,表示对所有应用生效。</li> |
| <li><code>timeout=1000</code> 表示将满足以上条件的 <code>timeout</code> 参数的值覆盖为 1000。如果想覆盖其它参数,直接加在 <code>override</code> 的 URL 参数上。</li> |
| </ul> |
| <p>示例:</p> |
| <ol> |
| <li> |
| <p>禁用提供者:(通常用于临时踢除某台提供者机器,相似的,禁止消费者访问请使用路由规则)</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>override://10.20.153.10/com.foo.BarService?category=configurators&amp;dynamic=false&amp;disbaled=true |
| </span></span></code></pre></div></li> |
| <li> |
| <p>调整权重:(通常用于容量评估,缺省权重为 100)</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>override://10.20.153.10/com.foo.BarService?category=configurators&amp;dynamic=false&amp;weight=200 |
| </span></span></code></pre></div></li> |
| <li> |
| <p>调整负载均衡策略:(缺省负载均衡策略为 random)</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-gdscript3" data-lang="gdscript3"><span style="display:flex;"><span>override:<span style="color:#719e07">//</span><span style="color:#2aa198">10.20</span><span style="color:#719e07">.</span><span style="color:#2aa198">153.10</span><span style="color:#719e07">/</span>com<span style="color:#719e07">.</span>foo<span style="color:#719e07">.</span>BarService?category<span style="color:#719e07">=</span>configurators<span style="color:#719e07">&amp;</span>dynamic<span style="color:#719e07">=</span><span style="color:#268bd2">false</span><span style="color:#719e07">&amp;</span>loadbalance<span style="color:#719e07">=</span>leastactive |
| </span></span></code></pre></div></li> |
| <li> |
| <p>服务降级:(通常用于临时屏蔽某个出错的非关键服务)</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>override://0.0.0.0/com.foo.BarService?category=configurators&amp;dynamic=false&amp;application=foo&amp;mock=force:return+null |
| </span></span></code></pre></div></li> |
| </ol> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">提示</h4> |
| <code>2.2.0</code> 以上版本支持 |
| </div></description></item><item><title>Docs: 消费端线程池模型</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/consumer-threadpool/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/consumer-threadpool/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/threading-model/consumer/">最新版本</a>。</p> |
| </div> |
| <p>2.7.5 版本对整个调用链路做了全面的优化,根据压测结果显示,总体 QPS 性能提升将近 30%,同时也减少了调用过程中的内存分配开销。其中一个值得提及的设计点是 2.7.5 引入了 Servicerepository 的概念,在服务注册阶段提前生成 ServiceDescriptor 和 MethodDescriptor,以减少 RPC 调用阶段计算 Service 原信息带来的资源消耗。</p> |
| <h2 id="消费端线程池模型优化">消费端线程池模型优化</h2> |
| <p>对 2.7.5 版本之前的 Dubbo 应用,尤其是一些消费端应用,当面临需要消费大量服务且并发数比较大的大流量场景时(典型如网关类场景),经常会出现消费端线程数分配过多的问题,具体问题讨论可参见 <a href="https://github.com/apache/dubbo/issues/2013">Need a limited Threadpool in consumer side #2013</a></p> |
| <p>改进后的消费端线程池模型,通过复用业务端被阻塞的线程,很好的解决了这个问题。</p> |
| <h4 id="老的线程池模型">老的线程池模型</h4> |
| <p><img src="https://dubbo.apache.org/imgs/user/consumer-threadpool0.png" alt="消费端线程池.png"></p> |
| <p>我们重点关注 Consumer 部分:</p> |
| <ol> |
| <li>业务线程发出请求,拿到一个 Future 实例。</li> |
| <li>业务线程紧接着调用 future.get 阻塞等待业务结果返回。</li> |
| <li>当业务数据返回后,交由独立的 Consumer 端线程池进行反序列化等处理,并调用 future.set 将反序列化后的业务结果置回。</li> |
| <li>业务线程拿到结果直接返回</li> |
| </ol> |
| <p><strong>2.7.5 版本引入的线程池模型</strong></p> |
| <p><img src="https://dubbo.apache.org/imgs/user/consumer-threadpool1.png" alt="消费端线程池新.png"></p> |
| <ol> |
| <li>业务线程发出请求,拿到一个 Future 实例。</li> |
| <li>在调用 future.get() 之前,先调用 ThreadlessExecutor.wait(),wait 会使业务线程在一个阻塞队列上等待,直到队列中被加入元素。</li> |
| <li>当业务数据返回后,生成一个 Runnable Task 并放入 ThreadlessExecutor 队列</li> |
| <li>业务线程将 Task 取出并在本线程中执行:反序列化业务数据并 set 到 Future。</li> |
| <li>业务线程拿到结果直接返回</li> |
| </ol> |
| <p>这样,相比于老的线程池模型,由业务线程自己负责监测并解析返回结果,免去了额外的消费端线程池开销。</p> |
| <p>关于性能优化,在接下来的版本中将会持续推进,主要从以下两个方面入手:</p> |
| <ol> |
| <li>RPC 调用链路。目前能看到的点包括:进一步减少执行链路的内存分配、在保证协议兼容性的前提下提高协议传输效率、提高 Filter、Router 等计算效率。</li> |
| <li>服务治理链路。进一步减少地址推送、服务治理规则推送等造成的内存、cpu 资源消耗。</li> |
| </ol></description></item><item><title>Docs: 优雅停机</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/graceful-shutdown/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/graceful-shutdown/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/others/graceful-shutdown/">最新版本</a>。</p> |
| </div> |
| <p>Dubbo 是通过 JDK 的 ShutdownHook 来完成优雅停机的,所以如果用户使用 <code>kill -9 PID</code> 等强制关闭指令,是不会执行优雅停机的,只有通过 <code>kill PID</code> 时,才会执行。</p> |
| <h2 id="原理">原理</h2> |
| <p>服务提供方</p> |
| <ul> |
| <li>停止时,先标记为不接收新请求,新请求过来时直接报错,让客户端重试其它机器。</li> |
| <li>然后,检测线程池中的线程是否正在运行,如果有,等待所有线程执行完成,除非超时,则强制关闭。</li> |
| </ul> |
| <p>服务消费方</p> |
| <ul> |
| <li>停止时,不再发起新的调用请求,所有新的调用在客户端即报错。</li> |
| <li>然后,检测有没有请求的响应还没有返回,等待响应返回,除非超时,则强制关闭。</li> |
| </ul> |
| <h2 id="设置方式">设置方式</h2> |
| <p>设置优雅停机超时时间,缺省超时时间是 10 秒,如果超时则强制关闭。</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><span style="color:#586e75"># dubbo.properties</span> |
| </span></span><span style="display:flex;"><span>dubbo.service.shutdown.wait<span style="color:#719e07">=</span><span style="color:#2aa198">15000</span> |
| </span></span></code></pre></div><p>如果 ShutdownHook 不能生效,可以自行调用:</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>DubboShutdownHook.destroyAll(); |
| </span></span></code></pre></div> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">建议</h4> |
| 使用 tomcat 等容器部署的场景,建议通过扩展 ContextListener 等自行调用以下代码实现优雅停机 |
| </div></description></item><item><title>Docs: 主机绑定</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/hostname-binding/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/hostname-binding/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/others/set-host/">最新版本</a>。</p> |
| </div> |
| <h2 id="查找顺序">查找顺序</h2> |
| <p>缺省主机 IP 查找顺序:</p> |
| <ul> |
| <li>通过 <code>LocalHost.getLocalHost()</code> 获取本机地址。</li> |
| <li>如果是 <code>127.*</code> 等 loopback 地址,则扫描各网卡,获取网卡 IP。</li> |
| </ul> |
| <h2 id="主机配置">主机配置</h2> |
| <p>注册的地址如果获取不正确,比如需要注册公网地址,可以:</p> |
| <ol> |
| <li> |
| <p>可以在 <code>/etc/hosts</code> 中加入:机器名 公网 IP,比如:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>test1 205.182.23.201 |
| </span></span></code></pre></div></li> |
| <li> |
| <p>在 <code>dubbo.xml</code> 中加入主机地址的配置:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:protocol</span> host=<span style="color:#2aa198">&#34;205.182.23.201&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span></code></pre></div></li> |
| <li> |
| <p>或在 <code>dubbo.properties</code> 中加入主机地址的配置:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-properties" data-lang="properties"><span style="display:flex;"><span>dubbo.protocol.host<span style="color:#719e07">=</span><span style="color:#2aa198">205.182.23.201</span> |
| </span></span></code></pre></div></li> |
| </ol> |
| <h2 id="端口配置">端口配置</h2> |
| <p>缺省主机端口与协议相关:</p> |
| <table> |
| <thead> |
| <tr> |
| <th>协议</th> |
| <th>端口</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>dubbo</td> |
| <td>20880</td> |
| </tr> |
| <tr> |
| <td>rmi</td> |
| <td>1099</td> |
| </tr> |
| <tr> |
| <td>http</td> |
| <td>80</td> |
| </tr> |
| <tr> |
| <td>hessian</td> |
| <td>80</td> |
| </tr> |
| <tr> |
| <td>webservice</td> |
| <td>80</td> |
| </tr> |
| <tr> |
| <td>memcached</td> |
| <td>11211</td> |
| </tr> |
| <tr> |
| <td>redis</td> |
| <td>6379</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>可以按照下面的方式配置端口:</p> |
| <ol> |
| <li> |
| <p>在 <code>dubbo.xml</code> 中加入主机地址的配置:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> port=<span style="color:#2aa198">&#34;20880&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span></code></pre></div></li> |
| <li> |
| <p>或在 <code>dubbo.properties</code> 中加入主机地址的配置:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-properties" data-lang="properties"><span style="display:flex;"><span>dubbo.protocol.dubbo.port<span style="color:#719e07">=</span><span style="color:#2aa198">20880</span> |
| </span></span></code></pre></div></li> |
| </ol></description></item><item><title>Docs: 主机配置</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/set-host/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/set-host/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/others/set-host/">最新版本</a>。</p> |
| </div> |
| <h2 id="背景">背景</h2> |
| <p>在 Dubbo 中, Provider 启动时主要做两个事情,一是启动 server,二是向注册中心注册服务。启动 server 时需要绑定 socket,向注册中心注册服务时也需要发送 socket 唯一标识服务地址。</p> |
| <ol> |
| <li><code>dubbo</code>中不设置<code>host</code>时默认<code>host</code>是什么?</li> |
| <li>那在<code>dubbo</code>中如何指定服务的<code>host</code>,我们是否可以用hostname或domain代替IP地址作为<code>host</code>?</li> |
| <li>在使用docker时,有时需要设置端口映射,此时,启动server时绑定的socket和向注册中心注册的socket使用不同的端口号,此时又该如何设置?</li> |
| </ol> |
| <h4 id="dubbo-中不设置-host-时默认-host-是什么">dubbo 中不设置 host 时默认 host 是什么</h4> |
| <p>一般的 dubbo 协议配置如下:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span> ... |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> port=<span style="color:#2aa198">&#34;20890&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> ... |
| </span></span></code></pre></div><p>可以看到,只配置了端口号,没有配置 host,此时设置的 host 又是什么呢?</p> |
| <p>查看代码发现,在 <code>org.apache.dubbo.config.ServiceConfig#findConfigedHosts()</code> 中,通过 <code>InetAddress.getLocalHost().getHostAddress()</code> 获取默认 host。其返回值如下:</p> |
| <ol> |
| <li>未联网时,返回 127.0.0.1</li> |
| <li>在阿里云服务器中,返回私有地址,如: 172.18.46.234</li> |
| <li>在本机测试时,返回公有地址,如: 30.5.10.11</li> |
| </ol> |
| <h4 id="那在-dubbo-中如何指定服务的-socket">那在 dubbo 中如何指定服务的 socket?</h4> |
| <p>除此之外,可以通过 <code>dubbo.protocol</code> 或 <code>dubbo.provider </code>的 <code>host</code> 属性对 <code>host</code> 进行配置,支持IP地址和域名,如下:</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></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> port=<span style="color:#2aa198">&#34;20890&#34;</span> host=<span style="color:#2aa198">&#34;www.example.com&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> ... |
| </span></span></code></pre></div><h4 id="在使用-docker-时有时需要设置端口映射此时启动-server-时绑定的-socket-和向注册中心注册的-socket-使用不同的端口号此时又该如何设置">在使用 docker 时,有时需要设置端口映射,此时,启动 server 时绑定的 socket 和向注册中心注册的 socket 使用不同的端口号,此时又该如何设置?</h4> |
| <p>见 <a href="https://github.com/dubbo/dubbo-samples/tree/master/2-advanced/dubbo-samples-docker">dubbo 通过环境变量设置 host</a></p> |
| <p>有些部署场景需要动态指定服务注册的地址,如 docker bridge 网络模式下要指定注册宿主机 ip 以实现外网通信。dubbo 提供了两对启动阶段的系统属性,用于设置对外通信的ip、port地址。</p> |
| <ul> |
| <li><strong>DUBBO_IP_TO_REGISTRY</strong>:注册到注册中心的 ip 地址</li> |
| <li><strong>DUBBO_PORT_TO_REGISTRY</strong>:注册到注册中心的 port 端口</li> |
| <li><strong>DUBBO_IP_TO_BIND</strong>:监听 ip 地址</li> |
| <li><strong>DUBBO_PORT_TO_BIND</strong>:监听 port 端口</li> |
| </ul> |
| <p>以上四个配置项均为可选项,如不配置 dubbo 会自动获取 ip 与端口,请根据具体的部署场景灵活选择配置。 |
| dubbo 支持多协议,如果一个应用同时暴露多个不同协议服务,且需要为每个服务单独指定 ip 或 port,请分别在以上属性前加协议前缀。 如:</p> |
| <ul> |
| <li><strong>HESSIAN_DUBBO_PORT_TO_BIND</strong>:hessian 协议绑定的 port</li> |
| <li><strong>DUBBO_DUBBO_PORT_TO_BIND</strong>:dubbo 协议绑定的 port</li> |
| <li><strong>HESSIAN_DUBBO_IP_TO_REGISTRY</strong>:hessian 协议注册的 ip</li> |
| <li><strong>DUBBO_DUBBO_IP_TO_REGISTRY</strong>:dubbo 协议注册的 ip</li> |
| </ul> |
| <p>PORT_TO_REGISTRY 或 IP_TO_REGISTRY 不会用作默认 PORT_TO_BIND 或 IP_TO_BIND,但是反过来是成立的。如:</p> |
| <ul> |
| <li>设置 <code>PORT_TO_REGISTRY=20881</code> 和 <code>IP_TO_REGISTRY=30.5.97.6</code>,则 <code>PORT_TO_BIND</code> 和 <code>IP_TO_BIND</code> 不受影响</li> |
| <li>设置 <code>PORT_TO_BIND=20881</code> 和 <code>IP_TO_BIND=30.5.97.6</code>,则默认 <code>PORT_TO_REGISTRY=20881</code> 且 <code>IP_TO_REGISTRY=30.5.97.6</code></li> |
| </ul> |
| <h2 id="总结">总结</h2> |
| <ol> |
| <li>可以通过<code>dubbo.protocol</code>或<code>dubbo.provider</code>的<code>host</code>属性对<code>host</code>进行配置,支持IP地址和域名.但此时注册到注册中心的IP地址和监听IP地址是同一个值</li> |
| <li>为了解决在虚拟环境或局域网内consumer无法与provider通信的问题,可以通过环境变量分别设置注册到注册中心的IP地址和监听IP地址,其优先级高于<code>dubbo.protocol</code>或<code>dubbo.provider</code>的<code>host</code>配置</li> |
| </ol> |
| <h2 id="参考">参考</h2> |
| <ol> |
| <li><a href="https://github.com/apache/dubbo/issues/2043">Proposal: support hostname or domain in service discovery.</a></li> |
| <li><a href="https://github.com/dubbo/dubbo-samples/tree/master/2-advanced/dubbo-samples-docker">dubbo通过环境变量设置host</a></li> |
| </ol></description></item><item><title>Docs: 注册信息简化</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/simplify-registry-data/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/simplify-registry-data/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/simplify-registry-data/">最新版本</a>。</p> |
| </div> |
| <h2 id="背景">背景</h2> |
| <p>Dubbo provider 中的服务配置项有接近 <a href="https://dubbo.apache.org/zh-cn/docsv2.7/user/references/xml/dubbo-service/">30 个配置项</a>。 排除注册中心服务治理需要之外,很大一部分配置项是 provider 自己使用,不需要透传给消费者。这部分数据不需要进入注册中心,而只需要以 key-value 形式持久化存储。</p> |
| <p>Dubbo consumer 中的配置项也有 <a href="https://dubbo.apache.org/zh-cn/docsv2.7/user/references/xml/dubbo-reference/">20+个配置项</a>。在注册中心之中,服务消费者列表中只需要关注 application,version,group,ip,dubbo 版本等少量配置,其他配置也可以以 key-value 形式持久化存储。</p> |
| <p>这些数据是以服务为维度注册进入注册中心,导致了数据量的膨胀,进而引发注册中心(如 zookeeper)的网络开销增大,性能降低。</p> |
| <h2 id="现有功能-sample">现有功能 sample</h2> |
| <p>当前现状一个简单展示。通过这个展示,分析下为什么需要做简化配置。</p> |
| <p>参考 sample 子工程: dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-nosimple (跑 sample 前,先跑下 ZKClean 进行配置项清理)</p> |
| <p>dubbo-provider.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-fallback" data-lang="fallback"><span style="display:flex;"><span>&lt;dubbo:application name=&#34;simplified-registry-nosimple-provider&#34;/&gt; |
| </span></span><span style="display:flex;"><span>&lt;dubbo:registry address=&#34;zookeeper://127.0.0.1:2181&#34;/&gt; |
| </span></span><span style="display:flex;"><span>&lt;bean id=&#34;demoService&#34; class=&#34;org.apache.dubbo.samples.simplified.registry.nosimple.impl.DemoServiceImpl&#34;/&gt; |
| </span></span><span style="display:flex;"><span>&lt;dubbo:service async=&#34;true&#34; interface=&#34;org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService&#34; |
| </span></span><span style="display:flex;"><span> version=&#34;1.2.3&#34; group=&#34;dubbo-simple&#34; ref=&#34;demoService&#34; |
| </span></span><span style="display:flex;"><span> executes=&#34;4500&#34; retries=&#34;7&#34; owner=&#34;vict&#34; timeout=&#34;5300&#34;/&gt; |
| </span></span></code></pre></div><p>启动 provider 的 main 方法之后,查看 zookeeper 的叶子节点(路径为:/dubbo/org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService/providers 目录下)的内容如下:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>dubbo%3A%2F%2F30.5.124.158%3A20880%2Forg.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService |
| </span></span><span style="display:flex;"><span>%3Fanyhost%3Dtrue%26application%3Dsimplified-registry-xml-provider%26async%3Dtrue%26dubbo%3D |
| </span></span><span style="display:flex;"><span>2.0.2%26**executes**%3D4500%26generic%3Dfalse%26group%3Ddubbo-simple%26interface%3D |
| </span></span><span style="display:flex;"><span>org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService%26methods%3D |
| </span></span><span style="display:flex;"><span>sayHello%26**owner**%3Dvict%26pid%3D2767%26**retries**%3D7%26revision%3D1.2.3%26side%3D |
| </span></span><span style="display:flex;"><span>provider%26**timeout**%3D5300%26timestamp%3D1542361152795%26valid%3Dtrue%26version%3D1.2.3 |
| </span></span></code></pre></div><p>从加粗字体中能看到有:executes, retries, owner, timeout。但是这些字段不是每个都需要传递给 dubbo ops 或者 dubbo consumer。 同样的,consumer 也有这个问题,可以在例子中启动 Consumer 的 main 方法进行查看。</p> |
| <h2 id="设计目标和宗旨">设计目标和宗旨</h2> |
| <p>期望简化进入注册中心的 provider 和 consumer 配置数量。 |
| 期望将部分配置项以其他形式存储。这些配置项需要满足:不在服务调用链路上,同时这些配置项不在注册中心的核心链路上(服务查询,服务列表)。</p> |
| <h2 id="配置">配置</h2> |
| <p>简化注册中心的配置,只在 2.7 之后的版本中进行支持。 |
| 开启 provider 或者 consumer 简化配置之后,默认保留的配置项如下:</p> |
| <p>provider:</p> |
| <table> |
| <thead> |
| <tr> |
| <th>Constant Key</th> |
| <th>Key</th> |
| <th>remark</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>APPLICATION_KEY</td> |
| <td>application</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>CODEC_KEY</td> |
| <td>codec</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>EXCHANGER_KEY</td> |
| <td>exchanger</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>SERIALIZATION_KEY</td> |
| <td>serialization</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>CLUSTER_KEY</td> |
| <td>cluster</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>CONNECTIONS_KEY</td> |
| <td>connections</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>DEPRECATED_KEY</td> |
| <td>deprecated</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>GROUP_KEY</td> |
| <td>group</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>LOADBALANCE_KEY</td> |
| <td>loadbalance</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>MOCK_KEY</td> |
| <td>mock</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>PATH_KEY</td> |
| <td>path</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>TIMEOUT_KEY</td> |
| <td>timeout</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>TOKEN_KEY</td> |
| <td>token</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>VERSION_KEY</td> |
| <td>version</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>WARMUP_KEY</td> |
| <td>warmup</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>WEIGHT_KEY</td> |
| <td>weight</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>TIMESTAMP_KEY</td> |
| <td>timestamp</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>DUBBO_VERSION_KEY</td> |
| <td>dubbo</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>SPECIFICATION_VERSION_KEY</td> |
| <td><strong>specVersion</strong></td> |
| <td>新增,用于表述dubbo版本,如2.7.0</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>consumer:</p> |
| <table> |
| <thead> |
| <tr> |
| <th>Constant Key</th> |
| <th>Key</th> |
| <th>remark</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>APPLICATION_KEY</td> |
| <td>application</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>VERSION_KEY</td> |
| <td>version</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>GROUP_KEY</td> |
| <td>group</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>DUBBO_VERSION_KEY</td> |
| <td>dubbo</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>SPECIFICATION_VERSION_KEY</td> |
| <td><strong>specVersion</strong></td> |
| <td>新增,用于表述dubbo版本,如2.7.0</td> |
| </tr> |
| </tbody> |
| </table> |
| <p>Constant Key 表示来自于类 org.apache.dubbo.common.Constants 的字段。</p> |
| <p>下面介绍几种常用的使用方式。所有的 sample,都可以查看<a href="https://github.com/dubbo/dubbo-samples/tree/master">sample-2.7</a></p> |
| <h3 id="方式1-配置dubboproperties">方式1. 配置dubbo.properties</h3> |
| <p>sample 在 dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-xml 工程下 (跑 sample 前,先跑下ZKClean 进行配置项清理)</p> |
| <p>dubbo.properties</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> |
| </span></span><span style="display:flex;"><span>dubbo.registry.simplified<span style="color:#719e07">=</span><span style="color:#2aa198">true</span> |
| </span></span><span style="display:flex;"><span>dubbo.registry.extra-keys<span style="color:#719e07">=</span><span style="color:#2aa198">retries,owner</span> |
| </span></span></code></pre></div><p>怎么去验证呢?</p> |
| <h5 id="provider端验证">provider端验证</h5> |
| <p>provider端配置</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd |
| </span></span></span><span style="display:flex;"><span><span style="color:#2aa198"> http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- optional --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;simplified-registry-xml-provider&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> address=<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;bean</span> id=<span style="color:#2aa198">&#34;demoService&#34;</span> class=<span style="color:#2aa198">&#34;org.apache.dubbo.samples.simplified.registry.nosimple.impl.DemoServiceImpl&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:service</span> async=<span style="color:#2aa198">&#34;true&#34;</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService&#34;</span> version=<span style="color:#2aa198">&#34;1.2.3&#34;</span> group=<span style="color:#2aa198">&#34;dubbo-simple&#34;</span> |
| </span></span><span style="display:flex;"><span> ref=<span style="color:#2aa198">&#34;demoService&#34;</span> executes=<span style="color:#2aa198">&#34;4500&#34;</span> retries=<span style="color:#2aa198">&#34;7&#34;</span> owner=<span style="color:#2aa198">&#34;vict&#34;</span> timeout=<span style="color:#2aa198">&#34;5300&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&gt;</span> |
| </span></span></code></pre></div><p>得到的 zookeeper 的叶子节点的值如下:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>dubbo%3A%2F%2F30.5.124.149%3A20880%2Forg.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService%3F |
| </span></span><span style="display:flex;"><span>application%3Dsimplified-registry-xml-provider%26dubbo%3D2.0.2%26group%3Ddubbo-simple%26**owner**%3D |
| </span></span><span style="display:flex;"><span>vict%26**retries**%3D7%26**timeout**%3D5300%26timestamp%3D1542594503305%26version%3D1.2.3 |
| </span></span></code></pre></div><p>和上面的<strong>现有功能 sample</strong>进行对比,上面的 sample 中,executes, retries, owner, timeout 四个配置项都进入了注册中心。但是本实例不是:</p> |
| <ul> |
| <li>配置了:dubbo.registry.simplified=true, 默认情况下,timeout 在默认的配置项列表,所以还是会进入注册中心;</li> |
| <li>配置了:dubbo.registry.extra-keys=retries,owner , 所以 retries,owner 也会进入注册中心。</li> |
| </ul> |
| <p>总结:timeout,retries,owner 进入了注册中心,而 executes 没有进入。</p> |
| <p>consumer 端配置</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;beans</span> xmlns:xsi=<span style="color:#2aa198">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns:dubbo=<span style="color:#2aa198">&#34;http://dubbo.apache.org/schema/dubbo&#34;</span> |
| </span></span><span style="display:flex;"><span> xmlns=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans&#34;</span> |
| </span></span><span style="display:flex;"><span> xsi:schemaLocation=<span style="color:#2aa198">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd |
| </span></span></span><span style="display:flex;"><span><span style="color:#2aa198"> http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd&#34;</span><span style="color:#268bd2">&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">&lt;!-- optional --&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;simplified-registry-xml-consumer&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:registry</span> address=<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span> username=<span style="color:#2aa198">&#34;xxx&#34;</span> password=<span style="color:#2aa198">&#34;yyy&#34;</span> check=<span style="color:#2aa198">&#34;true&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:reference</span> id=<span style="color:#2aa198">&#34;demoService&#34;</span> interface=<span style="color:#2aa198">&#34;org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService&#34;</span> |
| </span></span><span style="display:flex;"><span> owner=<span style="color:#2aa198">&#34;vvv&#34;</span> retries=<span style="color:#2aa198">&#34;4&#34;</span> actives=<span style="color:#2aa198">&#34;6&#34;</span> timeout=<span style="color:#2aa198">&#34;4500&#34;</span> version=<span style="color:#2aa198">&#34;1.2.3&#34;</span> group=<span style="color:#2aa198">&#34;dubbo-simple&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/beans&gt;</span> |
| </span></span></code></pre></div><p>得到的 zookeeper 的叶子节点的值如下:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>consumer%3A%2F%2F30.5.124.149%2Forg.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService%3F |
| </span></span><span style="display:flex;"><span>actives%3D6%26application%3Dsimplified-registry-xml-consumer%26category%3D |
| </span></span><span style="display:flex;"><span>consumers%26check%3Dfalse%26dubbo%3D2.0.2%26group%3Ddubbo-simple%26owner%3Dvvv%26version%3D1.2.3 |
| </span></span></code></pre></div><ul> |
| <li>配置了:dubbo.registry.simplified=true , 默认情况下,application,version,group,dubbo 在默认的配置项列表,所以还是会进入注册中心;</li> |
| </ul> |
| <h3 id="方式2-声明spring-bean">方式2. 声明spring bean</h3> |
| <p>sample在dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-annotation 工程下 (跑 sample 前,先跑下ZKClean 进行配置项清理)</p> |
| <h5 id="provider配置">Provider配置</h5> |
| <p>privide 端 bean 配置:</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">// 等同于dubbo.properties配置,用@Bean形式进行配置</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">@Bean</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> RegistryConfig <span style="color:#268bd2">registryConfig</span>() { |
| </span></span><span style="display:flex;"><span> RegistryConfig registryConfig <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> RegistryConfig(); |
| </span></span><span style="display:flex;"><span> registryConfig.setAddress(<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span>); |
| </span></span><span style="display:flex;"><span> registryConfig.setSimplified(<span style="color:#cb4b16">true</span>); |
| </span></span><span style="display:flex;"><span> registryConfig.setExtraKeys(<span style="color:#2aa198">&#34;retries,owner&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> registryConfig; |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><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:#268bd2">@Service</span>(version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.1.8&#34;</span>, group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;d-test&#34;</span>, executes <span style="color:#719e07">=</span> 4500, retries <span style="color:#719e07">=</span> 7, owner <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;victanno&#34;</span>, timeout <span style="color:#719e07">=</span> 5300) |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">AnnotationServiceImpl</span> <span style="color:#268bd2">implements</span> AnnotationService { |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span>(String name) { |
| </span></span><span style="display:flex;"><span> System.out.println(<span style="color:#2aa198">&#34;async provider received: &#34;</span> <span style="color:#719e07">+</span> name); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;annotation: hello, &#34;</span> <span style="color:#719e07">+</span> name; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>和上面 sample 中的 dubbo.properties 的效果是一致的。结果如下:</p> |
| <ul> |
| <li>默认情况下,timeout 在默认的配置项列表,所以还是会进入注册中心;</li> |
| <li>配置了 retries,owner 作为额外的 key 进入注册中心 , 所以 retries,owner 也会进入注册中心。</li> |
| </ul> |
| <p>总结:timeout,retries,owner 进入了注册中心,而 executes 没有进入。</p> |
| <h5 id="consumer配置">Consumer配置</h5> |
| <p>consumer 端 bean 配置:</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">@Bean</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> RegistryConfig <span style="color:#268bd2">registryConfig</span>() { |
| </span></span><span style="display:flex;"><span> RegistryConfig registryConfig <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> RegistryConfig(); |
| </span></span><span style="display:flex;"><span> registryConfig.setAddress(<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span>); |
| </span></span><span style="display:flex;"><span> registryConfig.setSimplified(<span style="color:#cb4b16">true</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> registryConfig; |
| </span></span><span style="display:flex;"><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">@Component</span>(<span style="color:#2aa198">&#34;annotationAction&#34;</span>) |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">AnnotationAction</span> { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Reference</span>(version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.1.8&#34;</span>, group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;d-test&#34;</span>, owner <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;vvvanno&#34;</span>, retries <span style="color:#719e07">=</span> 4, actives <span style="color:#719e07">=</span> 6, timeout <span style="color:#719e07">=</span> 4500) |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> AnnotationService annotationService; |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">doSayHello</span>(String name) { |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> annotationService.sayHello(name); |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><p>和上面 sample 中 consumer 端的配置是一样的。结果如下:</p> |
| <ul> |
| <li>默认情况下,application,version,group,dubbo 在默认的配置项列表,所以还是会进入注册中心。</li> |
| </ul> |
| <h6 id="注意">注意:</h6> |
| <p>如果一个应用中既有provider又有consumer,那么配置需要合并成:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Bean</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> RegistryConfig <span style="color:#268bd2">registryConfig</span>() { |
| </span></span><span style="display:flex;"><span> RegistryConfig registryConfig <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> RegistryConfig(); |
| </span></span><span style="display:flex;"><span> registryConfig.setAddress(<span style="color:#2aa198">&#34;zookeeper://127.0.0.1:2181&#34;</span>); |
| </span></span><span style="display:flex;"><span> registryConfig.setSimplified(<span style="color:#cb4b16">true</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">//只对provider生效</span> |
| </span></span><span style="display:flex;"><span> registryConfig.setExtraKeys(<span style="color:#2aa198">&#34;retries,owner&#34;</span>); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> registryConfig; |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><h2 id="后续规划">后续规划</h2> |
| <p>本版本还保留了大量的配置项,接下来的版本中,会逐渐删除所有的配置项。</p></description></item><item><title>Docs: 日志适配</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/logger-strategy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/logger-strategy/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/others/logger-management/">最新版本</a>。</p> |
| </div> |
| <p>自 <code>2.2.1</code> 开始,dubbo 开始内置 log4j、slf4j、jcl、jdk 这些日志框架的适配[1],也可以通过以下方式显式配置日志输出策略:</p> |
| <ol start="0"> |
| <li> |
| <p>命令行</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span> java -Ddubbo.application.logger<span style="color:#719e07">=</span>log4j |
| </span></span></code></pre></div></li> |
| <li> |
| <p>在 <code>dubbo.properties</code> 中指定</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span> dubbo.application.logger=log4j |
| </span></span></code></pre></div></li> |
| <li> |
| <p>在 <code>dubbo.xml</code> 中配置</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dubbo:application</span> logger=<span style="color:#2aa198">&#34;log4j&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></li> |
| </ol> |
| <p>[1]: 自定义扩展可以参考 <a href="../../../docsv2.7/dev/impls/logger-adapter/">日志适配扩展</a></p></description></item><item><title>Docs: 访问日志</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/accesslog/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/accesslog/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/accesslog/">最新版本</a>。</p> |
| </div> |
| <p>如果你想记录每一次请求信息,可开启访问日志,类似于apache的访问日志。<strong>注意</strong>:此日志量比较大,请注意磁盘容量。</p> |
| <p>将访问日志输出到当前应用的log4j日志:</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:protocol</span> accesslog=<span style="color:#2aa198">&#34;true&#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:protocol</span> accesslog=<span style="color:#2aa198">&#34;http://10.20.160.198/wiki/display/dubbo/foo/bar.log&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Docs: 服务容器</title><link>https://dubbo.apache.org/zh-cn/docs/advanced/service-container/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/docs/advanced/service-container/</guid><description> |
| <div class="pageinfo pageinfo-primary"> |
| <p>此文档已经不再维护。您当前查看的是快照版本。如果想要查看最新版本的文档,请参阅<a href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/others/service-container/">最新版本</a>。</p> |
| </div> |
| <p>服务容器是一个 standalone 的启动程序,因为后台服务不需要 Tomcat 或 JBoss 等 Web 容器的功能,如果硬要用 Web 容器去加载服务提供方,增加复杂性,也浪费资源。</p> |
| <p>服务容器只是一个简单的 Main 方法,并加载一个简单的 Spring 容器,用于暴露服务。</p> |
| <p>服务容器的加载内容可以扩展,内置了 spring, jetty, log4j 等加载,可通过<a href="../../references/spis/container">容器扩展点</a>进行扩展。配置配在 java 命令的 -D 参数或者 <code>dubbo.properties</code> 中。</p> |
| <h2 id="容器类型">容器类型</h2> |
| <h3 id="spring-container">Spring Container</h3> |
| <ul> |
| <li> |
| <p>自动加载 <code>META-INF/spring</code> 目录下的所有 Spring 配置。</p> |
| </li> |
| <li> |
| <p>配置 spring 配置加载位置:</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.spring.config<span style="color:#719e07">=</span><span style="color:#2aa198">classpath*:META-INF/spring/*.xml</span> |
| </span></span></code></pre></div></li> |
| </ul> |
| <h3 id="jetty-container">Jetty Container</h3> |
| <ul> |
| <li>启动一个内嵌 Jetty,用于汇报状态。</li> |
| <li>配置: |
| <ul> |
| <li><code>dubbo.jetty.port=8080</code>:配置 jetty 启动端口</li> |
| <li><code>dubbo.jetty.directory=/foo/bar</code>:配置可通过 jetty 直接访问的目录,用于存放静态文件</li> |
| <li><code>dubbo.jetty.page=log,status,system</code>:配置显示的页面,缺省加载所有页面</li> |
| </ul> |
| </li> |
| </ul> |
| <h3 id="log4j-container">Log4j Container</h3> |
| <ul> |
| <li>自动配置 log4j 的配置,在多进程启动时,自动给日志文件按进程分目录。</li> |
| <li>配置: |
| <ul> |
| <li><code>dubbo.log4j.file=/foo/bar.log</code>:配置日志文件路径</li> |
| <li><code>dubbo.log4j.level=WARN</code>:配置日志级别</li> |
| <li><code>dubbo.log4j.subdirectory=20880</code>:配置日志子目录,用于多进程启动,避免冲突</li> |
| </ul> |
| </li> |
| </ul> |
| <h2 id="容器启动">容器启动</h2> |
| <p>缺省只加载 spring</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>java org.apache.dubbo.container.Main |
| </span></span></code></pre></div><p>通过 main 函数参数传入要加载的容器</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>java org.apache.dubbo.container.Main spring jetty log4j |
| </span></span></code></pre></div><p>通过 JVM 启动参数传入要加载的容器</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>java org.apache.dubbo.container.Main -Ddubbo.container<span style="color:#719e07">=</span>spring,jetty,log4j |
| </span></span></code></pre></div><p>通过 classpath 下的 <code>dubbo.properties</code> 配置传入要加载的容器</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>dubbo.container=spring,jetty,log4j |
| </span></span></code></pre></div></description></item></channel></rss> |