www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]I作者:vivo互聯(lián)網(wǎng)服務(wù)器團(tuán)隊(duì)-WangGenfu一、Dubbo分層整體設(shè)計(jì)概述我們先從下圖開(kāi)始簡(jiǎn)單介紹Dubbo分層設(shè)計(jì)概念:(引用自Duboo開(kāi)發(fā)指南-框架設(shè)計(jì)文檔)如圖描述Dubbo實(shí)現(xiàn)的RPC整體分10層:service、config、proxy、registry、cl...

I作者:vivo互聯(lián)網(wǎng)服務(wù)器團(tuán)隊(duì)-Wang Genfu

一、Dubbo分層整體設(shè)計(jì)概述


我們先從下圖開(kāi)始簡(jiǎn)單介紹Dubbo分層設(shè)計(jì)概念:


源碼解讀Dubbo分層設(shè)計(jì)思想

(引用自Duboo開(kāi)發(fā)指南-框架設(shè)計(jì)文檔


如圖描述Dubbo實(shí)現(xiàn)的RPC整體分10層:service、config、proxy、registry、cluster、monitor、protocol、exchange、transport、serialize。


  • service:使用方定義的接口和實(shí)現(xiàn)類;

  • config:負(fù)責(zé)解析Dubbo定義的配置,比如注解和xml配置,各種參數(shù);

  • proxy:主要負(fù)責(zé)生成消費(fèi)者和提供者的代理對(duì)象,加載框架功能,比如提供者過(guò)濾器鏈,擴(kuò)展點(diǎn);

  • registry:負(fù)責(zé)注冊(cè)服務(wù)的定義和實(shí)現(xiàn)類的裝載;

  • cluster:只有消費(fèi)者有這么一層,負(fù)責(zé)包裝多個(gè)服務(wù)提供者成一個(gè)‘大提供者’,加載負(fù)載均衡、路有等擴(kuò)展點(diǎn);

  • monitor:定義監(jiān)控服務(wù),加載監(jiān)控實(shí)現(xiàn)提供者;

  • protocol:封裝RPC調(diào)用接口,管理調(diào)用實(shí)體的生命周期;

  • exchange:封裝請(qǐng)求響應(yīng)模式,同步轉(zhuǎn)異步;

  • transport:抽象傳輸層模型,兼容netty、mina、grizzly等通訊框架;

  • serialize:抽象序列化模型,兼容多種序列化框架,包括:fastjson、fst、hessian2、kryo、kryo2、protobuf等,通過(guò)序列化支持跨語(yǔ)言的方式,支持跨語(yǔ)言的rpc調(diào)用;


Dubbo這么分層的目的在于實(shí)現(xiàn)層與層之間的解耦,每一層都定義了接口規(guī)范,也可以根據(jù)不同的業(yè)務(wù)需求定制、加載不同的實(shí)現(xiàn),具有極高的擴(kuò)展性。


1.1. RPC調(diào)用過(guò)程


接下來(lái)結(jié)合上圖簡(jiǎn)單描述一次完整的rpc調(diào)用過(guò)程:


Dubbo分層的角度看,詳細(xì)時(shí)序圖如下,藍(lán)色部分是服務(wù)消費(fèi)端,淺綠色部分是服務(wù)提供端,時(shí)序圖從消費(fèi)端一次Dubbo方法調(diào)用開(kāi)始,到服務(wù)端本地方法執(zhí)行結(jié)束。


源碼解讀Dubbo分層設(shè)計(jì)思想


Dubbo核心領(lǐng)域?qū)ο蟮慕嵌瓤?,我們引?span>Dubbo官方文檔說(shuō)明,如下圖所示。Dubbo核心領(lǐng)域?qū)ο笫荌nvoker,消費(fèi)端代理對(duì)象是proxy,包裝了Invoker的調(diào)用;服務(wù)端代理對(duì)象是一個(gè)Invoker,他通過(guò)exporter包裝,當(dāng)服務(wù)端接收到調(diào)用請(qǐng)求后,通過(guò)exporter找到Invoker,Invoker去實(shí)際執(zhí)行用戶的業(yè)務(wù)邏輯。


源碼解讀Dubbo分層設(shè)計(jì)思想

(引用自Dubbo官方文檔)


1.2 Dubbo服務(wù)的注冊(cè)和發(fā)現(xiàn)流程


下圖出自開(kāi)發(fā)指南-框架設(shè)計(jì)-引用服務(wù)時(shí)序,主要流程是:從注冊(cè)中心訂閱服務(wù)提供者,然后啟動(dòng)tcp服務(wù)連接遠(yuǎn)端提供者,將多個(gè)服務(wù)提供者合并成一個(gè)Invoker,用這個(gè)Invoker創(chuàng)建代理對(duì)象。


源碼解讀Dubbo分層設(shè)計(jì)思想


下圖出自開(kāi)發(fā)指南-框架設(shè)計(jì)-暴露服務(wù)時(shí)序,主要流程是:創(chuàng)建本地服務(wù)的代理Invoker,啟動(dòng)tcp服務(wù)暴露服務(wù),然后將服務(wù)注冊(cè)到注冊(cè)中心。


源碼解讀Dubbo分層設(shè)計(jì)思想


接下來(lái)我們結(jié)合Dubbo服務(wù)的注冊(cè)和發(fā)現(xiàn),從配置層開(kāi)始解釋每一層的作用和原理。


示例服務(wù)接口定義如下:

public interface CouponServiceViewFacade { /** * 查詢單張優(yōu)惠券 */ CouponViewDTO query(String code);}

二、配置層


2.1. 做什么


配置層提供配置處理工具類,在容器啟動(dòng)的時(shí)候,通過(guò)ServiceConfig.export實(shí)例化服務(wù)提供者,ReferenceConfig.get實(shí)例化服務(wù)消費(fèi)者對(duì)象。


Dubbo應(yīng)用使用spring容器啟動(dòng)時(shí),Dubbo服務(wù)提供者配置處理器通過(guò)ServiceConfig.export啟動(dòng)Dubbo遠(yuǎn)程服務(wù)暴露本地服務(wù)。Dubbo服務(wù)消費(fèi)者配置處理器通過(guò)ReferenceConfig.get實(shí)例化一個(gè)代理對(duì)象,并通過(guò)注冊(cè)中心服務(wù)發(fā)現(xiàn),連接遠(yuǎn)端服務(wù)提供者。


Dubbo配置可以使用注解和xml兩種形式,本文采用注解的形式進(jìn)行說(shuō)明。


2.2. 怎么做


2.2.1 服務(wù)消費(fèi)端的解析


Spring容器啟動(dòng)過(guò)程中,填充bean屬性時(shí),對(duì)含有Dubbo引用注解的屬性使用

org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor進(jìn)行初始化。


如下是

ReferenceAnnotationBeanPostProcessor的構(gòu)造方法,Dubbo服務(wù)消費(fèi)者注解處理器處理以下三個(gè)注解:

DubboReference.class,?

Reference.class,?

com.alibaba.dubbo.config.annotation.Reference.class修飾的類。


ReferenceAnnotationBeanPostProcessor類定義:

public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements ApplicationContextAware { public ReferenceAnnotationBeanPostProcessor() { super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class); }}

Dubbo服務(wù)發(fā)現(xiàn)到這一層,Dubbo即將開(kāi)始構(gòu)建服務(wù)消費(fèi)者的代理對(duì)象,

CouponServiceViewFacade接口的代理實(shí)現(xiàn)類。


2.2.2 服務(wù)提供端的解析


Spring容器啟動(dòng)的時(shí)候,加載注解

@org.apache.dubbo.config.spring.context.annotation.DubboComponentScan指定范圍的類,并初始化;初始化使用dubbo實(shí)現(xiàn)的擴(kuò)展點(diǎn)

org.apache.dubbo.config.spring.beans.factory.annotation.ServiceClassPostProcessor。


ServiceClassPostProcessor處理的注解類有

DubboService.class,Service.class,com.alibaba.dubbo.config.annotation.Service.class。


如下是ServiceClassPostProcessor類定義:

public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware, ResourceLoaderAware, BeanClassLoaderAware { private final static List> serviceAnnotationTypes = asList( DubboService.class,Service.class,com.alibaba.dubbo.config.annotation.Service.class );。。。}

等待Spring容器ContextRefreshedEvent事件,啟動(dòng)Dubbo應(yīng)用服務(wù)監(jiān)聽(tīng)端口,暴露本地服務(wù)。


Dubbo服務(wù)注冊(cè)到這一層,Dubbo即將開(kāi)始構(gòu)建服務(wù)提供者的代理對(duì)象,CouponServiceViewFacade實(shí)現(xiàn)類的反射代理類。


三、?代理層


3.1 做什么


為服務(wù)消費(fèi)者生成代理實(shí)現(xiàn)實(shí)例,為服務(wù)提供者生成反射代理實(shí)例。


CouponServiceViewFacade的代理實(shí)現(xiàn)實(shí)例,消費(fèi)端在調(diào)用query方法的時(shí)候,實(shí)際上是調(diào)用代理實(shí)現(xiàn)實(shí)例的query方法,通過(guò)他調(diào)用遠(yuǎn)程服務(wù)。

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)// package org.apache.dubbo.common.bytecode; public class proxy1 implements DC, Destroyable, CouponServiceViewFacade, EchoService { public static Method[] methods; private InvocationHandler handler; public proxy1(InvocationHandler var1) { this.handler = var1; } public proxy1() { } public CouponViewDTO query(String var1) { Object[] var2 = new Object[]{var1}; Object var3 = this.handler.invoke(this, methods[0], var2); return (CouponViewDTO)var3; }}

CouponServiceViewFacade的反射代理實(shí)例,服務(wù)端接收到請(qǐng)求后,通過(guò)該實(shí)例的Invoke方法最終執(zhí)行本地方法query。

/** * InvokerWrapper */public class AbstractProxyInvoker implements Invoker { // 。。。 public AbstractProxyInvoker(CouponServiceViewFacade proxy, Class type, URL url) { //。。。 this.proxy = proxy; this.type = type; this.url = url; } @Override public Result invoke(Invocation invocation) throws RpcException { //。。。 Object value = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()); //。。。 } protected Object doInvoke(CouponServiceViewFacade proxy, String methodName, Class[] parameterTypes, Object[] arguments) throws Throwable{ //。。。 return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments); } }

3.2 怎么做


Dubbo代理工廠接口定義如下,定義了服務(wù)提供者和服務(wù)消費(fèi)者的代理對(duì)象工廠方法。服務(wù)提供者代理對(duì)象和服務(wù)消費(fèi)者代理對(duì)象都是通過(guò)工廠方法創(chuàng)建,工廠實(shí)現(xiàn)類可以通過(guò)SPI自定義擴(kuò)展。

@SPI("javassist")public interface ProxyFactory { // 生成服務(wù)消費(fèi)者代理對(duì)象 @Adaptive({PROXY_KEY}) T getProxy(Invoker invoker) throws RpcException; // 生成服務(wù)消費(fèi)者代理對(duì)象 @Adaptive({PROXY_KEY}) T getProxy(Invoker invoker, boolean generic) throws RpcException; // 生成服務(wù)提供者代理對(duì)象 @Adaptive({PROXY_KEY}) Invoker getInvoker(T proxy, Class type, URL url) throws RpcException; }

3.2.1 服務(wù)消費(fèi)者


3.2.1.1 創(chuàng)建服務(wù)消費(fèi)者代理類


默認(rèn)采用Javaassist代理工廠實(shí)現(xiàn),Proxy.getProxy(interfaces)創(chuàng)建代理工廠類,newInstance創(chuàng)建具體代理對(duì)象。

public class JavassistProxyFactory extends AbstractProxyFactory { @Override @SuppressWarnings("unchecked") public T getProxy(Invoker invoker, Class[] interfaces) { return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); } 。。。 }

3.2.1.2 服務(wù)消費(fèi)者代理


Dubbo為每個(gè)服務(wù)消費(fèi)者生成兩個(gè)代理類:代理工廠類,接口代理類。


CouponServiceViewFacade代理工廠類:

public class Proxy1 extends Proxy implements DC { public Proxy1() { } public Object newInstance(InvocationHandler var1) { return new proxy1(var1); }}

最終生成的CouponServiceViewFacade的代理對(duì)象如下,其中handler的實(shí)現(xiàn)類是InvokerInvocationHandler,

this.handler.invoke方法發(fā)起Dubbo調(diào)用。

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)// package org.apache.dubbo.common.bytecode; public class proxy1 implements DC, Destroyable, CouponServiceViewFacade, EchoService { public static Method[] methods; private InvocationHandler handler; public proxy1(InvocationHandler var1) { this.handler = var1; } public proxy1() { } public CouponViewDTO query(String var1) { Object[] var2 = new Object[]{var1}; Object var3 = this.handler.invoke(this, methods[0], var2); return (CouponViewDTO)var3; }}

3.2.2 服務(wù)提供者


3.2.2.1 創(chuàng)建服務(wù)提供者代理類


默認(rèn)Javaassist代理工廠實(shí)現(xiàn),使用Wrapper包裝本地服務(wù)提供者。proxy是實(shí)際的服務(wù)提供者實(shí)例,即CouponServiceViewFacade的本地實(shí)現(xiàn)類,type是接口類定義,URL是injvm協(xié)議URL。

public class JavassistProxyFactory extends AbstractProxyFactory { 。。。 @Override public Invoker getInvoker(T proxy, Class type, URL url) { // 代理包裝類,包裝了本地的服務(wù)提供者 final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type); // 代理類入口 return new AbstractProxyInvoker(proxy, type, url) { @Override protected Object doInvoke(T proxy, String methodName, Class[] parameterTypes, Object[] arguments) throws Throwable { return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments); } }; } }

3.2.2.2 Wrapper包裝類


Dubbo為每個(gè)服務(wù)提供者的本地實(shí)現(xiàn)生成一個(gè)Wrapper代理類,抽象Wrapper類定義如下:

public abstract class Wrapper { 。。。 abstract public Object invokeMethod(Object instance, String mn, Class[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException;}

具體Wrapper代理類使用字節(jié)碼技術(shù)動(dòng)態(tài)生成,本地服務(wù)CouponServiceViewFacade的代理包裝類舉例:

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)// package org.apache.dubbo.common.bytecode; import com.xxx.CouponServiceViewFacade;import java.lang.reflect.InvocationTargetException;import java.util.Map;import org.apache.dubbo.common.bytecode.ClassGenerator.DC; public class Wrapper25 extends Wrapper implements DC { 。。。 public Wrapper25() { } public Object invokeMethod(Object var1, String var2, Class[] var3, Object[] var4) throws InvocationTargetException { CouponServiceViewFacade var5; try { var5 = (CouponServiceViewFacade)var1; } catch (Throwable var8) { throw new IllegalArgumentException(var8); } try { if ("query".equals(var2)
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉