From 27aea0711b587414d37f853bbdcb1f3c28979984 Mon Sep 17 00:00:00 2001 From: AmyliaY <471816751@qq.com> Date: Mon, 20 Apr 2020 22:28:17 +0800 Subject: [PATCH] =?UTF-8?q?Dubbo=E6=95=B4=E4=BD=93=E6=9E=B6=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++-- .../architectureDesign/Dubbo整体架构.md | 47 +++++++++++++++++- ...原理图.png => Dubbo工作原理图.png} | Bin images/Dubbo/dubbo项目结构.png | Bin 0 -> 20042 bytes 4 files changed, 54 insertions(+), 4 deletions(-) rename images/Dubbo/{Dubbo原理图.png => Dubbo工作原理图.png} (100%) create mode 100644 images/Dubbo/dubbo项目结构.png diff --git a/README.md b/README.md index 13eb501..5dba16f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ [![issues](https://badgen.net/github/open-issues/doocs/source-code-hunter)](https://github.com/doocs/source-code-hunter/issues) [![PRs Welcome](https://badgen.net/badge/PRs/welcome/green)](http://makeapullrequest.com) -有被“读过哪些知名的开源项目源码?”这种问题所困扰过吗?加入我们,一起通读互联网公司主流框架及中间件源码,成为强大的“源码猎人”,目前开放的有 Spring 系列框架、Mybatis 框架、Netty 框架、Dubbo 框架,及 Redis、Tomcat 中间件等,让我们一起开拓新的领地,揭开这些源码的神秘面纱。本项目主要用于记录框架及中间件源码的阅读经验、个人理解及解析,希望能够使阅读源码变成一件更简单有趣,且有价值的事情,抽空更新中...(如果本项目对您有帮助,请watch、star、fork 素质三连一波,鼓励一下作者,谢谢) +“技术深度”与“技术广度”是对开发者来说最为重要的两个维度,本项目致力于从源码层面,剖析和挖掘互联网行业主流技术的底层实现原理,**为广大开发者“提升技术深度”提供便利**。 + +加入我们,一起通读互联网行业主流框架及中间件源码,成为强大的“源码猎人”,目前开放的有 Spring 系列框架、Mybatis 框架、Netty 框架、Dubbo 框架,及 Redis、Tomcat 中间件等,让我们一起开拓新的领地,揭开这些源码的神秘面纱。本项目主要用于记录框架及中间件源码的阅读经验、个人理解及解析,希望能够使阅读源码变成一件简单有趣,且有价值的事情,抽空更新中...(如果本项目对您有帮助,请watch、star、fork 素质三连一波,鼓励一下作者,谢谢) ## Spring 系列 ### IoC 容器 @@ -148,7 +150,7 @@ - [Dubbo与Java的SPI机制](docs/Dubbo/SPI/Dubbo与Java的SPI机制.md) ### 注册中心 -- [Dubbo注册中心](docs/Dubbo/registry/Dubbo注册中心.md) +- [Dubbo注册中心模块简析](docs/Dubbo/registry/Dubbo注册中心模块简析.md) - [注册中心的Zookeeper实现](docs/Dubbo/registry/注册中心的Zookeeper实现.md) ### 远程通信 @@ -156,7 +158,10 @@ ### RPC ### 集群 - +- [Dubbo集群模块简析](docs/Dubbo/cluster/Dubbo集群模块简析.md) +- [负载均衡](docs/Dubbo/cluster/负载均衡.md) +- [集群容错](docs/Dubbo/cluster/集群容错.md) +- [mock与服务降级](docs/Dubbo/cluster/mock与服务降级.md) ## Tomcat - [servlet-api 源码赏析](docs/Tomcat/servlet-api源码赏析.md) diff --git a/docs/Dubbo/architectureDesign/Dubbo整体架构.md b/docs/Dubbo/architectureDesign/Dubbo整体架构.md index fcb5dbe..b8eb5c3 100644 --- a/docs/Dubbo/architectureDesign/Dubbo整体架构.md +++ b/docs/Dubbo/architectureDesign/Dubbo整体架构.md @@ -1 +1,46 @@ -努力编写中... \ No newline at end of file +## 项目结构 +首先从GitHub 上 down下来Dubbo项目,我们根据里面的目录名 也能大概猜出来各个模块的作用。 + +![avatar](/images/Dubbo/dubbo项目结构.png) + +### dubbo-­common +公共逻辑模块,定义了各模块中 通用的 组件 和 工具类,如:IO、日志、配置处理等。 + +### dubbo-rpc +分布式协调服务框架的核心,该模块定义了 RPC相关的组件,包括 服务发布、服务调用代理、远程调用结果、RPC调用网络协议,RPC调用监听器和过滤器等等。该模块提供了默认的 基于dubbo协议的实现,还提供了hessian、http、rmi、及webservice等协议的实现,能够满足绝大多数项目的使用需求,另外 还提供了对自定义协议的扩展。 +### dubbo­ registry +注册中心,它是 RPC 中 consumer 和 provider 两个重要角色的协调者,该模块定义了核心的 注册中心组件,提供了mutilcast、redis和zookeeper等多种方式的注册中心实现,用于不同的使用场景。 +### dubbo­ remoting +远程通讯模块,RPC 的实现基础就是远程通讯,consmer 要调用 provider 的远程方法必须通过 远程通讯实现。该模块定义了远程传输器、endpoint 终端、客户端、服务端、编码解码器、数据交换、缓冲区、通讯异常定义 等核心组件。他是对于远程网络通讯的抽象,提供了诸如 netty、mina、http等 协议和技术框架的实现方式。 +### dubbo ­monitor +监控模块,该模块可以监控服务调用的各种信息,例如调用耗时、调用量、调用结果等等,监控中心在调用过程中收集调用的信息,发送到监控服务,在监控服务中可以存储这些信息,对这些数据进行统计分析 和 展示。dubbo默认提供了一个实现,该实现非常简单,只是作为默认的实现范例,生产环境使用价值不高,往往需要自行实现。 +### dubbo ­container +容器模块,是一个独立的容器,以简单的 Main(类) 加载Spring启动,因为服务通常不需要Tomcat/JBoss等Web容器的特性,没必要用Web容器去加载服务。 +### dubbo ­config +dubbo配置模块,该模块通过 配置信息,将dubbo组件的各个模块整合在一起,给 框架的使用者 提供 可配置的、易用的 分布式服务框架。它定义了面向dubbo使用者的各种信息配置,比如服务发布配置、方法发布配置、服务消费配置、应用程序配置、注册中心配置、协议配置、监控配置等等。 +### dubbo ­cluster +集群模块,将多个服务提供方伪装为一个提供方,包括:负载均衡、容错、路由等,集群的地址列表可以是静态配置的,也可以是由注册中心下发。 +### dubbo ­admin +该项目是一个web应用,可以独立部署,用于管理dubbo服务,该管理应用可以连接注册中心,读取和更新 注册中心中的内容。 + +## 实现原理 +### 角色类型与运行原理 +一个Dubbo项目 的角色主要分为如下五种。 +- Provider:服务提供方; +- Consumer:服务消费方; +- Registry:服务注册与发现的注册中心; +- Container:服务运行容器; +- Monitor:统计服务的调用次数、调用时间 的监控中心。 + +其运行原理如下图所示。 + +![avatar](/Dubbo工作原理图.png) + +### 工作原理 +最后总结下其工作原理。 +1. 服务导出:服务提供方 导出服务,监听服务端口; +2. 服务注册:服务提供方 注册服务信息到注册中心; +3. 服务订阅:服务消费方 订阅关注的服务; +4. 服务发现:当服务地址发生变更时,注册中心通知服务消费端; +5. 远程服务调用 (RPC) :根据负载均衡策略 选择服务地址,直接调用; +6. 监控:监控器 收集和展示 服务提供方、服务消费方之间 的服务调用统计信息 。 \ No newline at end of file diff --git a/images/Dubbo/Dubbo原理图.png b/images/Dubbo/Dubbo工作原理图.png similarity index 100% rename from images/Dubbo/Dubbo原理图.png rename to images/Dubbo/Dubbo工作原理图.png diff --git a/images/Dubbo/dubbo项目结构.png b/images/Dubbo/dubbo项目结构.png new file mode 100644 index 0000000000000000000000000000000000000000..8e801b191d36f084028251c8ac1affca5b7e67e8 GIT binary patch literal 20042 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

;{9;~&`&6}eU*-$=A)erA?Euq4-5Jl<2CLAM ztPcK0Qke?z_2P$sYD9%jJ!oHeZ?4y$L@D(DR$Ruw=1J{e&k{;W^klL*frYIIUJ-u6sF&=}ffRi5#tqO&c;# zQzY%C<-MKLUxBI{&O$L?5oRz~Ci|i5v8*{X!w^3{;eeC0-cpDyKzwJWmfqy(ihuw^ z%>Zf5zjMQTrqB@k184BN5-mF{R7|G(uP*vCU2>vxj(XDds(vfwcRKzvJil2B z$dQec6t045vr2Q@bzGn$ud{Ee!c^q_YdvE#?=p3~rkR1#p9AM7#%)U0OqYI(+xX1= z61OSpwoGD!_Vh!>t+6Qr3GI_lg6}8{Ff@X&&C4@sa+nZ~9q+10l3D3LN~!f`Z(pJE zu!j@8^7}cQ_}c@(iSLCk_XM#K$F*3R2^2!J0!RXR3a%{Ljm+BKtYV)iGx+$S|0{M^ z)a&iExXSglf+?GzUg~u}*I#woiK(M}bsIe%H1XZnqWu%ejq`AuGl%!BU3u-t<$wSM z`L7jPyv#^bpwK2D|Dw<)!TwpH&?^Pvvq{x(BtNal~sqzswyws4J!#9*OLQuflj z_IXK$jSN;eDDc8oLV>q}0famE@j)%$e*_Toh^L4fF4Ty6?@51cqEDl829(~wgY*@me-=1K@eCZ;SD?b|QnZn;@>IfuK zDe|tCsl^qK(G+1gHxx!EkZ@z*MQPh;!rgl|i86k2q(|nNr$ZPt3N>pPsTAN8)`a%N!>vdoR>MkJ_o**{8cdb+`hv_8R_=<27mQX+f4mLpBENa^)sqt29lj=-=Hc&c$W8l# z^+SW~rSy|(R2UGjVavk|5PBDqM(JPtGkX=!Q?{8f}7a8skdaw*A@T2y>MI^puEf67ihfnsyUVrL` z{)HS*^M{)`kR2UPKDiS!oU30}K|J;;$30@NqF2j4^?_yb8JwW6$j>$$@!lr_IQvYc z>WTpcG-M>NO<*j8TytXiSjAzNo^fT?awow)tos2l-tPUa#A|0V?1l3WvZE(T$LD0= z2}HxbkD3PyAQjx`3f15-12+G=etiV)@1vuw^)9k|XP{rtX>9FH;td{+@i(1AiL~FL!qu^j9L}f(^g>=0CAGo&U00000 literal 0 HcmV?d00001