b2c信息网

您现在的位置是:首页 > 明日新闻 > 正文

明日新闻

dubbo源码如何看懂(dubbo基础)

hacker2022-06-09 23:18:32明日新闻94
本文目录一览:1、求深度解剖dubbo源码的视频

本文目录一览:

求深度解剖dubbo源码的视频

你可以在CSDN中找到你想要的 框架和数据库估计你自己能拿下吧 关键是核心代码 在CSDN里你可以找到

android 可以使用dubbo吗

可以的

DUBBO配置规则详解

研究DUBBO也已经大半年了,对它的大部分源码进行了分析,以及对它的内部机制有了比较深入的了解,以及各个模块的实现。DUBBO包含很多内容,如果想了解DUBBO第一步就是启动它,从而可以很好的使用它,那么如何更好的使用呢?就需要知道DUBBO的各个配置项,以及它可以通过哪些途径进行配置。个人对配置的理解,就好比时对动物的驯服,如何很好的驯服一头猛兽,那就需要知道它各种因子,从而调整,已达到自己期望的结果。这篇不对DUBBO有哪些配置项可以配置,但是通过这篇文章,你应该能够知道DUBBO可以进行哪些配置。本文会通过分析DUBBO加载配置源码的分析,来使得大家对DUBBO的配置一块有更加深入的了解。从而达到“驯服”DUBBO,以使得它成为你们自己的DUBBO。

DUBBO在配置这一块做的确实很完美,提供很很多参数,以及提供了多种渠道。下面进入正题,看看DUBBO怎么加载配置的。在讲这些之前,先给大家介绍一下在DUBBO源码层面定义了哪些类来存储各个模块的配置项,从而了解DUBBO可以对哪些模块进行配置。

哪些东西可以配置

由于大部分项目都会使用Spring,而且DUBBO也提供了通过Spring来进行配置,那么先从这里进行着手。DUBBO加载Spring的集成时在dubbo-config下面的dubbo-config-spring模块下面,其中有一个类DubboNamespaceHandler,它实现了Spring提供的接口NamespaceHandlerSupport。那么Spring怎么发现整个实现类的呢?在该模块的META-INF文件夹下有两个文件: spring.handlers和spring.schemas,这两个文件里面制定了dubbo的namespace的XSD文件的位置以及dubbo的namespace由DubboNamespaceHandler来处理解析。说了这么多废话,只是想说明Spring是怎么解析dubbo:.../配置的。

知道了DUBBO和Spring关于配置一块时怎么整合的之后,那么你应该就不会诧异Spring怎么那么聪明,能够解析dubbo的namespace。接下来看看DubboNamespaceHandler类里面有什么东西。

dubbo-container源码怎么打包

Dubbo的服务的过程,也需要一个像reference的对象来维护service关联的所有对象及其属性,这里的reference就是provider。由于ServiceBean实现了

InitializingBean接口,所有在Spring实例化这个bean后会调用接口方法afterPropertiesSet:

[java] view plain copy

public void afterPropertiesSet() throws Exception {

//如果没有配置provider

if (getProvider() == null) {

//获取IOC容器里的所有provider

MapString, ProviderConfig providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);

if (providerConfigMap != null providerConfigMap.size() 0) {

MapString, ProtocolConfig protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);

if ((protocolConfigMap == null || protocolConfigMap.size() == 0)

providerConfigMap.size() 1) { // 兼容旧版本

ListProviderConfig providerConfigs = new ArrayListProviderConfig();

for (ProviderConfig config : providerConfigMap.values()) {

if (config.isDefault() != null config.isDefault().booleanValue()) {

providerConfigs.add(config);

}

}

//关联所有providers

if (providerConfigs.size() 0) {

setProviders(providerConfigs);

}

} else {

ProviderConfig providerConfig = null;

for (ProviderConfig config : providerConfigMap.values()) {

if (config.isDefault() == null || config.isDefault().booleanValue()) {

if (providerConfig != null) {

throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);

}

providerConfig = config;

}

}

if (providerConfig != null) {

setProvider(providerConfig);

}

}

}

}

//如果没有配置application,且没有配置provider

if (getApplication() == null

(getProvider() == null || getProvider().getApplication() == null)) {

//获取所有applications

MapString, ApplicationConfig applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);

if (applicationConfigMap != null applicationConfigMap.size() 0) {

ApplicationConfig applicationConfig = null;

for (ApplicationConfig config : applicationConfigMap.values()) {

if (config.isDefault() == null || config.isDefault().booleanValue()) {

if (applicationConfig != null) {

throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);

}

applicationConfig = config;

}

}

//关联application

if (applicationConfig != null) {

setApplication(applicationConfig);

}

}

}

//如果没有配置module,且没有配置provider

if (getModule() == null

(getProvider() == null || getProvider().getModule() == null)) {

MapString, ModuleConfig moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);

if (moduleConfigMap != null moduleConfigMap.size() 0) {

ModuleConfig moduleConfig = null;

for (ModuleConfig config : moduleConfigMap.values()) {

if (config.isDefault() == null || config.isDefault().booleanValue()) {

if (moduleConfig != null) {

throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);

}

moduleConfig = config;

}

}

//关联module

if (moduleConfig != null) {

setModule(moduleConfig);

}

}

}

//如果没有配置registries,且没有配置provider

if ((getRegistries() == null || getRegistries().size() == 0)

(getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)

(getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {

MapString, RegistryConfig registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);

if (registryConfigMap != null registryConfigMap.size() 0) {

ListRegistryConfig registryConfigs = new ArrayListRegistryConfig();

for (RegistryConfig config : registryConfigMap.values()) {

if (config.isDefault() == null || config.isDefault().booleanValue()) {

registryConfigs.add(config);

}

}

//关联registries

if (registryConfigs != null registryConfigs.size() 0) {

super.setRegistries(registryConfigs);

}

}

}

//如果没有配置monitor,且没有配置provider

if (getMonitor() == null

(getProvider() == null || getProvider().getMonitor() == null)

(getApplication() == null || getApplication().getMonitor() == null)) {

MapString, MonitorConfig monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);

if (monitorConfigMap != null monitorConfigMap.size() 0) {

MonitorConfig monitorConfig = null;

for (MonitorConfig config : monitorConfigMap.values()) {

if (config.isDefault() == null || config.isDefault().booleanValue()) {

if (monitorConfig != null) {

throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);

}

monitorConfig = config;

}

}

//关联monitor

if (monitorConfig != null) {

setMonitor(monitorConfig);

}

}

}

//如果没有配置protocol,且没有配置provider

if ((getProtocols() == null || getProtocols().size() == 0)

(getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {

MapString, ProtocolConfig protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);

if (protocolConfigMap != null protocolConfigMap.size() 0) {

ListProtocolConfig protocolConfigs = new ArrayListProtocolConfig();

for (ProtocolConfig config : protocolConfigMap.values()) {

if (config.isDefault() == null || config.isDefault().booleanValue()) {

protocolConfigs.add(config);

}

}

//关联protocol

if (protocolConfigs != null protocolConfigs.size() 0) {

super.setProtocols(protocolConfigs);

}

}

}

//如果没有配置path

if (getPath() == null || getPath().length() == 0) {

if (beanName != null beanName.length() 0

getInterface() != null getInterface().length() 0

beanName.startsWith(getInterface())) {

setPath(beanName);

}

}

//暴露provider

if (! isDelay()) {

export();

}

}

netty server怎么调用dubbo

下面看dubbo源码来看服务暴露的过程,服务暴露的入口为:com.alibaba.dubbo.config.ServiceConfig#export 方法,代码如下:

[java] view plain copy

//是否延时暴露

if (delay != null delay 0) {

Thread thread = new Thread(new Runnable() {

public void run() {

try {

Thread.sleep(delay);

} catch (Throwable e) {

}

doExport();

}

怎么将dubbox源码编译成dubbox2.8.4 jar

settings xmlns=""

xmlns:xsi=""

xsi:schemaLocation="

"

mirrors

mirror

idCN/id

nameOSChina Central/name

url;/url

mirrorOfcentral/mirrorOf

/mirror

/mirrors

如何更好地学习dubbo源代码

一、Dubbo整体架构 1、Dubbo与Spring的整合 Dubbo在使用上可以做到非常简单,不管是Provider还是Consumer都可以通过Spring的配置文件进行配置,配置完之后,就可以像使用 spring bean一样进行服务暴露和调用了,完全看不到dubbo api的存在。这是因为dubbo使用了spring提供的可扩展Schema自定义配置支持。在spring配置文件中,可以像、这样进行配置。 META-INF下的spring.handlers文件中指定了dubbo的xml解析类:DubboNamespaceHandler。像前面的被解 析成ServiceConfig,被解析成ReferenceConfig等等。 2、jdk spi扩展 由于Dubbo是开源框架,必须要提供很多的可扩展点。Dubbo是通过扩展jdk spi机制来实现可扩展的。具体来说,就是在META-INF目录下,放置文件名为接口全称,文件中为key、value键值对,value为具体实现类 的全类名,key为标志值。由于dubbo使用了url总线的设计,即很多参数通过URL对象来传递,在实际中,具体要用到哪个值,可以通过url中的参 数值来指定。 Dubbo对spi的扩展是通过ExtensionLoader来实现的,查看ExtensionLoader的源码,可以看到Dubbo对jdk spi做了三个方面的扩展: (1)jdk spi仅仅通过接口类名获取所有实现,而ExtensionLoader则通过接口类名和key值获取一个实现; (2)Adaptive实现,就是生成一个代理类,这样就可以根据实际调用时的一些参数动态决定要调用的类了。 (3)自动包装实现,这种实现的类一般是自动激活的,常用于包装类,比如Protocol的两个实现类:ProtocolFilterWrapper、ProtocolListenerWrapper。 3、url总线设计 Dubbo为了使得各层解耦,采用了url总线的设计。我们通常的设计会把层与层之间的交互参数做成Model,这样层与层之间沟通成本比较大,扩展起来也比较麻烦。因此,Dubbo把各层之间的通信都采用url的形式。比如,注册中心启动时,参数的url为: registry://0.0.0.0:9090?codec=registrytransporter=netty 这就表示当前是注册中心,绑定到所有ip,端口是9090,解析器类型是registry,使用的底层网络通信框架是netty。

二、Dubbo启动过程 Dubbo分为注册中心、服务提供者(provider)、服务消费者(consumer)三个部分。 1、注册中心启动过程 注册中心的启动过程,主要看两个类:RegistrySynchronizer、RegistryReceiver,两个类的初始化方法都是start。 RegistrySynchronizer的start方法: (1)把所有配置信息load到内存; (2)把当前注册中心信息保存到数据库; (3)启动5个定时器。 5个定时器的功能是: (1)AutoRedirectTask,自动重定向定时器。默认1小时运行1次。如果当前注册中心的连接数高于平均值的1.2倍,则将多出来的连接数重定向到其他注册中心上,以达到注册中心集群的连接数均衡。 (2)DirtyCheckTask,脏数据检查定时器。作用是:分别检查缓存provider、数据库provider、缓存consumer、数据库 consumer的数据,清除脏数据;清理不存活的provider和consumer数据;对于缓存中的存在的provider或consumer而数 据库不存在,重新注册和订阅。 (3)ChangedClearTask,changes变更表的定时清理任务。作用是读取changes表,清除过期数据。 (4)AlivedCheckTask,注册中心存活状态定时检查,会定时更新registries表的expire字段,用以判断注册中心的存活状态。如果有新的注册中心,发送同步消息,将当前所有注册中心的地址通知到所有客户端。 (5)ChangedCheckTask,变更检查定时器。检查changes表的变更,检查类型包括:参数覆盖变更、路由变更、服务消费者变更、权重变更、负载均衡变更。 RegistryReceiver的start方法:启动注册中心服务。默认使用netty框架,绑定本机的9090端口。最后启动服务的过程是在NettyServer来完成的。接收消息时,抛开dubbo协议的解码器,调用类的顺序是 NettyHandler-》NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》RegistryReceiver-》RegistryValidator-》RegistryFailover-》RegistryExecutor。 2、provider启动过程 provider的启动过程是从ServiceConfig的export方法开始进行的,具体步骤是: (1)进行本地jvm的暴露,不开放任何端口,以提供injvm这种形式的调用,这种调用只是本地调用,不涉及进程间通信。 (2)调用RegistryProtocol的export。 (3)调用DubboProtocol的export,默认开启20880端口,用以提供接收consumer的远程调用服务。 (4)通过新建RemoteRegistry来建立与注册中心的连接。 (5)将服务地址注册到注册中心。 (6)去注册中心订阅自己的服务。 3、consumer启动过程 consumer的启动过程是通过ReferenceConfig的get方法进行的,具体步骤是: (1)通过新建RemoteRegistry来建立与注册中心的连接。 (2)新建RegistryDirectory并向注册中心订阅服务,RegistryDirectory用以维护注册中心获取的服务相关信息。 (3)创建代理类,发起consumer远程调用时,实际调用的是InvokerInvocationHandler。 三、实际调用过程 consumer端发起调用时,实际调用经过的类是: 1、consumer: InvokerInvocationHandler-》MockClusterInvoker(如果配置了Mock,则直接调用本地Mock类)-》FailoverClusterInvoker(负载均衡,容错机制,默认在发生错误的情况下,进行两次重试)-》RegistryDirectory$InvokerDelegete-》ConsumerContextFilter-》FutureFilter-DubboInvoker 2、provider: NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》DubboProtocol.requestHandler-》EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter-》实际service。 四、Dubbo使用的设计模式 1、工厂模式 ServiceConfig中有个字段,代码是这样的: privatestaticfinalProtocolprotocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); Dubbo里有很多这种代码。这也是一种工厂模式,只是实现类的获取采用了jdk spi的机制。这么实现的优点是可扩展性强,想要扩展实现,只需要在classpath下增加个文件就可以了,代码零侵入。另外,像上面的 Adaptive实现,可以做到调用时动态决定调用哪个实现,但是由于这种实现采用了动态代理,会造成代码调试比较麻烦,需要分析出实际调用的实现类。 2、装饰器模式 Dubbo在启动和调用阶段都大量使用了装饰器模式。以Provider提供的调用链为例,具体的调用链代码是在 ProtocolFilterWrapper的buildInvokerChain完成的,具体是将注解中含有group=provider的 Filter实现,按照order排序,最后的调用顺序是 EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter。 更确切地说,这里是装饰器和责任链模式的混合使用。例如,EchoFilter的作用是判断是否是回声测试请求,是的话直接返回内容,这是一种责任 链的体现。而像ClassLoaderFilter则只是在主功能上添加了功能,更改当前线程的ClassLoader,这是典型的装饰器模式。 3、观察者模式 Dubbo的provider启动时,需要与注册中心交互,先注册自己的服务,再订阅自己的服务,订阅时,采用了观察者模式,开启一个listener。 注册中心会每5秒定时检查是否有服务更新,如果有更新,向该服务的提供者发送一个notify消息,provider接受到notify消息后,即运行 NotifyListener的notify方法,执行监听器方法。 4、动态代理模式 Dubbo扩展jdk spi的类ExtensionLoader的Adaptive实现是典型的动态代理实现。Dubbo需要灵活地控制实现类,即在调用阶段动态地根据参数决 定调用哪个实现类,所以采用先生成代理类的方法,能够做到灵活的调用。生成代理类的代码是ExtensionLoader的 createAdaptiveExtensionClassCode方法。代理类的主要逻辑是,获取URL参数中指定参数的值作为获取实现类的key。

发表评论

评论列表

  • 酒奴奢欲(2022-06-10 06:13:20)回复取消回复

    bo使用的设计模式 1、工厂模式 ServiceConfig中有个字段,代码是这样的: privatestaticfinalProtocolprotocol=ExtensionLoader.getExtensio

  • 南殷墓栀(2022-06-10 05:27:26)回复取消回复

    if (providerConfigs.size() 0) { setProviders(p