| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – 诊断与调优</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/</link><description>Recent content in 诊断与调优 on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview: 请求耗时采样</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/profiler/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/profiler/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>性能采样功能可以对 Dubbo 处理链路上的各处耗时进行检测,在出现超时的时候 <code>( usageTime / timeout &gt; profilerWarnPercent * 100 )</code> 通过日志记录调用的耗时。</p> |
| <p>此功能分为 <code>simple profiler</code> 和 <code>detail profiler</code> 两个模式,其中 <code>simple profiler</code> 模式默认开启,<code>detail profiler</code> 模式默认关闭。 |
| <code>detail profiler</code> 相较 <code>simple profiler</code> 模式多采集了每个 filter 的处理耗时、协议上的具体耗时等。 |
| 在 <code>simple profiler</code> 模式下如果发现 Dubbo 框架内部存在耗时长的情况,可以开启 <code>detail profiler</code> 模式,以便更好地排查问题。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>需要对 Dubbo 请求的精确耗时进行采集分析的场景,如服务不明原因的超时等</p> |
| <h2 id="使用方式">使用方式</h2> |
| <p><code>simple profiler</code> 默认自动开启,对于请求处理时间超过超时时间 3/4 的,都会通过日志打印出慢调用信息。如果需要开启 <code>detail profiler</code> 模式或者修改超时告警比例,可以参考<a href="../../../reference-manual/qos/profiler/">性能采样命令</a>文档。</p> |
| <h3 id="日志说明">日志说明</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-fallback" data-lang="fallback"><span style="display:flex;"><span>[Dubbo-Consumer] execute service 接口#方法 cost 实际耗时, this invocation almost (maybe already) timeout. Timeout: 超时时间 |
| </span></span><span style="display:flex;"><span>invocation context: |
| </span></span><span style="display:flex;"><span>请求上下文 |
| </span></span><span style="display:flex;"><span>thread info: |
| </span></span><span style="display:flex;"><span>Start time: 开始请求时间(nano 时间) |
| </span></span><span style="display:flex;"><span>+-[ Offset: 当前节点开始时间; Usage: 当前节点使用总耗时, 当前节点耗时比例 ] 当前节点描述 |
| </span></span><span style="display:flex;"><span> +-[ Offset: 当前节点开始时间; Usage: 当前节点使用总耗时, 当前节点耗时比例 ] 当前节点描述 |
| </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-fallback" data-lang="fallback"><span style="display:flex;"><span>methodA() { |
| </span></span><span style="display:flex;"><span> do something (1) |
| </span></span><span style="display:flex;"><span> methodB (2) |
| </span></span><span style="display:flex;"><span> do something (3) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>methodB() { |
| </span></span><span style="display:flex;"><span> do something (4) |
| </span></span><span style="display:flex;"><span> methodC (5) |
| </span></span><span style="display:flex;"><span> do something (6) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>methodC() { |
| </span></span><span style="display:flex;"><span> do something (7) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>+-[ Offset: 0 ms; Usage: (1) + (2) + (3) ms] execute methodA |
| </span></span><span style="display:flex;"><span> +-[ Offset: (1) ms; Usage: (4) + (5) + (6) = (2) ms ] execute methodB |
| </span></span><span style="display:flex;"><span> +-[ Offset: (1) + (4) ms; Usage: (7) = (5) ms ] execute methodC |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>(1) (2) (3) ... 均为时间占位符 |
| </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-fallback" data-lang="fallback"><span style="display:flex;"><span>methodA() { |
| </span></span><span style="display:flex;"><span> do something (1) |
| </span></span><span style="display:flex;"><span> methodB (2) |
| </span></span><span style="display:flex;"><span> methodE (3) |
| </span></span><span style="display:flex;"><span> do something (4) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>methodB() { |
| </span></span><span style="display:flex;"><span> do something (5) |
| </span></span><span style="display:flex;"><span> methodC (6) |
| </span></span><span style="display:flex;"><span> methodD (7) |
| </span></span><span style="display:flex;"><span> do something (8) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>methodC() { |
| </span></span><span style="display:flex;"><span> do something (9) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>methodD() { |
| </span></span><span style="display:flex;"><span> do something (10) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>methodE() { |
| </span></span><span style="display:flex;"><span> do something (11) |
| </span></span><span style="display:flex;"><span>} |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>+-[ Offset: 0 ms; Usage: (1) + (2) + (3) + (4) ms] execute methodA |
| </span></span><span style="display:flex;"><span> +-[ Offset: (1) ms; Usage: (5) + (6) + (7) + (8) = (2) ms ] execute methodB |
| </span></span><span style="display:flex;"><span> +-[ Offset: (1) + (5) ms; Usage: (9) = (6) ms ] execute methodC |
| </span></span><span style="display:flex;"><span> +-[ Offset: (1) + (5) + (6) ms; Usage: (10) = (7) ms ] execute methodD |
| </span></span><span style="display:flex;"><span> +-[ Offset: (1) + (2) ms; Usage: (11) = (3) ms ] execute methodE |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>(1) (2) (3) ... 均为时间占位符 |
| </span></span></code></pre></div><h3 id="simple-profiler">simple profiler</h3> |
| <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-fallback" data-lang="fallback"><span style="display:flex;"><span>[19/07/22 07:08:35:035 CST] main WARN proxy.InvokerInvocationHandler: [DUBBO] [Dubbo-Consumer] execute service org.apache.dubbo.samples.api.GreetingsService#sayHi cost 1003.015746 ms, this invocation almost (maybe already) timeout. Timeout: 1000ms |
| </span></span><span style="display:flex;"><span>invocation context: |
| </span></span><span style="display:flex;"><span>path=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>remote.application=first-dubbo-consumer; |
| </span></span><span style="display:flex;"><span>interface=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>version=0.0.0; |
| </span></span><span style="display:flex;"><span>timeout=1000; |
| </span></span><span style="display:flex;"><span>thread info: |
| </span></span><span style="display:flex;"><span>Start time: 285821581299853 |
| </span></span><span style="display:flex;"><span>+-[ Offset: 0.000000ms; Usage: 1003.015746ms, 100% ] Receive request. Client invoke begin. ServiceKey: org.apache.dubbo.samples.api.GreetingsService MethodName:sayHi |
| </span></span><span style="display:flex;"><span> +-[ Offset: 7.987015ms; Usage: 994.207928ms, 99% ] Invoker invoke. Target Address: xx.xx.xx.xx:20880, dubbo version: 3.0.10-SNAPSHOT, current host: xx.xx.xx.xx |
| </span></span></code></pre></div><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-fallback" data-lang="fallback"><span style="display:flex;"><span>[19/07/22 07:08:35:035 CST] DubboServerHandler-30.227.64.173:20880-thread-2 WARN filter.ProfilerServerFilter: [DUBBO] [Dubbo-Provider] execute service org.apache.dubbo.samples.api.GreetingsService:0.0.0#sayHi cost 808.494672 ms, this invocation almost (maybe already) timeout. Timeout: 1000ms |
| </span></span><span style="display:flex;"><span>client: xx.xx.xx.xx:51604 |
| </span></span><span style="display:flex;"><span>invocation context: |
| </span></span><span style="display:flex;"><span>input=281; |
| </span></span><span style="display:flex;"><span>path=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>remote.application=first-dubbo-consumer; |
| </span></span><span style="display:flex;"><span>dubbo=2.0.2; |
| </span></span><span style="display:flex;"><span>interface=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>version=0.0.0; |
| </span></span><span style="display:flex;"><span>timeout=1000; |
| </span></span><span style="display:flex;"><span>thread info: |
| </span></span><span style="display:flex;"><span>Start time: 285821754461125 |
| </span></span><span style="display:flex;"><span>+-[ Offset: 0.000000ms; Usage: 808.494672ms, 100% ] Receive request. Server invoke begin. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.030912ms; Usage: 804.236342ms, 99% ] Receive request. Server biz impl invoke begin., dubbo version: 3.0.10-SNAPSHOT, current host: xx.xx.xx.xx |
| </span></span></code></pre></div><h3 id="detail-profiler">detail profiler</h3> |
| <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-fallback" data-lang="fallback"><span style="display:flex;"><span>[19/07/22 07:10:59:059 CST] main WARN proxy.InvokerInvocationHandler: [DUBBO] [Dubbo-Consumer] execute service org.apache.dubbo.samples.api.GreetingsService#sayHi cost 990.828336 ms, this invocation almost (maybe already) timeout. Timeout: 1000ms |
| </span></span><span style="display:flex;"><span>invocation context: |
| </span></span><span style="display:flex;"><span>path=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>remote.application=first-dubbo-consumer; |
| </span></span><span style="display:flex;"><span>interface=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>version=0.0.0; |
| </span></span><span style="display:flex;"><span>timeout=1000; |
| </span></span><span style="display:flex;"><span>thread info: |
| </span></span><span style="display:flex;"><span>Start time: 285965458479241 |
| </span></span><span style="display:flex;"><span>+-[ Offset: 0.000000ms; Usage: 990.828336ms, 100% ] Receive request. Client invoke begin. ServiceKey: org.apache.dubbo.samples.api.GreetingsService MethodName:sayHi |
| </span></span><span style="display:flex;"><span> +-[ Offset: 0.852044ms; Usage: 989.899439ms, 99% ] Filter org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.814858ms; Usage: 988.924876ms, 99% ] Filter org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.853211ms; Usage: 988.877928ms, 99% ] Filter org.apache.dubbo.monitor.support.MonitorClusterFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.873243ms; Usage: 988.661708ms, 99% ] Filter org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 2.159140ms; Usage: 0.504939ms, 0% ] Router route. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 8.125823ms; Usage: 981.748366ms, 99% ] Cluster org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 8.258359ms; Usage: 981.612033ms, 99% ] Invoker invoke. Target Address: xx.xx.xx.xx:20880, dubbo version: 3.0.10-SNAPSHOT, current host: xx.xx.xx.xx |
| </span></span></code></pre></div><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-fallback" data-lang="fallback"><span style="display:flex;"><span>[19/07/22 07:10:59:059 CST] DubboServerHandler-30.227.64.173:20880-thread-2 WARN filter.ProfilerServerFilter: [DUBBO] [Dubbo-Provider] execute service org.apache.dubbo.samples.api.GreetingsService:0.0.0#sayHi cost 811.017347 ms, this invocation almost (maybe already) timeout. Timeout: 1000ms |
| </span></span><span style="display:flex;"><span>client: xx.xx.xx.xx:52019 |
| </span></span><span style="display:flex;"><span>invocation context: |
| </span></span><span style="display:flex;"><span>input=281; |
| </span></span><span style="display:flex;"><span>path=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>remote.application=first-dubbo-consumer; |
| </span></span><span style="display:flex;"><span>dubbo=2.0.2; |
| </span></span><span style="display:flex;"><span>interface=org.apache.dubbo.samples.api.GreetingsService; |
| </span></span><span style="display:flex;"><span>version=0.0.0; |
| </span></span><span style="display:flex;"><span>timeout=1000; |
| </span></span><span style="display:flex;"><span>thread info: |
| </span></span><span style="display:flex;"><span>Start time: 285965612316294 |
| </span></span><span style="display:flex;"><span>+-[ Offset: 0.000000ms; Usage: 811.017347ms, 100% ] Receive request. Server invoke begin. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.096880ms; Usage: 809.916668ms, 99% ] Filter org.apache.dubbo.rpc.filter.EchoFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.133478ms; Usage: 809.866204ms, 99% ] Filter org.apache.dubbo.rpc.filter.ClassLoaderFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.157563ms; Usage: 809.838572ms, 99% ] Filter org.apache.dubbo.rpc.filter.GenericFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.202075ms; Usage: 809.736843ms, 99% ] Filter org.apache.dubbo.rpc.filter.ContextFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.433193ms; Usage: 809.504401ms, 99% ] Filter org.apache.dubbo.auth.filter.ProviderAuthFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.470760ms; Usage: 809.464291ms, 99% ] Filter org.apache.dubbo.rpc.filter.ExceptionFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.489103ms; Usage: 809.440183ms, 99% ] Filter org.apache.dubbo.monitor.support.MonitorFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.515757ms; Usage: 809.381893ms, 99% ] Filter org.apache.dubbo.rpc.filter.TimeoutFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.526632ms; Usage: 809.366553ms, 99% ] Filter org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.536964ms; Usage: 809.335907ms, 99% ] Filter org.apache.dubbo.rpc.filter.ClassLoaderCallbackFilter invoke. |
| </span></span><span style="display:flex;"><span> +-[ Offset: 1.558545ms; Usage: 804.276436ms, 99% ] Receive request. Server biz impl invoke begin., dubbo version: 3.0.10-SNAPSHOT, current host: xx.xx.xx.xx |
| </span></span></code></pre></div> |
| <div class="alert alert-warning" role="alert"> |
| <h4 class="alert-heading">注意</h4> |
| 由于日志框架不匹配导致的日志为空可以参考<a href="../../others/logger-management/">日志框架适配及运行时管理</a>动态修改日志输出框架。 |
| </div></description></item><item><title>Overview: 线程模型</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/threading-model/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/threading-model/</guid><description/></item><item><title>Overview: 服务引用配置对象缓存</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/reference-config-cache/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/reference-config-cache/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p><code>ReferenceConfig</code> 实例很重,封装了与注册中心的连接以及与提供者的连接,需要缓存。否则重复生成 <code>ReferenceConfig</code> 可能造成性能问题并且会有内存和连接泄漏。在 API 方式编程时,容易忽略此问题。</p> |
| <p>因此,自 <code>2.4.0</code> 版本开始, dubbo 提供了简单的工具类 <code>ReferenceConfigCache</code>用于缓存 <code>ReferenceConfig</code> 实例。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>网关等存在动态创建订阅的场景,由于 ReferenceConfig 本身很重,会创建特别多的中间对象,而 proxy 本身是可以复用的,所以通过 ReferenceConfigCache 可以缓存这部分的属性。</p> |
| <h2 id="使用方式">使用方式</h2> |
| <h3 id="消除并销毁">消除并销毁</h3> |
| <p>消除 Cache 中的 <code>ReferenceConfig</code>,将销毁 <code>ReferenceConfig</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>ReferenceConfig<span style="color:#719e07">&lt;</span>XxxService<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>XxxService<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span>reference.setInterface(XxxService.class); |
| </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></span><span style="display:flex;"><span>ReferenceConfigCache cache <span style="color:#719e07">=</span> ReferenceConfigCache.getCache(); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// cache.get方法中会缓存 Reference对象,并且调用ReferenceConfig.get方法启动ReferenceConfig </span> |
| </span></span><span style="display:flex;"><span>XxxService xxxService <span style="color:#719e07">=</span> cache.get(reference); |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 注意! Cache会持有ReferenceConfig,不要在外部再调用ReferenceConfig的destroy方法,导致Cache内的ReferenceConfig失效! </span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">// 使用xxxService对象 </span> |
| </span></span><span style="display:flex;"><span>xxxService.sayHello(); |
| </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>ReferenceConfigCache cache <span style="color:#719e07">=</span> ReferenceConfigCache.getCache(); |
| </span></span><span style="display:flex;"><span>cache.destroy(reference); |
| </span></span></code></pre></div><p>缺省 <code>ReferenceConfigCache</code> 把相同服务 Group、接口、版本的 <code>ReferenceConfig</code> 认为是相同,缓存一份。即以服务 Group、接口、版本为缓存的 Key。</p> |
| <h3 id="修改策略">修改策略</h3> |
| <p>可以修改这个策略,在 <code>ReferenceConfigCache.getCache</code> 时,传一个 <code>KeyGenerator</code>。详见 <code>ReferenceConfigCache</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>KeyGenerator keyGenerator <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> ... |
| </span></span><span style="display:flex;"><span>ReferenceConfigCache cache <span style="color:#719e07">=</span> ReferenceConfigCache.getCache(keyGenerator); |
| </span></span></code></pre></div></description></item><item><title>Overview: 路由状态采集</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/router-snapshot/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/router-snapshot/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>路由状态收集功能可用于识别可能影响服务性能的任何潜在问题,识别可能阻碍服务尽可能高效使用的任何潜在瓶颈或问题,确保服务平稳运行,用户在尝试访问服务时不会遇到任何问题,允许用户检查路由的状态是启用还是禁用,确保仅使用授权的服务,并且访问仅限于具有适当授权的人员。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>Dubbo 的很多流量治理能力是基于 Router 进行实现的,在生产环境中,如果出现流量结果不符合预期的情况,可以通过路由状态命令来查看路由的状态,以此来定位可能存在的问题。</p> |
| <h2 id="使用方式">使用方式</h2> |
| <h3 id="查看路由缓存状态">查看路由缓存状态</h3> |
| <p>Dubbo 在收到地址变更的时候,会将地址信息推送给所有的 <code>Router</code>,这些 <code>Router</code> 可以在此阶段提前计算路由的分组,缓存起来,以避免在调用时需要遍历所有的提供者计算分组参数。 |
| 在 Dubbo 3 中引入的 <code>StateRouter</code> 提供了通过 qos 命令工具实时获取每个路由的状态的能力。</p> |
| <p>运维人员可以通过 <code>getRouterSnapshot</code> 命令获取路由的状态。具体命令使用方式可以参考 <a href="../../../reference-manual/qos/router-snapshot/#getroutersnapshot-%E5%91%BD%E4%BB%A4">getRouterSnapshot 命令</a> 文档。</p> |
| <p><strong>注:此功能仅支持 <code>StateRoute</code>,且 <code>StateRouter</code> 需要基于 <code>AbstractStateRouter</code> 实现 <code>doBuildSnapshot</code> 接口。</strong></p> |
| <h3 id="查看实际请求的路由计算结果">查看实际请求的路由计算结果</h3> |
| <p>Dubbo 3 中默认在路由筛选后为空的时候打印路由计算的节点状态。运维人员可以通过日志判断每个路由的计算结果是否符合预期。</p> |
| <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-fallback" data-lang="fallback"><span style="display:flex;"><span>No provider available after route for the service 服务 from registry 注册中心地址 on the consumer 消费端IP using the dubbo version 3.0.7. Router snapshot is below: |
| </span></span><span style="display:flex;"><span>[ Parent (Input: 当前节点输入地址数) (Current Node Output: 当前节点计算结果数) (Chain Node Output: 当前节点和后级节点交集结果数) ] Input: 输入的地址示例(显示最多 5 个) -&gt; Chain Node Output: 当前节点输出的地址示例(显示最多 5 个) |
| </span></span><span style="display:flex;"><span> [ 路由名称 (Input: 当前节点输入地址数) (Current Node Output: 当前节点计算结果数) (Chain Node Output: 当前节点和后级节点交集结果数) Router message: 路由日志 ] Current Node Output: 当前节点输出的地址示例(显示最多 5 个) |
| </span></span><span style="display:flex;"><span> [ 路由名称 (Input: 当前节点输入地址数) (Current Node Output: 当前节点计算结果数) (Chain Node Output: 当前节点和后级节点交集结果数) Router message: 路由日志 ] Current Node Output: 当前输入的地址示例(显示最多 5 个) |
| </span></span></code></pre></div><h4 id="注意">注意:</h4> |
| <ul> |
| <li>路由日志需要依赖路由实现判断 <code>needToPrintMessage</code> 参数,并在需要时写入 <code>messageHolder</code> 路由日志</li> |
| <li>由于多级路由结果是结果取交集的,所以当前节点计算结果数可能和后级取交后为空</li> |
| </ul> |
| <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-fallback" data-lang="fallback"><span style="display:flex;"><span>[19/07/22 07:42:46:046 CST] main WARN cluster.RouterChain: [DUBBO] No provider available after route for the service org.apache.dubbo.samples.governance.api.DemoService from registry 30.227.64.173 on the consumer 30.227.64.173 using the dubbo version 3.0.7. Router snapshot is below: |
| </span></span><span style="display:flex;"><span>[ Parent (Input: 2) (Current Node Output: 2) (Chain Node Output: 0) ] Input: 30.227.64.173:20881,30.227.64.173:20880 -&gt; Chain Node Output: Empty |
| </span></span><span style="display:flex;"><span> [ MockInvokersSelector (Input: 2) (Current Node Output: 2) (Chain Node Output: 0) Router message: invocation.need.mock not set. Return normal Invokers. ] Current Node Output: 30.227.64.173:20881,30.227.64.173:20880 |
| </span></span><span style="display:flex;"><span> [ StandardMeshRuleRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 0) Router message: MeshRuleCache has not been built. Skip route. ] Current Node Output: 30.227.64.173:20881,30.227.64.173:20880 |
| </span></span><span style="display:flex;"><span> [ TagStateRouter (Input: 2) (Current Node Output: 0) (Chain Node Output: 0) Router message: FAILOVER: return all Providers without any tags ] Current Node Output: Empty, dubbo version: 3.0.7, current host: 30.227.64.173 |
| </span></span></code></pre></div><h4 id="开启路由全采样">开启路由全采样</h4> |
| <p>在一些特殊情况下,请求可能调用到错误的服务端,但是因为选址非空,所以无法看到路由的过程信息,此时可以 <a href="../../../reference-manual/qos/router-snapshot/">通过 qos 开启路由全采样</a>。通过 qos 的 <code>getRecentRouterSnapshot</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&gt;getRecentRouterSnapshot |
| </span></span><span style="display:flex;"><span>1658224330156 - Router snapshot service com.dubbo.dubbointegration.BackendService from registry 172.18.111.184 on the consumer 172.18.111.184 using the dubbo version 3.0.9 is below: |
| </span></span><span style="display:flex;"><span>[ Parent (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) ] Input: 172.18.111.187:20880,172.18.111.183:20880 -&gt; Chain Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ MockInvokersSelector (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: invocation.need.mock not set. Return normal Invokers. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ StandardMeshRuleRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: MeshRuleCache has not been built. Skip route. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ TagStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: Disable Tag Router. Reason: tagRouterRule is invalid or disabled ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ ServiceStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ AppStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>1658224330156 - Router snapshot service com.dubbo.dubbointegration.BackendService from registry 172.18.111.184 on the consumer 172.18.111.184 using the dubbo version 3.0.9 is below: |
| </span></span><span style="display:flex;"><span>[ Parent (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) ] Input: 172.18.111.187:20880,172.18.111.183:20880 -&gt; Chain Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ MockInvokersSelector (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: invocation.need.mock not set. Return normal Invokers. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ StandardMeshRuleRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: MeshRuleCache has not been built. Skip route. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ TagStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: Disable Tag Router. Reason: tagRouterRule is invalid or disabled ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ ServiceStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </span></span><span style="display:flex;"><span> [ AppStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 2) Router message: Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty. ] Current Node Output: 172.18.111.187:20880,172.18.111.183:20880 |
| </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>dubbo&gt; |
| </span></span></code></pre></div><h4 id="注意-1">注意:</h4> |
| <p>由于日志框架不匹配导致的日志为空可以参考<a href="../../others/logger-management/">日志框架适配及运行时管理</a>动态修改日志输出框架。</p></description></item><item><title>Overview: 负载均衡</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/loadbalance/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/loadbalance/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <ul> |
| <li><a href="https://dubbo.apache.org/zh-cn/overview/core-features/load-balance/">Dubbo 负载均衡算法说明</a></li> |
| <li>如果要扩展更多负载均衡策略,参见 <a href="../../../reference-manual/spi/description/load-balance">Java SPI 负载均衡扩展</a></li> |
| </ul> |
| <p>目前 Dubbo 内置了如下负载均衡算法,用户可直接配置使用:</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">Weighted Random LoadBalance</td> |
| <td style="text-align:left">加权随机</td> |
| <td style="text-align:left">默认算法,默认权重相同</td> |
| <td style="text-align:left">random (默认)</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">RoundRobin LoadBalance</td> |
| <td style="text-align:left">加权轮询</td> |
| <td style="text-align:left">借鉴于 Nginx 的平滑加权轮询算法,默认权重相同,</td> |
| <td style="text-align:left">roundrobin</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">LeastActive LoadBalance</td> |
| <td style="text-align:left">最少活跃优先 + 加权随机</td> |
| <td style="text-align:left">背后是能者多劳的思想</td> |
| <td style="text-align:left">leastactive</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">Shortest-Response LoadBalance</td> |
| <td style="text-align:left">最短响应优先 + 加权随机</td> |
| <td style="text-align:left">更加关注响应速度</td> |
| <td style="text-align:left">shortestresponse</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">ConsistentHash LoadBalance</td> |
| <td style="text-align:left">一致性哈希</td> |
| <td style="text-align:left">确定的入参,确定的提供者,适用于有状态请求</td> |
| <td style="text-align:left">consistenthash</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">P2C LoadBalance</td> |
| <td style="text-align:left">Power of Two Choice</td> |
| <td style="text-align:left">随机选择两个节点后,继续选择“连接数”较小的那个节点。</td> |
| <td style="text-align:left">p2c</td> |
| </tr> |
| <tr> |
| <td style="text-align:left">Adaptive LoadBalance</td> |
| <td style="text-align:left">自适应负载均衡</td> |
| <td style="text-align:left">在 P2C 算法基础上,选择二者中 load 最小的那个节点</td> |
| <td style="text-align:left">adaptive</td> |
| </tr> |
| </tbody> |
| </table> |
| <h2 id="使用场景">使用场景</h2> |
| <ul> |
| <li> |
| <p>高可用性:部署服务的多个实例以确保即使一个或多个实例失败服务保持可用,负载均衡功能可用于在这些实例之间分配传入的请求确保以负载均衡方式使用每个实例的方式,还能最大限度地降低服务停机的风险。</p> |
| </li> |
| <li> |
| <p>流量管理:限制指向特定服务实例的流量,以防止过载或确保公平的资源分配,负载均衡特性提供了 Round Robin、Weighted Round Robin、Random、Least Active Load Balancing 等多种负载均衡策略,可以用来实现流量控制。</p> |
| </li> |
| <li> |
| <p>服务划分:将一个服务划分成多个逻辑组件,每个逻辑组件可以部署在不同的实例上,使用负载平衡以确保每个分区平衡的方式在这些实例之间分配请求,同时在实例发生故障的情况下提供故障转移功能。</p> |
| </li> |
| <li> |
| <p>性能优化:负载平衡可用于优化服务的性能,通过跨多个实例分发请求可以利用可用的计算资源来缩短响应时间并减少延迟。</p> |
| </li> |
| </ul> |
| <h2 id="使用方式">使用方式</h2> |
| <blockquote> |
| <p>只需要调整 <code>loadbalance</code> 相应取值即可,每种负载均衡策略取值请参见文档最上方表格。</p> |
| </blockquote> |
| <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>Overview: 注册信息简化</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/simplify-registry-data/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/simplify-registry-data/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>Dubbo provider 中的服务配置项有接近 <a href="https://dubbo.apache.org/zh-cn/docs/references/xml/dubbo-parameter">30 个配置项</a>。 排除注册中心服务治理需要之外,很大一部分配置项是 provider 自己使用,不需要透传给消费者。这部分数据不需要进入注册中心,而只需要以 key-value 形式持久化存储。</p> |
| <p>Dubbo consumer 中的配置项也有 <a href="https://dubbo.apache.org/zh-cn/docs/references/xml/dubbo-consumer">20+个配置项</a>。在注册中心之中,服务消费者列表中只需要关注 application,version,group,ip,dubbo 版本等少量配置,其他配置也可以以 key-value 形式持久化存储。 <br> |
| 这些数据是以服务为维度注册进入注册中心,导致了数据量的膨胀,进而引发注册中心 (如 zookeeper) 的网络开销增大,性能降低。</p> |
| <div class="alert alert-primary" role="alert"> |
| <h4 class="alert-heading">设计目标和宗旨</h4> |
| <ol> |
| <li>期望简化进入注册中心的 provider 和 consumer 配置数量。</li> |
| <li>期望将部分配置项以其他形式存储。这些配置项需要满足:不在服务调用链路上,同时这些配置项不在注册中心的核心链路上(服务查询,服务列表)。</li> |
| </ol> |
| </div> |
| <blockquote> |
| <p>注意:简化注册中心的配置,只在 2.7 之后的版本中进行支持。开启 provider 或者 consumer 简化配置之后,默认保留的配置项。</p> |
| </blockquote> |
| <p><strong>provider</strong></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>DUBBO_VERSION_KEY</td> |
| <td>dubbo</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>RELEASE_KEY</td> |
| <td>release</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>SIDE_KEY</td> |
| <td>side</td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table> |
| <p><strong>consumer</strong></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> |
| </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> |
| <h2 id="使用场景">使用场景</h2> |
| <p>数据量大导致注册中心的网络开销增大,性能降低。</p> |
| <h2 id="使用方式">使用方式</h2> |
| <p><strong>现有功能 sample</strong> 当前现状一个简单展示。通过这个展示,分析下为什么需要做简化配置。</p> |
| <p>参考 sample 子工程: dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-nosimple (跑 sample 前,先跑下 ZKClean 进行配置项清理)</p> |
| <h3 id="dubbo-providerxml">dubbo-provider.xml</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-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://30.5.124.158:20880/org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService |
| </span></span><span style="display:flex;"><span>?anyhost=true |
| </span></span><span style="display:flex;"><span>&amp;application=simplified-registry-xml-provider |
| </span></span><span style="display:flex;"><span>&amp;async=true |
| </span></span><span style="display:flex;"><span>&amp;dubbo=2.0.2 |
| </span></span><span style="display:flex;"><span>&amp;executes=4500 |
| </span></span><span style="display:flex;"><span>&amp;generic=false |
| </span></span><span style="display:flex;"><span>&amp;group=dubbo-simple |
| </span></span><span style="display:flex;"><span>&amp;interface=org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService |
| </span></span><span style="display:flex;"><span>&amp;methods=sayHello |
| </span></span><span style="display:flex;"><span>&amp;owner=vict |
| </span></span><span style="display:flex;"><span>&amp;pid=2767 |
| </span></span><span style="display:flex;"><span>&amp;retries=7 |
| </span></span><span style="display:flex;"><span>&amp;revision=1.2.3 |
| </span></span><span style="display:flex;"><span>&amp;side=provider |
| </span></span><span style="display:flex;"><span>&amp;timeout=5300 |
| </span></span><span style="display:flex;"><span>&amp;timestamp=1542361152795 |
| </span></span><span style="display:flex;"><span>&amp;valid=true |
| </span></span><span style="display:flex;"><span>&amp;version=1.2.3 |
| </span></span></code></pre></div><p>从中能看到有:<code>executes</code>, <code>retries</code>, <code>owner</code>, <code>timeout</code>。但是这些字段不是每个都需要传递给 dubbo ops 或者 dubbo consumer。 同样的,consumer 也有这个问题,可以在例子中启动 Consumer 的 main 方法进行查看。</p> |
| <h3 id="1-dubboproperties">1. dubbo.properties</h3> |
| <p>sample 在 dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-xml 工程下 (跑 sample 前,先跑下ZKClean 进行配置项清理)</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.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>和上面的 <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> |
| <h3 id="provider-端">provider 端</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;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://30.5.124.149:20880/org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService |
| </span></span><span style="display:flex;"><span>?application=simplified-registry-xml-provider |
| </span></span><span style="display:flex;"><span>&amp;dubbo=2.0.2 |
| </span></span><span style="display:flex;"><span>&amp;group=dubbo-simple |
| </span></span><span style="display:flex;"><span>&amp;owner=vict |
| </span></span><span style="display:flex;"><span>&amp;retries=7 |
| </span></span><span style="display:flex;"><span>&amp;timeout=5300 |
| </span></span><span style="display:flex;"><span>&amp;timestamp=1542594503305 |
| </span></span><span style="display:flex;"><span>&amp;version=1.2.3 |
| </span></span></code></pre></div><h3 id="consumer-端">consumer 端</h3> |
| <ul> |
| <li>配置:dubbo.registry.simplified=true</li> |
| <li>默认情况:application,version,group,dubbo 在默认的配置项列表,所以还是会进入注册中心。</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;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://30.5.124.149/org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService |
| </span></span><span style="display:flex;"><span>?actives=6 |
| </span></span><span style="display:flex;"><span>&amp;application=simplified-registry-xml-consumer |
| </span></span><span style="display:flex;"><span>&amp;category=consumers |
| </span></span><span style="display:flex;"><span>&amp;check=false |
| </span></span><span style="display:flex;"><span>&amp;dubbo=2.0.2 |
| </span></span><span style="display:flex;"><span>&amp;group=dubbo-simple |
| </span></span><span style="display:flex;"><span>&amp;owner=vvv |
| </span></span><span style="display:flex;"><span>&amp;version=1.2.3 |
| </span></span></code></pre></div><h3 id="2声明-spring-bean">2.声明 spring bean</h3> |
| <p>sample 在 dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-annotation 工程下 (跑 sample 前,先跑下 ZKClean 进行配置项清理)</p> |
| <p>和上面 sample 中的 dubbo.properties 的效果是一致的。</p> |
| <ul> |
| <li>默认情况:timeout 在默认的配置项列表,所以还是会进入注册中心;</li> |
| <li>配置: retries,owner 作为额外的 key 进入注册中心 , 所以 retries,owner 也会进入注册中心。</li> |
| </ul> |
| <h3 id="provider-配置">Provider 配置</h3> |
| <h4 id="privider-端-bean-配置">privider 端 bean 配置</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:#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><h3 id="consumer-配置">Consumer 配置</h3> |
| <p>和上面 sample 中 <strong>consumer 端配置</strong> 是一样的。</p> |
| <p>默认情况: application,version,group,dubbo 在默认的配置项列表,所以还是会进入注册中心。</p> |
| <h4 id="consumer-端-bean-配置">consumer 端 bean 配置</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">@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><blockquote> |
| <p>注意: 如果一个应用中既有 provider 又有 consumer,那么配置需要合并成如下</p> |
| </blockquote> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@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><blockquote> |
| <p>提示:本版本还保留了大量的配置项,接下来的版本中,会逐渐删除所有的配置项。</p> |
| </blockquote></description></item><item><title>Overview: 调用结果缓存</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/result-cache/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/result-cache/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>Dubbo支持了服务端结果缓存和客户端结果缓存。</p> |
| <h4 id="缓存类型">缓存类型</h4> |
| <p>目前Dubbo3.0版本及高于其的版本都支持以下几种内置的缓存策略:</p> |
| <ul> |
| <li><code>lru</code> 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。</li> |
| <li><code>lfu</code>基于淘汰使用频次最低的原则来实现缓存策略。</li> |
| <li><code>expiring</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="../../../reference-manual/spi/description/cache">缓存扩展</a></p> |
| <p>关于 <a href="https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-cache">示例代码</a></p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>结果缓存,用于加速热门数据的访问速度,Dubbo 提供声明式缓存,以减少用户加缓存的工作量。</p> |
| <h2 id="使用方式">使用方式</h2> |
| <h3 id="客户端缓存">客户端缓存</h3> |
| <p>Dubbo中对RPC调用结果缓存支持接口粒度和方法粒度的配置控制。</p> |
| <p><strong>接口粒度</strong></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> interface=<span style="color:#2aa198">&#34;com.foo.DemoService&#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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboReference</span>(cache <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;lru&#34;</span>) |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> DemoService demoService; |
| </span></span></code></pre></div><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-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.DemoService&#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> 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><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">@DubboReference</span>(methods <span style="color:#719e07">=</span> {<span style="color:#268bd2">@Method</span>(name<span style="color:#719e07">=</span><span style="color:#2aa198">&#34;sayHello&#34;</span>,cache <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;lru&#34;</span>)}) |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">private</span> DemoService demoService; |
| </span></span></code></pre></div><h3 id="服务端缓存">服务端缓存</h3> |
| <p><strong>接口粒度</strong></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;bean</span> id=<span style="color:#2aa198">&#34;demoService&#34;</span> class=<span style="color:#2aa198">&#34;org.apache.dubbo.demo.provider.DemoServiceImpl&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.foo.DemoService&#34;</span> ref=<span style="color:#2aa198">&#34;demoService&#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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboService</span>(cache <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;lru&#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">DemoServiceImpl</span> <span style="color:#268bd2">implements</span> DemoService { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> Logger logger <span style="color:#719e07">=</span> LoggerFactory.getLogger(DemoServiceImpl.class); |
| </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> logger.info(<span style="color:#2aa198">&#34;Hello &#34;</span> <span style="color:#719e07">+</span> name <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;, request from consumer: &#34;</span> <span style="color:#719e07">+</span> RpcContext.getContext().getRemoteAddress()); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;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><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><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-xml" data-lang="xml"><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.demo.provider.DemoServiceImpl&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:service</span> interface=<span style="color:#2aa198">&#34;com.foo.DemoService&#34;</span> ref=<span style="color:#2aa198">&#34;demoService&#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:method</span> name=<span style="color:#2aa198">&#34;sayHello&#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: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-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboService</span>(methods <span style="color:#719e07">=</span> {<span style="color:#268bd2">@Method</span>(name<span style="color:#719e07">=</span><span style="color:#2aa198">&#34;sayHello&#34;</span>,cache <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;lru&#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">DemoServiceImpl</span> <span style="color:#268bd2">implements</span> DemoService { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">final</span> Logger logger <span style="color:#719e07">=</span> LoggerFactory.getLogger(DemoServiceImpl.class); |
| </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> logger.info(<span style="color:#2aa198">&#34;Hello &#34;</span> <span style="color:#719e07">+</span> name <span style="color:#719e07">+</span> <span style="color:#2aa198">&#34;, request from consumer: &#34;</span> <span style="color:#719e07">+</span> RpcContext.getContext().getRemoteAddress()); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;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><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div></description></item><item><title>Overview: 并发控制</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/concurrency-control/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/concurrency-control/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>多种并发控制功能,帮助用户管理其应用程序和服务。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>限制从同一客户端到同一服务的并发请求数,防止恶意请求使服务器过载,确保服务的稳定性,并防止使用过多资源。</p> |
| <p>控制某些服务的最大并发请求数,确保其他服务的资源可用性。系统过载和确保系统稳定性。</p> |
| <p>允许在需求增加时更平滑地扩展服务。</p> |
| <p>确保服务在高峰使用时间保持可靠和稳定。</p> |
| <p>这种方式要求用户准确的预先评估系统能处理的并发数,而准确的评估系统处理能力并不是一件容易的事情,因此 Dubbo 还提供了自适应限流模式,根据系统负载自动识别系统健康程度并进行限流保护,可以在此 <a href="../adaptive-concurrency-control">查看使用文档</a>。</p> |
| <h2 id="使用方式">使用方式</h2> |
| <h3 id="样例一">样例一</h3> |
| <blockquote> |
| <p>限制 <code>com.foo.BarService</code> 的每个方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个</p> |
| </blockquote> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-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="样例二">样例二</h3> |
| <blockquote> |
| <p>限制 <code>com.foo.BarService</code> 的 <code>sayHello</code> 方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个</p> |
| </blockquote> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-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="样例三">样例三</h3> |
| <blockquote> |
| <p>限制 <code>com.foo.BarService</code> 的每个方法,每客户端并发执行(或占用连接的请求数)不能超过 10 个</p> |
| </blockquote> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-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><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-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="样例四">样例四</h3> |
| <blockquote> |
| <p>限制 <code>com.foo.BarService</code> 的 <code>sayHello</code> 方法,每客户端并发执行(或占用连接的请求数)不能超过 10 个</p> |
| </blockquote> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-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><blockquote> |
| <p>如果 <code>&lt;dubbo:service&gt;</code> 和 <code>&lt;dubbo:reference&gt;</code> 都配了actives,<code>&lt;dubbo:reference&gt;</code> 优先,参见:<a href="../../../reference-manual/config/principle/">配置的覆盖策略</a>。</p> |
| </blockquote> |
| <h3 id="load-balance-均衡">Load Balance 均衡</h3> |
| <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><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-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>Overview: 自适应限流</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/adaptive-concurrency-control/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/adaptive-concurrency-control/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>自适应限流的设计与实现思路请参考 <a href="../../../../../reference/proposals/heuristic-flow-control/">Dubbo 自适应限流功能</a>。自适应限流能够确保分布式系统稳定性和可靠性,例如在服务提供商资源有限且多变的场景下。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <ul> |
| <li> |
| <p>服务降级预防:当服务提供者因资源耗尽而性能下降时,使用自适应限流暂时减少其接受的请求数直至恢复正常。</p> |
| </li> |
| <li> |
| <p>峰值流量处理:当服务流量突然激增时,自适应流量限制可以通过动态减少接受的请求数量来帮助防止服务过载。</p> |
| </li> |
| <li> |
| <p>不可预测流量处理:服务提供商可能会遇到不可预测的流量,第三方应用程序使用服务时可能会偶尔产生流量,自适应流量限制可以根据当前系统负载调整允许的最大并发请求数并防止过载。</p> |
| </li> |
| </ul> |
| <h2 id="使用方式">使用方式</h2> |
| <p>设置方法与静态的最大并发值设置类似,只需在服务端设置 flowcontrol 参数即可,可选值有以下两种:</p> |
| <ul> |
| <li>heuristicSmoothingFlowControl。当服务端收到一个请求时,首先判断CPU的使用率是否超过50%。如果没有超过50%,则接受这个请求进行处理。如果超过50%,说明当前的负载较高,便从 HeuristicSmoothingFlowControl 算法中获得当前的 maxConcurrency 值。如果当前正在处理的请求数量超过了 maxConcurrency,则拒绝该请求。</li> |
| <li>autoConcurrencyLimiter。与 HeuristicSmoothingFlowControl 的最大区别是,AutoConcurrencyLimiter 是基于窗口的,每当窗口内积累了一定量的采样数据时,才利用窗口内的数据来更新得到 maxConcurrency,其次,利用exploreRatio来对剩余的容量进行探索。</li> |
| </ul> |
| <blockquote> |
| <p>在确保服务端存在多个节点,并且消费端开启重试策略的前提下,限流功能才能更好的发挥作用。</p> |
| </blockquote> |
| <h3 id="示例一使用-heuristicsmoothingflowcontrol-自适应限流算法">示例一:使用 heuristicSmoothingFlowControl 自适应限流算法</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.provider.flowcontrol<span style="color:#719e07">=</span><span style="color:#2aa198">heuristicSmoothingFlowControl</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:provider</span> flowcontrol=<span style="color:#2aa198">&#34;heuristicSmoothingFlowControl&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="示例二使用-autoconcurrencylimiter-自适应限流算法">示例二:使用 autoConcurrencyLimiter 自适应限流算法</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.provider.flowcontrol<span style="color:#719e07">=</span><span style="color:#2aa198">autoConcurrencyLimiter</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:provider</span> flowcontrol=<span style="color:#2aa198">&#34;autoConcurrencyLimiter&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="示例三设置服务粒度的-heuristicsmoothingflowcontrol-自适应限流">示例三:设置服务粒度的 heuristicSmoothingFlowControl 自适应限流</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;com.foo.BarService&#34;</span> flowcontrol=<span style="color:#2aa198">&#34;heuristicSmoothingFlowControl&#34;</span> <span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div></description></item><item><title>Overview: 连接控制</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/config-connections/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/config-connections/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>连接控制功能可以使用户能够控制和管理进出服务器连接数,限制连接数并设置超时,以确保 Dubbo 系统的稳定性和性能,还允许用户根据 IP 地址、端口和协议配置不同级别的访问控制,保护系统免受恶意流量的影响,并降低服务中断的风险,此外提供了一种监视当前流量和连接状态的方法。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <ol> |
| <li>服务器过载时减少连接数:当服务器过载时,使用 Dubbo 通过设置最大连接限制来减少连接数减少服务器上的负载并防止其崩溃。</li> |
| <li>减少服务器受到攻击时的连接数:Dubbo 可以限制服务器受到攻击的连接数防止恶意连接充斥服务器并导致服务器崩溃。</li> |
| <li>限制特定服务的连接数:Dubbo 可以限制特定服务连接数防止服务过载过多的请求并确保及时响应所有请求。</li> |
| <li>限制来自单个IP地址的连接数:Dubbo 可以限制来自单个地址的连接数降低来自单个IP地址的恶意活动的风险。</li> |
| </ol> |
| <h2 id="使用方式">使用方式</h2> |
| <h3 id="服务端连接控制">服务端连接控制</h3> |
| <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><h3 id="客户端连接控制">客户端连接控制</h3> |
| <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="../../../reference-manual/config/principle/">配置的覆盖策略</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>Overview: 延迟连接</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/lazy-connect/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/lazy-connect/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>当消费者请求服务时,实际使用服务时才建立真正的连接,避免不必要的连接来减少延迟并提高系统稳定性。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>延迟连接用于减少长连接数。当有调用发起时,再创建长连接。</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: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><blockquote> |
| <p>该配置只对使用长连接的 dubbo 协议生效。</p> |
| </blockquote></description></item><item><title>Overview: 粘滞连接</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/stickiness/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/stickiness/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>允许消费者在提供者接收请求之前向提供者发送请求,消费者等待提供者准备就绪,然后将发送消费者者的请求,当消费者需要连接到提供者,提供者尚未准备好接受请求时,确保在正确的时间发送请求,防止消费者被速度慢或不可用的提供程序阻止。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>粘滞连接用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非该提供者挂了,再连另一台。</p> |
| <p>粘滞连接将自动开启 <a href="../lazy-connect">延迟连接</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> 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>Overview: 支持 Graal VM</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/support-graalvm/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/support-graalvm/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>Dubbo3.2 支持 Native-Image 文档, 本文档将介绍将 dubbo3.x 项目接入 GraalVM Native Image,进行 native-image 编译为二进制的流程以及目前支持的组件。</p> |
| <p>关于 GraalVm 的更多信息可以阅读 <a href="https://www.graalvm.org/docs/getting-started/container-images/">https://www.graalvm.org/docs/getting-started/container-images/</a> 此文档。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <ul> |
| <li> |
| <p>本机映像编译:将应用程序预编译为本机映像,缩短启动时间并减少内存使用。</p> |
| </li> |
| <li> |
| <p>语言互操作:GraalVM 能够用多种语言编写代码,在同一应用程序中进行互操作。</p> |
| </li> |
| <li> |
| <p>优化:GraalVM 为用 Java、JavaScript 和其他语言编写的应用程序提供优化,提高 Dubbo 应用程序的性能。</p> |
| </li> |
| <li> |
| <p>Polyglot 调试:GraalVM 能够在同一会话中调试用多种语言编写的代码,对复杂 Dubbo 应用程序中的问题进行故障排除时非常有用。</p> |
| </li> |
| <li> |
| <p>Java 运行时:可以在 GraalVM 上运行,提供更快、更高效的 Java 运行时环境。</p> |
| </li> |
| <li> |
| <p>开发微服务:可以与 GraalVM 结合,创建高性能、低资源利用率的微服务。</p> |
| </li> |
| </ul> |
| <h2 id="使用方式">使用方式</h2> |
| <p>在编译我们的dubbo项目之前,需要确保我们正基于graalVm的环境。</p> |
| <h3 id="第一步安装graalvm">第一步:安装GraalVM</h3> |
| <ol> |
| <li>在Graalvm官网根据自己的系统选取对应Graalvm版本:https://www.graalvm.org/downloads/</li> |
| <li>根据官方文档安装native-image:https://www.graalvm.org/latest/reference-manual/native-image/#install-native-image</li> |
| </ol> |
| <h3 id="第二步配置profiles">第二步:配置profiles</h3> |
| <p>其中包括maven-compiler-plugin、spring-boot-maven-plugin、native-maven-plugin、dubbo-maven-plugin,修改dubbo-maven-plugin中的mainClass为所需的启动类全路径。(其中API使用方式无需添加spring-boot-maven-plugin依赖。)</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;profiles&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;profile&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;id&gt;</span>native<span style="color:#268bd2">&lt;/id&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;build&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;plugins&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>maven-compiler-plugin<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;release&gt;</span>17<span style="color:#268bd2">&lt;/release&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;fork&gt;</span>true<span style="color:#268bd2">&lt;/fork&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;verbose&gt;</span>true<span style="color:#268bd2">&lt;/verbose&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>spring-boot-maven-plugin<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;executions&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;id&gt;</span>process-aot<span style="color:#268bd2">&lt;/id&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goal&gt;</span>process-aot<span style="color:#268bd2">&lt;/goal&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/executions&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.graalvm.buildtools<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>native-maven-plugin<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>0.9.25<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;classesDirectory&gt;</span>${project.build.outputDirectory}<span style="color:#268bd2">&lt;/classesDirectory&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;metadataRepository&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;enabled&gt;</span>true<span style="color:#268bd2">&lt;/enabled&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/metadataRepository&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;requiredVersion&gt;</span>22.3<span style="color:#268bd2">&lt;/requiredVersion&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;executions&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;id&gt;</span>add-reachability-metadata<span style="color:#268bd2">&lt;/id&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goal&gt;</span>add-reachability-metadata<span style="color:#268bd2">&lt;/goal&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/executions&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.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-maven-plugin<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>${dubbo.version}<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;mainClass&gt;</span>com.example.nativedemo.NativeDemoApplication<span style="color:#268bd2">&lt;/mainClass&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/configuration&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;executions&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;phase&gt;</span>process-sources<span style="color:#268bd2">&lt;/phase&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;goal&gt;</span>dubbo-process-aot<span style="color:#268bd2">&lt;/goal&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/goals&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/execution&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/executions&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/plugin&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/plugins&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/build&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/profile&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/profiles&gt;</span> |
| </span></span></code></pre></div><h3 id="第三步在pom依赖中添加native相关的依赖">第三步:在Pom依赖中添加native相关的依赖:</h3> |
| <p><strong>其中API使用方式无需添加dubbo-config-spring6依赖</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-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-config-spring6<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>${dubbo.version}<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span><span 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-native<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><h3 id="第四步配置应用">第四步:配置应用</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-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#268bd2">dubbo</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">application</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">name</span>: ${spring.application.name} |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">logger</span>: slf4j |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">protocol</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">name</span>: dubbo |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">port</span>: -<span style="color:#2aa198">1</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">serialization</span>: fastjson2 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">registry</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">id</span>: zk-registry |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">address</span>: zookeeper://127.0.0.1:2181 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">config-center</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">address</span>: zookeeper://127.0.0.1:2181 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">metadata-report</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">address</span>: zookeeper://127.0.0.1:2181 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">provider</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">serialization</span>: fastjson2 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">consumer</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">serialization</span>: fastjson2 |
| </span></span></code></pre></div><h3 id="第五步编译">第五步:编译</h3> |
| <p>在项目根路径下执行以下编译命令:</p> |
| <ul> |
| <li>API方式直接执行</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> mvn clean install -P native -Dmaven.test.skip=true |
| </span></span></code></pre></div><ul> |
| <li>注解和xml方式(Springboot3集成的方式)</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-shell" data-lang="shell"><span style="display:flex;"><span> mvn clean install -P native native:compile -Dmaven.test.skip<span style="color:#719e07">=</span><span style="color:#b58900">true</span> |
| </span></span></code></pre></div><h3 id="第六步执行二进制文件即可">第六步:执行二进制文件即可</h3> |
| <p>二进制文件在target/目录下,一般以工程名称为二进制包的名称,比如target/native-demo</p> |
| <h2 id="支持的组件以及对应的版本">支持的组件以及对应的版本</h2> |
| <h3 id="日志组件">日志组件</h3> |
| <table> |
| <thead> |
| <tr> |
| <th>组件名称</th> |
| <th>所需的插件</th> |
| <th>插件版本</th> |
| <th>备注</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Apache Commons Logging</td> |
| <td>native-maven-plugin</td> |
| <td>0.9.24 及其以上</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>JDK Logger</td> |
| <td>native-maven-plugin</td> |
| <td>0.9.24 及其以上</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>slf4j</td> |
| <td>spring-boot-maven-plugin</td> |
| <td>3.x.x (用最新版本即可)</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>Log4j</td> |
| <td></td> |
| <td></td> |
| <td>计划推动GraalVM支持</td> |
| </tr> |
| <tr> |
| <td>Log4j2</td> |
| <td></td> |
| <td></td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table> |
| <h3 id="序列化组件">序列化组件</h3> |
| <table> |
| <thead> |
| <tr> |
| <th>组件名称</th> |
| <th>所需的插件</th> |
| <th>插件版本</th> |
| <th>备注</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>FastJson2</td> |
| <td>dubbo-maven-plugin</td> |
| <td>3.3.0-beta.1-SNAPSHOT (Preview)及其以上</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>JDK</td> |
| <td>native-maven-plugin</td> |
| <td>0.9.24 及其以上</td> |
| <td></td> |
| </tr> |
| <tr> |
| <td>Hessian-Lite</td> |
| <td></td> |
| <td></td> |
| <td>对JDK 17支持不友好,暂不支持</td> |
| </tr> |
| </tbody> |
| </table> |
| <h3 id="注册中心组件">注册中心组件</h3> |
| <table> |
| <thead> |
| <tr> |
| <th>组件名称</th> |
| <th>所需的插件</th> |
| <th>插件版本</th> |
| <th>备注</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Zookeeper</td> |
| <td>dubbo-maven-plugin</td> |
| <td>3.3.0-beta.1-SNAPSHOT (Preview)</td> |
| <td>仅支持Zookeeper Curator5</td> |
| </tr> |
| </tbody> |
| </table> |
| <h3 id="元数据中心组件">元数据中心组件</h3> |
| <table> |
| <thead> |
| <tr> |
| <th>组件名称</th> |
| <th>所需的插件</th> |
| <th>插件版本</th> |
| <th>备注</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Zookeeper</td> |
| <td>dubbo-maven-plugin</td> |
| <td>3.3.0-beta.1-SNAPSHOT (Preview)</td> |
| <td>仅支持Zookeeper Curator5</td> |
| </tr> |
| </tbody> |
| </table> |
| <h3 id="配置中心组件">配置中心组件</h3> |
| <table> |
| <thead> |
| <tr> |
| <th>组件名称</th> |
| <th>所需的插件</th> |
| <th>插件版本</th> |
| <th>备注</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Zookeeper</td> |
| <td>dubbo-maven-plugin</td> |
| <td>3.3.0-beta.1-SNAPSHOT (Preview)</td> |
| <td>仅支持Zookeeper Curator5</td> |
| </tr> |
| </tbody> |
| </table> |
| <h3 id="可观测性组件">可观测性组件</h3> |
| <table> |
| <thead> |
| <tr> |
| <th>组件名称</th> |
| <th>所需的插件</th> |
| <th>插件版本</th> |
| <th>备注</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Micrometer</td> |
| <td></td> |
| <td></td> |
| <td></td> |
| </tr> |
| </tbody> |
| </table></description></item><item><title>Overview: 导出线程堆栈</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/dump/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/dump/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <p>dubbo 通过 Jstack 自动导出线程堆栈来保留现场,方便排查问题。</p> |
| <p>默认策略</p> |
| <ul> |
| <li>导出路径: user.home标识的用户主目录</li> |
| <li>导出间隔: 最短间隔允许每隔10分钟导出一次</li> |
| <li>导出开关: 默认打开</li> |
| </ul> |
| <h2 id="使用场景">使用场景</h2> |
| <p>当业务线程池满时,我们需要知道线程都在等待哪些资源、条件,以找到系统的瓶颈点或异常点。</p> |
| <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-properties" data-lang="properties"><span style="display:flex;"><span><span style="color:#586e75"># dubbo.properties</span> |
| </span></span><span style="display:flex;"><span>dubbo.application.dump.enable<span style="color:#719e07">=</span><span style="color:#2aa198">true</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;demo-provider&#34;</span> dump-enable=<span style="color:#2aa198">&#34;false&#34;</span><span style="color:#268bd2">/&gt;</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-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#268bd2">dubbo</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">application</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">name</span>: dubbo-springboot-demo-provider |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">dump-enable</span>: <span style="color:#cb4b16">false</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-properties" data-lang="properties"><span style="display:flex;"><span><span style="color:#586e75"># dubbo.properties</span> |
| </span></span><span style="display:flex;"><span>dubbo.application.dump.directory<span style="color:#719e07">=</span><span style="color:#2aa198">/tmp</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-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#268bd2">&lt;dubbo:application</span> name=<span style="color:#2aa198">&#34;demo-provider&#34;</span> dump-directory=<span style="color:#2aa198">&#34;/tmp&#34;</span><span style="color:#268bd2">/&gt;</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-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#268bd2">dubbo</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">application</span>: |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">name</span>: dubbo-springboot-demo-provider |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">dump-directory</span>: /tmp |
| </span></span></code></pre></div></description></item><item><title>Overview: Kryo 和 FST 序列化</title><link>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/serialization/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/performance/serialization/</guid><description> |
| <h2 id="功能说明">功能说明</h2> |
| <h3 id="序列化漫谈">序列化漫谈</h3> |
| <h4 id="漫谈一">漫谈一</h4> |
| <p>dubbo RPC是dubbo体系中最核心的一种高性能、高吞吐量的远程调用方式,我喜欢称之为多路复用的TCP长连接调用。主要用于两个dubbo系统之间作远程调用,特别适合高并发、小数据的互联网场景。</p> |
| <p><strong>长连接:避免了每次调用新建TCP连接,提高了调用的响应速度。</strong></p> |
| <p><strong>多路复用:单个TCP连接可交替传输多个请求和响应的消息,降低了连接的等待闲置时间,从而减少了同样并发数下的网络连接数,提高了系统吞吐量。</strong></p> |
| <h4 id="漫谈二">漫谈二</h4> |
| <p>而序列化对于远程调用的响应速度、吞吐量、网络带宽消耗等同样也起着至关重要的作用,是我们提升分布式系统性能的最关键因素之一。</p> |
| <p>在dubbo RPC中,同时支持多种序列化方式</p> |
| <p><strong>dubbo序列化:阿里尚未开发成熟的高效java序列化实现,阿里不建议在生产环境使用它</strong></p> |
| <p><strong>hessian2序列化:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式。</strong></p> |
| <p><strong>json序列化:目前有两种实现,一种是采用的阿里的fastjson库,另一种是采用dubbo中自己实现的简单json库,但其实现都不是特别成熟,而且json这种文本序列化性能一般不如上面两种二进制序列化。</strong></p> |
| <p><strong>java序列化:主要是采用JDK自带的Java序列化实现,性能很不理想。</strong></p> |
| <p>在通常情况下,这四种主要序列化方式的性能从上到下依次递减。</p> |
| <p>对于dubbo RPC这种追求高性能的远程调用方式来说,实际上只有1、2两种高效序列化方式比较般配,而第1个dubbo序列化由于还不成熟,所以实际只剩下2可用,所以dubbo RPC默认采用hessian2序列化。</p> |
| <p>但hessian是一个比较老的序列化实现了,而且它是跨语言的,所以不是单独针对java进行优化的。而dubbo RPC实际上完全是一种Java to Java的远程调用,其实没有必要采用跨语言的序列化方式(当然肯定也不排斥跨语言的序列化)。</p> |
| <p>最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型包括:</p> |
| <p><strong>专门针对Java语言的:Kryo,FST等等</strong></p> |
| <p><strong>跨语言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等</strong></p> |
| <p>这些序列化方式的性能多数都显著优于hessian2(甚至包括尚未成熟的dubbo序列化)。</p> |
| <p>有鉴于此,我们为dubbo引入Kryo和FST这两种高效Java序列化实现,来逐步取代hessian2。</p> |
| <p>其中,Kryo是一种非常成熟的序列化实现,已经在Twitter、Groupon、Yahoo以及多个著名开源项目(如Hive、Storm)中广泛的使用。而FST是一种较新的序列化实现,目前还缺乏足够多的成熟使用案例,但我认为它还是非常有前途的。</p> |
| <p>在面向生产环境的应用中,我建议目前更优先选择Kryo。</p> |
| <h2 id="使用场景">使用场景</h2> |
| <p>高性能微服务,大型对象图,分布式系统等</p> |
| <h2 id="实现方式">实现方式</h2> |
| <h3 id="启用kryo和fst">启用Kryo和FST</h3> |
| <p>使用Kryo和FST非常简单,只需要先增加对应的依赖。 |
| 更多插件: <a href="https://dubbo.apache.org/zh-cn/download/spi-extensions">Dubbo SPI Extensions</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;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.apache.dubbo.extensions<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>dubbo-serialization-kryo<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<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><div class="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.extensions<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>dubbo-serialization-fst<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<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>然后在dubbo RPC的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:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> serialization=<span style="color:#2aa198">&#34;kryo&#34;</span><span style="color:#268bd2">/&gt;</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-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> serialization=<span style="color:#2aa198">&#34;fst&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><h3 id="注册被序列化类">注册被序列化类</h3> |
| <p>要让Kryo和FST完全发挥出高性能,最好将那些需要被序列化的类注册到dubbo系统中,实现如下</p> |
| <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-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">SerializationOptimizerImpl</span> <span style="color:#268bd2">implements</span> SerializationOptimizer { |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Collection<span style="color:#719e07">&lt;</span>Class<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">getSerializableClasses</span>() { |
| </span></span><span style="display:flex;"><span> List<span style="color:#719e07">&lt;</span>Class<span style="color:#719e07">&gt;</span> classes <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> LinkedList<span style="color:#719e07">&lt;</span>Class<span style="color:#719e07">&gt;</span>(); |
| </span></span><span style="display:flex;"><span> classes.add(BidRequest.class); |
| </span></span><span style="display:flex;"><span> classes.add(BidResponse.class); |
| </span></span><span style="display:flex;"><span> classes.add(Device.class); |
| </span></span><span style="display:flex;"><span> classes.add(Geo.class); |
| </span></span><span style="display:flex;"><span> classes.add(Impression.class); |
| </span></span><span style="display:flex;"><span> classes.add(SeatBid.class); |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> classes; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>} |
| </span></span></code></pre></div><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:protocol</span> name=<span style="color:#2aa198">&#34;dubbo&#34;</span> serialization=<span style="color:#2aa198">&#34;kryo&#34;</span> optimizer=<span style="color:#2aa198">&#34;org.apache.dubbo.demo.SerializationOptimizerImpl&#34;</span><span style="color:#268bd2">/&gt;</span> |
| </span></span></code></pre></div><p>在注册这些类后,序列化的性能可能被大大提升,特别针对小数量的嵌套对象的时候。</p> |
| <p>当然,在对一个类做序列化的时候,可能还级联引用到很多类,比如Java集合类。</p> |
| <p>针对这种情况,我们已经自动将JDK中的常用类进行了注册,所以你不需要重复注册它们(当然你重复注册了也没有任何影响)。</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-fallback" data-lang="fallback"><span style="display:flex;"><span>GregorianCalendar |
| </span></span><span style="display:flex;"><span>InvocationHandler |
| </span></span><span style="display:flex;"><span>BigDecimal |
| </span></span><span style="display:flex;"><span>BigInteger |
| </span></span><span style="display:flex;"><span>Pattern |
| </span></span><span style="display:flex;"><span>BitSet |
| </span></span><span style="display:flex;"><span>URI |
| </span></span><span style="display:flex;"><span>UUID |
| </span></span><span style="display:flex;"><span>HashMap |
| </span></span><span style="display:flex;"><span>ArrayList |
| </span></span><span style="display:flex;"><span>LinkedList |
| </span></span><span style="display:flex;"><span>HashSet |
| </span></span><span style="display:flex;"><span>TreeSet |
| </span></span><span style="display:flex;"><span>Hashtable |
| </span></span><span style="display:flex;"><span>Date |
| </span></span><span style="display:flex;"><span>Calendar |
| </span></span><span style="display:flex;"><span>ConcurrentHashMap |
| </span></span><span style="display:flex;"><span>SimpleDateFormat |
| </span></span><span style="display:flex;"><span>Vector |
| </span></span><span style="display:flex;"><span>BitSet |
| </span></span><span style="display:flex;"><span>StringBuffer |
| </span></span><span style="display:flex;"><span>StringBuilder |
| </span></span><span style="display:flex;"><span>Object |
| </span></span><span style="display:flex;"><span>Object[] |
| </span></span><span style="display:flex;"><span>String[] |
| </span></span><span style="display:flex;"><span>byte[] |
| </span></span><span style="display:flex;"><span>char[] |
| </span></span><span style="display:flex;"><span>int[] |
| </span></span><span style="display:flex;"><span>float[] |
| </span></span><span style="display:flex;"><span>double[] |
| </span></span></code></pre></div><p>由于注册被序列化的类仅仅是出于性能优化的目的,所以即使你忘记注册某些类也没有关系。</p> |
| <p>事实上,即使不注册任何类,Kryo和FST的性能依然普遍优于hessian和dubbo序列化。</p> |
| <blockquote> |
| <p>当然,有人可能会问为什么不用配置文件来注册这些类?这是因为要注册的类往往数量较多,导致配置文件冗长;而且在没有好的IDE支持的情况下,配置文件的编写和重构都比java类麻烦得多;最后,这些注册的类一般是不需要在项目编译打包后还需要做动态修改的。</p> |
| </blockquote> |
| <blockquote> |
| <p>另外,有人也会觉得手工注册被序列化的类是一种相对繁琐的工作,是不是可以用annotation来标注,然后系统来自动发现并注册。但这里annotation的局限是,它只能用来标注你可以修改的类,而很多序列化中引用的类很可能是你没法做修改的(比如第三方库或者JDK系统类或者其他项目的类)。另外,添加annotation毕竟稍微的“污染”了一下代码,使应用代码对框架增加了一点点的依赖性。</p> |
| </blockquote> |
| <blockquote> |
| <p>除了annotation,我们还可以考虑用其它方式来自动注册被序列化的类,例如扫描类路径,自动发现实现Serializable接口(甚至包括Externalizable)的类并将它们注册。当然,我们知道类路径上能找到Serializable类可能是非常多的,所以也可以考虑用package前缀之类来一定程度限定扫描范围。</p> |
| </blockquote> |
| <blockquote> |
| <p>当然,在自动注册机制中,特别需要考虑如何保证服务提供端和消费端都以同样的顺序(或者ID)来注册类,避免错位,毕竟两端可被发现然后注册的类的数量可能都是不一样的。</p> |
| </blockquote> |
| <h3 id="无参构造函数和serializable接口">无参构造函数和Serializable接口</h3> |
| <p>如果被序列化的类中不包含无参的构造函数,则在Kryo的序列化中,性能将会大打折扣,因为此时我们在底层将用Java的序列化来透明的取代Kryo序列化。所以,尽可能为每一个被序列化的类添加无参构造函数是一种最佳实践(当然一个java类如果不自定义构造函数,默认就有无参构造函数)。</p> |
| <p>另外,Kryo和FST本来都不需要被序列化的类实现Serializable接口,但我们还是建议每个被序列化类都去实现它,因为这样可以保持和Java序列化以及dubbo序列化的兼容性,另外也使我们未来采用上述某些自动注册机制带来可能。</p> |
| <h3 id="序列化性能分析与测试">序列化性能分析与测试</h3> |
| <p>本文我们主要讨论的是序列化,但在做性能分析和测试的时候我们并不单独处理每种序列化方式,而是把它们放到dubbo RPC中加以对比,因为这样更有现实意义。</p> |
| <p><strong>测试环境</strong></p> |
| <ul> |
| <li>两台独立服务器</li> |
| <li>4核Intel(R) Xeon(R) CPU E5-2603 0 @ 1.80GHz</li> |
| <li>8G内存</li> |
| <li>虚拟机之间网络通过百兆交换机</li> |
| <li>CentOS 5</li> |
| <li>JDK 7</li> |
| <li>Tomcat 7</li> |
| <li>JVM参数-server -Xms1g -Xmx1g -XX:PermSize=64M -XX:+UseConcMarkSweepGC</li> |
| </ul> |
| <blockquote> |
| <p>当然这个测试环境较有局限,故当前测试结果未必有非常权威的代表性。</p> |
| </blockquote> |
| <h3 id="测试脚本">测试脚本</h3> |
| <p>和dubbo自身的基准测试保持接近:</p> |
| <p>10个并发客户端持续不断发出请求:</p> |
| <ul> |
| <li>传入嵌套复杂对象(但单个数据量很小),不做任何处理,原样返回</li> |
| <li>传入50K字符串,不做任何处理,原样返回(TODO:结果尚未列出)</li> |
| </ul> |
| <p>进行5分钟性能测试。(引用dubbo自身测试的考虑:主要考察序列化和网络IO的性能,因此服务端无任何业务逻辑。取10并发是考虑到rpc协议在高并发下对CPU的使用率较高可能会先打到瓶颈。)</p> |
| <h3 id="dubbo-rpc中不同序列化生成字节大小比较">Dubbo RPC中不同序列化生成字节大小比较</h3> |
| <p>序列化生成字节数的大小是一个比较有确定性的指标,它决定了远程调用的网络传输时间和带宽占用。</p> |
| <p>针对复杂对象的结果如下(数值越小越好):</p> |
| <table> |
| <thead> |
| <tr> |
| <th>序列化实现</th> |
| <th>请求字节数</th> |
| <th>响应字节数</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>Kryo</td> |
| <td>272</td> |
| <td>90</td> |
| </tr> |
| <tr> |
| <td>FST</td> |
| <td>288</td> |
| <td>96</td> |
| </tr> |
| <tr> |
| <td>Dubbo Serialization</td> |
| <td>430</td> |
| <td>186</td> |
| </tr> |
| <tr> |
| <td>Hessian</td> |
| <td>546</td> |
| <td>329</td> |
| </tr> |
| <tr> |
| <td>FastJson</td> |
| <td>461</td> |
| <td>218</td> |
| </tr> |
| <tr> |
| <td>Json</td> |
| <td>657</td> |
| <td>409</td> |
| </tr> |
| <tr> |
| <td>Java Serialization</td> |
| <td>963</td> |
| <td>630</td> |
| </tr> |
| </tbody> |
| </table> |
| <h3 id="dubbo-rpc中不同序列化响应时间和吞吐量对比">Dubbo RPC中不同序列化响应时间和吞吐量对比</h3> |
| <table> |
| <thead> |
| <tr> |
| <th>远程调用方式</th> |
| <th>平均响应时间</th> |
| <th>平均TPS(每秒事务数)</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>REST: Jetty + JSON</td> |
| <td>7.806</td> |
| <td>1280</td> |
| </tr> |
| <tr> |
| <td>REST: Jetty + JSON + GZIP</td> |
| <td>TODO</td> |
| <td>TODO</td> |
| </tr> |
| <tr> |
| <td>REST: Jetty + XML</td> |
| <td>TODO</td> |
| <td>TODO</td> |
| </tr> |
| <tr> |
| <td>REST: Jetty + XML + GZIP</td> |
| <td>TODO</td> |
| <td>TODO</td> |
| </tr> |
| <tr> |
| <td>REST: Tomcat + JSON</td> |
| <td>2.082</td> |
| <td>4796</td> |
| </tr> |
| <tr> |
| <td>REST: Netty + JSON</td> |
| <td>2.182</td> |
| <td>4576</td> |
| </tr> |
| <tr> |
| <td>Dubbo: FST</td> |
| <td>1.211</td> |
| <td>8244</td> |
| </tr> |
| <tr> |
| <td>Dubbo: kyro</td> |
| <td>1.182</td> |
| <td>8444</td> |
| </tr> |
| <tr> |
| <td>Dubbo: dubbo serialization</td> |
| <td>1.43</td> |
| <td>6982</td> |
| </tr> |
| <tr> |
| <td>Dubbo: hessian2</td> |
| <td>1.49</td> |
| <td>6701</td> |
| </tr> |
| <tr> |
| <td>Dubbo: fastjson</td> |
| <td>1.572</td> |
| <td>6352</td> |
| </tr> |
| </tbody> |
| </table> |
| <p><img src="https://dubbo.apache.org/imgs/user/rt.png" alt="rt"></p> |
| <p><img src="https://dubbo.apache.org/imgs/user/tps.png" alt="tps"></p> |
| <blockquote> |
| <p>测试总结: 就目前结果而言,我们可以看到不管从生成字节的大小,还是平均响应时间和平均TPS,Kryo和FST相比Dubbo RPC中原有的序列化方式都有非常显著的改进。</p> |
| </blockquote> |
| <blockquote> |
| <p>未来展望:当Kryo或者FST在dubbo中当应用足够成熟之后,我们很可能会将dubbo RPC的默认序列化从hessian2改为它们中间的某一个。</p> |
| </blockquote></description></item></channel></rss> |