本文主要是介绍dubbo服务暴露简版总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
dubbo服务导出
1.serviceBean实现了ApplicationListener接口,当spring刷新上下文的时候,会回调onApplicationevent事件
2.是否延迟导出,执行export方法
3.执行父类ServiceConfig的export方法,
4.执行doExport
5.执行doExportUrl导出服务
6.执行doExportUrlForProtocol为每个协议下面导出服务
7.执行RegisteyProtocol里面的export方法,将服务者链接包装成invoker,并包装为exporter注册到注册中心,同时启动nettyServer进行端口监听
dubbo服务导入
1.饿汉式 referenceBean实现了initBean接口,当初始化bean的时候,执行afterPropertiesSet,进行服务引用
2.懒汉式 实现了FactoryBean接口,当spring加载自定义扩展bean的时候,调用getObjects方法,进行服务引入。默认为这种方式
3.调用父类referenceConfig的init方法进行初始化导出,
4.创建proxy,合并多个invoker
5.调用RegistryProtocol的refer ->doRefer向注册中心订阅服务,并获取invoker列表 通过cluster将多个invoker合并为一个invoker,将invoker转换为接口代理 同时启动nettyClient进行通讯
调用过程
1.消费者通过路由,智能容错,负载均衡确定某一个invoker,通过nettyclient进行编码,序列化并发送请求
2.服务者服务器接收到请求后,将数据分发到线程池,进行解码,执行invoke方法,并调用相应的代理类执行具体的接口方法
ioc
dubbo的ioc,是目标实例,类上没有注释@Adapative,并且有set方法,并且set方法只有一个参数,从工厂里面获取对象 并通过反射调用实例的set方法进行参数注入
aop
类上没有注释@Adapative 构造方法只有一个接口类型的参数,通过反射创建instance的一个代理类
对于接口方法,我们可以按照需求标注 Adaptive 注解。
在获取实现类的过程中,如果某个实现类被 Adaptive 注解修饰了,那么该类就会被赋值给 cachedAdaptiveClass 变量。
以 Protocol 接口为例,该接口的 destroy 和 getDefaultPort 未标注 Adaptive 注解,其他方法均标注了 Adaptive 注解。
Dubbo 不会为没有标注 Adaptive 注解的方法生成代理逻辑,对于该种类型的方法,仅会生成一句抛出异常的代码。
RegistryService的Registry ->AbstractRegistry的subscribe方法
FailbackRegistry的构造方法调用父类的构造方法,加载本地文件,同时调用自己的retry方法 zookeeperRegistry的doSubscribe方法调用父类FailbackRegistry的notify方法,执行super.notify(),执行父类 abstractRegistry中的notify.
将变化的url保存在缓存中,保存进properties,通过properties保存进file文件
调用RegistryDirectory 中的notify方法,执行refreshInvokers刷新本地缓存的服务者地址()
调用listener的notify方法 执行子类的RegistryDirectory的notify方法->执行refreshInvoker方法,刷新服务者本地缓存,并删除不可用的服务者信息
本地调用 则生成injvmInvoker 代理
远程调用
1.如果配置了服务者地址,则表示直连,则将地址放进map
2.则加载注册额中心地址,并放进map
2.对上面的map里面的信息创建dubboInvoker(直连情况下)
2.如果注册中心链接不为空 非直连情况,则需要使用cluster将创建的所有invoker进行合并
创建proxy代理类
DubboProtocol 创建inviker时候
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
optimizeSerialization(url);
// 创建 DubboInvoker
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
调用了getClients生成ExchangeClient客户端
RegistryProtocol中的doRefer方法具体进行注册zk(订阅 providers、configurators、routers 等节点数据),同时获取服务者子节点信息,放进urls中 进行处理
导出服务
ServiceBean实现了ApplicationListener接口,在spring刷新上下文时候会回调onApplicationEvent方法,进行服务导出
ServiceBean#onApplicationEvent事件,export方法(父类方法),
-->ServiceConfig#export方法:是否延迟加载,如果延迟则放进延迟线程池延迟执行导出任务,否则调用导出
-->ServiceConfig#doExport:数据参数校验
-->ServiceConfig#doExportUrls:获取注册中心地址,为每个地址导出在各种协议下导出服务,
1.doExportUrls:获取配置文件中的注册中心地址
2.doExportUrlsFor1Protocol:填充信息,默认导出到本地和远程,加载监视器链接地址,生成对应的exporter
-->DubboProtocol#export:启动服务器server
-->RegistryProtocol#export:导出服务到远程,进行注册中心注册
导入服务
ReferenceBean实现了FactoryBean,InitializingBean接口
1.第一种饿汉式:在spring调用接口InitializingBean初始化Bean调用afterPropertiesSet时候,引用服务
2.第一种懒汉式:在spring调用FactoryBean扩展自定义类型的Bean时候调用getObject时候,引用服务,默认第二种,当我们的服务被注入到其他类中时,Spring 会第一时间调用 getObject 方法,并由该方法执行服务引用逻辑
-->ReferenceBean#getObject()当服务被注入到其他类的时候spring调用getObjects
-->ReferenceConfig#get()状态判断
-->ReferenceConfig#init()进行初始化处理,参数校验,填充
-->ReferenceConfig#createProxy创建代理并合并消费者invoker
1.RegistryProtocol#refer获取注册中心地址并进行分组处理
2.DubboProtocol#refer创建底层为netty的通讯客户端client
-->RegistryProtocol#doRefer向注册中心注册服务,并订阅服务,将多个服务者进行合并
集群部署
FailOverClusterInvoker 在调用失败时,会自动切换 Invoker 进行重试 doInvoke 方法首先是获取重试次数,然后根 据重试次数进行循环调用,失败后进行重试。在 for 循环内,首先是通过负载 均衡组件选择一个 Invoker,然后再通过这个 Invoker 的 invoke 方法进行远程 调用。如果失败了,记录下异常,并进行重试。重试时会再次调用父类的 list 方 法列举 Invoker
FailbackClusterInvoker 会在调用失败后,返回一个空结果给服务消费者。并通 过定时任务对失败的调用进行重传,适合执行消息通知等操作。
FailfastClusterInvoker 只会进行一次调用,失败后立即抛出异常。适用于幂等操 作,比如新增记录
FailsafeClusterInvoker 是一种失败安全的 Cluster Invoker。所谓的失败安全是 指,当调用过程中出现异常时,FailsafeClusterInvoker 仅会打印异常,而不会抛 出异常。适用于写入审计日志等操作。
Forking Cluster 并行调用,只要有成功就返回
Broadcast Cluster 广播调用所有的服务者,只要有一个失败就返回
负载均衡
负载均衡所有的负载均衡方法都继承自AbstractLoadBalance,该类实现LoadBalance接口,并封装了一些公共的逻辑
1,如果只有一个invoker直接返回,
2.多余一个则根据时间(需要的启动时间和已经启动的时间)判断机器是否部署完成,进行重新计算权重
默认是RandomLoadBalance加权随机算法
-->doSelect获取所有invoker的加权数总和,默认加权数相等状态设置为true,只要有加权数与上一个不相等,则设置为false,
取从0-总权重数之间取一个随机总数,循环遍历所有的invoker的权重进行相减,当小于0时候,则返回当前的invoker
LeastActiveLoadBalance最小活跃数负载均衡
1.初始的活跃值都为0.收到一个请求,活跃值+1,处理完一个请求活跃值-1,性能高的机器,活跃值越小
-->doSelect 记录最小活跃数invoker的下标和权重总数,如果最后的总量只有1,则直接返回,
否则,取0-总权重之间一个随机数,循环这些invoker,总量的权重-当前invoker的权重,如果小于0,则返回当前invoker
ConsistentHashLoadBalance一致性 hash 算法
-->doSelect 它的工作过程是这样的,首先根 据 ip 或者其他的信息为缓存节点生成一个 hash,并将这个 hash 投射到 [0, 2^32 - 1] 的圆环上。当有查询或写入请求时,则为缓存项的 key 生成一个 hash 值。然后查找第一个大于或等于该 hash 值的缓存节点,并到这个节点中查询或 写入缓存项。如果当前节点挂了,则在下一次查询或写入缓存时,为缓存项查找 另一个大于其 hash 值的缓存节点即可
RoundRobinLoadBalance加权轮询 在轮询过程中进行重新加权重,以调控每台机器的负载
//服务调用过程
InvokerInvocationHandler invoke方法 拦截object中的方法
-->MockClusterInvoker invoke方法 是否配置force,判断是否执行mock逻辑,或者调用远程
—> AbstractClusterInvoker#invoke(Invocation) 数据校验,创建负载均衡实例
—> FailoverClusterInvoker#doInvoke(Invocation, List<Invoker<T>>, LoadBalance)
—> Filter#invoke(Invoker, Invocation) // 包含多个 Filter 调用
—> ListenerInvokerWrapper#invoke(Invocation)
-->AbstractInvoker invoke方法设置invocation的参数(path,attachment),
-->DubboInvoker doInvoke ExchangeClient客户端(在注册消费者时候创建的客户端)调用发送请求(异步无返回(返回空的RpcResult),异步又返回(暂时返回空的RpcResult),同步调用(get方法需等待DefaultFuture实现))
-->ReferenceCountExchangeClient request(Object request, int timeout) 调用send接口 由HeaderExchangeClient实现
-->HeaderExchangeClient request(Object request, int timeout) 返回ResponseFuture
-->HeaderExchangeChannel request(Object request, int timeout)创建Request对象
-->NettyClient send方法(父类AbstractPeer的实现)
--> AbstractClient send(Object message, boolean sent) 获取到channel
--> NettyChannel send(Object message, boolean sent) 发送消息
--> NioClientSocketChannel#write(Object) 写数据信息
//接收到调用请求处理过程
解码器将数据包解析成 Request 对象后 NettyHandler 的 messageReceived 方法紧接着会收到这个对象,并将这个对象继续向下传递
NettyHandler#messageReceived(ChannelHandlerContext, MessageEvent) 获取NettyChannel实例,
—> AbstractPeer#received(Channel, Object) 是否关闭校验
—> MultiMessageHandler#received(Channel channel, Object message) 按照message进行处理(MultiMessage类型的,则遍历调用,否则直接调用)
—> HeartbeatHandler#received(Channel, Object) 心跳递增,并设置Attribute,并创建Response
—> AllChannelHandler#received(Channel, Object) 将数据分发到线程池
—> ExecutorService#execute(Runnable) // 由线程池执行后续的调用逻辑
-->DecodeHandler received对接收到的数据进行解码
-->HeaderExchangeHandler received(Channel channel, Object message) 处理事件转换对象
-->DubboProtocol received接收到请求
-->DubboProtocol reply方法根据Invocation获取invoker实例,执行invoke方法,
-->AbstractProxyInvoker invoke(Invocation invocation) // 调用 doInvoke(子类JavassistProxyFactory实现) 执行后续的调用,并将调用结果封装到 RpcResult 中,
Wrapper 是一个抽象类,其中 invokeMethod 是一个抽象方法。Dubbo 会在运行时通过 Javassist 框架为 Wrapper 生成实现类,并实现 invokeMethod 方法,该方法最终会根据调用信息调用具体的服务
-->JavassistProxyFactory doInvoke(T proxy, String methodName,Class<?>[] parameterTypes,Object[] arguments)方法,调用具体的wrapper.invokeMethod()
这篇关于dubbo服务暴露简版总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!