Nacos高级特性Raft算法以及原理和源码分析

  • 对比springcloud-config配置中心
    • springcloud-config工作原理
    • Nacos的工作原理图
    • springcloud-config和Nacos对比
  • 长轮训Pull模型
    • 什么是长轮询pull模型
    • ==nacos中的长轮训pull模型改进版本:==
  • nacos集群如何保证数据的最终一致性?
    • NacosAP和CP模式互相切换
  • Raft 算法
    • 介绍
    • ==Raft算法中的几个角色==
    • 算法过程几个重要的点
  • Raft算法下脑裂的情况
    • 什么是脑裂?
    • 例子说明
      • 情况1
      • 情况2:
      • 情况3
      • 情况4:
      • 情况5
  • Raft算法下如何解决脑裂问题下的数据最终一致性?
  • Leader宕机 对集群数据一致性有影响吗?
    • 问题描述
      • 情况1:
      • 情况2
      • 情况3
      • 情况4:
  • Nacos Discovery(注册中心) 原理源码分析
    • Eureka注册中心架构图
    • Nacos架构图
    • Nacos的Clinet客户端的服务注册与心跳
      • 目标1.理解Nacos和springCloud整合源码分析
        • 类图:
      • 目标2.客户端client注册流程和心跳的流程
      • 目标3 理解Nacos对httpClient的封装
    • 运行服务端源码
    • Nacos服务端注册与心跳源码

对比springcloud-config配置中心

最初的springcloud微服务架构采用的配置中心是config 用过的都知道 界面不够优化并且性能没有那么好 已经很少公司使用 nacos架构上跟config有一些相似.

springcloud-config工作原理


1. 提交配置触发post请求给server端的bus/refresh接口
2. server端接收到请求并发送给Spring Cloud Bus总线
3. Spring Cloud bus接到消息并通知给其它连接到总线的客户端
4. 其它客户端接收到通知,请求Server端获取最新配置
5. 全部客户端均获取到最新的配置

Nacos的工作原理图


1.客户端发起长轮询请求 服务端接到请求后比较缓存中的数据是否一致,如果不一致则直接返回并更新缓存,如果一致,则通过线程池延迟30s之后再次进行比较

2.为了保证30s的数据变化能够通知到客户端,服务端采用事件订阅的方式来监听配置数据的变化,一旦收到事件那么将触发通知把结果推给客户端完成一次数据推送

springcloud-config和Nacos对比

Nacos Config 无需消息总线系统,系统搭建成本与复杂度比 Spring Cloud Config 低很多。

Nacos Config可以说是高内聚,低耦合

Nacos Config 不会一窝蜂向配置中心索要配置信息,Nacos Config是定点更新。

Nacos Config 有远程配置更新后,会自动更新到 client。其采用了长轮询 Pull 模型。而Spring
Cloud Config 则需要 client 提交请求

长轮训Pull模型

什么是长轮询pull模型

1.配置中心Server和客户端Client实现配置的动态感知一般无外乎两种办法:
一种是Client发起,叫pull模式
一种是Server发起,叫push模式

2.长轮询中Push模式和Pull模式的对比

若使用 Push 模型,需要在 Server 与 Client 间通过心跳机制维护一个长连接。这个长连接的维护成本是比较高的。其适合于 Client 数量不多,且 Server 端数据变化较频繁的场景。优点:数据更新很及时

若使用 Pull 模型,其无需维护长连接,但其实时性不好。因为客户端一定是采用定时间隔去拉取数据。

nacos中的长轮训pull模型改进版本:

1.Nacos 采用的是长轮询机制的 Pull 模型,但不单纯是Pull模型。
是一个HttpPost的长轮询,过期时间默认是30S。
Nacos 长轮询 Pull 模型融合了 Push 与 Pull 模型的优势。

2. 保留了pull
Client 仍定时发起 Pull 请求,查看 Server 端数据是否更新。
若发生了更新,则 Server 立即将更新数据以响应的形式发送给 Client 端;

3.保留了push
若没有发生更新,Server 端并不立即向 Client 返回响应,而是临时性的保持住这个连接一段时间【29.5s】若在此时间段内,Server 端数据发生了变更,则立即将变更数据返回给 Client【这里是动态感知的】若仍未发生变更,则放弃这个连接。等待着下一次 Client 的 Pull 请求。
长轮询 Pull 模型,是 Push 与 Pull 模型的整合,既降低了 Push 模型中长连接的维护问题,又降低了Push 模型实时性较低的问题。

nacos集群如何保证数据的最终一致性?

nacos默认是ap模式。nacos集群允许数据的短暂不一致性,满足其高可用的特性,那么是如何实现的呢?

nacos底层原理:raft算法

注意:一致性Raft算法 raft是一个最终一致性算法。不是强一致性算法。

是不是基本上一致性都是采用raft算法?不是,Nacos里面就有很多种
一致性算法,就是一个接口的实现类!

扩展:Zookeeper是CP的,允许服务出现不可用的状态,但是要保证数据强一致性 CAP理论面试常考!!

NacosAP和CP模式互相切换

默认是AP的 可以调整 提交PUT请求

http://localhost:8848/nacos/v1/ns/operator/switches?entry=ServerMode&value=CP

Raft 算法

介绍

Raft算法是一种非常易于理解的分布式共识算法。在理解与性能方面等同于业界公认的老牌复杂的paxos共识算法。注意 Raft是一种保证最终一致性的算法,不是强一致性算法。这是一种通过对日志进行管理来达到一致性的算法。
有难度 需要多理解!!不要放弃 这个raft相比于Paxos已经是非常好理解的了 这是简化版的paxos共识算法

Raft算法动画演示:http://thesecretlivesofdata.com/raft/

Raft算法中的几个角色

1.leader(领导):唯一一个负责处理客户端写请求的节点。也可以处理读的请求,同时负责日志复制工作

2.condidate(候选人):参与Leader选举的候选人,有可能会成为Leader的角色

3.follower(跟随者):可以处理客户端的读请求。负责同步来自于Leader的日志。当收到其他候选人的投票请求后进行投票。当发现Leader挂了,其会转变成候选人从而发起Leader选举

4.term(任期/年号 这个不是角色 是角色中的一个重要属性):古代皇帝上位都会给自己封一个年号,比如武帝上位的年号是永初。在Raft算法中对term的变化是+1,以便解决选举过程中的一些复杂性问题。可以通过term年号的大小新旧来判断节点的操作。

算法过程几个重要的点

1.成为候选人的条件:
当follower在心跳超时的范围内没接收到Leader的心跳,此时就会认为Leader挂了。此时会先将自己的term+1 然后会执行以下三个步骤

  • 1.1此时如果收到了其他candidate的投票请求(此时还是follower),那么会将选票投给这个candidate。如果没有收到其他的投票请求,则自己由follower转变为candidate角色。然后term+1
  • 1.2.如果之前没有给别人投票,那么此时给自己投一票
  • 1.3.向其他节点发出投票请求,等待响应

2.跟随者follower如何投票?
follower在接收到投票请求后,会根据以下两个情况来判断是否投票

  • a.若当前该follower的票还没投出去,并且收到的投票请求发起方的节点的term要大于当前该follower,那么就会把票投给该candidate
  • b.如果当前follower节点收到多个candidate的请求,那么采取先到先得的方式进行投票。(前提和a条件一样 term必须要大于当前follower节点)

3.等待响应
当一个candidate发起投票请求后,会等待其他节点的响应结果。有以下三种情况

  • a.收到半数选票的candidate【有可能】成为新的leader。然后将该消息广播给其他节点,并包含了自己的term年号
  • b.接收到新的canditade发来的新leader通知,比较了新leader的term年号比当前节点的大,则当前节点转变为follower
  • c.经过一段时间没有收到半票也没有新的leader发广播,那么进行新一轮的选举

4.票数相同如何处理
票数相同是无法选举出Leader的
这种情况会让这几个票数相同的candidate再次进行一次选举,但是发起选举的时间不一样,此时就会有一个先发起选举的candidate大几率将成为新的leader。

数据写入流程:
当leader节点接收到client的写操作请求时,leader对该请求进行日志记录索引等操作后,广播给其他节点,当集群内过半的节点收到该广播并响应结果,此时Leader将client的这次请求响应回去.此时client就认为这个写的操作已经成功了.但此时还没有真正做修改. 此时leader开始对真实数据进行修改 修改完毕后将结果广播给其他节点 其他节点收到后 通过日志去把最新的数据同步到自己的内存中 实现了数据同步

Raft算法下脑裂的情况

什么是脑裂?

学名叫网络分区
在一个高可用系统中,当联系着的节点断开联系时,本来为一个整体的系统,分裂成两个独立节
点,两个节点开始争抢共享资源造成系统混乱、数据损坏的现象,成为“脑裂”。也称为网络分区。
Raft 集群存在脑裂问题。在多机房部署中,由于网络连接问题,很容易形成多个分区。而多分区的形
成,很容易产生脑裂,从而导致数据不一致。由于三机房部署的容灾能力最强,所以生产环境下,三机房部署是最为常见的。下面以三机房三节点部署为例进行分析,根据机房断网情况,可以分为五种

例子说明

以下的例子以3节点3机房的情况描述脑裂问题 ABC三节点 A是Leader节点 BC都是follower节点

情况1

会出现脑裂问题吗? 会

脑裂问题产生过程描述:

A和B之前的链接由于网络不通断开了。但是A和C之间的网络是相通的。
此时B节点觉得A节点Leader挂了。此时B节点将自己的年号term增加了1 并且发起了一轮新的Leader选举并且自己成为了候选人的角色candidate。此时A和B之间是互相感知不到的。C收到了B的新一轮leader选举请求,由于B的term是最大的,因此C只能选择投票给B。并且此时C没有办法成为候选人的角色,原因是C和A始终是相同的,心跳并没有timeout,此时B节点收到了C节点的投票,成为了新的leader,但是此时A也是leader。此时就出现了脑裂的问题。A节点由于写请求无法获取到过半节点响应,因此不能完成写操作。B节点是可以获取到过半响应的(BC构成了一个集群),因此可以完成写操作。此时就出现了数据不一致的问题。

关键判断点:
1.成为候选人:B会成为候选人。但是C不会,因为成为候选人的条件是连接leader出现timeout。A和C始终是想通的因此不会成为候选人更加不会成为leader

2.follower投票:C会不会给B投票呢?肯定是会的,因为C接到了更大的年号term的投票请求

3.在一个集群中写得操作需要得到半数节点响应才能成功

情况2:

会出现脑裂问题吗? 会

这个情况和情况1是差不多的。 会出现脑裂问题

B和C也会选出一个节点出来

情况3

会出现脑裂问题吗? 不会

原因:C节点不会成为候选人,因为AC是想通的。B节点会成为候选人角色,但是它永远不可能成为主节点,因为他跟A或者C都是不通的,没有办法获取投票,因此不可能成为leader。那么这个集群中A还是作为主节点。

情况4:

会出现脑裂问题吗? 不会

AB和AC始终是想通的。B和C没有机会成为候选人角色。

情况5

会出现脑裂问题吗? 不会

B和C都有可能成为候选人,但是永远获取不到投票,没有办法成为leader

Raft算法下如何解决脑裂问题下的数据最终一致性?

1.日志索引
2.任期

这里不展开细讲 以后有时间单独整理一篇文章

Leader宕机 对集群数据一致性有影响吗?

问题描述

client发送一个写得请求到了nacos集群中 leader宕机了 对集群中的数据会产生影响吗?

情况1:

写请求还没到达leader,leader就挂了

会保证数据一致性吗? 会

解析:因为这个请求在这个集群中压根就没有存在过,不会对一致性有任何影响


情况2

写请求到达leader,leader在同步数据给其他节点的时候挂了

会保证数据一致性吗? 会

解析: 这个请求一开始到旧leader,由于旧leader挂了,这个写得操作还没来得及同步就挂了,而client此时没有收到旧leader的成功处理响应(可以理解是一个ack的机制)于是再次请求发起写得请求,但是第二次这个请求到集群时,新的leader已经出现了,此时新的leader会进行同步数据并把结果响应给client完成一次写操作
当client发送写得操作给leader,还没同步给其他节点就挂了,此时其他两个节点会产生新的leader,前任leader重启之后会作为follower的身份重新加入集群并同步新的leader的数据从而保证数据的最终一致性。


情况3

client发送写请求给leader,leader接受到后开始向follower复制数据。在部分follower复制完之后leader挂了。(有可能过半、也有可能不过半、也有可能一个都没复制完) 。此时client等待响应结果。

会保证数据一致性吗? 会

解析:
此时另外两个节点会产生一个新的leader,以下两种情况
(1):如果新leader产生于已经复制过同步数据日志的follower(新leader节点收到过旧leader挂之前发出的复同步数据请求),那么新的leader会把这个未完成的工作进行完成,并返回结果给client进行ack签收。会保证数据的最终一致性

(2):如果新leader产生于没有复制过同步数据日志的follower(新leader没有收到过旧leader挂之前发出的复制同步数据请求),会把这个日志请求放弃,此时client会重新发送该请求,新leader收到后会进行同步,从而保证数据的最终一致性。


情况4:

比较难理解

讲这个之前先回忆一下,raft算法中同步数据的步骤,leader收到请求之后会发起同步数据的请求到其他的节点,当有过半数的节点对其进行响应后(此时只是对请求做回复 follower节点此时并不会对数据做真实的修改),leader就会对这次请求做一个结果响应到client,这时候client就知道,我这次写得请求发送成功了。最后一个步骤,leader会进行广播本次修改的数据到底怎么修改。

当client发送写得请求到leader,leader吧同步数据的请求发送并且收到过半数的节点响应,client也收到了响应,最后一个步骤进行广播的时候,广播还没发出去,leader挂了。。会对数据的一致性有影响嘛??

答案:raft算法下这种情况下是可以保证数据的最终一致性的。

遵循一个原则:完全领导人原则。 一句话理解,新的领导会把旧的领导没做完的事做完,并且raft算法保证了既然本次请求得到了半数节点的响应,那么证明这个请求是完全合情合理的,此时应该被记录下来(日志提交),当新的leader产生时,需要追溯一下集群中是否有上任领导没干完的活,如果有,新领导需要把这个工作完成,从而保证了数据的最终一致性

Nacos Discovery(注册中心) 原理源码分析

Eureka注册中心架构图

Registry(注册服务):Client会发送一个rest请求到eureka服务端,并把自身的信息带过去 比如ip 端口元数据等.服务端收到请求后把元数据存储在s双层map中


Renew(服务续约):心跳/续约. 服务注册后client会维护一个心跳来持续通知Eureka服务端.说明本服务处于可用状态方式被剔除.默认30s发送一次心跳


Get Registry(获取注册列表):消费者启动会发送一个rest请求到eureka服务端获取注册中心的服务提供者清单并缓存到本地.同时为了性能安全性考虑,Eureka会每隔30s更新缓存中的清单


Make Remote Call(服务调用):根据客户端通过注册中心存放的提供者地址进行远程调用 通常是http 客户端使用feign


Cancel(下线通知):当client需要关闭或者重启时.会提前发送一个rest请求给eureka服务端.收到请求后会吧该服务状态设置为下线down.并通过事件广播出去


evict(失效剔除):eureka为了有些服务由于网络故障原因等不能提供服务.因此eureka服务端在启动的时候会创建一个定时任务,每隔90s从服务清单内把超时没有续约的服务剔除


注意点:

  • 1.服务注册到不同的erueka
  • 2.eureka集群之间会进行同步数据 一个服务向某一个eureka拿注册列表,拿到的都是同一份数据,这是集群之间实现的数据同步

Nacos架构图


Nacos Server:nacos集群

pri-raft:Raft一致性方案

config Service:配置中心

Naming Service:注册中心

Naos Core:核心组件

OpenApi:通过OpenAPI暴露

Name Server:消费者通过服务名远程调用提供者

User Console:控制台

MVC架构:分层- User Console-控制台 服务模块: 1.openAPI 2.模块(注册 配置) 3.持久层(raft一致性)

Nacos的Clinet客户端的服务注册与心跳

Nacos 源码分析目标

看源码一定要带问题和目标去看 否则你会发现你很迷茫 你根本不知道你想了解什么 看源码不要没一行都去点 只看核心的!

目标1.理解Nacos和springCloud整合源码分析

  • Spring-cloud-commons依赖以及nacos discovery starter依赖
  • springcoud应用程序入口:监听器接口的触发

参考流程图 找到对应核心的类

startr坐标里面带了springcloud-commons依赖包,可以让该服务注册到注册中心,怎么做到的???

a.commons包中通过SPI机制找到入口AutoServiceRegistrationAutoConfiguration,这个类只要导入了starter就会通过commons包被注入spring容器。这个类就是完成NacosClient服务注册的自动配置类
b.AutoServiceRegistrationAutoConfiguration中注入了AutoServiceRegistration对象,怎么进来的呢?非常重要。
c.AutoServiceRegistration是个接口,它的实现类是怎么进入spring容器的呢?注意 这个时候不要通过这个接口找实现类 因为此时点过去你依然无法确定这个类是什么时候被加载到spring容器管理的

d.此时需要搞清楚这个问题,需要去starter包中去寻找答案。通过spring-cloud-starter-alibaba-nacos-config的spi中找到NacosServiceRegistryAutoConfiguration

e.其中有个Bean叫做NacosAutoServiceRegistration,然后通过它注入。查看一下它的类图。 AutoServiceRegistration的实现类。发现NacosAutoServiceRegistration有个抽象父类AbstractAutoServiceRegistration,这个抽象父类实现了AutoServiceRegistration。也就是说其实AutoServiceRegistration接口注入的实现类就是这个NacosAutoServiceRegistration 至此完成闭环。

类图:

监听器接口的触发

AbstractAutoServiceRegistration实现了spring的监听器,它是NacosAuthServiceRegistration的抽象父类,看他的监听器的实现方法onApplicationEvent方法。Tomcat启动会触发这个监听器开始工作。

这里需要了解spring的事件发布机制 非常简单

总结:Nacos和springcloud整合的关键在于.通过starter包注入相关的依赖对象.这个对象必须拥有一个可被触发的点.那么就是通过spring的发布event事件的机制.感兴趣的可以去搜索一下 其实就是所谓的观察者模式.那么这个事件在springboot启动的时候发布,那么监听器在这个starter包中的类中,当我们引入依赖,就会触发这个监听器对这个事件做处理.不得不说设计得很妙

看到这里 源码已经用到了两种我们常用的设计模式 1.模板方法 注入对象不直接实现接口 而是由父类去实现 2.观察者模式 spring的事件发布机制

目标2.客户端client注册流程和心跳的流程

流程图:

注意:看源码只需要看那些关键的动作 比如 doXX registerXXX getInstance 一路找到NcosServiceRegistry这个类



根据最后一张图我们看到有两个核心的方法
beatReactor.addBeatInfo:这个一看就是发送心跳的方法
serverProxy.registerService:服务client注册

总结:当springboot程序启动后,会触发bind事件.监听器会处理客户端client注册到nacos的流程.其中包括了服务注册和发送心跳. 接下来我们详细了解下这两个方法内部做了哪些事情.一定要结合图来看!!

服务注册

这个代码相信你也一定写过
1.组装请求参数
2.发起http请求(RestTemplate okHttp httpClient …)

此时回过头去看一下nacos的架构图就能看到.nacos server服务端的所有操作都是通过Open-API来提供支持的 链接:https://nacos.io/zh-cn/docs/open-api.html 聪明的小伙伴应该知道 那一定会有controller入口 此时我们只需要知道 服务组装了一些自己的参数ip port group name等等然后发送一个post请求提交给nacos 此时就完成了注册的服务

服务心跳



总结: 熟悉的味道 又是发起了一次http请求 将自己的信息提交给nacos告诉它 我很好 我还活着!

目标3 理解Nacos对httpClient的封装

为什么需要封装httpClient? 因为nacos的架构非常庞大 所有的服务端模块的服务都需要通过openapi暴露.那么需要定义一套nacos自己的http规范 比如独有的响应题 请求头 这样提高了效率 并且最重要的是 高大上!像很多框架都会这么做 比如分布式事务框架seata也是封装了restTemlate.


运行服务端源码

1.源码下载 选择client-1.3.3版本

2.使用idea打开

3.修改配置

3.1修改application.propertie存储数据到mysq

3.2 启动参数增加 使用单节点启动 否则报错(默认启动集群模式)

4.启动

Nacos服务端注册与心跳源码

首先搞个服务启动 在控制器打个断点

主要动作:
重点看ServiceManager这个类的操作

Nacos高级特性Raft算法以及原理和源码分析相关推荐

  1. java.lang.ThreadLocal实现原理和源码分析

    java.lang.ThreadLocal实现原理和源码分析 1.ThreadLocal的原理:为每一个线程维护变量的副本.某个线程修改的只是自己的副本. 2.ThreadLocal是如何做到把变量变 ...

  2. 【项目一、xxx病虫害检测项目】1、SSD原理和源码分析

    目录 前言 一.SSD backbone 1.1.总体结构 1.2.修改vgg 1.3.额外添加层 1.4.需要注意的点 二.SSD head 2.1.检测头predictor 2.2.生成defau ...

  3. ConcurrentHashMap的实现原理和源码分析

    原文链接:http://www.jianshu.com/p/7f42ba895a64 前言 在Java1.5中,并发编程大师Doug Lea给我们带来了concurrent包,而该包中提供的Concu ...

  4. RocketMq-dashboard:topic 5min trend 原理和源码分析(一)

    本文阅读基础:使用或了解过rocketMq:想了解"topic 5min trend"背后的原理:想了解监控模式如何实现. RocketMq的dashboard,有运维页面,驾驶舱 ...

  5. 高级JAVA - 动态代理的实现原理和源码分析

    在之前的一篇文章中 , 我们简单了解了一下代理模式(JAVA设计模式 - 代理模式) , 本篇我们来学习一下动态代理的实现原理 , 以及源码是怎样的 . JDK动态代理的主要实现步骤如下 : 1 . ...

  6. ConcurrentLinkedQueue的实现原理和源码分析

    原文链接:http://www.jianshu.com/p/26d9745614dd 前言 我们要实现一个线程安全的队列有两种实现方式一种是使用阻塞算法,另一种是使用非阻塞算法.使用阻塞算法的队列可以 ...

  7. Tomcat原理和源码分析

    Tomcat是什么? 首先看下官网的解释说明(看不懂的可以翻译一下),从第一句Tomcat是Java Servlet,JavaServer页,Java表达式语言和Java的WebSocket技术的一个 ...

  8. 深入理解GO语言:map结构原理和源码分析

    Map结构是go语言项目经常使用的数据结构,map使用简单对于数据量不大的场合使用非常合适.Map结构是如何实现的?我们先从测试程序入手,我们希望分析map的创建.插入.查询.删除等流程,因此我们的测 ...

  9. Alertmanager 配置文件分析、原理和源码分析

    相关prometheus组件的基本知识总结,以下分析仅代表个人观点,如有错误还请指出,不胜感谢! 基本概述 我们先从应用的角度来看详细的介绍一下alertmanager以下简称am,以下是官方文档介绍 ...

最新文章

  1. 通讯录(容量不可变)
  2. Vista 下的注册 com 类失败解决方法
  3. HVM is required for this operation - Run Xen on Nested System
  4. java爬虫(二)- Jsoup
  5. python程序开发入门教程_史上最全Python快速入门教程,满满都是干货
  6. 【读书笔记】IOS帝国-Apple Ⅱ/Mac/皮克斯/iPod/iTunes/iPhone/App Store/iPad,苹果教父:史蒂夫·乔布斯传_2020.02.15
  7. 在vscode和android studio中安装代码注释翻译插件
  8. dicards qualifiers
  9. 实现B站弹幕很难么?这个开源项目了解一下
  10. css中关于旋转属性trtransform: rotate影响文字轻微变形的解决办法。
  11. 华为metebook 电脑应用市场应用无法下载
  12. mysql数据库读取数据,教你如何从 MySQL 数据库读取数据
  13. 22届春招实习试水之路汇总(前端+后端)
  14. Python3.10.2安装教程
  15. 冒泡排序法和选择排序法比较(从小到大,升序)
  16. linux安装和配置 MariaDB (ubuntu20.04)
  17. 教资必备的5大证件,丢失后该如何补办?
  18. 开始积极开发支持机器学习PC正式迈入AI世代
  19. idea 的 maven 项目报错:The program‘s entry point class ‘xxx‘ was not found in the jar file.
  20. 基于MSF框架下的kiwi模块制作黄金票据

热门文章

  1. Java 列举数组中任意元素和为定值的组合
  2. 什么是RAID 0?什么是RAID 1?了解硬盘阵列的作用
  3. 竞价账户创意如何编辑,干货奉上
  4. 红米Note 4X获得Root超级权限的经验
  5. hibernate.cfg.xml配置时出现的问题
  6. js获取指定日期的前一年(需要判断闰年和平年)
  7. 高斯日记(c语言习题)
  8. doris insert数据时出现问题:Invalid floating-point literal
  9. Java程序 CPU使用率过高怎么办?
  10. AKS==donet6代码生成镜像到dockerhub并发布到Azure Kubernetes 服务 (AKS)