赞
踩
读写并发这里指的就是线程安全问题,解决线程安全的问题就是加锁。
JAVA中常用的synchronized可以解决问题。使用synchronized存在性能问题,现在相当于所有的读写操作都进行了锁定,即“串行化”。
为了提高性能,可以使用读写锁。
读写锁是特殊的自旋锁,它把共享资源的访问者分为了读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。同时只允许一个线程对共享资源写或者多个读,但不能同时读又有写。
Nacos内部接收到注册的请求时,不会立即写数据,而是将服务注册的任务放入一个阻塞队列就立即响应给客户端。然后利用线程池读取阻塞队列中的任务,异步来完成实例更新,从而提高并发写能力。
首先分析Spring Cloud集成Nacos client的服务注册和服务拉取的逻辑。
细心的同学可能已经发现NacosAutoServiceRegistration的继承的AbstractAutoServiceRegistration类实现了ApplicationListener接口,那么必定在AbstractAutoServiceRegistration类中监听的某个Event(实现方法:onApplicationEvent),源码中发现最终会调用一个register方法,这个方法就是真正向 Nacos Server 注册了当前实例,源码中可以看出最终调用了reqApi方法,向 Nacos Server /nacos/v1/ns/instance 接口发送了一个POST请求,把当前实例注册进去,到这里整个客户端的核心注册流程就分析完了
现在接着分析一下Nacos Server注册中心的核心功能逻辑及源码,首先来分析Nacos怎么能支持高并发的Intance的注册的。
采用内存队列的方式进行服务注册
也就是说客户端在把自己的信息注册到Nacos Server的时候,并不是同步把信息写入到注册表中的,而且采取了先写入内存队列中,然后用独立的线程池来消费队列进行注册的。
从源码可看出最终会执行listener.onChange()这个方法,并把Instances传入,然后进行真正的注册逻辑,这里的设计就是为了提高Nacos Server的并发注册量,如果你非常关注Nacos性能相关问题,可以查看官方的压测报告(Nacos服务发现性能测试报告),或者自己去做一下压测。
Nacos 2.0 通过升级通信协议和框架、数据模型的方式将性能提升了约 10 倍,解决继 Nacos 1.0 发布逐步暴露的性能问题
在eureka client拉取注册表的时候,就会用到所谓的多级缓存机制,多级缓存机制中有两个缓存,一个叫只读缓存ReadOnlyCacheMap,一个叫读写缓存ReadWriteCacheMap。eureka client拉取注册表的时候,会先从ReadOnlyCacheMap中去获取注册表数据,如果获取不到的话再去ReadWriteCacheMap中找,如果还是找不到的话,那就只能重新从注册表中拉取了
ReadOnlyCacheMap就是一个普通的ConcurrentHashMap,而ReadWriteCacheMap是guava cache,如果ReadWriteCacheMap读不到数据,就会通过ClassLoader的load方法直接从注册表获取数据再返回
多级缓存机制有多种过期策略
通过过期的机制,可以发现一个问题,就是如果ReadWriteCacheMap发生了主动过期或定时过期,此时里面的缓存就被清空或部分被过期了,但是在此之前readOnlyCacheMap刚执行了被动过期,发现两个缓存是一致的,就会接着使用里面的缓存数据
所以可能会存在30秒的时间,readOnlyCacheMap和ReadWriteCacheMap的数据不一致
Sentinel的限流原理
限流效果,对应有DefaultController快速失败
WarmUpController慢启动(令牌桶算法)
RateLimiterController(漏桶算法)
滑动时间窗口算法
1、固定时间窗口算法
即比如每一秒作为一个固定的时间窗口,在一秒内最多可以通过100个请求,那么在统计数据的时候,如果0-500ms没有请求,而500-1000ms有100个请求,那么这一百个请求都能通过,在1000-1500ms的时候,又有100个请求过来了,它依然能够通过,因为在1000ms的时候又开启了一个新的固定时间窗口。这样,500-1500ms这一秒内有了200个请求,但是它依然能够通过,所以这就会造成数据统计的不准确性,并不能保证在任意的一秒内都使得通过请求数小于100,。
2、普通的滑动窗口做法
因为固定时间窗口带来的数据同的不准确性,就会造成可能局部的时间压力过高,所以就需要采用滑动窗口算法来进行统计,滑动窗口时间算法意思就是,从请求过来的时刻开始,统计往前一秒中的数据,通过这个数据来判断是否进行限流等操作。这样的话准确性就会有很大的提升,但是由于每一次请求过来都需要重新统计前一秒的数据,就会造成巨大的性能损失。所以这也是他的不合理的地方。
3、Sentinel的滑动时间窗口算法
由于固定时间窗口带来的不准确性和普通滑动窗口带来的性能损失的缺点,所以Sentinel对这两种方案采取了折中的方案。
在Sentinel中会将原本的固定的时间窗口划分成很多更小的样本窗口,每一次请求的数据都会被保存在小的样本窗口中去,而每一次获取的时候都会去获取这些样本时间窗口中的数据,从而不需要进行重新统计,就减小了性能损耗,同时时间窗口被细粒度化了,不准确性也会降低很多。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。