| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – 限流降级</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/</link><description>Recent content in 限流降级 on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview: Sentinel 限流</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/sentinel/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/sentinel/</guid><description> |
| <h2 id="sentinel-是什么">Sentinel 是什么</h2> |
| <p>随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。</p> |
| <h2 id="一示例架构说明">一、示例架构说明</h2> |
| <p>完整示例项目地址 <a href="https://github.com/apache/dubbo-samples/tree/master/4-governance/dubbo-samples-sentinel" target="_blank">dubbo-samples-sentinel</a></p> |
| <p>接口定义:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">FooService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>接口实现:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboService</span><span style="color:#719e07">(</span>timeout <span style="color:#719e07">=</span> 3000<span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">FooServiceImpl</span> <span style="color:#268bd2">implements</span> FooService <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> String<span style="color:#719e07">.</span>format<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Hello, %s at %s&#34;</span><span style="color:#719e07">,</span> name<span style="color:#719e07">,</span> LocalDateTime<span style="color:#719e07">.</span>now<span style="color:#719e07">());</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>限流配置:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>FlowRule flowRule <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> FlowRule<span style="color:#719e07">(</span>FooService<span style="color:#719e07">.</span>class<span style="color:#719e07">.</span>getName<span style="color:#719e07">())</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">.</span>setCount<span style="color:#719e07">(</span>10<span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">.</span>setGrade<span style="color:#719e07">(</span>RuleConstant<span style="color:#719e07">.</span>FLOW_GRADE_QPS<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span>FlowRuleManager<span style="color:#719e07">.</span>loadRules<span style="color:#719e07">(</span>Collections<span style="color:#719e07">.</span>singletonList<span style="color:#719e07">(</span>flowRule<span style="color:#719e07">));</span> |
| </span></span></code></pre></div><h2 id="二快速启动示例">二、快速启动示例</h2> |
| <h3 id="step-1-下载源码">Step 1: 下载源码</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-shell" data-lang="shell"><span style="display:flex;"><span>git clone -b master https://github.com/apache/dubbo-samples.git |
| </span></span><span style="display:flex;"><span><span style="color:#b58900">cd</span> ./dubbo-samples-sentinel/ |
| </span></span></code></pre></div><h3 id="step-2-构建用例">Step 2: 构建用例</h3> |
| <p>执行 maven 命令,打包 demo 工程</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mvn clean package |
| </span></span></code></pre></div><h3 id="step-3-启动-provider">Step 3: 启动 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-java" data-lang="java"><span style="display:flex;"><span>java <span style="color:#719e07">-</span>classpath <span style="color:#719e07">./</span>target<span style="color:#719e07">/</span>dubbo<span style="color:#719e07">-</span>samples<span style="color:#719e07">-</span>sentinel<span style="color:#719e07">-</span>1<span style="color:#719e07">.</span>0<span style="color:#719e07">-</span>SNAPSHOT<span style="color:#719e07">.</span>jar org<span style="color:#719e07">.</span>apache<span style="color:#719e07">.</span>samples<span style="color:#719e07">.</span>sentinel<span style="color:#719e07">.</span>FooProviderBootstrap |
| </span></span></code></pre></div><h3 id="step-4-启动-orderservice">Step 4: 启动 OrderService</h3> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>java <span style="color:#719e07">-</span>classpath <span style="color:#719e07">./</span>target<span style="color:#719e07">/</span>dubbo<span style="color:#719e07">-</span>samples<span style="color:#719e07">-</span>sentinel<span style="color:#719e07">-</span>1<span style="color:#719e07">.</span>0<span style="color:#719e07">-</span>SNAPSHOT<span style="color:#719e07">.</span>jar org<span style="color:#719e07">.</span>apache<span style="color:#719e07">.</span>samples<span style="color:#719e07">.</span>sentinel<span style="color:#719e07">.</span>FooConsumerBootstrap |
| </span></span></code></pre></div><p>可以看到控制台输出中,<code>Blocked</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>Success: Hello, dubbo at 2022-08-08T15:42:40.809 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.812 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.815 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.818 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.821 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.823 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.826 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.828 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.830 |
| </span></span><span style="display:flex;"><span>Success: Hello, dubbo at 2022-08-08T15:42:40.834 |
| </span></span><span style="display:flex;"><span>Blocked |
| </span></span><span style="display:flex;"><span>Blocked |
| </span></span><span style="display:flex;"><span>Blocked |
| </span></span><span style="display:flex;"><span>Blocked |
| </span></span><span style="display:flex;"><span>Blocked |
| </span></span></code></pre></div><blockquote> |
| <p>关于 Sentinel 的更多使用方式可以参考:<a href="https://dubbo.apache.org/zh-cn/blog/2018/07/27/sentinel-%E4%B8%BA-dubbo-%E6%9C%8D%E5%8A%A1%E4%BF%9D%E9%A9%BE%E6%8A%A4%E8%88%AA/">Sentinel 为 Dubbo 服务保驾护航</a>,<a href="https://sentinelguard.io/zh-cn/index.html">Sentinel 官网</a></p> |
| </blockquote></description></item><item><title>Overview: Hystrix 熔断降级</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/hystrix/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/hystrix/</guid><description> |
| <h2 id="背景">背景</h2> |
| <p>Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能。</p> |
| <p>本文介绍在spring应用里,怎么把 Dubbo 和 Hystrix 结合起来使用。</p> |
| <ul> |
| <li><a href="https://github.com/Netflix/Hystrix">https://github.com/Netflix/Hystrix</a></li> |
| <li><a href="https://github.com/apache/dubbo">https://github.com/apache/dubbo</a></li> |
| </ul> |
| <h2 id="spring-boot应用">Spring Boot应用</h2> |
| <p>Demo 地址: <a href="https://github.com/dubbo/dubbo-samples/tree/master/4-governance/dubbo-samples-spring-boot-hystrix">https://github.com/dubbo/dubbo-samples/tree/master/4-governance/dubbo-samples-spring-boot-hystrix</a></p> |
| <h3 id="生成dubbo集成spring-boot的应用">生成dubbo集成spring boot的应用</h3> |
| <p>对于不熟悉dubbo 集成spring boot应用的同学,可以在这里直接生成dubbo + spring boot的工程: <a href="http://start.dubbo.apache.org/bootstrap.html/">http://start.dubbo.apache.org/bootstrap.html/</a></p> |
| <h3 id="配置spring-cloud-starter-netflix-hystrix">配置spring-cloud-starter-netflix-hystrix</h3> |
| <p>spring boot官方提供了对hystrix的集成,直接在pom.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;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.springframework.cloud<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>spring-cloud-starter-netflix-hystrix<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>1.4.4.RELEASE<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>然后在Application类上增加<code>@EnableHystrix</code>来启用hystrix starter:</p> |
| <div class="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">@SpringBootApplication</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">@EnableHystrix</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">ProviderApplication</span> <span style="color:#719e07">{</span> |
| </span></span></code></pre></div><h3 id="配置provider端">配置Provider端</h3> |
| <p>在Dubbo的Provider上增加<code>@HystrixCommand</code>配置,这样子调用就会经过Hystrix代理。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Service</span><span style="color:#719e07">(</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">HelloServiceImpl</span> <span style="color:#268bd2">implements</span> HelloService <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@HystrixCommand</span><span style="color:#719e07">(</span>commandProperties <span style="color:#719e07">=</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@HystrixProperty</span><span style="color:#719e07">(</span>name <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;circuitBreaker.requestVolumeThreshold&#34;</span><span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;10&#34;</span><span style="color:#719e07">),</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@HystrixProperty</span><span style="color:#719e07">(</span>name <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;execution.isolation.thread.timeoutInMilliseconds&#34;</span><span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;2000&#34;</span><span style="color:#719e07">)</span> <span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">// System.out.println(&#34;async provider received: &#34; + name); |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#586e75">// return &#34;annotation: hello, &#34; + name; |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"></span> <span style="color:#719e07">throw</span> <span style="color:#719e07">new</span> RuntimeException<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Exception to show hystrix enabled.&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><h3 id="配置consumer端">配置Consumer端</h3> |
| <p>对于Consumer端,则可以增加一层method调用,并在method上配置<code>@HystrixCommand</code>。当调用出错时,会走到<code>fallbackMethod = &quot;reliable&quot;</code>的调用里。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span> <span style="color:#268bd2">@Reference</span><span style="color:#719e07">(</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0.0&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> HelloService demoService<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@HystrixCommand</span><span style="color:#719e07">(</span>fallbackMethod <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;reliable&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">doSayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> demoService<span style="color:#719e07">.</span>sayHello<span style="color:#719e07">(</span>name<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">reliable</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;hystrix fallback value&#34;</span><span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>通过上面的配置,很简单地就完成了Spring Boot里Dubbo + Hystrix的集成。</p> |
| <h2 id="传统spring-annotation应用">传统Spring Annotation应用</h2> |
| <p>Demo地址: <a href="https://github.com/dubbo/dubbo-samples/tree/master/4-governance/dubbo-samples-spring-hystrix">https://github.com/dubbo/dubbo-samples/tree/master/4-governance/dubbo-samples-spring-hystrix</a> |
| 传统spring annotation应用的配置其实也很简单,和spring boot应用不同的是:</p> |
| <ol> |
| <li>显式配置Spring AOP支持:<code>@EnableAspectJAutoProxy</code></li> |
| <li>显式通过<code>@Configuration</code>配置<code>HystrixCommandAspect</code> Bean。</li> |
| </ol> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span> <span style="color:#268bd2">@Configuration</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@EnableDubbo</span><span style="color:#719e07">(</span>scanBasePackages <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;com.alibaba.dubbo.samples.annotation.action&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@PropertySource</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;classpath:/spring/dubbo-consumer.properties&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@ComponentScan</span><span style="color:#719e07">(</span>value <span style="color:#719e07">=</span> <span style="color:#719e07">{</span><span style="color:#2aa198">&#34;com.alibaba.dubbo.samples.annotation.action&#34;</span><span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@EnableAspectJAutoProxy</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">static</span> <span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">ConsumerConfiguration</span> <span style="color:#719e07">{</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> HystrixCommandAspect <span style="color:#268bd2">hystrixCommandAspect</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> HystrixCommandAspect<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span></code></pre></div><h2 id="hystrix集成spring-aop原理">Hystrix集成Spring AOP原理</h2> |
| <p>在上面的例子里可以看到,Hystrix对Spring的集成是通过Spring AOP来实现的。下面简单分析下实现。</p> |
| <div class="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">@Aspect</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">HystrixCommandAspect</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Pointcut</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">hystrixCommandAnnotationPointcut</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Pointcut</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">hystrixCollapserAnnotationPointcut</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Around</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Object <span style="color:#268bd2">methodsAnnotatedWithHystrixCommand</span><span style="color:#719e07">(</span><span style="color:#268bd2">final</span> ProceedingJoinPoint joinPoint<span style="color:#719e07">)</span> <span style="color:#268bd2">throws</span> Throwable <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> Method method <span style="color:#719e07">=</span> getMethodFromTarget<span style="color:#719e07">(</span>joinPoint<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> Validate<span style="color:#719e07">.</span>notNull<span style="color:#719e07">(</span>method<span style="color:#719e07">,</span> <span style="color:#2aa198">&#34;failed to get method from joinPoint: %s&#34;</span><span style="color:#719e07">,</span> joinPoint<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#719e07">(</span>method<span style="color:#719e07">.</span>isAnnotationPresent<span style="color:#719e07">(</span>HystrixCommand<span style="color:#719e07">.</span>class<span style="color:#719e07">)</span> <span style="color:#719e07">&amp;&amp;</span> method<span style="color:#719e07">.</span>isAnnotationPresent<span style="color:#719e07">(</span>HystrixCollapser<span style="color:#719e07">.</span>class<span style="color:#719e07">))</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">throw</span> <span style="color:#719e07">new</span> IllegalStateException<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;method cannot be annotated with HystrixCommand and HystrixCollapser &#34;</span> <span style="color:#719e07">+</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#2aa198">&#34;annotations at the same time&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> MetaHolderFactory metaHolderFactory <span style="color:#719e07">=</span> META_HOLDER_FACTORY_MAP<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span>HystrixPointcutType<span style="color:#719e07">.</span>of<span style="color:#719e07">(</span>method<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> MetaHolder metaHolder <span style="color:#719e07">=</span> metaHolderFactory<span style="color:#719e07">.</span>create<span style="color:#719e07">(</span>joinPoint<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> HystrixInvokable invokable <span style="color:#719e07">=</span> HystrixCommandFactory<span style="color:#719e07">.</span>getInstance<span style="color:#719e07">().</span>create<span style="color:#719e07">(</span>metaHolder<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> ExecutionType executionType <span style="color:#719e07">=</span> metaHolder<span style="color:#719e07">.</span>isCollapserAnnotationPresent<span style="color:#719e07">()</span> <span style="color:#719e07">?</span> |
| </span></span><span style="display:flex;"><span> metaHolder<span style="color:#719e07">.</span>getCollapserExecutionType<span style="color:#719e07">()</span> <span style="color:#719e07">:</span> metaHolder<span style="color:#719e07">.</span>getExecutionType<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> Object result<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">try</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#719e07">(!</span>metaHolder<span style="color:#719e07">.</span>isObservable<span style="color:#719e07">())</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> result <span style="color:#719e07">=</span> CommandExecutor<span style="color:#719e07">.</span>execute<span style="color:#719e07">(</span>invokable<span style="color:#719e07">,</span> executionType<span style="color:#719e07">,</span> metaHolder<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">else</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> result <span style="color:#719e07">=</span> executeObservable<span style="color:#719e07">(</span>invokable<span style="color:#719e07">,</span> executionType<span style="color:#719e07">,</span> metaHolder<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">catch</span> <span style="color:#719e07">(</span>HystrixBadRequestException e<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">throw</span> e<span style="color:#719e07">.</span>getCause<span style="color:#719e07">()</span> <span style="color:#719e07">!=</span> <span style="color:#cb4b16">null</span> <span style="color:#719e07">?</span> e<span style="color:#719e07">.</span>getCause<span style="color:#719e07">()</span> <span style="color:#719e07">:</span> e<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">catch</span> <span style="color:#719e07">(</span>HystrixRuntimeException e<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">throw</span> hystrixRuntimeExceptionToThrowable<span style="color:#719e07">(</span>metaHolder<span style="color:#719e07">,</span> e<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> result<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span></code></pre></div><ol> |
| <li><code>HystrixCommandAspect</code>里定义了两个注解的AspectJ Pointcut:<code>@HystrixCommand</code>, <code>@HystrixCollapser</code>。所有带这两个注解的spring bean都会经过AOP处理</li> |
| <li>在<code>@Around</code> AOP处理函数里,可以看到Hystrix会创建出<code>HystrixInvokable</code>,再通过<code>CommandExecutor</code>来执行</li> |
| </ol> |
| <h2 id="spring-cloud-starter-netflix-hystrix的代码分析">spring-cloud-starter-netflix-hystrix的代码分析</h2> |
| <ol> |
| <li><code>@EnableHystrix</code> 引入了<code>@EnableCircuitBreaker</code>,<code>@EnableCircuitBreaker</code>引入了<code>EnableCircuitBreakerImportSelector</code> |
| <div class="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">@EnableCircuitBreaker</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">@interface</span> EnableHystrix <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">@Import</span><span style="color:#719e07">(</span>EnableCircuitBreakerImportSelector<span style="color:#719e07">.</span>class<span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">@interface</span> EnableCircuitBreaker <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div></li> |
| <li><code>EnableCircuitBreakerImportSelector</code>继承了<code>SpringFactoryImportSelector&lt;EnableCircuitBreaker&gt;</code>,使spring加载<code>META-INF/spring.factories</code>里的<code>EnableCircuitBreaker</code>声明的配置 |
| 在<code>META-INF/spring.factories</code>里可以找到下面的配置,也就是引入了<code>HystrixCircuitBreakerConfiguration</code>。 |
| <div class="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>org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker<span style="color:#719e07">=</span><span style="color:#2aa198">\ |
| </span></span></span><span style="display:flex;"><span><span style="color:#2aa198">org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration</span> |
| </span></span></code></pre></div></li> |
| <li>在<code>HystrixCircuitBreakerConfiguration</code>里可以发现创建了<code>HystrixCommandAspect</code> |
| <div class="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">@Configuration</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">HystrixCircuitBreakerConfiguration</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><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> HystrixCommandAspect <span style="color:#268bd2">hystrixCommandAspect</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> HystrixCommandAspect<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span></code></pre></div></li> |
| </ol> |
| <p>可见<code>spring-cloud-starter-netflix-hystrix</code>实际上也是创建了<code>HystrixCommandAspect</code>来集成Hystrix。 |
| 另外<code>spring-cloud-starter-netflix-hystrix</code>里还有metrics, health, dashboard等集成。</p> |
| <h2 id="总结">总结</h2> |
| <ul> |
| <li>对于dubbo provider的<code>@Service</code>是一个spring bean,直接在上面配置<code>@HystrixCommand</code>即可</li> |
| <li>对于dubbo consumer的<code>@Reference</code>,可以通过加一层简单的spring method包装,配置<code>@HystrixCommand</code>即可</li> |
| <li>Hystrix本身提供<code>HystrixCommandAspect</code>来集成Spring AOP,配置了<code>@HystrixCommand</code>和<code>@HystrixCollapser</code>的spring method都会被Hystrix处理</li> |
| </ul> |
| <h2 id="链接">链接</h2> |
| <ul> |
| <li><a href="https://github.com/Netflix/Hystrix">https://github.com/Netflix/Hystrix</a></li> |
| <li><a href="https://github.com/apache/dubbo">https://github.com/apache/dubbo</a></li> |
| <li><a href="http://start.dubbo.io/">http://start.dubbo.io/</a></li> |
| <li><a href="https://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_circuit_breaker_hystrix_clients">https://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_circuit_breaker_hystrix_clients</a></li> |
| </ul></description></item><item><title>Overview: Resilience4j</title><link>https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/resilience4j/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/tasks/rate-limit/resilience4j/</guid><description> |
| <p>Resilience4j 提供了一组高阶函数(装饰器),包括断路器,限流器,重试,隔离,可以对任何的函数式接口,lambda表达式,或方法的引用进行增强,并且这些装饰器可以进行叠加。这样做的好处是,你可以根据需要选择特定的装饰器进行组合。</p> |
| <p>关于 Resilience4j 与 Dubbo 集成的使用示例请参见 <a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-resilience4j">dubbo-samples-resilience4j</a></p></description></item></channel></rss> |