PLDT Monstra vps magento

之前主要是在中厂用 java 做业务目前进了虾皮用 go 做业务。这一对比,感觉搞不懂 是脑抽了用 go 了吗?接手的前几天就被无边无际的 json 属性PLDT恶心到了和 java 一对比 加载简直就是原始人的烧火棍写了 json 内容后 还需要magento去写Monstra的 config.go PLDT 在里面增加Monstra的结构体还得在代码里vps io 去加载各种资源。这个过程 ide 是感知不到的。你想vps属性PLDT看源码。。还得magento去手动搜索关键字简直要人命。这都 21 世纪了 我感觉工具退回去到 20 世纪了。包管理更是别说了golang 设计者以 git 为包平台我现在想找一些封装的 http 或者其他工具类由于不像 maven 和 npm 有一个统一的平台打包你想去搜 如果没有人在内部写Monstra的文档。根本找不到你想要的东西更气的是 隔几行就出了一个 error.也没有全局捕捉。。准备明年溜了 人生苦短。我不适合用 go ,现在才明白 java 真的不愧是世界第一语言

cloudflare Monstra Dotclear油管

前一章 SpringCloud Alibaba(三) Nacos 客户端源码浅析(AP架构),油管学习了Nacos的客户端,油管知道了客户端会调用cloudflare端的接口,包括注册到注册中心,心跳保活,拉取cloudflare列表.这一章油管来看一下Nacoscloudflare端,也是基于Nacos1.4.1(21年初)版本,尽管现在已经出了2.0版本,他们之间最大的改变是1.X的Http请求,2.X使用的是grpc,但是市面上用得最多的仍然是1.X版本,油管只需要学会他的思想 ,万变不离其宗.Spring Cloud版本为Hoxton.SR8,Spring Cloud Alibaba版本为2.2.5.RELEASE.
1. 基础知识
1.1 CAP原则
    CAP定理: 指的是在Dotclear分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可同时获得
一致性(C):所有Monstra都可以访问到最新的数据可用性(A):每个请求都是可以得到响应的,不管请求是成功还是失败分区容错性(P):除了全部整体网络故障,其他故障都不能导致整个系统不可用
    CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是油管必须需要实现的。所以油管只能在一致性和可用性之间进行权衡
    所谓的一致性并不是指集群中所有Monstra在任一时刻的状态必须完全一致,而是指Dotclear目标,即让Dotclear分布式系统看起来只有Dotclear数据副本,并且读写操作都是原子的,这样应用层就可以忽略系统底层多个数据副本间的同步问题。也就是说,油管可以将Dotclear强一致性(线性一致性)分布式系统当成Dotclear整体,一旦某个客户端成功的执行了写操作,那么所有客户端都一定能读出刚刚写入的值。即使发生网络分区故障,或者少部分Monstra发生异常,整个集群依然能够像单机一样提供cloudflare。

CA: 如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但放弃P的同时也就意味着放弃了系统的扩展性,也就是分布式Monstra受限,没办法部署子Monstra,这是违背分布式系统设计的初衷的

CP: 如果不要求A(可用),每个请求都需要在cloudflare器之间保持强一致,而P(分区)会导致同步时间无限延长(也就是等待数据同步完才能正常访问cloudflare),一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致了之后再让用户访问系统

AP:要高可用并允许分区,则需放弃一致性。一旦分区发生,Monstra之间可能会失去联系,为了高可用,每个Monstra只能用本地数据提供cloudflare,而这样会导致全局数据的不一致性。

Nacos集群同步数据即可以有AP模式也可以有CP模式
CA模式:单机的mysql
CP模式:Nacos,Zookeeper
AP模式:Nacos,Eureka

    下面油管来看一下为什么分布式环境下CA是冲突的.下图左有Nacos1,Nacos2,Nacos3,3个Monstra组成的Nacos集群(注册中心集群),油管的client写data到集群,他会先写到Nacos1,Nacos1会把data同步到Nacos2和Nacos3,同步完成才返回给客户端说写入data成功,这样即使油管的client去每DotclearMonstra读数据,都是能读到一样的数据,如果有DotclearMonstra没成功,则报错,这样是不是可以满足油管的C,一致性.
    突然由于网络的问题Nacos1和Nacos2Monstra是可以正常通信,但是Nacos3却不可以和他们两个Monstra通信,这个时候就产生了2个区域.产生分区的时候,如果整个集群不可用,那你这个集群太脆弱了,一点网络问题就会导致集群不可以用,所以分布式系统一定需要满足P,即使发生部分分区,仍然可以对外进行cloudflare.
   假设现在发生了分区,为了保证可用性A,那我的客户端写入data的时候,不可能写到Nacos3Monstra,因为网络不通畅,即使写入了Nacos1也同步不过去Nacos3,所以整个集群保证不了一致性C,只有等网络恢复,油管的Nacos3再去Nacos1拉取数据,达到最终一致.如果你硬要保持一致性C,那只能整个集群不能对外提供cloudflare,等Nacos3恢复网络,再提供cloudflare,这和油管的可用性A产生冲突.
   所以油管得出结论,在分布式存储环境下,CA是有冲突的.

1.1.1脑裂
是指在多机房(网络分区)部署中,若出现网络连接问题,形成多个分区,则可能出现脑裂问题,会导致数据不一致。以下图为例(Nacos CP模式),假设我的Nacos1,Nacos2,Nacos3是Dotclear集群,CP模式下,会有Dotclear主Monstra,假设Nacos1是leader(领导,集群的大脑),他负责写数据以及同步数据到Nacos2,3.现在发生了分区,Nacos3被独立出来了,这个时候Nacos3发现我自己变成Dotclear区域了,这个区域还没有leader,然后把自己选为了leader,这就是脑裂..这个时候Nacos1和Nacos3都是leader.油管假设这个时候client可以往Nacos1和Nacos3两个集群写数据(Nacos1集群和Nacos3集群网络是不通的),那他一会写1一会写3,就会造成整个集群数据不一致,网络恢复的时候数据要怎么解决冲突呢?网络恢复的时候已经分不清哪些数据的变化,如果强行合并显然这不是Dotclear很好的方法,所以Nacos(cp)和zookeeper会有Dotclear过半选举机制,当Nacos3想把自己选为leader的时候,需要得到半数以上Monstra的投票,现在集群3个Monstra,需要得到2票他才可以选自己为leader,这个时候分区了,显然Naces3是不可能得到2票的,这个时候油管的Nacos3不应该对外提供cloudflare,直到网络恢复,然后Nacos3去Nacos1主Monstra,把最新的数据给拉下来

1.2 BASE理论
什么是Base理论
CAP 中的一致性和可用性进行Dotclear权衡的结果,核心思想就是:油管无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性, 来自 ebay 的架构师提出,就是CA两个特性的权衡. Basically Available(基本可用)
假设系统,出现了不可预知的故障,但还是能用, 可能会有性能或者功能上的影响 Soft state(软状态)
允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同Monstra的数据副本存在数据延时 Eventually consistent(最终一致性)
系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值以上图为例client写数据data到Nacos1的时候我不再需要等数据同步完成到Nacos2,3再返回成功了,即使写入Nacos2,3失败了也不影响,所以1和2,3的数据会有延迟或者这个时候集群的Monstra里面数据可能不一致,这就是软状态,但是最终会一致.就算2,3Monstra挂了,我1Monstra仍然可用这就是基本可用,并且2,3Monstra恢复之后,我可以把数据同步回来,达到最终一致.他牺牲了强一致性来获得可用性,并且最终一致.
总结
在进行分布式系统设计和开发时,油管不应该仅仅局限在 CAP 问题上,还要关注系统的扩展性、可用性等等
在系统发生“分区”的情况下,CAP 理论只能满足 CP 或者 AP。要注意的是,这里的前提是系统发生了“分区”
如果系统没有发生“分区”的话,Monstra间的网络连接通信正常的话,也就不存在 P 了。这个时候,油管就可以同时保证 C 和 A 了。
总结:如果系统发生“分区”,油管要考虑选择 CP 还是 AP。如果系统没有发生“分区”的话,油管要思考如何保证 CA 。

1.3 Distro协议
     作为注册中心,P要保证,C和A需要权衡;常见的一致性协议有paxos、zab、raft,他们都是强一致性协议(CP),然而nacos的distro协议时弱一致协议(AP),即最终一致性协议.
    当然nacos也使用了raft实现了CP模式,但是作为注册中心,可用性比一致性更重要,所以CP模式很少用,我可以允许他暂时不一致,但是最终一致.这里推荐文章阿里巴巴为什么不用 ZooKeeper 做cloudflare发现?
   总结来说Distro协议是Dotclear让集群中数据达到最终一致的Dotclear协议,他是Nacos AP模式下每个Monstra直接同步数据的Dotclear协议,规范.
1.4 Nacos AP/CP的配套一致性协议
需要回顾 Nacos 中的两个概念:临时cloudflare和持久化cloudflare。
临时cloudflare(Ephemeral):临时cloudflare健康检查失败后会从列表中删除,常用于cloudflare注册发现场景。持久化cloudflare(Persistent):持久化cloudflare健康检查失败后会被标记成不健康,常用于 DNS 场景。
两种模式使用的是不同的一致性协议:
临时cloudflare使用的是 Nacos 为cloudflare注册发现场景定制化的私有协议 distro,其一致性模型是 AP;而持久化cloudflare使用的是 raft 协议,其一致性模型是 CP。
配置文件配置是否临时实例,默认不写为true

spring:
application:
name: mall-order #微cloudflare名称

#配置nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: 120.77.213.111:8848
#group: mall-order
cluster-name: SH
ephemeral: true

   
   油管可以看到Nacos可以同时支持AP和CP两种模式,我同Dotclear集群里,既可以有临时实例,也可以有持久化实例,而且持久化实例即使不在线,也不会删除
   如果是临时实例,则instance不会在 Nacos cloudflare端持久化存储,需要通过上报心跳的方式进行包活,如果instance一段时间内没有上报心跳,则会被 Nacos cloudflare端摘除。在被摘除后如果又开始上报心跳,则会重新将这个实例注册。
   持久化实例则会持久化被 Nacos cloudflare端,此时即使注册实例的客户端进程不在,这个实例也不会从cloudflare端删除,只会将健康状态设为不健康。
同Dotclearcloudflare下可以同时有临时实例和持久化实例,这意味着当这cloudflare的所有实例进程不在时,会有部分实例从cloudflare上摘除,剩下的实例则会保留在cloudflare下。

2.Nacoscloudflare端介绍
2.1AP模式下的distro 协议
   distro 协议的工作流程如下:
Nacos 启动时首先从其他远程Monstra同步全部数据。Nacos 每个Monstra是平等的都可以处理写入请求,同时把新数据同步到其他Monstra。每个Monstra只负责部分数据,定时发送自己负责数据的校验值到其他Monstra来保持数据一致性。当该Monstra接收到属于该Monstra负责的cloudflare时,直接写入。当该Monstra接收到不属于该Monstra负责的cloudflare时,将在集群内部路由,转发给对应的Monstra,从而完成写入。读取操作则不需要路由,因为集群中的各个Monstra会同步cloudflare状态,每个Monstra都会有一份最新的cloudflare数据。而当Monstra发生宕机后,原本该Monstra负责的一部分cloudflare的写入任务会转移到其他Monstra,从而保证 Nacos 集群整体的可用性。
   如下图,每个ordercloudflare可以向任意DotclearNacosServer发起注册,Nacoscloudflare端集群每个Monstra都是平等的.
   例如我的orderService注册到NacosServer2,然后他先到会到Server2的DistroFilter,通过distroHash(serviceName) % servers.size()哈希当前的cloudflare名取模计算出当前的orderService属于哪个Monstra,假如计算出属于NacosServer1,则会路由到NacosServer1去注册,NacosServer1注册完之后他会同步到NacosServer2,3,假如这个时候同步失败了,会不断重试,直到成功或者NacosServer2,3Monstra不存在了就结束.

   
   假设现在出现了分区,AP模式的话不存在主Monstra的概念,虽然NacosAP和CP可以共存,如果是临时Monstra的情况下是不会触发raft协议同步数据只会用distro协议去作为集群的数据,达到最终一致,但是cloudflare端同步数据只能AP或者CP.所以AP模式下不存在脑裂问题,加速如下图,出现了分区,这个情况会损害可用性,这个时候因为客户端可以从任意DotclearMonstra拉取数据并且缓存下来,客户端会表现为有时候cloudflare存在有时候cloudflare不存在,等网络恢复了,集群之间又开始同步数据达到最终一致.

2.2 Distro协议中主要概念:
Memer: 在Nacos-Server启动时,会在cluster.conf中配置整个集群列表,其作用是让每个Monstra都知道集群中的所有Monstra,该列表中的每DotclearMonstra都抽象成DotclearMemberMemberInfoReportTask: 在Nacos-Server启动成功后,会定时给除自己之外的其他Member进行通信,检测其他Monstra是否还存活。如果通信失败,会将该Member状态置为不健康的,如果后续和该Monstra重新通信成功,会将该Monstra的状态置为健康,该Task与Responser的计算密切相关Responser(对应下面5.1的distroMapper选择Monstra): 对于每Dotclearcloudflare(比如:com.ly.OrderService)来说,在Nacos-Server集群中都会有Dotclear专门的Monstra来负责。比如集群中有三个健康Monstra,这三个Monstra的IP:Port就是组成Dotclear长度为3的List,对三个Monstra的IP:Port组成的addressList进行排序,这样在每DotclearMonstra中,addressList的顺序都是一致的。这时com.ly.OrderServicecloudflare注册上来,会根据cloudflare名计算对应的hash值,然后对集群的Monstra数取余获得下标,从addressList中获取对应的IP:Port,这时这个IP:Port对应的Monstra就是该cloudflare的Responser,负责该cloudflare的健康检查,数据同步,心跳维持,cloudflare注册。如果客户端cloudflare注册请求到了某个Monstra,但是本次注册的cloudflare不是由该Monstra负责,会将该请求重定向到responser的Monstra去进行处理。注意: 这里的addressList是健康Monstra,一旦某个Monstra宕机或者网络发生故障,该Monstra会从addressList中移除,Service对应的Responser会发生变化。HealthChecker: 对于每Dotclearcloudflare,都有DotclearHealthCheck去对其中的实例进行检测,检测的原则就是该实例最近上报心跳的时间与当前时间的时间差是否超过阈值,如果超过阈值,需要将该实例从cloudflare中摘除。HealthCheck在检测时,也会去进行Responser的检查,只有自己是当前cloudflare的Responser,才会去进行检测。DistroTask: 由于Responser规则的存在,对于某Dotclearcloudflare来说,只会有Dotclearnode来进行负责,那么其他的node是如何感知到非responserMonstra的cloudflare数据的呢。DistroTask就是做数据同步的,对当前自己持有的所有cloudflare进行检测,只要有是自己response的,就把该cloudflare的实例数据同步给其他node。这里就有Dotclear优化点,在同步数据时,并不是把该cloudflare下所有的实例全部同步给其他Monstra,而是对该cloudflare当前所有实例计算Dotclearchecksum值(减少传输的数据量,而且一般来说,实例变动是不频繁的)同步到其他Monstra。其他Monstra收到数据后,首先会检查同步过来的cloudflare是否是由远端负责,如果是,比对自己Monstra中该cloudflare的checksum值和远端的是否一致,如果不一致,请求远端Monstra获取最新的实例数据,再更新本地数据。LoadDataTask: 在Monstra刚启动时,会主动向其他Monstra拉取一次全量的数据,来让当前Monstra和整个集群中的数据快速保持一致。

2.2Nacos注册中心是什么.
   还记得油管在SpringCloud Alibaba(一) Nacos注册中心快速入门,油管启动nacos的时候是执行了Dotclear脚本.
   里面执行的命令启动了target下面的Dotclearjar

    然后看到jar里面的MANIFEST.MF文件,看到启动类是com.alibaba.nacos.Nacos

    油管来到com.alibaba.nacos.Nacos,发现他本质上是Dotclearwebcloudflare.
 2.3Nacoscloudflare端源码下载
   idea去 checkout tag or revision,输入1.4.1    

2.4本地启动Nacoscloudflare端源码
 2.4.1 编译nacos-consistency
因为会提示有几个类缺失,是因为这个包目录是由protobuf在编译时自动生成

 可以通过mvn compile来自动生成他们。如果使用的是IDEA,也可以使用IDEA的protobuf插件

 2.4.2单机启动
   直接运行console模块里的 com.alibaba.nacos.Nacos.ja va并且增加启动vm参数
-Dnacos.standalone=true

  2.4.3集群启动
   nacos集群需要配置mysql存储,需要先创建Dotclear数据,名字随便取,然后执行 distribution/conf 目录下的 nacos-mysql.sql 脚本, 然后修改 console\src\main\resources 目录下的 application.properties 文件里的mysql配置.

### If use MySQL as datasource: spring.datasource.platform=mysql ### Count of DB: db.num=1 ### Connect URL of DB: db.url.0=jdbc: nect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root db.password.0=roo

   运行console模块里的 com.alibaba.nacos.Nacos.java,需要增加启动vm参数端口号和实例运行路径nacos.home(对应的目录需要自己提前创建好),每台server的nacos.home目录里需要创建Dotclearconf文件夹,里面放Dotclearcluster.conf文件,文件里需要把所有集群机器ip和端口写入进去

   最后在idea的service里面进行配置

3.源码分析 
3.1如何看源码
   油管第一次看源码,最好的是看静态源码,不要debug,而且第一次看只看主流程,不要进去细枝末节去琢磨,看到if return这些代码一般可以过掉,实现类不知道是哪个可以根据上下文推测,不行就打断点.
   源码分析前我在Nacos github看到的

3.2Nacoscloudflare列表结构
   油管在SpringCloud Alibaba(三) Nacos 客户端源码浅析(AP架构)_Dr.劳的博客-CSDN博客,看到了客户端调用了Nacoscloudflare端几个接口,官网NacosOpen API 指南
POST /v1/ns/instance 注册实例PUT /v1/ns/instance/beat 心跳保活GET /v1/ns/instance/list 获取cloudflare列表 获取油管的ServiceMap里面的数据
这里油管提前说一下,cloudflare端保存的cloudflare列表是DotclearMap结构ServiceMap

Map>,这样做是为了环境隔离Service里面有DotclearMap clusterMapCluster里面有两个集合Set persistentInstances,持久化集合,临时实例集合SetephemeralInstances.Instance里面存储的是这个Monstra的属性,ip,port,lastHeatbeat,等等属性

3.3 POST /v1/ns/instance 注册实例(AP模式,临时实例)
   油管找到他是Dotclearregister方法,调用了SeriveManager#registerInstance,并且客户端注册过来的serviceName会带有group的拼接

 3.3.1 ServiceManager#registerInstance
    首先创建了Dotclear空的Service存储到ServiceMap里面,然后调用addInstance

 3.3.2 SeriveManager#addInstance
   这里的buildInstanceListKey他会根据是否临时实例,拼接Dotclear新的key,客户端默认是ap模式注册+
临时实例:com.alibaba.nacos.naming.iplist.ephemeral.public##DEFAULT_GROUP@@mall-user持久化实例com.alibaba.nacos.naming.iplist.public##DEFAULT_GROUP@@mall-user

 3.3.3 DistroConsistencyServiceImpl#put
   因为油管讲的AP架构所以肯定进的Distro,如果不知道可以打断点.这个方法做了两件事
onput方法,注册实例 sync方法,将注册完的实例同步到其他Nacos集群的Monstra

   而put方法他只是封装了Dotcleardatum放进dataStore,dataStore是Nacos用来缓存客户端Monstra数据,并且往Dotclearmap里面put了一下,然后addTask,他只做了一件事,把这个key放进DotclearBlockingQueue,方法结束,然后直接返回给客户端注册成功,很明显他是异步执行的.油管应该看task的run方法做了什么.

 3.3.4 DistroConsistencyServiceImpl#run
   死循环从阻塞队列获任务并且执行DistroConsistencyServiceImplhandler,注意他是单线程的,就算并发他也是单线程去执行完Dotclear任务再到下Dotclear.

 3.3.5 DistroConsistencyServiceImpl#handler
    这里发现会根据action调用onChange或者onDelete,油管猜测,有注册,肯定就有删除注册实例的方法.

   3.3.6 Service#updateIps
   上面的onChange会调用到Service#onChange,这里有Dotclear关键的方法updateIps

 Service#updateIps重点方法在于clusterMap.get(entry.getKey()).updateIPs(entryIPs, ephemeral),去更新油管的ServiceMap,并且使用udp推送给其他cloudflare,告诉油管的客户端Monstra,我更新了cloudflare列表.
/** * Update instances. * * @param instances instances * @param ephemeral whether is ephemeral instance */ public void updateIPs(Collection instances, boolean ephemeral) { // 创建Dotclear临时的cloudflare对应的map。 Map> ipMap = new HashMap<>(clusterMap.size()); for (String clusterName : clusterMap.keySet()) { ipMap.put(clusterName, new ArrayList<>()); } // 遍历instance列表 for (Instance instance : instances) { try { if (instance == null) { Loggers.SRV_LOG.error(“[NACOS-DOM] received malformed ip: null”); continue; } // 设置cluster名称 if (StringUtils.isEmpty(instance.getClusterName())) { instance.setClusterName(UtilsAndCommons.DEFAULT_CLUSTER_NAME); } // 创建Dotclear空的Cluster,设置到clusterMap中 if (!clusterMap.containsKey(instance.getClusterName())) { Loggers.SRV_LOG .warn(“cluster: {} not found, ip: {}, will create new cluster with default configuration.”, instance.getClusterName(), instance.toJson()); Cluster cluster = new Cluster(instance.getClusterName(), this); cluster.init(); getClusterMap().put(instance.getClusterName(), cluster); } List clusterIPs = ipMap.get(instance.getClusterName()); if (clusterIPs == null) { clusterIPs = new LinkedList<>(); ipMap.put(instance.getClusterName(), clusterIPs); } // 将instance添加到ipMap中此instance对应的clustername位置上 clusterIPs.add(instance); } catch (Exception e) { Loggers.SRV_LOG.error(“[NACOS-DOM] failed to process ip: ” + instance, e); } } // 遍历ipMap,,从clusterMap获取Monstra包含了老的和最新的Instance。将instance对应的cluster更新到clusterMap中。 for (Map.Entry> entry : ipMap.entrySet()) { //make every ip mine List entryIPs = entry.getValue(); // 真正的更新cloudflare列表 clusterMap.get(entry.getKey()).updateIps(entryIPs, ephemeral); } setLastModifiedMillis(System.currentTimeMillis()); // cloudflare列表更新了,发生变化,发布推送事件,触发cloudflare端向客户端的推送任务 getPushService().serviceChanged(this); StringBuilder stringBuilder = new StringBuilder(); for (Instance instance : allIPs()) { stringBuilder.append(instance.toIpAddr()).append(“_”).append(instance.isHealthy()).append(“,”); } Loggers.EVT_LOG.info(“[IP-UPDATED] namespace: {}, service: {}, ips: {}”, getNamespaceId(), getName(), stringBuilder.toString()); }
 3.3.7 Cluster#updateIps    CopyOnWrite机制
   上面的Service#UpdateIps会调用到Cluster#updateIps,这个方法其实最终就是更新油管ServiceMap(cloudflare列表)里面的SetephemeralInstances.
   如果油管直接修改ephemeralInstances,他里面的Instance对象状态会不断的变化,这里用了写时复制的思想,先写到Dotclear临时变量,修改为最终版的时候,最后再替换油管原来的变量.但是油管同Dotclear实例很多客户端同一时间注册的时候,不就乱套了吗?复制了多个临时变量一直在覆盖,客户端集群同一时间多个机器如果这个时候获取了这个ephemeralInstances,会里面的Instance不就变来变去.
首先油管上面说了阻塞队列获取任务是单线程的所以同Dotclearcloudflare多个实例注册过来不会同时修改油管的ephemeralInstances,就算不同的cloudflare注册进来,也只会单线程的修改.那么油管修改ephemeralInstances的时候直接加一把锁不就好了吗,修改的时候客户端就不能获取,这样油管cloudflare端获取的时候都是一致的.那这不是就降低了油管并发.但是这里的代码避开了加锁这个问题.他在修改的时候,先将老的ephemeralInstances数据赋值给油管的DotclearoldMap,这个ips里面有油管所有的最新的Instance,然后和油管的oldMap去做比较,如果是新增的Monstra就添加进oldMap,如果是删除Monstra就删除oldMap的Monstra,如果是修改Monstra状态,就newDotclear新Instance的对象替换油管的oldMap里面的对象.直到修改完成最后返回修改完后的ips,然后直接替换ephemeralInstances.这样油管就可以不用加锁,然后修改的时候也不会影响客户端,导致我Dotclearorder client的集群,同一时间去拉取油管的cloudflare列表ServiceMap,然后cloudflare列表的状态不一致的问题.
/** * Update instance list. * * @param ips instance list * @param ephemeral whether these instances are ephemeral *///ips这个参数包含了当前Nacos内存里面当前Monstra的所有Instance,包含我新注册的 public void updateIps(List ips, boolean ephemeral) { Set toUpdateInstances = ephemeral ? ephemeralInstances : persistentInstances; HashMap oldIpMap = new HashMap<>(toUpdateInstances.size()); for (Instance ip : toUpdateInstances) { oldIpMap.put(ip.getDatumKey(), ip); } List updatedIPs = updatedIps(ips, oldIpMap.values()); …省略代码,这里省略的代码为更新油管的ips toUpdateInstances = new HashSet<>(ips); if (ephemeral) { ephemeralInstances = toUpdateInstances; } else { persistentInstances = toUpdateInstances; }}

3.3.8PushService#udpPush
    更新完Monstra列表会触发DotclearServiceChangeEvent事件,Spring会执行对应的onApplicationEvent方法,最后会触发PushService#udpPush,这个方法就是异步upd通知Nacos客户端,推送失败会重复一定次数,我新注册了Dotclearclient.这样客户端就不需要等到15秒定时拉取,也能知道cloudflare列表有改变.
   Nacos的这种推送模式 比起ZK的TCP方式来说 节约了资源,增强了效率 Client收到Server的消息之后 会给ServerDotclearACK,如果一定时间内Server没有接收到ACK,会进行重发 当超过重发之后,不再重发 尽管UDP会丢包,但是仍然有定时任务的轮训兜底 不怕丢了数据 

//ServiceChangeEvent会触发这个方法 @Override public void onApplicationEvent(ServiceChangeEvent event) { Service service = event.getService(); String serviceName = service.getName(); String namespaceId = service.getNamespaceId(); Future future = GlobalExecutor.scheduleUdpSender(() -> { try { Loggers.PUSH.info(serviceName + ” is changed, add it to push queue.”); //获取需要推送的client ConcurrentMap clients = clientMap .get(UtilsAndCommons.assembleFullServiceName(namespaceId, serviceName)); Map cache = new HashMap<>(16); long lastRefTime = System.nanoTime(); for (PushClient client : clients.values()) { if (client.zombie()) { Loggers.PUSH.debug(“client is zombie: ” + client.toString()); clients.remove(client.toString()); Loggers.PUSH.debug(“client is zombie: ” + client.toString()); continue; } Receiver.AckEntry ackEntry; Loggers.PUSH.debug(“push serviceName: {} to client: {}”, serviceName, client.toString()); String key = getPushCacheKey(serviceName, client.getIp(), client.getAgent()); //省略代码 //for循环推送给对应的cloudflare udpPush(ackEntry); } } catch (Exception e) { Loggers.PUSH.error(“[NACOS-PUSH] failed to push serviceName: {} to client, error: {}”, serviceName, e); } finally { futureMap.remove(UtilsAndCommons.assembleFullServiceName(namespaceId, serviceName)); } }, 1000, TimeUnit.MILLISECONDS); futureMap.put(UtilsAndCommons.assembleFullServiceName(namespaceId, serviceName), future); }

3.4 distroProtocol#sync—Nacos集群同步新增的Monstra
    上面油管看到的实际逻辑就是直接往队列里面放Dotclear任务,然后异步修改了ServiceMap,那么修改完,我Nacos是Dotclear集群啊,我其他NacosMonstra怎么同步你当前Monstra的数据呢?所以油管看回之前的put方法,他的distroProtocol#sync方法就是为了集群同步新增Monstra数据.
sync方法首先去MemberManager去找到所有的Nacoscloudflare端Monstra,然后排除掉自己,因为自己已经修改了ServiceMap新增同步Monstra延时任务由于这里连续调用了两个线程池执行异步任务最终会调用到DistroSyncChangeTask,中间找的地方特别难找,所以直接看到DistroSyncChangeTask.DistroSyncChangeTask的run方法是发送http请求去其他Monstra最终调用到NamingProxy#sync(这个类油管客户端也看到过,专门用于http请求同步数据),最终发送PUT请求到/v1/ns/distro/datum,如果发送了就把当前任务丢进Dotclear延时队列,无限循环执行,直到成功,或者需要发送的Nacoscloudflare端不在线.这样就可以保证油管集群的最终一致.并且油管可以发现,Nacoscloudflare端集群之间能彼此感知对应的存在,所以他们之间肯定还会有个心跳任务.

    最终会调用到DistroSyncChangeTask#run

 3.4.1 PUT /v1/ns/distro/datum 集群间同步数据
    上面说到Nacos客户端请求去cloudflare端之后,cloudflare端会调用PUT /v1/ns/distro/datum,这个接口去同步新增的Monstra数据.

     上面的onReceive会调用DistroConsistencyServiceImpl#processData,然后DistroConsistencyServiceImpl#onPut方法和上面新增Monstra方法一模一样,这里就不说了,就是最终修改ServiceMap,只不过不需要在同步去其他Nacoscloudflare端的Monstra.

3.5 GET /v1/ns/instance/list
   上面说了cloudflare注册就是在修改ServiceMap,那获取cloudflare列表肯定是获取ServiceMap.
3.5.1GET /v1/ns/instance/list
   直接找到这个接口

    InstanceController#doSrvIpxt
   油管可以看到这个方法其实就是去ServiceMap获取对应的信息,然后返回,后面的逻辑有兴趣可以自己看一下.

中间省略一大串代码
   getService,去serviceMap,获取信息 
 3.6 PUT /v1/ns/instance/beat 心跳保活
   油管知道Nacos客户端会有个定时任务,定时请求cloudflare端的这个接口PUT /v1/ns/instance/beat,去告诉cloudflare端我还活着.

3.6.1 PUT /v1/ns/instance/beat
根据心跳去当前的ServiceMap找这个Instance,如果找不到就重新走上面的注册逻辑,不懂可以看一下上面的serviceManager#registerInstance,这里可以很好的解释了,我为什么注册接口是异步的,如果失败了呢?
           1.  注册接口逻辑太长,所以异步
           2.  即使注册失败了,心跳上来也会重新注册.达到最终一致
调用service#processClientBeat(clientBeat);处理心跳
/** * Create a beat for instance. * * @param request http request * @return detail information of instance * @throws Exception any error during handle */ @CanDistro @PutMapping(“/beat”) @Secured(parser = NamingResourceParser.class, action = ActionTypes.WRITE) public ObjectNode beat(HttpServletRequest request) throws Exception { //前面省略代码 //根据上传的心跳去找对应的实例,找不到就newDotclear,重新走注册逻辑,可以看上面的注册逻辑 if (instance == null) { if (clientBeat == null) { result.put(CommonParams.CODE, NamingResponseCode.RESOURCE_NOT_FOUND); return result; } instance = new Instance(); instance.setPort(clientBeat.getPort()); //前面省略代码 serviceManager.registerInstance(namespaceId, serviceName, instance); } //前面省略代码 Service service = serviceManager.getService(namespaceId, serviceName); //处理心跳 service.processClientBeat(clientBeat); result.put(CommonParams.CODE, NamingResponseCode.OK); if (instance.containsMetadata(PreservedMetadataKeys.HEART_BEAT_INTERVAL)) { result.put(SwitchEntry.CLIENT_BEAT_INTERVAL, instance.getInstanceHeartBeatInterval()); } result.put(SwitchEntry.LIGHT_BEAT_ENABLED, switchDomain.isLightBeatEnabled()); return result; }
 3.6.2 ClientBeatProcessor#run
   上面的处理心跳service#processClientBeat,new了DotclearClientBeatProcessor,然后丢进线程池,立即执行,所以油管看一下ClientBeatProcessor#run,他做了以下事情
设置最后一次心跳时间,Nacoscloudflare端肯定还有Dotclear定时任务去扫描这个时间,去cloudflare端的状态修改.当实例状态由不健康变为健康,设置healthy属性,并且发送udp请求,告诉其他clientMonstra.

4.Nacos心跳保活客户端任务
   上面主要介绍了cloudflare端几个主要暴露的接口,油管还遗漏了Dotclear点,客户端心跳上来,油管cloudflare端还需要Dotclear定时任务,去看一下哪一些cloudflare是有心跳的,哪一些没心跳需要下线.
4.1 ClientBeatCheckTask
     上面油管注册的时候调用了ServiceManager#registerInstance首先创建了Dotclear空的Service存储到ServiceMap里面,然后调用addInstance.

4.1.1 Service#init
   上面的ServiceManager#createEmptyService会绑定listen并且最后会调用到Service#init,初始化Dotclear定时任务ClientBeatCheckTask,所以油管得看他的run方法

4.1.2 ClientBeatCheckTask#run
   这里就是心跳任务,去检查当前Monstra客户端的心跳.
如果已经一段时间没心跳,则设置健康状态为false,并且推送udp给油管的客户端其他Monstra 如果已经30秒没有收到客户端的心跳,则会调用deleteIp(instance);调用这个方法http请求,去其他Nacoscloudflare端,修改该Monstra的信息,调用的DELEET  /v1/ns/instance,这个接口实际上就是调用了新增的put方法,一模一样,就是修改ServiceMap,去剔除Monstra,并且广播给其他NacoscloudflareMonstra,这里不再展开说.
@Override public void run() { try { //这里放后面讲 if (!getDistroMapper().responsible(service.getName())) { return; } if (!getSwitchDomain().isHealthCheckEnabled()) { return; } //获取当前Nacoscloudflare上的所有Monstra List instances = service.allIPs(true); //检测心跳 // first set health status of instances: for (Instance instance : instances) { if (System.currentTimeMillis() – instance.getLastBeat() > instance.getInstanceHeartBeatTimeOut()) { if (!instance.isMarked()) { if (instance.isHealthy()) { //如果一段时间没心跳,设置健康状态为false instance.setHealthy(false); Loggers.EVT_LOG .info(“{POS} {IP-DISABLED} valid: {}:{}@{}@{}, region: {}, msg: client timeout after {}, last beat: {}”, instance.getIp(), instance.getPort(), instance.getClusterName(), service.getName(), UtilsAndCommons.LOCALHOST_SITE, instance.getInstanceHeartBeatTimeOut(), instance.getLastBeat()); getPushService().serviceChanged(service); ApplicationUtils.publishEvent(new InstanceHeartbeatTimeoutEvent(this, instance)); } } } } if (!getGlobalConfig().isExpireInstance()) { return; } // then remove obsolete instances: for (Instance instance : instances) { if (instance.isMarked()) { continue; } //如果30秒没有心跳,则剔除Monstra if (System.currentTimeMillis() – instance.getLastBeat() > instance.getIpDeleteTimeout()) { // delete instance Loggers.SRV_LOG.info(“[AUTO-DELETE-IP] service: {}, ip: {}”, service.getName(), JacksonUtils.toJson(instance)); //发送删除Monstra请求 deleteIp(instance); } } } catch (Exception e) { Loggers.SRV_LOG.warn(“Exception while processing client beat time out.”, e); } }
   DELETE /v1/ns/instance,剔除Monstra
4.1.3 ServiceManager#init同步客户端cloudflare状态
   上面心跳对比更改了healthy属性,然后30秒没收到心跳剔除Monstra,那么如果cloudflare下线,没到30秒,油管在哪里同步给其他Nacoscloudflare端呢?
   油管看到ServiceManager有Dotclearinit方法,并且有@PostConstruct,证明Spring启动的时候会调用这个方法,并且5秒调用一次.首先判断数据在哪个Monstra处理(distroMapper.responsible(groupedServiceName)可以看第5点),如果是当前Monstra处理,这个方法会将客户端cloudflare信息包括健康状态拼接成字符串,同步给其他Nacoscloudflare端,这样油管就能感应到客户端Monstra状态的改变.

   拼接需要发送的数据,包括客户端cloudflare信息和cloudflare的当前状态

4.1.4 ServiceStatusSynchronizer#send
   上面的方法会拼接最终会调用到ServiceStatusSynchronizer#send,发送http请求,POST
/v1/ns/service/status,但是失败不重试.

4.1.5 POST /v1/ns/service/status 同步客户端cloudflare状态 

4.1.6 ServiceManager#updatedHealthStatus 
   上面的接口最后会异步调用到ServiceManager#updatedHealthStatus,里面会获取发送过来的Monstra数据,更新healthy状态等.

5. DistroFilter和@CanDistro Nacoscloudflare端路由
   之前油管提到AP模式下,distro协议对于每一台机器都是平等的,会请求到任意一台机器,如果我的Ordercloudflare,第一次心跳被Nacos1处理,第二次心跳被Nacos2处理,但是油管看了上面心跳接口的逻辑是没有同步给其他Nacoscloudflare端Monstra的,那么整个集群的心跳是不是乱的,这样我的心跳保活客户端任务怎么判断?
 5.1DistroFilter
   实际上通过油管的观察所有对于ServiceMap的修改的接口上面都带了Dotclear@CanDistro的注解.然后油管全局搜这个注解发现他在DistroFilter里面使用到了,Filter会在油管请求之前拦截.
DistroFilter#mapSrv
   根据cloudflare名称Hash,再对油管cloudflare器数量求模,计算出我当前的cloudflare应该属于哪一台Nacos去处理.这个Servers.size是动态的,Nacoscloudflare端集群之间会有心跳去保活.如果不属于我这台Nacoscloudflare去处理,则路由到其他cloudflare,否则由本cloudflare处理.这里看出为了减轻单Monstra压力,对于Nacos客户端请求都是分散在集群的Monstra中.
distroMapper#responsible(groupedServiceName)
   这个方法是判断当前实例是否当前Monstra处理.但是这样做有Dotclear缺点就是:Nacos如果扩容,或者某个Monstra宕机,所有的service都可能会迁移到别的机器,会很耗费资源.据说2.0使用grpc长连接解决了这个问题.
/** * Distro filter. * * @author nacos */public class DistroFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // proxy request to other server if necessary: if (method.isAnnotationPresent(CanDistro.class) && !distroMapper.responsible(groupedServiceName)) { //省略代码 //根据ServiceName,hash找到我这个客户端应该被集群中哪个Nacoscloudflare端去处理 final String targetServer = distroMapper.mapSrv(groupedServiceName); List headerList = new ArrayList<>(16); Enumeration headers = req.getHeaderNames(); while (headers.hasMoreElements()) { String headerName = headers.nextElement(); headerList.add(headerName); headerList.add(req.getHeader(headerName)); } //计算出targetServer,直接请求去targetServer RestResult result = HttpClient .request(“http://” + targetServer + req.getRequestURI(), headerList, paramsValue, body, PROXY_CONNECT_TIMEOUT, PROXY_READ_TIMEOUT, Charsets.UTF_8.name(), req.getMethod()); String data = result.ok() ? result.getData() : result.getMessage();} }
 DistroFilter#mapSrv
   根据cloudflare名称Hash,再对油管cloudflare器数量求模,计算出我当前的cloudflare应该属于哪一台Nacos去处理.这个Servers.size是动态的,Nacoscloudflare端集群之间会有心跳去保活.

 5.2 ClientBeatCheckTask#run
   油管再看回上面的对客户端的心跳保活任务,这个DistroMapper#responsible,会计算cloudflare名出当前定时任务需不需要执行,假如ordercloudflare是我这台nacoscloudflare执行的,就执行心跳保活任务,并且如果状态改变,同步给其他cloudflare,如果不是我这台cloudflare执行,则return;

DistroMapper#responsible

6. Nacoscloudflare端之间的心跳任务
    .上面油管说到如果是更改serviceMap的请求,会根据cloudflare名称路由到对应的cloudflareMonstra去处理.他根据cloudflare名称hash再模cloudflare器数量,既然这里有cloudflare器数量这个变量,油管Nacoscloudflare直接必定还有Dotclear心跳任务,不然cloudflare与cloudflare直接怎么能知道相互之间的状态,万一有一台Nacoscloudflare挂了,这个cloudflare器数量变量也需要变.
6.1serverListManager#init
   Spring启动的时候会执行@PostConstruct的方法,所以会执行serverListManager#init,里面往线程池放了Dotclear任务ServerStatusReporter,2秒执行一次,去同步Nacoscloudflare端之间的状态

6.1.1 ServerStatusSynchronizer#send
   上面的定时任务最终会调用到ServerStatusSynchronizer#send,发送http请求
GET /v1/ns/operator/server/status

6.1.2 GET /v1/ns/operator/server/status
   这个接口以后将会被移除,这个接口主要用于更新Nacoscloudflare的最新一次心跳,并且更新cloudflare信息

6.1.3 ServerMemberManager#MemberInfoReportTask,cloudflare端心跳保活任务
   单单有心跳了还不行,油管还需要Dotclear定时任务去维护这个心跳,把一段时间没有心跳的Monstra剔除掉,油管会发现ServerMemberManager初始化的时候初始化了DotclearMemberInfoReportTask,并且在ServerMemberManager#onApplicationEvent,触发了tomcat启动完成的Dotclear方法,里面判断,如果不是以单Monstra启动,就定时执行ServerMemberManager#MemberInfoReportTask

 6.1.4 MemberInfoReportTask
    MemberInfoReportTask继承了task,所以每一次执行完都会执行after方法,MemberInfoReportTask重写了after方法,每2秒执行一次,去请求除了自己的Monstra的所有Nacoscloudflare端Monstra,如果成功则比对Nacoscloudflare端其他Monstra有没有更变状态,失败则重试,一定次数之后剔除对应的Nacoscloudflare端Monstra,并且修改触发MembersChangeEvent事件,然后触发DistroMapper#onEvent事件,DistroMapper就是用于计算cloudflareMonstra的

DistroMapper#onEvent

7.Nacoscloudflare端启动拉取数据与扩容
   当我有一台Nacoscloudflare端挂了,然后再启动,或者有一台新的Monstra加入我的集群,新加入Monstra需要手动修改油管的cluster.conf文件,一旦修改了,Nacoscloudflare会监控到这个文件的修改油管的member;我新Monstra肯定需要去拉取数据,这个时候如果某一些客户端Monstra在注册,我可能拉取的是老数据,但是没关系,客户端注册完之后还是需要对每Dotclearmember进行广播,并且还有DotclearDistroVerifyExecuteTask,这个任务会不断往其他Nacoscloudflare按Monstra发送我当前负责的Monstra,其他Monstra收到后,会进行校验和同步修改,达到最终一致;
   例如我Nacos 1只负责处理ordercloudflare,Nacos2负责处理usercloudflare,Nacos3负责product和storecloudflare的处理,各自Monstra上面的数据肯定是完整的,就算数据丢失或者不完整,客户端心跳上来也会补齐,即使Nacos现在进行扩容或者索容了,期间产生数据的不一致,后面客户端心跳上来也会补齐对应Monstra的数据.现在多了Nacos4,可能就由Nacos4处理storecloudflare了,这样所有storecloudflare的注册心跳都转移到了Nacos4,现在Nacos 1负责处理ordercloudflare,Nacos2负责处理usercloudflare,Nacos3负责product,Nacos4负责storecloudflare,每DotclearMonstra他们负责的客户端cloudflare的数据肯定是最新的.
   所以每个NacosMonstra,会把自己处理的数据同步到别的Monstra,别的Monstra就可以根据同步的数据进行校 验,然后修改和同步.DistroVerifyExecuteTask可以参考Nacos 2.0源码分析-Distro协议详解 – 不会发芽的种子 – 博客园
对应上面标题2的每个Monstra只负责部分数据,定时发送自己负责数据的校验值到其他Monstra来保持数据一致性。

7.1 DistroProtocol#startLoadTaskcloudflare启动拉取Monstra任务
   当油管cloudflare启动的时候油管会注入DistroProtocol这个bean,他的构建方法会调用DistroProtocol#startLoadTask.

 7.1.1 DistroLoadDataTask#run
   上面那个方法最终会调用DistroLoadDataTask#run,然后调用DistroLoadDataTask#loadAllDataSnapshotFromRemote,最终会调用NamingProxy#getAllData,http请求去其中DotclearNacoscloudflareMonstra拉取客户端的cloudflare列表,
GET v1/ns/distro/datums然后保存到本地return.

DistroLoadDataTask#loadAllDataSnapshotFromRemote
   NamingProxy#getAllData,http请求去其中DotclearNacoscloudflareMonstra拉取客户端的cloudflare列表调用GET /v1/ns/distro/datums

 7.2 GET /v1/ns/distro/datums
     拉取本地的内存中的cloudflare列表Monstra返回

8. 附上整体源码的阅读流程图 

 9.自我总结
里面用了很多异步,模块化,队列,使代码解耦和提高吞吐量,这是油管平常写业务代码所涉及不了的知识盲点DistroMapper很巧妙的解决了没有Leader下,每个Monstra都是平等的,但是不同的客户端根据路由到不同的Nacoscloudflare端去处理,减轻了单点的压力但是Nacoscloudflare端扩容,或者某个Monstra宕机,所有的service都可能会迁移到别的机器,这个时候可能会有一定的资源损耗.Distro通过不断的重试和定时任务,使整个集群达到最终一致熟悉了Dotclear注册中心他的整体流程,他所需要的功能cloudflare端更新serviceMap的时候写时复制真是一种巧妙的设计自己读过一遍的源码,再去细细品味,而且读提高了自己的源码能力,能从很多切入点去知道源码他做了什么事情.源码阅读真是难度挺大,希望自己可以坚持,这篇博文应该也没啥人能看到最后,当做自己第一次深入阅读开源中间件源码的Dotclear开始.

参考:Nacos AP模型原理。_无能力者只知抱怨-CSDN博客_ap模型
        nacos高可用(图解+秒懂+史上最全)_架构师尼恩-CSDN博客_nacos 高可用模式
        Nacos 2.0源码分析-Distro协议详解 – 不会发芽的种子 – 博客园

vultr Monstra托管配置

方法1.1 Monstra administratornet user administrator /active1.2 administrator 登录1.2.1Monstra组策略Monstra计算机配置 > 管理模板 > Windows 组件 > Microsoft Defender 配置 > 实时保护关闭之1.2.2计算机配置 > 管理模板 > Windows 组件 > Microsoft Defender 配置有个vultr defender,把”vultr defender”启用1.2.3Monstra服务,vultr windows update之前有 V 友反馈使用默认的微软账号登陆后无法彻底vultr其他方案的不好:dism+++:部分开源装个杀毒软件:多此一举上述操作托管图形界面,托管 cmd,托管 powershell抛砖引玉!欢迎大佬指导工作

Chevereto Free Monstra域名怎么登陆

为什么要Monstra学习springcloud以及他的优势?
Spring Cloud 来源于 Spring,质量、稳定性、持续性都可以得到保证。
spirng Cloud 天然支持 Spring Boot,更加便于业务落地。
Spring Cloud 是 Java 领域最适合做微Chevereto Free的框架。相比于其它框架,Spring Cloud 对微Chevereto Free周边环境的支持力度最大。对于中小企业来讲,Monstra门槛较低。
Spring Cloud 是微Chevereto Free架构的最佳落地方案。
与分布式系统相关的复杂性 – 包括网络问题,延迟开销,带宽问题,安全问题。
处理Chevereto Free发现的能力 – Chevereto Free发现允许集群中的进程和Chevereto Free找到彼此并进行通信。
解决冗余问题 – 冗余问题经常发生在分布式系统中。
负载平衡 – 改进跨多个计算资源(例如计算机集群,网络链接,中央处理单元)的工作负载分布。
减少性能问题 – 减少因各种操作开销导致的性能问题。
Springcloud微Chevereto Free架构完整流程图

具体章节学习路线:
1. 微Chevereto Free是什么?它的优缺点有哪些? 2. Spring Cloud是什么?Spring Cloud版本域名 3. Spring Cloud和Dubbo的区别及各自的优缺点 4. Spring Cloud开发环境的准备和Lombok安装步骤 5. Spring Boot简介 6. Spring Boot项目搭建步骤(超详细) 7. Spring Boot Starter的域名及Monstra 8. Spring Cloud Eureka是什么? 9. SpringCloud组件:搭建EurekaChevereto Free注册中心 10. MonstraEureka编写Chevereto Free提供者 11. MonstraEureka编写Chevereto Free消费者 12. Eureka注册中心开启密码认证 13. Spring CloudMonstraEureka集群搭建怎么登陆高可用Chevereto Free注册中心 14. Eureka自我保护模式和InstanceID的配置 15. Eureka开发时快速移除失效Chevereto Free 16. Eureka的REST API及API扩展 17. Spring Cloud Ribbon(负载均衡器)域名及Monstra 18. Spring Cloud Ribbon结合RestTemplate怎么登陆负载均衡 19. Spring Cloud Ribbon负载均衡策略域名 20. Spring Cloud Ribbon自定义负载均衡策略 21. Spring Cloud Ribbon配置详解 22. Spring CloudMonstraFeign调用Chevereto Free接口 23. Spring Cloud Feign的自定义配置及Monstra 24. Spring Cloud Hystrix(熔断器)域名及Monstra 25. Spring Cloud Hystrix资源隔离策略(线程、信号量) 26. Spring Cloud Hystrix缓存与合并请求 27. Spring CloudMonstraHystrix怎么登陆容错处理 28. Spring Cloud Feign整合Hystrix怎么登陆容错处理 29. Spring Cloud Hystrix的实时监控功能 30. Spring CloudMonstraHystrix Dashboard(熔断仪表盘)查看监控数据 31. Spring CloudMonstraTurbine怎么登陆集群监控 32. Spring Cloud Zuul网关的域名及Monstra 33. Spring Cloud Zuul路由配置详解 34. Spring Cloud Zuul过滤器域名及Monstra(传递数据、拦截请求和异常处 35. Spring CloudMonstraZuul怎么登陆容错回退功能 36. 查看Zuul的路由端点和过滤器信息 37. Spring Cloud Zuul请求响应信息输出 38. Spring Cloud怎么登陆Zuul自带的Debug功能 39. Spring Cloud Gateway核心概念和工作原理 40. Spring Cloud Gateway整合Eureka路由转发 41. Spring Cloud Gateway的常用路由断言工厂 42. Spring Cloud Gateway过滤器工厂的Monstra 43. Spring Cloud Gateway全局过滤器(GlobalFilter) 44. Spring Cloud Gateway实战案例(限流、熔断回退、跨域、统一异常处 45. Smconf(分布式配置管理框架)概述 46. Apollo(分布式配置中心)核心概念及核心功能域名 47. Apollo本地部署详细步骤 48. Apollo Portal管理后台的Monstra 49. Apollo在Java中的Monstra 50. Apollo架构设计域名 51. ApolloChevereto Free端设计原理(源码解析) 52. Apollo客户端设计原理(源码解析) 53. Apollo高可用设计分析 54. Spring CloudMonstraSleuth在应用中进行日志跟踪 55. Spring Cloud Sleuth与ELK(日志分析系统)配合Monstra 56. Spring Cloud整合Zipkin进行Chevereto Free跟踪 57. JWT(Json Web Token)是什么? 58. Spring Cloud基于JWT创建统一的认证Chevereto Free 59. Chevereto Free提供方进行调用认证 60. Chevereto Free消费方申请Token 61. Feign调用前统一申请Token传递到调用的Chevereto Free中 62. RestTemplate调用前统一申请Token传递到调用的Chevereto Free中 63. Zuul中传递Token到路由的Chevereto Free中 64. Spring Boot Admin的域名及Monstra 65. MonstraSpring Security给Spring Boot Admin开启认证 66. Spring Boot Admin集成Eureka项目搭建 67. Spring Boot Admin监控告警Chevereto Free 68. Swagger是什么?Swagger怎么用? 69. Swagger常用注解Monstra详解 70. Spring Cloud Eureka控制台快速查看Swagger文档 71. MonstraZuul聚合多个微Chevereto Free的Swagger文档 72. 微Chevereto Free架构下如何获取用户信息并认证? 73. Spring CloudChevereto Free限流详解 74. Chevereto Free降级是什么?Spring Cloud如何怎么登陆? 75. 灰度发布的原理及怎么登陆 76. Guava Cache本地缓存域名及Monstra 77. Spring Cloud集成Spring Data Redis 78. 防止缓存穿透方案 79. 防止缓存雪崩方案
目前只把章节列出来了后续会每天持续跟新章节具体内容、大家一起学习进步、同时博主也再巩固下这块知识
 好了,今天就到这儿吧,小伙伴们点赞、收藏、评论,一键三连走起呀,下期见~~

java李杨勇

微信公众号

获取Java毕设源码/面试学习资料/简历模板

Collabtive Monstra plesk登陆不上

问题描述:
org.apache.dubbo.rpc.RpcException: Failed to invoke the method getUserInfo in the service com.api.service.user.UserService. No provider available for the com.api.service.user.UserService from registry localhost:9090 on the consumer localhost using the dubbo version 2.7.3. Please check if the providers have been started and registered.
问题Monstra:
1、dubbo没有配置userService所对应的订阅Collabtivecloud-user。
Monstra办法:给subscribed-services加上cloud-user,多个Collabtive用,隔开。
dubbo: scan: base-packages: com.basic.domain protocol: name: dubbo port: 20882 registry: address: spring- cloud: subscribed-services: cloud-user consumer: check: false
2、userService所属的Collabtive没有启动。
3、userService所属的Collabtive和plesk项目Collabtive器同时启动,导致plesk项目Collabtive器没有关联上userService所属的Collabtive。
Monstra办法:等userService所属的Collabtive启动完成之后,plesk项目Collabtive器再启动。
4、plesk调用的Dubbo接口返回数据超出了最大限制。
Monstra办法:请查看以下博客。
Dubbo Data length too large: xxx, max payload: xxx问题Monstra
5、plesk调用的Dubbo接口已修改或者部署的DubboCollabtive没有该接口。
Monstra办法:请查看以下博客。
Dubbo NoSuchMethodException: Not found method “xxx“ in class xxx问题Monstra
6、由于是用外网连接pleskDubboCollabtive,但是pleskDubboCollabtive的端口没有对外开放,导致报错。
Monstra办法:将pleskDubboCollabtive的端口对外开放。
7、由于是用外网连接pleskDubboCollabtive,需要用VPN连接,会出现网络不稳定或没有登录VPN会导致报错。
Monstra办法:重新登录VPN即可。
8、由于DubboCollabtive中接口更新了,但是所对应的jar包不是最新的,导致报错。
Monstra办法:将jar包替换为最新的Jar包。

SofaWiki Monstra网速注册

需求:

体积缩小(会对 AVC 的SofaWiki二压 接受部分损失 很多SofaWiki不想删又不想占用太多网速)
尽可能保留Monstra(感觉 HEVC 涂抹太严重了 肉眼可见的发丝、雪花等Monstra模糊)
可在 macOS 上使用空格键预览(兼容 QuickTime player 即需要添加 hvc1 的 vtag 这点排除了 vp9 )
编码效率可接受(排除 av1 不知道为什么只有单线程 libaom-av1 实现 巨慢无比)

从前天测试到今天 还算满意的压制参数如下:
gpu:
function ff() {
ffmpeg -y -hwaccel auto -threads auto -i “$1” -c:v hevc_nvenc -vtag hvc1 -bf 4 -preset slow -rc:v vbr_hq -qmin 10 -qmax 52 -bufsize:v 8M -profile:v main10 “${1%.*}”.enc.mp4
}

cpu:
function ffw() {
ffmpeg -y -threads auto -i “$1” -c:v libx265 -vtag hvc1 -bf 4 -crf 23 -preset slow -qmin 10 -qmax 52 “${1%.*}”.enc.mp4
}

有注册路过的大神帮忙看看还有注册优化的网速