This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/dubbo-website.git
The following commit(s) were added to refs/heads/asf-site by this push:
new 6905928 Automated deployment: Sat Mar 7 16:23:13 UTC 2020
1c41196ff38c31a49f925910510849921386112a
6905928 is described below
commit 6905928fccfcd7d0d62f96010d027e09e9cb8618
Author: lovepoem <[email protected]>
AuthorDate: Sat Mar 7 16:23:13 2020 +0000
Automated deployment: Sat Mar 7 16:23:13 UTC 2020
1c41196ff38c31a49f925910510849921386112a
---
build/blog.js | 2 +-
.../consistent-hash-balance-model.jpg | Bin 0 -> 29205 bytes
.../consistent-hash-delete-node-model.jpg | Bin 0 -> 32314 bytes
.../consistenthash/consistent-hash-init-model.jpg | Bin 0 -> 29515 bytes
.../consistent-hash-new-node-model.jpg | Bin 0 -> 35015 bytes
.../consistent-hash-request-model.jpg | Bin 0 -> 34165 bytes
.../consistent-hash-virtual-node-model.jpg | Bin 0 -> 33019 bytes
md_json/blog.json | 9 ++
.../blog/dubbo-consistent-hash-implementation.html | 96 +++++++++++++++++++++
.../blog/dubbo-consistent-hash-implementation.json | 10 +++
zh-cn/blog/index.html | 2 +-
11 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/build/blog.js b/build/blog.js
index dad8a76..c4d80e8 100644
--- a/build/blog.js
+++ b/build/blog.js
@@ -1,4 +1,4 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var
o=n[r]={i:r,l:!1,exports:{}};return
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var
n={};t.m=e,t.c=n,t.i=function(e){return
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
n=e&&e.__esModule?function(){return e.default}:function(){return e};return
t.d(n,"a",n),n},t.o=function(e,t){return
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=317 [...]
+!function(e){function t(r){if(n[r])return n[r].exports;var
o=n[r]={i:r,l:!1,exports:{}};return
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var
n={};t.m=e,t.c=n,t.i=function(e){return
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
n=e&&e.__esModule?function(){return e.default}:function(){return e};return
t.d(n,"a",n),n},t.o=function(e,t){return
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=317 [...]
Copyright (c) 2017 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
diff --git a/img/blog/consistenthash/consistent-hash-balance-model.jpg
b/img/blog/consistenthash/consistent-hash-balance-model.jpg
new file mode 100644
index 0000000..9bcee0c
Binary files /dev/null and
b/img/blog/consistenthash/consistent-hash-balance-model.jpg differ
diff --git a/img/blog/consistenthash/consistent-hash-delete-node-model.jpg
b/img/blog/consistenthash/consistent-hash-delete-node-model.jpg
new file mode 100644
index 0000000..a07e294
Binary files /dev/null and
b/img/blog/consistenthash/consistent-hash-delete-node-model.jpg differ
diff --git a/img/blog/consistenthash/consistent-hash-init-model.jpg
b/img/blog/consistenthash/consistent-hash-init-model.jpg
new file mode 100644
index 0000000..bcbbc00
Binary files /dev/null and
b/img/blog/consistenthash/consistent-hash-init-model.jpg differ
diff --git a/img/blog/consistenthash/consistent-hash-new-node-model.jpg
b/img/blog/consistenthash/consistent-hash-new-node-model.jpg
new file mode 100644
index 0000000..1af435b
Binary files /dev/null and
b/img/blog/consistenthash/consistent-hash-new-node-model.jpg differ
diff --git a/img/blog/consistenthash/consistent-hash-request-model.jpg
b/img/blog/consistenthash/consistent-hash-request-model.jpg
new file mode 100644
index 0000000..fb5f3d4
Binary files /dev/null and
b/img/blog/consistenthash/consistent-hash-request-model.jpg differ
diff --git a/img/blog/consistenthash/consistent-hash-virtual-node-model.jpg
b/img/blog/consistenthash/consistent-hash-virtual-node-model.jpg
new file mode 100644
index 0000000..b9de63d
Binary files /dev/null and
b/img/blog/consistenthash/consistent-hash-virtual-node-model.jpg differ
diff --git a/md_json/blog.json b/md_json/blog.json
index 861d294..8e75d14 100644
--- a/md_json/blog.json
+++ b/md_json/blog.json
@@ -407,6 +407,15 @@
}
},
{
+ "filename": "dubbo-consistent-hash-implementation.md",
+ "link": "/zh-cn/blog/dubbo-consistent-hash-implementation.html",
+ "meta": {
+ "title": "Dubbo一致性Hash负载均衡实现剖析",
+ "keywords": "Dubbo, Consistent Hash,一致性Hash,一致性哈希",
+ "description": "本文以一般的一致性Hash实现作为引子,详细剖析了Dubbo一致性Hash负载均衡算法的实现"
+ }
+ },
+ {
"filename": "dubbo-context-information.md",
"link": "/zh-cn/blog/dubbo-context-information.html",
"meta": {
diff --git a/zh-cn/blog/dubbo-consistent-hash-implementation.html
b/zh-cn/blog/dubbo-consistent-hash-implementation.html
new file mode 100644
index 0000000..be85f06
--- /dev/null
+++ b/zh-cn/blog/dubbo-consistent-hash-implementation.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no">
+ <meta name="keywords" content="Dubbo, Consistent Hash,一致性Hash,一致性哈希" />
+ <meta name="description"
content="本文以一般的一致性Hash实现作为引子,详细剖析了Dubbo一致性Hash负载均衡算法的实现" />
+ <!-- 网页标签标题 -->
+ <title>Dubbo一致性Hash负载均衡实现剖析</title>
+ <link rel="shortcut icon" href="/img/dubbo.ico"/>
+ <link rel="stylesheet" href="/build/blogDetail.css" />
+</head>
+<body>
+ <div id="root"><div class="blog-detail-page" data-reactroot=""><header
class="header-container header-container-normal"><div class="header-body"><a
href="/zh-cn/index.html"><img class="logo"
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span
class="icon-search"></span></div><span class="language-switch
language-switch-normal">En</span><div class="header-menu"><img
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item
menu-item-normal"><a h [...]
+<h3>一、环形队列Hash映射模型</h3>
+<p>这种方案,其基础还是基于取模运算。对2^32取模,那么,Hash值的区间为[0, 2^32-1]。接下来要做的,就包括两部分:</p>
+<h4><strong>a、映射服务</strong></h4>
+<p>将服务地址(ip+端口)按照一定规则构造出特定的识别码(如md5码),再用识别码对2^32取模,确定服务在Hash值区间对应的位置。假设有Node1、Node2、Node3三个服务,其映射关系如下:</p>
+<p><img src="../../img/blog/consistenthash/consistent-hash-init-model.jpg"
alt="Init"></p>
+<h4><strong>b、映射请求、定位服务</strong></h4>
+<p>在发起请求时,我们往往会带上参数,而这些参数,就可以被我们用来确定具体调用哪一个服务。假设有请求R1、R2、R3,对它们的参数也经过计算特定识别码、取余的一系列运算之后,有如下映射关系:</p>
+<p><img src="../../img/blog/consistenthash/consistent-hash-request-model.jpg"
alt="Request"></p>
+<p>从图中,我们可以看到,R1请求映射在0-Node1中间,R2请求映射在Node1-Node2中间,R3请求映射在Node2-Node3中间。我们取<strong>服务Hash值大于请求Hash值</strong>的<strong>第一个服务</strong>作为实际的调用服务。也就是说,R1请求将调用Node1服务,R2请求将调用Node2服务,R3请求将调用Node3服务。</p>
+<h4><strong>c、新增服务节点</strong></h4>
+<p>假设新增服务Node4,映射在Node3之前,恰巧破坏了原来的一个映射关系:</p>
+<p><img src="../../img/blog/consistenthash/consistent-hash-new-node-model.jpg"
alt="New Node"></p>
+<p>这样,请求R3将会实际调用服务Node4,但请求R1、R2不受影响。</p>
+<h4><strong>d、删除服务节点</strong></h4>
+<p>假设服务Node2宕机,那么R2请求将会映射到Node3:</p>
+<p><img
src="../../img/blog/consistenthash/consistent-hash-delete-node-model.jpg"
alt="Delete Node"></p>
+<p>原本的R1、R3请求不受影响。</p>
+<blockquote>
+<p>可以看出,当新增、删除服务时,受影响的请求是有限的。不至于像简单取模映射一般,服务发生变化时,需要调整全局的映射关系。</p>
+</blockquote>
+<h4><strong>e、平衡性与虚拟节点</strong></h4>
+<p>在我们上面的假设中,我们假设Node1、Node2、Node3三个服务在经过Hash映射后所分布的位置恰巧把环切成了均等的三分,请求的分布也基本是平衡的。但是实际上计算服务Hash值的时候,是很难这么巧的。也许一不小心就映射成了这个样子:</p>
+<p><img src="../../img/blog/consistenthash/consistent-hash-balance-model.jpg"
alt="Balance"></p>
+<p>这样,就会导致大部分请求都会被映射到Node1上。因此,引出了虚拟节点。</p>
+<p>所谓虚拟节点,就是除了对服务本身地址进行Hash映射外,还通过在它地址上做些处理(比如Dubbo中,在ip+port的字符串后加上计数符1、2、3......,分别代表虚拟节点1、2、3),以达到同一服务映射多个节点的目的。通过引入虚拟节点,我们可以把上图中映射给Node1的请求进一步拆分:</p>
+<p><img
src="../../img/blog/consistenthash/consistent-hash-virtual-node-model.jpg"
alt="Virtual Node"></p>
+<p>如上图所示,若有请求落在Node3-Node1'区间,该请求应该是调用Node1'服务,但是因为Node1'是Node1的虚拟节点,所以实际调用的是Node1服务。通过引入虚拟节点,请求的分布就会比较平衡了。</p>
+<h3><strong>二、Dubbo一致性Hash的使用与负载均衡策略的引入阶段</strong></h3>
+<h4><strong>a、如何使用一致性Hash作为Dubbo的负载均衡策略?</strong></h4>
+<p>dubbo:service、dubbo:reference、dubbo:provider、dubbo:consumer、dubbo:method这几个配置项都可以配置Dubbo的负载均衡策略,其中一致性Hash的属性值是:<strong>consistenthash</strong>。</p>
+<p>以dubbo:reference为例:</p>
+<p><strong>XML配置:</strong></p>
+<blockquote>
+<p><dubbo:reference loadbalance="consistenthash" /></p>
+</blockquote>
+<p><strong>Properties配置:</strong></p>
+<blockquote>
+<p>dubbo.reference.loadbalance=consistenthash</p>
+</blockquote>
+<p><strong>注解:</strong></p>
+<blockquote>
+<p>@Reference(loadbalance = "consistenthash")</p>
+</blockquote>
+<h4><strong>b、Dubbo负载均衡策略的引入阶段</strong></h4>
+<p>Dubbo实现的是客户端负载均衡。关于服务接口代理类的实现,这里不做详细描述,可以参考官网:</p>
+<blockquote>
+<p>服务引入:<a
href="http://dubbo.apache.org/zh-cn/docs/source_code_guide/refer-service.html%E3%80%82">http://dubbo.apache.org/zh-cn/docs/source_code_guide/refer-service.html。</a></p>
+</blockquote>
+<p>在接口代理类生成、并且装配好后,服务的调用基本是这样一个流程:proxy -> MockClusterInvoker ->
集群策略(如:FailoverClusterInvoker) -> 根据选定的负载均衡策略确定选定的远程调用对象Invoker。</p>
+<p><strong>负载均衡策略的初始化</strong>是在AbstractClusterInvoker中的initLoadBalance方法中初始化的:</p>
+<pre><code class="language-java"><span class="hljs-function"><span
class="hljs-keyword">protected</span> LoadBalance <span
class="hljs-title">initLoadBalance</span><span
class="hljs-params">(List<Invoker<T>> invokers, Invocation
invocation)</span> </span>{
+ <span class="hljs-keyword">if</span>
(CollectionUtils.isNotEmpty(invokers)) {
+ <span class="hljs-keyword">return</span>
ExtensionLoader.getExtensionLoader(LoadBalance<span class="hljs-class">.<span
class="hljs-keyword">class</span>).<span
class="hljs-title">getExtension</span>(<span
class="hljs-title">invokers</span>.<span class="hljs-title">get</span>(0).<span
class="hljs-title">getUrl</span>()
+ .<span class="hljs-title">getMethodParameter</span>(<span
class="hljs-title">RpcUtils</span>.<span
class="hljs-title">getMethodName</span>(<span
class="hljs-title">invocation</span>), <span
class="hljs-title">LOADBALANCE_KEY</span>, <span
class="hljs-title">DEFAULT_LOADBALANCE</span>))</span>;
+ } <span class="hljs-keyword">else</span> {
+ <span class="hljs-keyword">return</span>
ExtensionLoader.getExtensionLoader(LoadBalance<span class="hljs-class">.<span
class="hljs-keyword">class</span>).<span
class="hljs-title">getExtension</span>(<span
class="hljs-title">DEFAULT_LOADBALANCE</span>)</span>;
+ }
+}
+</code></pre>
+<p>这部分代码逻辑分为两部分:</p>
+<p>1、获取调用方法所配置的LOADBALANCE_KEY属性的值,LOADBALANCE_KEY这个常量的实际值为:loadbalance,即为我们的所配置的属性;</p>
+<p>2、利用SPI机制来初始化并加载该值所代表的负载均衡策略。</p>
+<p>所有的负载均衡策略都会继承LoadBalance接口。在各种集群策略中,最终都会调用AbstractClusterInvoker的select方法,而AbstractClusterInvoker会在doSelect中,<strong>调用LoadBalance的select方法,这里即开始了负载均衡策略的执行。</strong></p>
+</section><footer class="footer-container"><div class="footer-body"><img
src="/img/dubbo_gray.png"/><img class="apache" src="/img/apache_logo.png"/><div
class="cols-container"><div class="col col-12"><h3></h3><p></p></div><div
class="col col-4"><dl><dt>ASF</dt><dd><a href="http://www.apache.org"
target="_self">基金会</a></dd><dd><a href="http://www.apache.org/licenses/"
target="_self">证书</a></dd><dd><a
href="http://www.apache.org/events/current-event"
target="_self">事件</a></dd><dd><a href=" [...]
+ <script
src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
+ <script
src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
+ <script>
+ window.rootPath = '';
+ </script>
+ <script src="/build/blogDetail.js"></script>
+ <!-- Global site tag (gtag.js) - Google Analytics -->
+ <script async
src="https://www.googletagmanager.com/gtag/js?id=UA-112489517-1"></script>
+ <script>
+ window.dataLayer = window.dataLayer || [];
+ function gtag(){dataLayer.push(arguments);}
+ gtag('js', new Date());
+
+ gtag('config', 'UA-112489517-1');
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/zh-cn/blog/dubbo-consistent-hash-implementation.json
b/zh-cn/blog/dubbo-consistent-hash-implementation.json
new file mode 100644
index 0000000..4b99bfc
--- /dev/null
+++ b/zh-cn/blog/dubbo-consistent-hash-implementation.json
@@ -0,0 +1,10 @@
+{
+ "filename": "dubbo-consistent-hash-implementation.md",
+ "__html":
"<p>需要强调的是,Dubbo的Hash映射模型与大部分网上资料描述的<strong>环形队列Hash映射模型</strong>是存在一些区别的。于我而言,环形队列Hash映射模型,不足以让我对一致性Hash有足够彻底的了解。直到看懂了Dubbo的一致性Hash的实现,才觉得豁然开朗。</p>\n<h3>一、环形队列Hash映射模型</h3>\n<p>这种方案,其基础还是基于取模运算。对2^32取模,那么,Hash值的区间为[0,
2^32-1]。接下来要做的,就包括两部分:</p>\n<h4><strong>a、映射服务</strong></h4>\n<p>将服务地址(ip+端口)按照一定规则构造出特定的识别码(如md5码),再用识别码对2^32取模,确定服务在Hash值区间对应的位置。假设有Node1、Node2、Node3三个服务,其映射关系如下:</p>\n<p><img
src=\"../../img/blog/consistenthash/consistent-hash-init-model.jpg\"
alt=\"Init\">< [...]
+ "link": "/zh-cn/blog/dubbo-consistent-hash-implementation.html",
+ "meta": {
+ "title": "Dubbo一致性Hash负载均衡实现剖析",
+ "keywords": "Dubbo, Consistent Hash,一致性Hash,一致性哈希",
+ "description": "本文以一般的一致性Hash实现作为引子,详细剖析了Dubbo一致性Hash负载均衡算法的实现"
+ }
+}
\ No newline at end of file
diff --git a/zh-cn/blog/index.html b/zh-cn/blog/index.html
index 0f2e582..ea6de38 100644
--- a/zh-cn/blog/index.html
+++ b/zh-cn/blog/index.html
@@ -12,7 +12,7 @@
<link rel="stylesheet" href="/build/blog.css" />
</head>
<body>
- <div id="root"><div class="blog-list-page" data-reactroot=""><header
class="header-container header-container-normal"><div class="header-body"><a
href="/zh-cn/index.html"><img class="logo"
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span
class="icon-search"></span></div><span class="language-switch
language-switch-normal">En</span><div class="header-menu"><img
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item
menu-item-normal"><a hre [...]
+ <div id="root"><div class="blog-list-page" data-reactroot=""><header
class="header-container header-container-normal"><div class="header-body"><a
href="/zh-cn/index.html"><img class="logo"
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span
class="icon-search"></span></div><span class="language-switch
language-switch-normal">En</span><div class="header-menu"><img
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item
menu-item-normal"><a hre [...]
<script
src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
<script
src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
<script>