共计 3187 个字符,预计需要花费 8 分钟才能阅读完成。
某日中午,午睡正香的时候,接到零碎的报警电话,提醒生产某物理机异样宕机了,目前该物理机已复原,须要重启下面部署的利用。
这时霎时没有了睡意,登上堡垒机,疾速重启了利用,零碎恢复正常。本想着持续午睡,然而曾经没有了睡意。
旁边的小师弟( 咱们叫他小灰吧 )方才在咱们边上,目击这所有,而后向我求教个问题。
小灰:
黑哥,方才利用忽然宕机,会不会对交易有影响啊?
小黑:
影响的确会有,不过也不大,就过后利用正在运行那些那些交易会受到影响。
小灰:
不对啊,咱们当初零碎架构是上面这样。
咱们这次宕机的是业务逻辑层,那依照目前应用 Dubbo 轮询的负载平衡形式,不是还会有交易散发到宕机那台利用上,这些交易申请显然会异样。
运气差点,不是会有一半交易申请都会有问题吗?
小黑:
没错,咱们的零碎架构图的确如说的一样。
不过你说的这个问题,它是不存在的。
这是因为 Dubbo 外部会主动帮咱们的摘除宕机的利用节点。
小灰:
啥?Dubbo 外部还有这性能啊?黑哥你给我讲讲原理呗!
小黑:
能够啊,不过讲这个原理之前,咱们首先须要理解 Dubbo 服务注册发现流程。
我看你最近始终在看『深刻了解 Apache Dubbo 与实战』,这本书的确不错,外面框架原理,代码细节都讲的很透彻。
你应该曾经理解了 Dubbo 服务注册发现流程,那你先跟我简略讲讲原理吧。
小灰拿起纸笔,在下面画了个图:
恩,我以后理解的还不是很深,那我先聊聊目前我晓得的。
咱们目前应用 ZooKeeper 当做服务注册核心,ZooKeeper 能够简略了解成是一个 KV 零碎,外部是一个树形的数据结构。
Dubbo 默认将会在 ZooKeeper 中创立一个四层的数据结构,从上到下别离为:
- Root
- Service
- Category
- URL
其中 Root 层是注册核心分组,默认命名为 dubbo。咱们能够通过批改 <dubbo:registry>
中的 group 属性批改默认值,这样批改之后不同分组的 dubbo 服务不会相互影响,也不会相互调用,能够用于环境隔离。
接下来 Service 就是服务类的全门路,包含包门路。
Service 层上面就是 Category 层,这其中总共有四类目录(下面图形只画了两种),别离为:
- providers:蕴含服务提供者 URL 元数据信息
- consumers:蕴含消费者 URL 元数据信息
- routers:蕴含消费者路由策略的 URL 元数据信息
- configurators:蕴含动静配置元数据信息
最初一层就是具体 Dubbo 服务 URL,相似如下:
dubbo://2.0.1.13:12345/com.dubbo.example.DemoService?xx=xx
小黑:
没错,这个内部结构你理还是蛮清晰的么!
平时应用的状况下,咱们重点关注 providers 以及 consumers 就好了。如果咱们须要配置服务路由信息以及动静配置,那咱们须要在 Dubbo-Admin 服务治理核心下发配置。这时 routers
与 configurators
就会减少相干配置。
小灰:
嘿嘿????,咱接下来讲服务注册流程。
当服务提供者启动之后,会向注册核心写入本人的元数据信息,其实就是在 providers 节点下创立一个 URL 节点(如果下级节点都不存在,将会逐层创立),存储值相似如下:
dubbo://10.10.11.22:20880/com.foo/BarService?key=value....
接着启动服务消费者,消费者第一次连贯上 ZooKeeper 时,将会拉取 provider 节点下所有服务提供者的 URL 信息,而后与相应的服务提供者建设连贯。
同时服务消费者也会将本人信息注册到在 consumer 节点下,这个目标是为了服务治理核心(Dubbo-Admin)发现自己。
同时消费者将会在 provider 节点上注册一个 watcher,当有新的服务提供者启动胜利,provider 节点产生变更,ZooKeeper 将会推送变更信息给 Dubbo 服务,而后 Dubbo 将会从新建设与服务提供者的连贯。
小黑:
你说的整个 Dubbo 服务注册发现流程没有什么问题,这里消费者与服务提供者建设的连贯的流程,咱们之前踩过一个坑,你有空能够看看 天啦噜!生产机器连接数飙升到上万,背地产生了什么?。
另外,再考你一下:
服务节点变更时,ZooKeeper 推送 provider 下全量子节点数据给消费者吗?
小灰:
呀,难道不是吗?
小黑:
不是的。ZooKeeper 的 watch 机制目前只能推送节点变更信息,比方节点内容数据变更,监听节点下子节点列表变更等,具体如下图:
进一步从 Zookeeper 客户端的源码上来看,watcher 回调告诉内容最终转为 WatchedEvent
。
这个类只有三个字段,所以是不会推送子节点列表数据过去。
小灰:
既然不是通过推送获取子节点列表的信息,那如何拿到变动子节点列表?
有了,在收到推送的时候,咱们能获取到变动节点信息,而后我再拉取一下子节点的列表不就好了!
小黑:
没错,Dubbo 就是这么做的。
这一点咱们能够具体看下 Dubbo 的源码,位于 CuratorZookeeperClient
。
画外音:上面的源码基于 Dubbo 2.6.7
图中标注的中央,Dubbo 通过拉取获取了字节点的全量数据,同时再次注册了一个 watcher
。
不过这么多,有个缺点的,当微服务节点数量有很多的时候,全量拉取将会占用过多的内网带宽,很容易造成网络风暴。
下面咱们讲到 Zookeeper 的这种形式,是一种典型的 Push 模式,对应的还有一种的模式为 Pull 模式,eureka 就是这种模式的典型的代表。
eureka 客户端就是通过定期轮询拉取数据,获取最新的变更数据。不过拉取模式也存在很大的劣势,如果轮询频率低,那么服务变更信息无奈及时获取,如果轮率太高这就会减少注册核心的压力。
小黑:
服务发现流程这下咱们曾经搞明确了。如果有新增服务节点,Dubbo 消费者通过告诉,而后再拉取全量的子节点列表,这样 Dubbo 消费者就会新增与新的服务提供者连贯,后续再通过负载平衡应用新的连贯。
如果 Dubbo 服务提供者失常进行下线,那么他将会删除 ZooKeeper 上的本人注册的节点信息。删除之后 Dubbo 消费者第一工夫收到了告诉,通过拉取全量的子节点列表,而后通过比对,发现某个节点下线,而后删除之前简历的连贯。这样后续,就不会再调用这个节点。
小灰:
恩,失常利用高低线,Dubbo 消费者能够感知到,然而像服务提供者宕机的状况,消费者是怎么感知到的?
小黑:
这一点,就与 Zookeeper 的本身个性无关了。
Zookeeper 中咱们能够创立四种节点类型的节点:
- 永恒节点
- 长期节点
-
程序节点
- 永恒节点
- 长期节点
长期节点与永恒节点惟一的区别在于,一旦 Zookeeper 客户端断开连接,Zookeeper 服务感知到之后就会主动删除长期节点。
Dubbo 服务提供者就是在 Zookeeper 注册了长期节点,如果服务提供者宕机了,长期节点主动被删除,前面的流程就跟 Dubbo 利用失常下线一样了。
小灰:
すごい! 原来如此,这个设计 666 啊。
小黑:
其实利用宕机这种,Dubbo RPC 框架外部都能够主动帮咱们解决,这种故障其实很好解决。然而如果碰到上面这这种状况:
- 服务提供者与服务消费者网络隔离
- 服务提供陷入迟缓
在服务消费者看来,服务提供者其实是「活着」,这是因为服务提供者与 Zookeeper 还是失常连贯。
然而理论状况下,服务消费者其实曾经不能失常调用服务提供者了,那这种状况就比拟辣手了。
不过 Dubbo 外部也提供了解决办法。马上就下班了,也来不及讲了,咱们前面再探讨!
小灰:
好的,黑哥!明天学到了!
黑哥????????!爱你~
帮忙链接
- https://www.sofastack.tech/bl…
欢送关注我的公众号:程序通事,取得日常干货推送。如果您对我的专题内容感兴趣,也能够关注我的博客:studyidea.cn