From 1b0f8a09b918a97e947355e2b12abaaf63d0a147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=99=93?= Date: Sun, 26 Aug 2018 19:15:43 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dubbo-cluster/readme.md | 28 ++++++++++++++++++ .../org/apache/dubbo/rpc/cluster/Cluster.java | 5 ++++ .../dubbo/rpc/cluster/Configurator.java | 2 ++ .../apache/dubbo/rpc/cluster/Directory.java | 5 ++++ .../apache/dubbo/rpc/cluster/LoadBalance.java | 4 +++ .../org/apache/dubbo/rpc/cluster/Merger.java | 6 ++++ .../org/apache/dubbo/rpc/cluster/Router.java | 5 ++++ .../\346\265\201\347\250\213\345\233\276.jpg" | Bin 0 -> 30817 bytes dubbo-common/readme.md | 3 ++ .../apache/dubbo/config/AbstractConfig.java | 12 ++++++++ dubbo-config/readme.md | 5 ++++ dubbo-container/readme.md | 8 +++++ .../META-INF/spring/dubbo-demo-consumer.xml | 3 +- .../META-INF/spring/dubbo-demo-provider.xml | 3 +- dubbo-filter/readme.md | 5 ++++ dubbo-monitor/readme.md | 2 ++ dubbo-registry/readme.md | 9 ++++++ dubbo-remoting/readme.md | 18 +++++++++++ dubbo-rpc/readme.md | 7 +++++ ...6\345\205\263\347\263\273\345\233\276.jpg" | Bin 0 -> 22860 bytes 20 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 dubbo-cluster/readme.md create mode 100644 "dubbo-cluster/\346\265\201\347\250\213\345\233\276.jpg" create mode 100644 dubbo-common/readme.md create mode 100644 dubbo-config/readme.md create mode 100644 dubbo-container/readme.md create mode 100644 dubbo-filter/readme.md create mode 100644 dubbo-monitor/readme.md create mode 100644 dubbo-registry/readme.md create mode 100644 dubbo-remoting/readme.md create mode 100644 dubbo-rpc/readme.md create mode 100644 "dubbo\346\250\241\345\235\227\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.jpg" diff --git a/dubbo-cluster/readme.md b/dubbo-cluster/readme.md new file mode 100644 index 000000000000..95ba44841d0b --- /dev/null +++ b/dubbo-cluster/readme.md @@ -0,0 +1,28 @@ + ## dubbo-cluster + > 集群模块:将多个服务提供方伪装为一个提供方,包括:负载均衡, 集群容错,路由,分组聚合等。集群的地址列表可以是静态配置的,也可以是由注册中心下发。 + +注册中心下发,由 dubbo-registry 提供特性。 + +### 容错 +> com.alibaba.dubbo.rpc.cluster.Cluster 接口 + com.alibaba.dubbo.rpc.cluster.support 包。 +Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。 +拓展参见 《Dubbo 用户指南 —— 集群容错》 和 《Dubbo 开发指南 —— 集群扩展》 文档。 + +### 目录 +> com.alibaba.dubbo.rpc.cluster.Directory 接口 + com.alibaba.dubbo.rpc.cluster.directory 包。 +Directory 代表了多个 Invoker ,可以把它看成 List ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更。 + +### 路由 +> com.alibaba.dubbo.rpc.cluster.Router 接口 + com.alibaba.dubbo.rpc.cluster.router 包。 +负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等。 + +### 配置 +> 接口 + com.alibaba.dubbo.rpc.cluster.configurator 包。 + +### 负载均衡 +> com.alibaba.dubbo.rpc.cluster.LoadBalance 接口 + com.alibaba.dubbo.rpc.cluster.loadbalance 包。 +LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选。 + +### 整体流程如下 + +![](流程图.jpg) diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java index e5ecb157c050..64596475b042 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java @@ -33,6 +33,11 @@ public interface Cluster { /** + * + *
+     * com.alibaba.dubbo.rpc.cluster.Cluster 接口 + com.alibaba.dubbo.rpc.cluster.support 包。
+     * Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。
+     * 
* Merge the directory invokers to a virtual invoker. * * @param diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java index aa229fabc553..ef0b5765bed2 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java @@ -19,6 +19,8 @@ import org.apache.dubbo.common.URL; /** + * + * 配置 com.alibaba.dubbo.rpc.cluster.configurator 包 * Configurator. (SPI, Prototype, ThreadSafe) * */ diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java index 67f021659e77..0df8f8c0e1df 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java @@ -33,6 +33,11 @@ public interface Directory extends Node { /** + * + *
+     *     com.alibaba.dubbo.rpc.cluster.Directory 接口 + com.alibaba.dubbo.rpc.cluster.directory 包。
+     * Directory 代表了多个 Invoker ,可以把它看成 List ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更。
+     * 
* get service type. * * @return service type. diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java index 4e6ced18a0e5..c368a4d4f873 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java @@ -27,6 +27,10 @@ import java.util.List; /** + *
+ *     com.alibaba.dubbo.rpc.cluster.LoadBalance 接口 + com.alibaba.dubbo.rpc.cluster.loadbalance 包。
+ * LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选。
+ * 
* LoadBalance. (SPI, Singleton, ThreadSafe) *

* Load-Balancing diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Merger.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Merger.java index 64bccf8cbdd5..1c1b227f31b2 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Merger.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Merger.java @@ -18,6 +18,12 @@ import org.apache.dubbo.common.extension.SPI; +/** + * 合并结果 + * com.alibaba.dubbo.rpc.cluster.Merger 接口 + com.alibaba.dubbo.rpc.cluster.merger 包。 + * 合并返回结果,用于分组聚合。 + * @param + */ @SPI public interface Merger { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java index 47aa2515a3c0..655b807da7c4 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java @@ -24,6 +24,11 @@ import java.util.List; /** + *

+ * com.alibaba.dubbo.rpc.cluster.Router 接口 + com.alibaba.dubbo.rpc.cluster.router  包。
+ * 负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等。
+ * 
+ *

* Router. (SPI, Prototype, ThreadSafe) *

* Routing diff --git "a/dubbo-cluster/\346\265\201\347\250\213\345\233\276.jpg" "b/dubbo-cluster/\346\265\201\347\250\213\345\233\276.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..ca8e7340a7480de4baf880db08b85df83798c011 GIT binary patch literal 30817 zcmb5Ub9iOTwm!UK+w9o3ZKq=!9ox2TCmq|ijgD=jV|0?vm)_@`d-uM-^UqgnKC5cr zeaEO;&#YBdbAGIR>;Mp@#3aQ4KtKQh(B}v6u?`RhfP#ShxjqXR7$_J7305E1|w2?zuU=wlFo_n9OxFvy>L|5L!gK_P&EK_H<% z%{ZTiPvhUsKp>#NVBioRYXDe~Pb?w`;wSL+864_LA4#MVgc+*YK04*a5)! zruY1m_xp9`{4md=RC{ysvLACd<^b6pXNuJ*JqlPRcbtu&5v56CL&}B|JTX{JYxcUk z*QKA_R@@~J{Z1AR`=nLB4OWm|*&?c^D>L12f4%3bRVM87Hq&-rGULe#hq~dY2WH}v zkWx{e5^=?%2V~+io3v-)LDg#74!+j4-@`{Uhd+{=$JcSx{?NPLjZu^-TI=y`>PY`; zZ!u%7I>YR=IrhY)@^U(OerEYeum4@Q`ku+!m*3RNS&70}F-8}`v8=CN06dEU&RlcG zuu^L(M`!mtFF#+O=-SNE-EZw*da$t5G%Y)GSMK;5(_dt$Ey}O*f*_XoY45*?x$(6m zjg-w1ck&eT8vGD>3QZa*_mIlfEvLsm*Q|Z3_=V7a!-L{+_vpqs+z@MiP8>e5UrF~o zc*X2~72AW^xx4x}GwjV*a&KolLp?VczC4tcNd!dq*O34Fmww6Jxa~H6daDKC8Tqey z0)QTDr#(IZLeIZbnE(I?$Q`l@-3&O-Ds-bB*946A4*=Ki^<$3nIDm-Le)ppTNV+rV zrrqY#)0j6JgsQnE(QCq`;WJi+G8Iu%7iUV@&f><8GSmwJI8juf^YE6Q92QmaR308YrJ^DzF7c}MPwf5B_ojH zua;Oj zf8Q{|GDzT+WRSOR-P@|eN3>|#pDwIGRbj-Za#n@&r&6wR;|()UsrsL4fGBgeM@wbX zJYYo}ypqOLvSw_5VO4CI?9&8PD36@upgC?p;EitRtlGILwsqG`Z~|B+?JPc@N`&)I zl>opKgz`f8W6XGT_lOB`tg*kW3jARO!ooYV+UmYo-17sR#q<&U(Sf-QQy-T4@kVRf z0@oE}^72kCZ@}vs)ZRiMT4 z=6?)K_CgWvoJ*TNw)o`20yvq@eww_zDiM6zKMQ>6B{JZgR`NFe!FT8w5JRNh7AGAB zZydL-XaC*En=jiyyl9uX@$!y@47`M@Xk|IHta~??00|L8?dAQK-oV2Z1Q96%5NH7k z5AgPp_3Oml2cWh}O9w@k8-XsGSj~0Jnc6J9LE8K?7MOH48uWu7Ws+^=OAmh6Z8twT z61uI_bhEgb1`3nr5i>d8dj-C;o5q-f%)9IC(^HpqvTHi|qH$1J5ojW>yplQI+-TVF zaXYz-SKqJD!%Z$fcJdjII#;!5YX!DDyO9E}X^ZX`O=1~E26OJde6xhHPjxaYJvb& z+wvz8?-^Umvl}|^eUV~L2>^iWdmz>#wDoi5y=}lb16VHHW91r8`!TSgR?PnEUgW9C zNRC@vr@`W**@!n??tPs%@xBMA;-c3isUV~aH}cNsFf4|&kVFkAXM!ty09a)~j!JQ* zb0qD7*30&Y)9eW#W^yvk==by#P84b@w=b2(fG4&q#mqGGPmIcIUp+EaJ!Cw4RKmUCh`6mXu_bdVy$=PlW! z^P;M_F~&S9WCh%;@i*jOO%7I4zT{y?P3x&cID6d{%?GQ@&Pxmv7W4E*$#fIHEqwsc zAO-7rPzxzXWhQ7OrD)a+E29rjBx4&?+&{VSO$$pFI-VkCmVC&(2&<^>sl8U~e%@6k z4nv)|l70>!6bm*lY~`4|6wj<+7*@FR>E<|! zYroG8<~#=Hc;%`%qC_*wt*6ET7>H|fZ{EMmb@*7;0(PEiI&ySSy*bY^I9J?iUY>F) z85u!WVO>eWLEQZQPK`h;r+9ji$tdqCPq2%r{Zw&w?@?mDc{H*ve*ARW1Ahhp*uxtG zfY%SNUT1dr2DGflJjY7d(<=w(4o}n}g(2&64nO~H|5gx~W#-PUUcFAc%K?zj+2Z15 z75hJad@1)4wwQ2|cOF|bM6b-CQNLRJJq%?*8`In-=MmKst4sF1hjn0P^=Z4$+ofqe zAnO?mDFOw1YbPJl9 zk~R;Tz&V|On7zwmG~_1N!0%yYNAnq%j$7uYw`*9 z(wje*O>btC#fo1d^fSf>7mPAZBa@6V!4J{@I~QOi{Kx9M_keFA;WB6tBWbm>;*tR1 zID!_x>Rdb{4hZ(Q77FXHZ5ypES**IHZcg4PCfq3cLy}C=SfQhT5CMk6e=K;sCVT+M zk=@fc!JO(oXMe}cgZ5$(VAw3c(%S8&<2JdTrcqht080QJI25{OSbeqCzQsRTz!8{> zPah5&Ul?wt)JLgAZW^ZwfcmP-w~MR#m^@QJ6jO=TYy$YJS*y!!-D`69^Zp6{BQY3N z!H8G1-McfG&+s518`lAhlFpi6)+3y%@nVS+M%4xWUkm^g1^Zml?4d>Ww|L_)uL1y= ziRPu{%MWkymLqNg017Aif589%BHFH{Cl4-z?qAq^bdKBnIMN|wIdUaQLV1Pb((W&R zN#93jjs7?jCa%=rKPycV! z|JHHZ(;5HO^!?lvupk0}fk1(PK|#TRKlcuw`p+!`02l-U2o)U(83h9p5e<`okcfd@ zflYu_pO}$}S?F`O0QtFz0D=U(tb4b(ck+WJ*co?Bn8o6L0A{;Mi*BGy-8pEly%~lm5m3>dzO{O-pB!6UoNj!997WYpi zX7f}u9M@hEP31q4KUwa$uG_6|I%v^2C&?3;t+#_50-=;8?9+x%Y7KJ@rIDQ)&Ast8I`*Gzq|dfe7%Geu@4U{IcS7L(2ypRUA0%9(QG*;9&(KX?i6=$y?lXerO%d$Z(m*|@ zYwD{UIPdx1nsztVf0~>TEw2jTEO}!C4SO@m5q^P{XfhbDF8}2l#`+`=+chqp{%zB6znMGW-AUTYVq`p+zEIf>u`+)sraAsof`|V}>-MX%)<&3raWeq>R z=1eGyOpAW}adYRJTF%=4ns}S88(xC=e@CW1ho9Zu?EeMv=u}B{TmFyR&?f_L(gz%GQjHc~Is zT_ifd7_wUtBaipge5c2y(=;@<8ffI|*;q}fSB5v4>2w&h98jd8p>+a4Pyksb6KZ`S+4I#XD)gR{d*5NoX6C+nC|Es0yS6$Q$) z>s&iKfyY8%fLbtIe6L_g#ZllGvjMaVWKEfTF2w>PvEk8UbYNdJJM3c;!&5b zABMEG{+c`4ol>@dZ(-G{k z(K;a$7q^=cWU$)Lt0|wh?B_b8A=?nXkUzGFiOZw)zi`7lzgp{d4Pcu)E@U)}_QMNq z07;X&&M&??4`+9}HLNH`Fqe6K(h{pdW@ctH3>9xbNd3@y2e-N%Q9Exmnh_sM>y4!n zn{CFur160fu4&QSing>&a95TX4cBGu*Sd zUH5dC0_)jUY+a3Kyt&)jJ5D9(Wk^$MHX=`??xnKNuZMt`+;j40=DdBbLE$L|+X`*O zwEWve-H1u`p!9sv{#vQRpD<0=@;BSR{HS*&tmYz3FS19jSoneENA|?-=y9O0?0c0L z^Ot!XRcTxd8zzjLv$iT7)*UEn-G5fk8dT5f|8@PlQK2%uo$#jZ5(xL#1@@l?oCVl- zg~zW~?r1H+;|u|+B!nGFEN*FbvN{GKlWeQk%@Q2|Ttg2hpV*uyZM;t;4 zDx7ImfG3}EapyVN;3d@iDv*1+tx2N0e;;Np{3{0KeUg4!>7N-tDgUO#ewVlfT+Ify zdIL+Rm8rwd#ARoEMSo;ROuu`|3)08f4`X{hkouo4BL4VjIqDyP#>q1@A^vhTYUb~k zTVbL)ax`e~+EJMHyA2buht64gCQF;+C)2)9{|^C8xrZlbyO_`4VqW$of4Tt}Z+`BR z@k1YN(d`dp_6v;7M9=N*N5;+%>giF|CiKhnvD%f831r9}fN4dV(NCT2I%L;AN}5lQ z2pWLUn6DTT>;~}PST&YSXHnd98^AWqP^ard&6?`d4r0l2$;@4AF}T1y%vW&Z&R0ru zVaBDH6f`{CI-bRGKr=VtXEK+08X>OXyzQAC=ZIl;YE0YQY5X!dq$uml+u7#GUCeWO zHeOP5E}h#MonkFStZS8+US(fT)nVK=?f3vd=)QMFT=qj^4%y(#DJKN)neiPVne!11 z(sZw1-f79u8Y~((l61SOE@yUuC1*?V==w;+_kBV2EBrxCblKd!m`+hl(Lfpki_Lwv zpcpQc{rb;cbN3wQZ=l?Z#1yr3w(6SL4AXx{Vb?{b{vuL`QE`q`=b}xxg2!eDZPsaC zm4+Er>rX`Y#yyV9t@Akp*7$4>`aT23nV5i@ZNtn#*Iu;De;je0j3_Or5Ssau8!&U~ z%~Q~wQKXT2D{Q!>8EPC3jQj*q_@$JHbY);A8icpoaA}f5p!~{C8X7wlv{@mN!Lb+4 zT5)pJ$0*-A!Iqe8d`N-(@MVxu<`viJCPs#0mU&G2>uLx7R5&H)PX<{AV$cD?YCAdZ z0AK>{b*HclU+uIbEq?&U$P^+pD3M;%4W3s8Xr2yOa?|wQ=(q!3?)pP7UOO}Rc9N}@ z{8G{3+N_sZLpReV{!cMauLiRY)+2K-R03Vtn~=c)a%usNH=T1Dv>-=&>@@Bhxkbgo zG_J3}&lE6#9dL}MReb?%G7P>tBR>%mK}KJUFM(tO=yu&@*HR+e~VZf=ZBPAdLmrXG2~!538ubYg~bo+N#`e(2RW zrJjEZz!N~R=$5-)VM!rGWRgl|)?aC`Y(kQVl@7?6`lI7QhVWv?0v}7Hhk$Xz-Me?^ zDy|5zyZ4a(Ru$R~Qo1qecTt>CV6+7}z7G(qZ3wY?4-zkL2=RVae|@wR6YpfQ^Jy6%x@B6(R~tBbjK>=`=`4HLP*8@8ldwwmh#AJN*u$~- zp#@GM@RGFpq*3uoJ%LXIQZ3N`T*~BN;b1zrBG15qM*}y zI1OM|0+aJw_mzL`hQ%0u@+TXHr%1HbW2?TCVmH>fT23qLyi znPpjZx&P&xL|k!ytbeq7j!GiluywW*Fsh?+ukXvE=)V>gX0QL#raz(6&o70df_$sZI4(uew z)ubq>O&Xh~JwQ5Ys*YR&#lM?f5WGj1~FOIvA)H1+B-$x+HG)BWMfDN;5E>cDy|ls10csL>`KUohMCu+(2c{&=Cgj}^xh_mH zwY@8Mc5c2!?jPS;G)%Oxp6Rmk!z;MG?r)ZwoNmvHQnkg>b$G^450_<`+TD}qC#y3| zobISgQgvwBPfeDk>AJsIb@z%qkG=(G*m#lmM)`F$6PnhWB;+(LZb>h?5RkpPk3c-( z`VPvgT$6vUn*yAjP%84Wbzsl-V9!p>)CAeuv6^P5|LB=5KlPwz^Y)|~jp#OGS~=+M zzfPJV``MA5XRi&%Q4hc|d1P_HCq;e8@aSo7sI=9JKvkBk!w&Lbj6i!u+fr5QTZb|! zwBU;GB@<;6XL!F)bZZRnQ{rGVWYuZl4p3Nj1!sL1UUJTM>6Bkl0# zL2J>bzlWQpsIF1t=2f+Nj8+A!99g^@UW!D#D>sewiBoKJ!c@p7h7O^IeC>e5b3x>~ zAaGt0IIs0zHUO#ahtLUv|9{l^2Kk{QE*y=&!l_Q(G*aTTcRQk|hQ+Eh31dG1yoM}4 zYpU-@EBFHKhFs@)d@bp4n2kE{-U>jg2OxAp;5%Ud6Gi`2MHSw<_!NiUAn;G9f7vj( zE*PAVctmiQOb0X=Rx|NdZp~y7i0@j>NB6$l2Qd3I08W{puwL%lbL?T;JA;!BiaI8!U5gY&1LKL8SE6M3p9TeZ2pSjRx2 z&B5GMZ&^n5=WV)tyrrlhLcaP2H}fl#P<=pg2Ew8PgXk_u;i86vSz-he44X{hb#SmE z9H%`@bRc4E!Rj;bdTckY__!TpGstpFO(G>6bOG(HO(}eo=#Dn3*3y8a+|uZ%>y3C< zx#{)=ymE}MgvGlSuO3HOFQRge*>$#`GYijkU=LD*0HxnFLD%pPR;H^aLqQO4FNz3l z|Dq)a|M%dg^zY3m23aTkQ?CKlac7HHlK{Hb5YD1lZuD>w~M|a&dz)16(Sj{r!`##*fTSX`0sKV|S6r4(hT9RLqyhtWriWg_STe?sml0 z$J8VwxF!6hw>Pf1HxmirX#MYNr5XD`3$hLQUWLK~bTee8aN;N|-BQ3&eUv=gptyNE z@^0OnlN|cP1Jpc~hAKcni9`aW(gg&FX<`IBMk0>n@gIN~r{@8}qf{Ecz82<49;`_Z z4YbxRBa_i{6T?>Mk@QQ8&~Jw-`G)&oIG9eH(7OlYc+~XzRSvi(F%sl~GKLE1cDcfc|+AEck zJd0E15wd|BBI+Wp)7qGKmA7W>Wo~_Jw-boX?oF1z)D+3|aYC*7wkeV8L}F9KY~7G8 zw@@RVf{D6zC2HKhQhy4h4YLuki4a`;)Qq~f*Wz2K9{(^u`ICiOJs>wQ2nA~?Yz!@Y zo!=2&_yHx_z=$R~N!4%lCD3MteyiSLf;urHvH-d22>;16Aw0l~C{ra-Q=`s~H7Vpc z(B)KDi+9VpNAq>Sh-}bna-fL_pzG<>l@I>8XaAuWv(c<$Jp~gK4|`yxu4d-9K@3H> z;RE%Z7;(sj=a5y*K#2+E>zAeyz{DWA!QgI6xN)f*|DJfo$XyLS^+?3cUZ>k%jdwmi zi~kY+G(J}i5pB0yzQaW)dPi(u#s^PQ_{?ng;luC%>Kp|O=6&e!CqKC>ftk?_vn2Sk znsJclZdV#1Cl&d^ZJP!-(`!vsY3)JKovfBV0Me;w>2;eX7X;y!ff^cW80w)-Q2i2S zyE#NyGVDfip1QipgWo3+$O{T^MTe|aQyL0Y5vwU+ATApzC#lgt;y{Y{z+o4O5e7sAh(~(*?M8UDk#S*pZ)>GuaQBO4lDtmHUFNDt~gj+rXNt;a+>t z^et!65J4D&*>$P4ewUD}cB>3I#G5uM0lOtdUPDeulIT@ph0sRCv-0y~# zPAa(}7zP;u18agj81rFP#9OytQTZn{ywo*;NV>stQNNw+@aW`y$C@0lzVr$~gAMS7 z>SRv!PHUUH#5xltp+1Sh1a($={XvJk-hP8>S=XA!;H0{d6m1tWKr;`BBBGQlRfr zmYn&(Fv5J?u+LwDC*DLJjHf;TiKHHj=W12DP5-wlx_!PR^=Rkg>3Pp=2er~XXx0Mz z0E~#d*hBMcOt!~0;%jp<9PGgIQCxxV;MZg7!q^Em8sjhy4QVX(kLD8j=n{(8>q=@% zYQXULDBjkF`iJ0}yY0}1Vj+uAu)zjL(($b92}dJuWQqSy5YcvI*o-6@op-v)3eu0H zL>$CbGVpo zJXSbdiYdy@A1O1=$MT)~hz7z0F}}{K&rrTjjKbBNwrYkFG$N!AbC)3q_shI=XoL$) z?a`R=C6gXWB_jDSB?9Vbl$EfG&?JN2$kFr?tuW+9kuTz^e|>FAG@`wP=(Wid$WiSy zX<%8Y&TZJI5E5g3#n% zS4Laxo20ZU9)p_H(~An}b+E67Fq~{0m-V<06VXzOplOwx*W}}ia?xX0E7O*CNR@md zhaZ6XX@9>Yt^Lu4svn0}Rliml;G->#wW)ZR&#$bIu=BY&X;!Qb_=Rr@jXn(?>o|LH>ed>wsy=$B79ef^c zi?9?zpOggQ-yM3c28C3o*5$BbcAtY+%^+LZ&RV@=QC2n*ZV*aM6$#p>T^>@=8LlPk zd+uoZUeDO>%APO!hrdW>l zTQwa!@3WS$olbpe!i4qaQM8PP}@Zz17 zlIi7VFhUx+r!!cUi@L|%dOzC|61+Ve8t0QtANBqh@0;1L;Gioa%O=v z>IO%5yhBV6yg)Rzr;%qF;y)Cb`i1(t=54|^4wl6P12KKt4?xC|P_1??FR=cS(;28++##s}a*TcSp{J>ra7)8wu*xSGEs z7bU#5aJZsThP(PWPhpP_)L7 zXcmqakpfwY~cwo*a$hJ0Nv>}hTw7Y4@w zJwK;}T=1F`!2_>?mGaJR3Dsw9){*~i`_vmq+9E8w?`=$ju%UujGT~~uClH9>8S_i} z#*l5rSQ`vAqS9Pm%6bv$%KY|Xb@Q- z!u>T78_4IfsvIqwWqc&87M%o{70}AW-UJ-M`yeN6wQ?2xU=UM-v2>8atVK@x?tz0X zAxLau4=9U52@Qoz8!jm+0b}a&g%=0wsa`0+MySdpl(Zc72cT8SgSNnuCD zlZ{NzcCO~S2-JsxL>yeSX)slsYf|M3Zu%4%sW)J%9cd^Q7uGMERmg5MYO(fm4$;D0 zyQ*a=W)q#NAyl9_zSA3363sy-mygxAVXAg5L*k-zbuqn$h1d@!=KG387ONuYc!|^0 z`>@s9lV=x~NT4Sks~$T)`Lnd1=X-yKq9M<-sFi;xKC#ooAR-PjsY(eM4s6aviZaGt zif*49AayHTnpiSnEokX5(Dl9=-M^ZsHKudSjof1XCo6_A{)Tq6=7DFPW5u}z8Jb1w z+TxU=p>`(v7Qz-1k^K2V(o8?q=ZfgNY39_D`f*JAe!^*uZ|WOqP1o;TC;PVQ6)g`= z=?RC>veOjk;38f!o4L&r?pfM(+?U?d=;rbG?=kIr6k#`{gCnyQMRTFMK1v1Z3ntRy z2TrVBtTE^P6oSfYU{@$>Giamm>VJhP}MuVXfzmb=>ZUs2KnRyX$1xE1r(X0+~8)J8?vJxNT-&h+Ge17nUG&{(ziC-^G zOTJ2c0M`CUq5n<#jlDX?|Lx0w7AN^7@w25F$$OzM+&}0bckh)16q$vV^{$8$M2)u; ze+r^${=cBhKMcbEmEnIA`ezFNPVb*7Sd71dvCf&x| zOfo(eX<=t9xFRhnhXt+iQO2c}BUVRrrZjtezU|W*yxA%F$ppjJMK$)gEVA4N-7nP=hP2T$LGNZ*4^)G5HV&7IZL2L>GkL zzeqKQwfd;{05PJ#h7zj6IA5_SSALeGcb(Gxl=z$dogX9NR(ITFSXY+SdRCEekyQ@n zmR|zlieJ$43S&@nzeL0S>V>|9^{F!qhBh7*_QgUZT+6^7j8W(ZA8ZL~MO6CFe5#)Z zIc8TXRZ(r$+K^fV>nD@oNc&M`lowfh25Re0k&C~HZ;>BZHZt+T{PQ6Y2Xkq3j8Ve! zm8H$KC%y@rA)n}S;q;Jd|&3Qmf_!%G0AQ>3wG(>yH6BkZP#wmR?^0&uxD zqBjPD$&OvR1#4JX!}_z-tIlJBXl_PImFUMYVpr^aF`au{Y3C78@Wx&+eng8`gBLi- zb79;su?bK|Zkd9ycpm_L|8GlW3VCa6hS!K#@kbBP+z?C4I+C*E-NP`P9dmR0qmnxB zIne3H4^HFNk8Q@bu$ZQ|Dd&Y{d8KKw8mJITgjLPWGcKOS=gjFbm4(G|t*z0}8DX*C z+{@&fh)DdzvE9E5fuQXL1!c{7C9H%YtYd?Z-3g#*Ck9Y04il$4^zG`sEWg?Q@*(3z zmkHX6>2@oiGTaj3Ly!WLwj zxFI}kydVI=2Pxj`v8dl&n{VMg9qzbM2Ar27dU>`VPNdTP%C^8HMk0Z1T&y9s`IO~;;w>4s|!lnIV3gotL# zSj&y##^^jPN=vYn^Rd6ti8917T|w9cwyEaQ^oBk>wC4-vZhs}p6+kw>V(w;8O-06H zoecOWzb(F4le|a^&y5tN57n*|VTxr$40E1oso7y4R9U&@mT@3hoqPi@z-}s#9K`(ha{(RLt zw4rx7s+v?q>9ERX^Fv=)P;7MahF~uvk5;;!w{cw*9p}b_` z5_%ICOh6lI%G|V42qYP-IW% z>gYURqyVYUenOV#kl&V`eqQT!k&DHFWD)FG#94l?$u;EdSed~jHEy!~eN6jF@X0G7 zYrE^4&Ej0EK^TwC@y~^G^CK;@i-Yh`^OPu{d-Zw*qA=MS2y8jXtYil0beA=PNRLxB ztfdnxk`(NdpKKIJNy@lj#Dj5hi-_a79m1>diGa$Vvi{gKbsO#UT$#mwf;gi<5DLh9 z&P_~st0|@%9x`~Xr2YR(lCKA4EHh&Xi<&&ih$6WD>bvVC^ zRpz)=J9mi$>lRc&Uf%2`IH+l=1G_G=h(uB&;~dMAd5(BAQJ){YAC!lb3MQPO()2`q z$JPg+WRJT&9cj+_yKcW|Rd|b7w>-+Wv?Lvlq3C2^j*xffQe~y2zgHOI(Rzp=5d|PD z9I7NkM{1R0%&3v=mA219D=UkHrr{_g!?FfXwF-dVp-kMu4s=Sk%Q1Eknpm+k(WXdk z3a&aSk-)U#*D$Fab_UJ~vu3~GUQncg9SHt}Rk|J@XVxmfQ$N~y>FMsJfc*OhDiQHU z(x~NjG-T<#5cO8LY&iXr6cW;vlrii38j@nMpL7>^CW>BV5-{ce_z8Uai6xMK02)Gi zf9mqv6#*`$qF(B!gGol#v_s-_Oi3`nzcA@#>PS>9-Ckr_)@wXHmK z)ShnZlXi%G0K^u=f|`(k9+hMV(v8CLsX<9|q{h$4x_>WJ#aV2-r+JQizOe)eSg0og zZ-Z}YKtlOu$^s|Z9+fz!f`sBm^HN|rrdm1Kvg_KQuLaZjW>)|;ZLoG#wryRPX8XWT1f{pWoq z{8QOqp0urgDJB)veJ>Nsf5xdmB*~ zQi>7!V}vF5F`LBMv5ayeR})STk`Uw?<3O9mr_G}f`!KesA{9#dBnd*|k83Nt@dv>6 zsNYBatOF0iE~20|YAa-VfESDP{4M6`dz-$c?r1hjU(;%mKBHHCRZxm3gMe<5B-E{^ z2-YB|7I5X%%uMU6?`*M!0OVPCZ^Y$Y1Fv+71;- ziFI2viG>nd6O7MNS{7TEC2&xvjlfQ`7KRhe%xO%g(v;eW%Zgj^Na)n1H>C4;e7wI* zB2cFa0^z-$ZLT&TOL9E$^i75<`dzpf-r4%ao-L%gwE$q(MvL zihwbtxAJyOvv3WZ(P%m17RL{>;A)ycASZ^>fGc4$Ew{^5$7dQgrcqKU05zYTk~M|` zomZp5{Yp2SKNL@al6i^k=Y|a?2cA;~5$IYn{$QN8~V`-?Ce3 z{cM5bgB`LR@^69K+z9cE*un&MziA7S9# zVSaVUL`6MktIf<^4RG*_>7cFWNhnB(Slnbq1+`qp3K5WQmLK&Pz%eicg5IdSOe3pR zR+nY3IG9&eS0cbMm@n;Y-@{I?N~1)AdUxiL`f#iuT1AvZ_Pq@;y{g-=y%(n$+pGRINutP;782RSoA z2yyF+tWg+bu-vBviXGN%?7f7Z$0q)nJPw_-gjs;TD$9hs5vk5;`oLneb4{F9T`6uW z@zjl1BN6oDvHB?W&wKgQ(IqqSi+MAB+uYgv7Lih_dD5k<@}xSuhHbbzOk6E%B_`w= zQ0Dvr2-dZp)0Y^+PI!w0kJZ&gqKgzEAq5*kdo=9q{j%!Q&F~Go#L7w%Fwy31G(v>39qL;qEfVoF~*rT z+Bdlo}iHp4DHFMN(W|+F75rQJ)(E2 zi2H3bM1<)+w3Yj-VoGb$hhJcivbq18N>bx4Jgj)%2kf!W_RV-m9- z(+d`M@@9gjanPHn3=WqGZl{|p0vg*gMZ2*?vwdLA{b#SKm3YuP@V8WL(q9`IiWQyU zMH6=E27z%zHfb;YL=|PouB4L2nGquJ3E1YV2w6eh5hd2Tm$UsA1>zdW0!RIa<` zm^f-Hj)h54&rNeryg8efx>a+R<64a=_i^B15A!mMPRp9DqNYqNH9xc6MA(gr#S^O2 z3Xtt93OSh#^yO8`8nn8bdGEC=U}xs!=*tCeDyPv)GC z81T^feQ_v#A%#(@k;_EPP$b>P1mcj09AiOJDXU~8J36aFD}fPmn^jH{@3KeMi~MUg zsQaPr`|T2NuBT8GfMzw+m`66V9*(IV*g83_W!m~JMhdQ(Z?__g+h($^J`}60#SM&! z<=a{1%Sj={Dz$_Vndo`6cHlQQm*W>fN=;@MdqgbzGBKHETqV0;MOwQml#6R?&zI(r zgW#$H>r3q@q%{W6^Fx1XZ@cN5NAnK!tMS^Qj8mr;r%^fl>*NDuVE_ojM(Q$lNAl9f z0;LYV>aM!%Du*!v;R+zq?_IGbpY_Q{{sS<2(ew6b@p~wSd6^p9Y0Q_gpBR+js*uY+ zRUuJ%!P2BzCoGe*3H`>$q!9GdCSo+QJ8tYG1N>kCw=AX9lLPJ)%^=POm4A1)H}T10 zqc;BwLeMe9hV6~g)h1ohv`E2dPpJMZLF`0NYJb7F&HbI7R41dA#_qS1^>-zYfWG{1 zYPNp)KJLN^lTT?|wJ}ZDgdz7B{w;Ag&Kbeq2a1;%rz&4%ZR#gb(5YqxQZ>w?m^DW}6{)NrU-QCRu$qvQ6SL=ZeW5XEjIe zY-n^fE11~$orP9_flU^>;Y{rcigl~#v^q@{CF+?8kHi0cCJl`n#MA|p&1y$0;Kp=Y zta%!XOCrXglo&yuh(|33LawQ?gGs!RDNtQqWU!V2)H1@x?-{(QE+5>wR5Zn!n~F(9Y})y~NGKxdmpokCP4_Wdkw88pA6o)NzpJ zCHM%^{EwXt*`)+QV8I*2F%En%77Fa!Y70u*IZtW8TT()Xs3(iJkIj4CY9vB#&eXr)rO z5~PXls2I_DRG;{PQWC*xPM30*w=^gsD!Pb_8#(0*_3I5;Jn|a>K5X;$y9xq!>v`At zBj!ksn$qRMWP&TlJ``kM860_KAg+R(K`ARi{#L>YBrS3{9Nb6|SvOL7PV{s$untG! zk;)zWLErKZfSYl)wDO~keH|05o~<^N(^YZKG|oO5OX&;_GEsX*0gerDK9qTRGP-uD z>n%##Xd>&fi45U98hcp14x%V>Iyt#|j{UP($anut<2kAV$1^Nt5Gz_W_N!}6j2Ty~ zC%@hsd?BhBGo;~ByQV@`sI8}sMLR14s&L=#6pzBey*UZctrX4p3M0Z`kN z5`2>y4{{G_Imut7(Xk$D^jc9+w}#b?YtL*QkYcHHF)lm9MEz3}U7*|kLB^FaQjo95x+lz$~e9RG?u+6xMQwK0?H zVeW*!`;n`3hf7c*~tj#HGHW?vPoOYEYFs3zM*h} zMRsJtn_gbm6U^c7tk0ug<{tI_w5ACr6+w}_Mj`VNzeuvZ`N=MR($O_o2)SvrCXDx_ zl_!JR6s_#4%|YFyLi1ZmPc%XPj9%?Cl>o8%&8pe-bUT)mNqy@UX0cx*z1h60RM12S z?y6%OMbi-*oXk1w8Q)6d4@}BF4^IdNCh?TZ@#l2WPn!~HVA<~S?%s(#esfV$6tE_$ z$Ck6!Pp`ABo6<(|65%%I*xKn|AqTx+1~j^ZX+kgZ?x2yOU3;=9iVBZ%ko8cSBs;1} zii&YU8(ivG8rpO-RE4)c_cxQB??bO-)L!k2<`RuXTi2zDInkr+i5nuP%%lP|WTv^e zl+AIW>*v~yo^wnM6I-@|_nsImVZe%h^g zJ!;W%(()KSfj@y9Yj-!f+*;b^^G!@4h1oZKhMG>OjO^Hr`s%4Ub4FNtJ>L9Vr+m5T zB9L9(7dUg;0``je+tAKhoIZ6answbkc3sM16Y-3OjvJXc+bZ$`D=w5Ohw64wG2HL3 zGs)0$Gu+frB1B~S;&Da^fHSg?bd_mAPY;})kZK3M!OvX!-s3;>s(&T!390dr5YXAG z!#`d<`2i{Gf-}{?M1g<$prGy1ZCC!L#hT!KW6Paw6V<4fze%p3GE=p}%0R2dY=qvf z6vZU|p7*PKo}ip(3cAMlJ>v;qdhQ6g%- zc<5WO<*N0O(99dYj4z&}JA@gbzFHAiR~u&oE{vpnfhg-4_8K|Q zzcIkYC8E7*HZzBG4#qED&s;J7$k1cJg6ET_K*R}&BE!7jJ!QbI zjTi|Qn;^^^{_yhOa|wOyXK{2U9df6Sc(Ff#6;>4-{AWc09)?OiZTj~8>;+WH57 zej{5fZ~ziy>{e_yj=Y=_7~T;|lh%^Lp`636097T)m&>&Bgs-z&cV)-*AA<`+v3@DG z2P5UJjBFT? zj)6bT5Ql78hy@d+onOr~;WQCu-y)HUyxcl9)EjY7!u~wDOP>GTmX=v`qPt;yQQFux zY1b#XHRTns&-E}BcRSrAjadnUqZpd)c+v8Zn5{`{xA^^SJF(s$7*FvXTm)x~vme>f5FVtKj135RODZpf6PK7+Xq$elwK*=I)oF2#M4`Ji$7wNgz76K zj*qAaNp~J@8(z@o1QRJKn2Qb`d9!!}MLo#FzU)25zt+!DyhLeG{C(aP`55Maw}Svy z^CK(~+4~2QL18@<_U;)*L$!aQ>;I#*kCE2Y_a|jEIU|JMijHsf*%F4KQu#a{eyz4$ zCBXoI#0!wOD#9}BI%i|HXLD8$?(Xnba$|al%vpFH6-@+I*n8i8OFvpY!L%h;KQgR zH26ln;Fm<}BBmT2ZB17$d`Z+AUeH5CnDn&A>(Vg(M0R8JZNRC}!SaH8s`cHyHw=Z2^RB|W)XbX0e#KWWe6^iL zSkty1*`yQ1)5d4og<4;tlKgWJq|~-H%~}w$++g+FKB0CaES;M8;4rXR+4~UuxMY8g zyYX_>AM)lgCxGy$w|kqilDb{r`(r(&oJEK7-h8?vLF?W!TScWmFtyU8vAoz0R7(=z z2n|FK#(#n;dn`x3pxpyM3W_<=8$-uZyUh^F2zi5K!|Kpsc8e&brCFj+c#Q)$TG+NyJIa0X^ zjuSKx>>Cl&8wJ#r6MaG>x$5}Vlcdwuh&~}7TC>DI#GhphT?^oLX?e=0ypQu@u2q^&Mg&rPS@B0i|$z&h1^-(77f!DQUW4JL~Z-iME0= zx`{NGTu$3JcK#g38KF7~4#KyVD+j%eEvysx>uLn)b%}-tH4fbJ8s-$;^kypjB?lv<7Q?y~W^GAuLDBW|93~!Bs-j+CxCK ztRo~t;HS}}x^d)XPtxFA+!lIj6be_-fq z@=_Lx6+WII5sS{#{eVf+O4_U|8KRdydn?Y;+Tj;Oiw^X{>lvtQX0BI)`wsWWbgQVu zzKAe#0Sz%)xa(S{WZRU);2+Cfl|z=p{hn6m?Xw=JyE@o6Vf%LDySsPXLq-20C|zpI zXb|__7zF$*yS_;c+jtU#VvzF^K~tSI%Jl~(O!*JYz&X!WmY!!nDo+{xR6jK2g1t=s zLO#lUqx(KJ1Yhct5_cd3u1VugaxB*PBs*UUn|>mU{L(1KgFQ7mDw|;Lvm8a72O&<; zYXoSu$`-nvrND%a{FF?Kq=MvIV1&Nq(0huc#U5XPd}WFDc73~u-KHO3rv}3|hK)?n zt}7Lz`mFGqp?u-^GSmHYJT7ti3ycQA;6>m`&#ETOFfXGtImcGj9~k6y%oom$>_t?~ zE+sfq>$+6jw68{1!M5KTyCpo8q*%wbKVpn>0i8!W1rde_Fzb?QPwbxYHUX{_6%*6i z@p~~%LZS76Z>k+0qR~ZCw$>N4ZTP(cFyQC`aViOjZ0y0LGH)z+Z$9w4vjyA~E znL)D{$6?RTYs(|QT7(4i+4)loaPLy-Ovw4Kck)j`5E@~3tc{iVZMGP{CpU&(RP(#` zL!LO<>3vnq{Ulj}4}D6T(~CymS%Y0z<%iyge+^56CymFfvz_Ny0oO?NkkM$Cj(D3m zw|gDXIK-uWz*-j8um={3eb*2{2|LSPximccw(K8qyZ-m`2*=gB+_)?qe~O9=OlYXK zDVfZH4|m3AlIW9o{#GGh)YYXeB(kC;=u$!M=DyOcC8<4TA3dUUN^=NeinJ3vi0oNa z(XGjP!W#RzYAK5tH@l-Dty8T`e0v=9nq?I#cy*P>AoJ?*#x8+v*!$ih72{hy535#< z>GDq`3Gh^WYKJklY=w-=B34NmqX2{AspE;`sLoeiMCP~J5d|3I*R3E)B7uDxm`(Blua-D+=hjeCb#~aeEz#m1RvmUc~ zuE>x6CZox1X;tT;HbiyOIVYj9_)41iT-XVu7^sQw_4&Bm$n||fpEFn2=gsEFL{hTE zc5-f9uSj=%O;w4Bv{k|LeCwG>x@>*_Xu61KI4qWsK&8?MIk>w(UTfPIL}lV(q9FG4 zFP)rPB0#@Q#c)}4KRWEwSNiV@a`{vckyeLw;XUndD zyH=~C==Lvk@`1?cN));H+wVH1031XWMZK{J}W6K#vXck=GB(<)s@* zpkDD`ih1#i4twu@_qtH1h5J;lUK;xHk>9}j#4%b{4%?{^R(3lSOhqNYw&J$kc?H(OK3joRvuYO|ADSEO3zo^ zMWm%nQ&0j=!1M&$F&MAN^x z@q-6W2A2;9)t1J=wLrE0pr($^nDo-`$*YP%rtv@A*q2O~w9m~xj-_!RRF4}-G*0iG z5YLO4*96cX<23v}8rvjFZN+xuz10ZR8hdkyf~d5C0AKGA4eik-Ab!4y5f4TaLOiR?{7kpIw(5{5hQZZt_D6{%&BXY zjPG=!N(u<00A*xqb2@q9oHH2ZHzZPy&sZP}sn#q@W7shgsL!IC}FDXAJ7A#`%KTuv}N7KMoZ#8FN&3p?+nBbUA**u`VPv*zX`^S{aT zcIrT`Ra7ACJWn_m8S+4Q;J^o0(lZ#BY)TuQGh?AinjUF_ucid1@ggV$X}Zp0A$!P> zytHp1hn_Q*d6na+fuv^|GQ*^fG@81|Pucf04lF8o4+iuFBO8=|V8qpoJ{J*zKEH!a z9#PI0Ma@KMbh8iz%ZsU3uT-&+;tZsc7ZQ$L)1u3`lWt_@!u>)5b-Foh9R{QK4~5CA z#f3i{YR13VBzpQBx@T~GBpb``hY^1sVlGbAS>fIBZu`AFl!j1W(mX$>?T(2YU$vvt zqP9hUfv!Vbb4QDBPq1~(!=c)?aL~Vg(U_BJV~IDsfYC5FN>7J@T0YpcC3$+DdvH-* zA^d{s&$r2#6dEp~QyQRz=hMj!84E-0#KOfrTvO8Xb46Hm(_K?%6TzniVwRY{kGJ+) zN_%3E#1o2|rs9j$!(VL&K!bw=Y}(K?%wq2| zY)Ht0a7NS!N~e{VmU?Y;Rt^8U((CKloNnBD25vG4-nV|sp%+~A*eH`J)_ydEU8l54 zX|c%PFVz^9f?$2$CRib5(R#eO&!$GA6E!5@Y@3b@W>?;7=33jf&Fr_GhoPgK4u(o_hfS)MpU-~rpz(z>HMo1EbqsS+ZhDK`WtxvQ=|l#T^@+oM_S z(=8Fd7pP{^_kA$Gd?W`*iRFvs;C?mM+-Br6%CEXqGi72=H`%+Ht`gi^;p{=3|y#E6&wvi4&*^w zmfx-Abiey8$vl^`mTFzZV2q6+m5`v6QB09Qf1SW8Sh@<5+~}u;L6;2+Qz)(+tED5Y zb6f?fM{N-gfvf0~y?R^h=oGMoGkAZQRYzBjSLGr7qG$g6X7H`e zQ(G}r&nh?L-mQmc2k^?qClirl<9S&f?27WNS^D{FjC#gs;SP!s>h(lzjH3!4Gqd2+ zV%&N@Y2lB`9LLouDTzL`uTAoy5$42DuUaL&6N=%&(RyRtVxm|>l)ctz6#rhyVe2Oo zg)_3-Xef<2U@CwSzqY7PF(M?2MnjaaN@!#Z8Cworh@0&Mvr@OdlD@*#?R;-coM8cefdtOE zNkk9G&1L*V!yLQRE~(PSgIk1cJ}VtOV4p&+;o&xg@&>P_l_ChOwGS@cwNsYqDwLvw zg8l^7(h&PBFD|5#JQS=dJEA09#wn~z!ofpXwUcozLa;CC+;5^D<)A*)E=|7U7nuqB z&JpDPl!lVhsb;zURvP&>_;9#!e^T?p6y;{TyjxE8*%0~E5Z8gUR>@XLMbL?)$nGdsTh-{j61N(TUlB3-I{iG6`p*?|X$@`0}?Vybejk;!+$|RNfu?Io$g+7p_hQ#}rF3m5IP0=$k7jG#}L7ui_qi zHz%9A=qAt=8=iffnIFT-LwzNXLQ%&t0YNEjb zs;nAGRs`@EX>n!OYI>@PbT}or26Fj#wU!0<=C-)iUu_T<#hhB&ZMw_K`&WmimiUmY zjG3K3^2Bec<_33_jTYFWC;JGBo*~DDfMNNjf!cNC|s_B zFPpI3t{m!Dl^h@0iqcyi`AfjfRG;3l#Y*8F!_196*1@ZdZRkCy{m68Pfjt;9%VX~J zBcYv>@{2saP^|YQxqUdkb5_b+r;c}Gazb|okFQWF*fcX;Pq6(lO0&!?oqJ# znFF@FCIKpe<0?S1odC*VS7NPjfrfzFelI}Q(z|Te3F~f+p6^2YUtZGtO$;}Pu4bLi zk;#-u#@%z|k_3C8(eCm3FvW&{->3F~_K2)t!;?x^w95Ln ztjv5}c4!sDNMdnvyfe8x-o>9R(Zhbnv86YXeeV+E(`i_`ksH6ppP(5FJ1D}VrR;SE z!AfoP5E_h&|6!;{`v>N^fU^=~WazI`ke%H6!H|!gZx0M1kYOo0+PLlzT&Sv)UTV4v zSYy_r(j&{T)%VdSO%t4Su-;%K_fpwsuiDjRpjcnyK)cybElkWw17{i7Oe>a)kV{Nv2KpbJ2mx_BDn}Oa+x;p=;_I~Iw zqE9X73!xrZFdJOWr)56kcrmCXxW| z`(LCX!LL+O%QPGDXE%}-L=6V3%32M2+KTXq^eQ2qxuj|7^#XO!)l^)LRW|rU0RSLU zu$)<>aUog$hiJIcY4%d7B%F$RdOX0N(s3l?#S~b%aZ@h3n#lanW3SeFsOVpAt0g^O zVLz@}{uOoMyQ;ADffcP!9`vzITN(eMVsJgF)`j0f(SP(6M(rI_c>Y%6UMVA^-rMr6 zx5)#G*c0m$%{|tcFIzCluo~*z-?E^o4wLF>NUEr)NJ{#w^dazmOEqHwC|!$uCIfPe z57do!6>rZi^U48W0T&~}fF@Cu?}v9L0=%$uYN0`#-jh#unT~16W4H`qa&eY<**A;L z1>F0b^T;?@)HJtpyShJd*1qO?Ec-iFavUmmo%^M31}~n3W7|}5{M2a^mmEe5kQyX7 zf)vE|K5HXIQ@{ltyhVb$)jJ5L?&~S4djc)-Ee!}ovQ)aTm=xhU!gj2Gg=5>Rz}yQG ziPDs=819LTv`em&==vV$WvZk_n(EAa;+f){1t#$}qM!iZDs~NIU*`k1+-&8$G%?iZ zJf&|naLY!V*M#D1O2LU+urMA3?2B)K(kuCm?{K|5Fmsxfg3Kk3U4Gnl$0%m8w@g=s za^fw+&b)Jo8|%RA!}~`4*k>9{vfHKoIqfyqKO{x0o=DmcnP{u3+`_19d*!lSr>l0^ zrP|vFvaNg8?%iFZF?Jj+c6kEbDJX~o1I^G0j|hhh&F244c7JHHe)u;yxYS&l2zdAe zG#Z2w*i@X{Kyh^oL>~7rS~}=Le@Ww){eN}@!ok9d!93u*p%$&H6vmRtF(+6`VpTpE zJW2e@3c=}Hf4@%}o|?kri51e4O^>RDUiG<3Kn5E=>V036a2?@YcW34s7_*Nz9e zk}4Pya%4D5Lbr_N)s<>TdHwYOwe^Tk;dP)m%t3L7NN`&_*zN3$h$#gg5fc&xBR##O zL5(OFwyct6m2b4fV0xw-PX~)0xU60r^U*{GmmnId%0Os0&BZ)1@<@Pf812(RM2`EV zt!5s1`8_g9b_8*0aDia#lekfqY+gL&!ylOVH~pASME5W%Sm)aBo|ZhfFZm#di}7Z9 zR%Um_qxl~f333V8-Vu^le>!&`d@bSU!Z;xRz?m<`(}h!T3Fc9aBbh>imGOXV#QfAN z9{rT@kvK8<(!qzF@hgN|9h8IH-zwN3fCPm@RaWQ6t7! zVn{$UxMF($QZZ^`U+xDx5%r@@f$?0g< zXcw5IMB}(wzu4`IR#)e5xdqGCxM*sjQS*|{c`M#o=9n@-v3!`TWTH+P3@X zfWHVz{lh~o+In<{W6^Y_Hi#2l?6Q0L@MP_*i_LGID`q5%jjicNB#o^JMkJup@Iako zVx);;9XIMB)xRs;Lu%%4VApIm1oJXWL|KSedP3YA#->H7AEWzZrwG&I#$P=%XY}4d zn~dg9mYNWuPZTmb|04eKxQBTZV?79ZLoW;x7~)!sX`K@%ET8H;pben#TV}_>KjOcb z0~u6&w3*`SxLfILfYw*F0sgg#-=5l|CzQ_8c!ev+37?>=o^)eYj}M)Zlv--VMUfOE zTDRdjuZI_s4Doew;nsxhm!a?+E-UJ*r(~5r8q`@zFrE??XY(2g5`nv(K^aSot&c*p zYos50C8cB(IXGTh#(=|rU})2<)lFrBgMM4948biN8Jp!zE6)sMy>%=cKQn$%(>!Sk z$QDUo>O3zjpS8Yc<`_y#q0#Q<<$p@k6*i2q{x{Da$XMmME~51BPMM!#fPh&Ape(fy z_M!#(mO6~h`3Ar)dNhxw#W>4V@u)dKk3N5)lXWL^yrP?30r;Vu=lXTbA84HA2vr*D z(dR*xE1BcAEpMTn_|%OCk&1-(=u zQR;Q@w0Q`H7Pz~-o^nd+6%xEtKA5N_I+f$vfT-5r1gA&Ek~;#N)i!y88R8pvb@d!6 z$Xy9RUbQz1?W2mjZvm`&&GhX`J0sOPkVVNhFV55b%0`tG3-kDs6Ek`|TVf|RR}DGa zXs*>h0JA;!;Nr6OcJ8b3TS*>cu<5+F1SA>ZqX?5JH|nzGTCyi~7g!{Ds)VFaf+RYs z&*6Zy{lZv^2zz*l%N_l%u-s?4+vvL15xt>ZHfcgqdYN;X0)ap(55l-sF_S zG*=?~veK`pF=Xb9nd ze?C@1)Gvz6`WB60FBKFib$TqRS?sx7EJu+UvWOe*Huld1Uqmka1G@^;?$ctJ$pU-g zuK?84*aKVJmq#DV^dvov&zCsGb@W)W7M|q5cw|l5Ew?+$R7uuFxtlfY7{x|0K1SI- zD&YqTAZ*jKJc3Sd4<@A^c=2|QVsjU!FCiJ`@77=<`PG3@9lkc5|MzInm*&@I92Dnf z@FS3GzQm)636v}eF=tNAw;Ogf+Wz;UkKyo97bkBA1}%ISm=HEhJUs)JaX|#jx_Z&_ zckQ(QJ&OGH3t3K6-JBdM$A=M1>7HyV@kNb8JyAy-%z z8%YH-IrsEoX={lo+uTzY4YfKa7pHD=!}#*-(O0j#t9N_(^0MC7JMep+V?l_+f91NX zKY5CVg?BtYYq|ATHWf$#M`MnfRKr&RpD9R+_d=v`e3w5>3g(pz^}&IgRn2dwkwglA zD|@cN2DpkFfTJ&ub=X($eRUHy`&JIU0W7YAgRNFvvHfF zP8cN)CV(r}XT`=qLlAG!Mh#PEs}alezjHctax2Qcdw+MpuOB&T zEMkchX%MTK`iTJ{Fmfyu=Bo(jliQ`M`yUu>|1Yowre4Y$tW?>k0{#rngk4wPsKx9> z>GUmf;LUd5T$Ga5@yADG2Wi{iU_vtic>Ju$?~(^#&f{Q&s(;Gni9Cnx-`D;HTKPN@ zzX<$QF=jK6`~E>C7Wqvr*b#8&(B_S9_M;&8If^CEy*Zv@u_+1p*4oa$^~zz0O5K&I?e%IksXAKdzfySbTn)f% z-+2*wZHwD$mI&|j!gre0jaICd@EL(av-G|1-TpJ}fEF+NWwMRh|FKGjmy}$RbTL!R`|WyfDf|g^zJG^%Fht4*Saw)fDVtQE z{O(DaakRgr16g)}-P?+7r=+RrCOn8JbQ4v`v}0GnYNnTbos0I+t=64-swl}`*<#0+ zvzo-y886Rf$TH3|@UXY}e-krAG7<6W9L6kuW!gy{i9!7qeyHC94+oEchzR@UpLYxV zeL>kjev1Y+)NSEHprYZF(B$TUx-BKCv|8q2i0+c}|8iQOFDiqkG2wzudqdtg5Czn4 zQV$$Gz!fZdZK;nV2< z0963LXyahC?WlI+{RkFz_y5)Cf9W1y)Y3lFwiz1sY;ik**2d%NNk^Ix*y$@o754UX zw8kFO##fuBVIvolXIOjLakEJLv90e<=}3!2<^@RM-DdL!2H4^q+D^C%2ddz}EkjvF z5L$NXlX6A!fc#lWRM;f~1RyKV^-Qfq!DxAk7kVeo!ooi7ZXL{C>hJc=`n{WXL#60+ z2TI!E8EXOadkL@Auk)_c7f}NHL?~(5%yeJo+cm_9G;I2)Hc>emdea#=#8A^D5hbL4 zY1n@CPEuE5a}&{Uu`vKzdh8M(*ufIJTLuPelv@zG>M`4Gto)WtL*5rlsR-v+198gA z9IBRCgq$;*d(sY{)zpAPcR$X18ZB#2lGtMBr!+kK^81UV+grNIY=oj27#LU%?lV`y z59SpJp)|N^12}t!lByQN_buj0OJen@g`C6JX_@H1l+rd$OiVU~;?$&2Q3scxQSnOd z75TNAi1lP;8^){fizt)YscDx{yWscwNzdTS)LMtl2yCq*0Qa*L`BU zHri|d;%W$iXRrycK#$5|30Uq$3nKihSgFXrNMaOTdow|NKzt(hO<{vr7TGA0=A@gS z?5FiUk@3u@fI54`>O2X^af(A{8EM^nHHfRjz}8?hYUOVY^o%c|Psuvd%=g9%7<#}6 zooT9NPkCM_(AK$8blR<$?as@f={0!``sRlH!S}8MS*-h68;F1DZjny(Y*H&fVZb`NYmX9UA&~%wt`GNRtLeOM+*^w) zJwtaA4cjGd2)Y{XCFib{#sIxVf@-+Ihdb01hTmQKYoCmg(fMg6Uy zipq0#Xm#O{S2X&gQ$_9YZx6LKXtnu*(wnKdYA`+dd*Fg%Ajs|AO~cJXl*j6%yib;h7oycrB43zs2qPUN>?O;y zG3~~yZbzM1NlG;iMCWspI?9btOmNlBN%xG2-Snm}?0Q+Wc<;?&G~)usNCmG_L2&jsPd2HR$fMD&pX zACF6dms5klGc{h90r3`hQ~w1aJZQUHrrRezH70<2T@yBuySyZuxo-F&PchYbst-j6 zSQoWJ8F>dNY?H@`>yT+_rR9LnxNDNQ!N{V9JzBG?0qT;nU=R|XHnhvw-Z$m@4#=5v z6f8$4pn3gO5Jblh%2-rvVzn+TeI(2Ebf_xld@BnkP&0k<@UfD%3a=J;MUoK#rW6s) zeP)c^IGp>nkyR|uuk{LmR+bpxFKF}5ypKBAce}ec7;@{D0b)h&r%fi z^|Uo~?7Ql)5foeH-;n(@2=2-&Y36a~SCax2B8k5Uf!gHB5<^pS)b+4Ar?~i~?Wv0d zJ&W4^z(C~9NCs{!n{&SN7o$blVR{@2)6~Rmx?}`=>F@yPr351SJ{(EgRyvoLDdjI&_srGdj(!R(_=QO{)#zWKyY4jGY4EYY= z{fDxrtwBrt{ypa5Rlud5M|b8{-Pa%yK^nI-9jN5X(rGgGZnAj`eb1?8Mu_2=vOQeZ zLV^X5V+sC#sy+9ah)}F&6=x3Yu*rp^$i+T?-tolJxQ!PP5eq0J?EG0F6@Llq7Ktq< zS)dTT)2kf1WruM5|Z8CpY+ zNX{?IA8lNNV8Mc-uh_4P3*NY4(tQJH;J4u^en~f$wcu=PW5s-mku1W?k!PaVCqj!# zmKhiY?OV;eHJ*0p-x;$8u;U7)+h`~uAra&kI{r^JgH~f*$GYB+iT4tZd>t)Y44s+N z1LsAjg`=_u6g(7W+7BW%m?Bte3}ASIbmYNhcrT=_JS8>bxxo$e`NM|%g$vlxS7rfavLHR(_=0O4Bb2F^A!@h@%#~l(VujPa3DZUr$cfNmg}u zIU6e`eZ;>&$b3TF2CP|1^l9nHp-K<50A J^x@C?{{aZ06XgH^ literal 0 HcmV?d00001 diff --git a/dubbo-common/readme.md b/dubbo-common/readme.md new file mode 100644 index 000000000000..7f23fad64124 --- /dev/null +++ b/dubbo-common/readme.md @@ -0,0 +1,3 @@ +## dubbo-common + +> 公共逻辑模块:提供工具类和通用模型 \ No newline at end of file diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java index a4b037b62a80..c72f99fba6ad 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -76,6 +76,11 @@ public abstract class AbstractConfig implements Serializable { Runtime.getRuntime().addShutdownHook(DubboShutdownHook.getDubboShutdownHook()); } + /** + * 配置对象的编号,适用于除了 API 配置之外的三种配置方式,标记一个配置对象, + * 可用于对象之间的引用。例如 XML 的 , + * 其中 provider 为 的 ID 属性。 + */ protected String id; private static String convertLegacyValue(String key, String value) { @@ -172,15 +177,22 @@ protected static void appendParameters(Map parameters, Object co appendParameters(parameters, config, null); } + /** + * @param parameters 参数集合 实际上 该集合会用于 URL.parameters + * @param config 配置对象 + * @param prefix 属性前缀 + */ @SuppressWarnings("unchecked") protected static void appendParameters(Map parameters, Object config, String prefix) { if (config == null) { return; } + //获得所有方法的数组 为下面通过反射获得配置项的值做准备 Method[] methods = config.getClass().getMethods(); for (Method method : methods) { try { String name = method.getName(); +// 方法为获得基本类型 + public 的 getting 方法 if ((name.startsWith("get") || name.startsWith("is")) && !"getClass".equals(name) && Modifier.isPublic(method.getModifiers()) diff --git a/dubbo-config/readme.md b/dubbo-config/readme.md new file mode 100644 index 000000000000..44f8a5ac357f --- /dev/null +++ b/dubbo-config/readme.md @@ -0,0 +1,5 @@ +## dubbo-config +> 配置模块:是 Dubbo 对外的 API,用户通过 Config 使用Dubbo,隐藏 Dubbo 所有细节。 + +- dubbo-config-api ,实现了 API 配置 和 属性配置 功能。 +- dubbo-config-spring ,实现了 XML 配置 和 注解配置 功能。 \ No newline at end of file diff --git a/dubbo-container/readme.md b/dubbo-container/readme.md new file mode 100644 index 000000000000..27c1ccaf9c59 --- /dev/null +++ b/dubbo-container/readme.md @@ -0,0 +1,8 @@ +### dubbo-container +> 容器模块:是一个 Standlone 的容器,以简单的 Main 加载 Spring 启动,因为服务通常不需要 Tomcat/JBoss 等 Web 容器的特性,没必要用 Web 容器去加载服务。 + +- dubbo-container-api :定义了 com.alibaba.dubbo.container.Container 接口,并提供 加载所有容器启动的 Main 类。 +实现 dubbo-container-api +- dubbo-container-spring ,提供了 com.alibaba.dubbo.container.spring.SpringContainer 。 +- dubbo-container-log4j ,提供了 com.alibaba.dubbo.container.log4j.Log4jContainer 。 +- dubbo-container-logback ,提供了 com.alibaba.dubbo.container.logback.LogbackContainer 。 \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml index a56a10ee7ea0..050ad444aa09 100644 --- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml +++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml @@ -26,7 +26,8 @@ - + + diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml index c2ab4a21e01c..9806068100ef 100644 --- a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml +++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml @@ -25,7 +25,8 @@ - + + diff --git a/dubbo-filter/readme.md b/dubbo-filter/readme.md new file mode 100644 index 000000000000..f42d129e12af --- /dev/null +++ b/dubbo-filter/readme.md @@ -0,0 +1,5 @@ +## dubbo-filter +> 过滤器模块:提供了内置的过滤器。 + +- dubbo-filter-cache ,缓存过滤器。 +- dubbo-filter-validation ,参数验证过滤器。 \ No newline at end of file diff --git a/dubbo-monitor/readme.md b/dubbo-monitor/readme.md new file mode 100644 index 000000000000..2c3e974f4604 --- /dev/null +++ b/dubbo-monitor/readme.md @@ -0,0 +1,2 @@ +## dubbo-monitor +> 监控模块:统计服务调用次数,调用时间的,调用链跟踪的服务。 \ No newline at end of file diff --git a/dubbo-registry/readme.md b/dubbo-registry/readme.md new file mode 100644 index 000000000000..c4caa35b9c15 --- /dev/null +++ b/dubbo-registry/readme.md @@ -0,0 +1,9 @@ +## dubbo-registry + +> 注册中心模块:基于注册中心下发地址的集群方式,以及对各种注册中心的抽象。 + +dubbo-registry-api ,抽象注册中心的注册与发现接口。 + +其他模块,实现 dubbo-registry-api ,提供对应的注册中心实现 + +另外,dubbo-registry-default 对应 Simple 注册中心。 \ No newline at end of file diff --git a/dubbo-remoting/readme.md b/dubbo-remoting/readme.md new file mode 100644 index 000000000000..b13ab3ca33cb --- /dev/null +++ b/dubbo-remoting/readme.md @@ -0,0 +1,18 @@ +## dubbo-remoting + +> 远程通信模块:提供通用的客户端和服务端的通讯功能 + +- dubbo-remoting-zookeeper ,相当于 Zookeeper Client ,和 Zookeeper Server 通信。 +- dubbo-remoting-api , 定义了 Dubbo Client 和 Dubbo Server 的接口。 + +### 实现 dubbo-remoting-api +- dubbo-remoting-grizzly ,基于 Grizzly 实现。 +- dubbo-remoting-http ,基于 Jetty 或 Tomcat 实现。 +- dubbo-remoting-mina ,基于 Mina 实现。 +- dubbo-remoting-netty ,基于 Netty 3 实现。 +- dubbo-remoting-netty4 ,基于 Netty 4 实现。 +- dubbo-remoting-p2p ,P2P 服务器。注册中心 dubbo-registry-multicast 项目的使用该项目。 + +### 从最小化的角度来看,我们只需要看: +dubbo-remoting-api + dubbo-remoting-netty4 +dubbo-remoting-zookeeper \ No newline at end of file diff --git a/dubbo-rpc/readme.md b/dubbo-rpc/readme.md new file mode 100644 index 000000000000..3267dc59a047 --- /dev/null +++ b/dubbo-rpc/readme.md @@ -0,0 +1,7 @@ +## dubbo-rpc + +> 远程调用模块:抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群的管理 + +### dubbo-rpc-api + +> 抽象各种协议以及动态代理,实现了一对一的调用。 \ No newline at end of file diff --git "a/dubbo\346\250\241\345\235\227\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.jpg" "b/dubbo\346\250\241\345\235\227\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..eea11ec15c77a3224f8fcf12ca7e80b057b99c5e GIT binary patch literal 22860 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 BN%a5# literal 0 HcmV?d00001 From 08843fbe2845764d2774a73979099dc7af4b95b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=99=93?= Date: Tue, 28 Aug 2018 11:56:54 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=98=85=E8=AF=BB?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dubbo/config/AbstractInterfaceConfig.java | 34 ++++++- .../apache/dubbo/config/ServiceConfig.java | 93 ++++++++++++++----- .../dubbo/config/support/Parameter.java | 51 ++++++++-- 3 files changed, 142 insertions(+), 36 deletions(-) diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java index 70ab62e4493a..0c9b2900118f 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java @@ -102,8 +102,15 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { // the scope for referring/exporting a service, if it's local, it means searching in current JVM only. private String scope; + /** + *

+     * 校验 RegistryConfig 配置数组。
+     * 实际上,该方法会初始化 RegistryConfig 的配置属性。
+     * 
+ */ protected void checkRegistry() { - // for backward compatibility + // 当 RegistryConfig 对象数组为空时,若有 `dubbo.registry.address` 配置,进行创建。 + // for backward compatibility 向后兼容 if (registries == null || registries.isEmpty()) { String address = ConfigUtils.getProperty("dubbo.registry.address"); if (address != null && address.length() > 0) { @@ -125,14 +132,22 @@ protected void checkRegistry() { + Version.getVersion() + ", Please add to your spring config. If you want unregister, please set "); } + // 读取环境变量和 properties 配置到 RegistryConfig 对象数组。 for (RegistryConfig registryConfig : registries) { appendProperties(registryConfig); } } + /** + *
+     * 校验 ApplicationConfig 配置。
+     * 实际上,该方法会初始化 ApplicationConfig 的配置属性。
+     * 
+ */ @SuppressWarnings("deprecation") protected void checkApplication() { - // for backward compatibility + // 当 ApplicationConfig 对象为空时,若有 `dubbo.application.name` 配置,进行创建。 + // for backward compatibility 向后兼容 if (application == null) { String applicationName = ConfigUtils.getProperty("dubbo.application.name"); if (applicationName != null && applicationName.length() > 0) { @@ -143,8 +158,9 @@ protected void checkApplication() { throw new IllegalStateException( "No such application config! Please add to your spring config."); } + // 读取环境变量和 properties 配置到 ApplicationConfig 对象。 appendProperties(application); - + // 初始化优雅停机的超时时长,参见 http://dubbo.io/books/dubbo-user-book/demos/graceful-shutdown.html 文档。 String wait = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY); if (wait != null && wait.trim().length() > 0) { System.setProperty(Constants.SHUTDOWN_WAIT_KEY, wait.trim()); @@ -255,6 +271,16 @@ protected URL loadMonitor(URL registryURL) { return null; } + /** + *
+     * 校验接口和方法
+     *  1. 接口类非空,并是接口
+     *  2. 方法在接口中已定义
+     * 
+ * + * @param interfaceClass 接口类 + * @param methods 方法数组 + */ protected void checkInterfaceAndMethods(Class interfaceClass, List methods) { // interface cannot be null if (interfaceClass == null) { @@ -341,7 +367,6 @@ public String getLocal() { } /** - * @param local * @deprecated Replace to setStub(Boolean) */ @Deprecated @@ -354,7 +379,6 @@ public void setLocal(Boolean local) { } /** - * @param local * @deprecated Replace to setStub(String) */ @Deprecated diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index e9d5e6b56715..0144e489599b 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -70,30 +70,83 @@ public class ServiceConfig extends AbstractServiceConfig { private static final long serialVersionUID = 3033787999037024738L; - + /** + * 自适应 Protocol 实现对象 + */ private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); - + /** + * 自适应 ProxyFactory 实现对象 + */ private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); - + /** + * 协议名对应生成的随机端口 + * + * key :协议名 value :端口 + */ private static final Map RANDOM_PORT_MAP = new HashMap(); - + /** + * 延迟暴露执行器 + */ private static final ScheduledExecutorService delayExportExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true)); + /** + * 服务配置对应的 Dubbo URL 数组 + * + * 非配置。 + */ private final List urls = new ArrayList(); + /** + *
+     * 服务配置暴露的 Exporter 。
+     * URL :Exporter 不一定是 1:1 的关系。
+     * 例如 {@link #scope} 未设置时,会暴露 Local + Remote 两个,也就是 URL :Exporter = 1:2
+     *      {@link #scope} 设置为空时,不会暴露,也就是 URL :Exporter = 1:0
+     *      {@link #scope} 设置为 Local 或 Remote 任一时,会暴露 Local 或 Remote 一个,也就是 URL :Exporter = 1:1
+     *
+     * 非配置。
+     * 
+ */ private final List> exporters = new ArrayList>(); - // interface type + /** + * interface type + */ private String interfaceName; + /** + * {@link #interfaceName} 对应的接口类 + * + * 非配置 + */ private Class interfaceClass; - // reference to interface impl + /** + * Service 对象 reference to interface impl + */ private T ref; - // service name + /** + * service name + */ private String path; - // method configuration + /** + * method configuration + */ private List methods; private ProviderConfig provider; + /** + * 是否已经暴露服务,参见 {@link #doExport()} 方法。 + * + * 非配置。 + */ private transient volatile boolean exported; - + /** + * 是否已取消暴露服务,参见 {@link #unexport()} 方法。 + * + * 非配置。 + */ private transient volatile boolean unexported; - + /** + * 是否泛化实现,参见 实现泛化调用 + * true / false + * + * 状态字段,非配置。 + */ private volatile String generic; public ServiceConfig() { @@ -545,14 +598,9 @@ protected Class getServiceClass(T ref) { } /** - * Register & bind IP address for service provider, can be configured separately. - * Configuration priority: environment variables -> java system properties -> host property in config file -> + * Register & bind IP address for service provider, can be configured separately. Configuration + * priority: environment variables -> java system properties -> host property in config file -> * /etc/hosts -> default network address -> first available network address - * - * @param protocolConfig - * @param registryURLs - * @param map - * @return */ private String findConfigedHosts(ProtocolConfig protocolConfig, List registryURLs, Map map) { boolean anyhost = false; @@ -624,13 +672,9 @@ private String findConfigedHosts(ProtocolConfig protocolConfig, List regist } /** - * Register port and bind port for the provider, can be configured separately - * Configuration priority: environment variable -> java system properties -> port property in protocol config file - * -> protocol default port - * - * @param protocolConfig - * @param name - * @return + * Register port and bind port for the provider, can be configured separately Configuration + * priority: environment variable -> java system properties -> port property in protocol config + * file -> protocol default port */ private Integer findConfigedPorts(ProtocolConfig protocolConfig, String name, Map map) { Integer portToBind = null; @@ -740,7 +784,6 @@ public Class getInterfaceClass() { } /** - * @param interfaceClass * @see #setInterface(Class) * @deprecated */ diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/support/Parameter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/support/Parameter.java index 0183a228a9e5..174c8050e6a3 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/support/Parameter.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/support/Parameter.java @@ -16,11 +16,17 @@ */ package org.apache.dubbo.config.support; +import org.apache.dubbo.config.AbstractConfig; +import org.apache.dubbo.config.AbstractInterfaceConfig; +import org.apache.dubbo.config.AbstractReferenceConfig; +import org.apache.dubbo.config.AbstractServiceConfig; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.Map; /** * Parameter @@ -29,17 +35,50 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Parameter { - + /** + * 键(别名) + */ String key() default ""; - + /** + * 是否必填 + */ boolean required() default false; - + /** + * 是否忽略 + */ boolean excluded() default false; - + /** + * 是否转义 + */ boolean escaped() default false; - + /** + * 是否为属性 + * + * 目前用于《事件通知》https://dubbo.gitbooks.io/dubbo-user-book/demos/events-notify.html + */ boolean attribute() default false; - + /** + * 是否拼接默认属性,参见 {@link AbstractConfig#appendParameters(Map, Object, String)} 方法。 + * + * 我们来看看 `#append() = true` 的属性,有如下四个: + * + {@link AbstractInterfaceConfig#getFilter()} + * + {@link AbstractInterfaceConfig#getListener()} + * + {@link AbstractReferenceConfig#getFilter()} + * + {@link AbstractReferenceConfig#getListener()} + * + {@link AbstractServiceConfig#getFilter()} + * + {@link AbstractServiceConfig#getListener()} + * + * 那么,以 AbstractServiceConfig 举例子。 + * + * 我们知道 ProviderConfig 和 ServiceConfig 继承 AbstractServiceConfig 类,那么 `filter` , `listener` 对应的相同的键。 + * 下面我们以 `filter` 举例子。 + * + * 在 ServiceConfig 中,默认会继承 ProviderConfig 配置的 `filter` 和 `listener` 。 + * 所以这个属性,就是用于,像 ServiceConfig 的这种情况,从 ProviderConfig 读取父属性。 + * + * 举个例子,如果 `ProviderConfig.filter=aaaFilter` ,`ServiceConfig.filter=bbbFilter` ,最终暴露到 Dubbo URL 时, + * 参数为 `service.filter=aaaFilter,bbbFilter` 。 + */ boolean append() default false; } \ No newline at end of file From 66b64a5154c4d0481bee9b0dca49f4f3c3330784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=99=93?= Date: Sun, 2 Sep 2018 19:16:45 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E9=98=85=E8=AF=BB=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/apache/dubbo/common/URL.java | 32 ++++++++++++++-- .../apache/dubbo/config/AbstractConfig.java | 19 ++++++++++ .../dubbo/config/AbstractServiceConfig.java | 4 ++ .../apache/dubbo/config/ConsumerConfig.java | 2 + .../apache/dubbo/config/ReferenceConfig.java | 37 ++++++++++++++++++- 5 files changed, 89 insertions(+), 5 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java index a83ca91e227e..9e6bfb549b54 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java @@ -38,6 +38,12 @@ /** * URL - Uniform Resource Locator (Immutable, ThreadSafe) + * + *
+ * 格式为 protocol://username:password@host:port/path?key=value&key=value ,通过 URL#buildString(...) 方法生成。
+ * parameters 属性,参数集合。从上面的 Service URL 例子我们可以看到,里面的 key=value ,实际上就是 Service 对应的配置项。
+ * 该属性,通过 AbstractConfig#appendParameters(parameters, config, prefix) 方法生成。
+ * 
*

* url example: *