经过两天断断续续的摸索以及资料(说到这理要落泪了)的查询该问题得意解决这就是本次要扯的内容。
本次 dubbo 服务 是以docker-compose进行服务编排部署,服务者与消费者也在同一个Java 工程目录下
当我们服务者工程开启的时候会在Nacos中服务列表中产生新的一项接口其内容是这样的,根据下方的图片可以很清楚的看到IP及端口是不是有点似曾相识的感觉呢,特别是20880端口!
又经历了一资料的查询之后,我发现20800端口并没有被我映射出来。于是我把服务提供者配置文件改这样:
消费者配置文件改成这样
终于在我本地以及不同的服务器之间可以正常运行了!
其实如果不在测试环境上遇到这些问题以后在生产环境上也同样会遇到,我们能做的就是在问题到来之前做一定的知识储备避免一些常见的坑。
1、InvokerInvocationHandler jdk动态代理
5、RegistryDirector返回Invokers
Router分为:Script 脚本路由、Condition 条件路由
6、通过MockInvokersSelector的route方法(getNormalInvokers)拿到能正常执行的invokers
8、当回到AbstractClusterInvoker后,执行(默认FailoverClusterInvoker,根据配置的是,Failfast Cluster(快速失败) , Failsafe Cluster(失败安全) , Failback Cluster(失败自动恢复) , Forking Cluster(并行调用多个服务器,只要一个成功即返回) , Broadcast Cluster(广播调用所有提供者,逐个调用,任意一台报错则报错))doInvoker方法
9、FailoverClusterInvoker调用AbstractClusterInvoker的select方法
10、执行doSelect方法
11、调用AbstractLoadbalance的select方法
12、根据配置的负载均衡策略调用对应的(如RoundRobinLoadBalance)类的doSelect方法
13、返回invokers.get()方法
14、调用FailoverClusterInvoker的invoke方法
均继承自抽象类AbstractDirectory
Directory 获取 invoker 是从 methodInvokerMap 中获取的,主要都是读操作,那它的写操作是在什么时候写的呢?就是在回调方法 notify 的时候操作的,也就是注册中心有变化,则更新 methodInvokerMap 和 urlInvokerMap 的值
根据dubbo-admin配置的路由规则来过滤相关的invoker,当我们对路由规则点击启用,就会触发 RegistryDirectory 类的 notify 方法。
notify方法调用refreshInvoker方法。
route方法的实现类为ConditionRoute 根据条件进行过滤
1、调用mathThen方法
2、调用matchCondition方法
3、调用isMatch判断
4、调用isMatchGlobPattern方法
集群模块是服务提供者和服务消费者的中间层,为服务消费者屏蔽了服务提供者的情况,这样服务消费者就可以专心处理远程调用相关事宜。比如发请求,接受服务提供者返回的数据等。这就是Dubbo Cluster集群的作用。
通过cluster来指定集群容错方式
其实就是应对出错情况采取的策略
用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非提供者挂了,再连另一台,自动开启延迟链接,以减少长接数
启动时服务提供者将当前进程启动时间注册到ZK;服务消费者发现该节点后计算服务启动时间(相对当前时间),在默认预热时间的前20%时间内,该节点权重始终固定为2,这样客户端的负载均衡器只会分发极少的请求至节点。
在预热时间之后的80%时间内,该节点权重将随着时间的推移而线性增长;待预热时间到期后,权重自动恢复为默认值100;负载均衡器的内核是一个标准的WLC算法模块,即加权最少连接算法;
如果某个节点Hang住或宕机,其权重会迅速自动调节降低,避免持续性影响;当节点下线时,服务端提前触发权重调节,重载默认权重至1并发布到注册中心,服务消费者将迅速感知到该事件;
服务提供者优雅下线步骤(注意这套逻辑仅在服务端执行)在ok.htm?down=true对应的controller中加入下列逻辑,注意要判断down是否为true,因为正常来说false表示启动验证而不是关机
服务者消费者配置
dubbo服务支持参数动态调整,例如动态调整权重,但dubbo实现方式较为特殊,并不是常规思路。
ServiceConfig类拿到对外提供服务的实际类ref,然后通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转换(javassistProxyFacory、JdkProxyFactory),接着要做Invoker转换到Export的过程
服务发布:本地暴露、远程暴露
为什么会有 本地暴露 和 远程暴露 呢?不从场景考虑讨论技术的没有意义是.在dubbo中我们一个服务可能既是 Provider ,又是 Consumer ,因此就存在他自己调用自己服务的情况,如果再通过网络去访问,那自然是舍近求远,因此他是有 本地暴露 服务的这个设计.从这里我们就知道这个两者的区别
1、spring启动,解析配置文件
2、创建dubbo标签解析器
3、解析dubbo标签
4、ServiceBean解析
5、容器创建完成,触发ContextRefrestEvent
6、export暴露服务
7、duExportUrls
8、doExportUrlsFor1Protocol
9、getInvoker
10、protocol.export
11、开启服务器 openServer()如nettyServer
12、注册服务到注册中心 registerProvider
Filter 在服务暴露前,做拦截器初始化,在加载所有拦截器时会过滤支队provider生效的数据。
可以。zookeeper的信息会缓存到本地作为一个缓存文件,并且转换成 properties 对象方便使用。建立线程池,定时检测并连接注册中心,失败了就重连。
注册服务到zk其实就是在zk上创建临时节点,当节点下线或者down掉时,即会删除临时节点,从而使服务从可用列表中剔除。
持久节点
临时节点
1、export的时候进行zk订阅
2、设置监听回调的地址,回调给FailbackRegistry的notify
3、创建持久节点
4、设置对该节点的监听
5、更新新的服务信息,服务启动和节点更新回调,都会调用到这里
6、更新缓存文件
7、对比新旧信息是否有变化,有则重新暴露服务
高并发大业务量情况下,暂时屏蔽边缘业务
MockClusterInvoker
SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。接下来,我们先来了解一下 Java SPI 与 Dubbo SPI 的用法,然后再来分析 Dubbo SPI 的源码。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)