zrlw
zrlw
apache httpclient5的FutureRequestExecutionService采取的方式是构造函数提供一个ExecutorService入参,由用户负责创建并用来执行异步任务。
有位netty member提交了一个PR,HashedWheelTimer类增加一个带Executor入参的构造函数。 https://github.com/netty/netty/pull/11728 虽然有netty member认为并不需要改,但该PR已merged。 更新:参照netty的PR 11728重新做了修订,不同之处是默认的executor改成了static fixedThreadpool全局共享线程池。
我们有同样的问题,看 #7375 我们加了获取连接超时解决了OOM问题,内存耗尽不是连接泄露,而是堆积起来的获取连接请求,这些请求没有设置超时,所以会一直等。 ``` leasingRequest,deadline都是LONG.MAX_VALUE,不会被自动清理,只进不出把内存撑爆了 ```
设置获取连接超时只是避免OOM的问题,我们最终还是修改了HttpClientManager的ApacheSyncHttpClientFactory的buildHttpClientConfig,把线程池调大才解决了大规模临时注册实例场景下的注册数量抖动问题,原因就是连接数不够用,导致节点之间转发临时实例心跳不及时。
> Will too many threads be created? The original value of these parameters are too small to support large scale beat forwarding between nacos nodes for Distro protocol. These values...
大规模注册实例运行场景下,启动之前停掉的nacos节点也是有问题的: 1. DistroProtocol的isInitialized从false变为true的前提条件是startLoadTask方法执行成功:至少要从其他一个节点获取全部快照成功,大规模实例场景下全部快照获取耗时很长,测试30万实例快照获取耗时大约16秒,已经超出心跳默认超时15秒了; 2. DistroProtocol的isInitialized为false时,TrafficReviseFilter会拒绝收到的临时实例心跳请求; 这样刚刚重启的节点会直接将自己负责的很多实例变成不健康甚至下线了事,然后通过DistroVerifyTask定时任务同步到其他节点,相关实例在所有的nacos节点控制台都会变成不健康甚至DOWN。 这个参数可以在客户端配置注册中心的URL时配置preserved.heart.beat.timeout进行调整,但是客户端如果非常多,难免会有疏漏,nacos服务端尚未提供可以配置的方式,需要自己修改代码。
有一个尚未解决的问题: 当实例数量多的时候,新启动的节点从其他节点拉取快照耗时超过了15秒,这种情况下还需要定制: 方法1:改代码,把默认的心跳超时15秒调大,要超过拉取快照的耗时。 方法2:在nacos集群前面的负载均衡设施增加http健康检查机制,通过httpget对应nacos节点/health接口判断节点是否健康,这样就能把心跳请求绕过正在启动的节点。 这么做的原因在于:打开了监听端口但尚未完成快照拉取操作的节点会把收到的心跳请求拒掉,极端情况下(运气比较差),客户端每次包括重试都把心跳发到了这个节点,那么等待这个节点完成快照拉取,心跳也超时了,注意,这些心跳包括需要转发到其他节点的实例心跳,所以影响的范围不仅是刚启动的节点负责的临时实例,还有其他节点负责的实例。 我们是直接把心跳超时加大一倍了事,但是我们认为应该将TrafficReviseFilter和DistroFilter合并,对于并非本节点负责的请求,直接转发到对应的责任节点就好了,不是自己负责的啥都不用做,这样即使启动的节点拉取快照要1分钟也没有问题,让它自己慢慢拉吧。
> 我这边是 nacos server 源码改了,不往下推送 空 hosts 信息,即 hosts 为空,则不推送,通过接口拉取时,如果 hosts 为空,则返回 null,这种情况下,我 nacos 三个节点全部宕机,也只影响服务发布,已有服务无影响,主要还得容灾搞好,bug 难免。非常建议官方能将 dubbo.registry.parameters.namingPushEmptyProtection 的配置默认为 true 可以测试一下这个ISSUE对应的PR,我们之前遇到的no provider问题都是启停nacos节点时出现的,目前修订之后40万注册实例,任意启停节点都不再出现实例变动了,要看各个节点的naming-event.log日志有没有变化,没有变化说明当前节点保存的实例未变化,肉眼看控制台是看不过来的。
#7687也是我提的,这个PR一起搞了,忘了加注解。 这个PR涉及#7687 的修订内容有两部分: 1. Distro协议未完成初始化或完成初始化之后尚未满一个心跳超时(刚启动的节点),不做节点之间的同步,不做udp推送,收到服务列表查询时直接返回空列表(客户端收到空列表不会更新) 2. 当服务列表发生变化时(有新的服务节点加入集群或集群有的节点退出),和1一样暂停同步、推送、返回空列表,等待一个心跳超时后再恢复。 之所以这样做,是因为上述情况下大部分临时实例的责任节点将发生改变,各节点都需要重新收全自己负责的实例心跳,此时如果继续同步或推送,就会把自己尚未收集完整的服务实例列表同步给其他节点或推送给客户端。 注册实例推空保护机制我们也曾尝试过,但是我们有服务端实际下线后客户端需要准实时感知的需求,所以这个开关对我们来说用处不大。
目前我们实际的注册实例数量还没有达到这个量级,现在只是先做一下压测,看看是不是还有哪些坑在等着填,server端用的7个16c32g的虚拟机,consumer是自己写的java request测试类,一台windows16c32g模拟了800个服务,每个服务500个实例。