Eureka源码剖析
2019-05-30 本文已影响0人
康俊1024
思考一些问题
- Eureka注册中心使用什么样的方式来储存各个服务注册时发送过来的机器地址和端口号?
- 各个服务找Eureka Server拉取注册表的时候,是什么样的频率?
- 各个服务是如何拉取注册表的?
- 一个几百服务,部署上千台机器的大型分布式系统,会对Eureka Server造成多大的访问压力?
- Eureka Server从技术层面是如何抗住日千万级访问量的?
前提须知
- 各个服务内的Eureka Client组件,默认情况下,每隔30秒会发送一个请求到Eureka Server,来拉取最近有变化的服务信息。
-
Eureka有一个心跳机制,各个Eureka Client每隔30秒会发送一次心跳到Eureka Server,通知人家说,哥们,我这个服务实例还活着!如果某个Eureka Client很长时间没有发送心跳给Eureka Server,那么就说明这个服务实例已经挂了。
Eureka心跳机制.png
Eureka Server注册表存储结构
假设有一套大型的分布式系统,一共100个服务,每个服务部署在20台机器上,机器是4核8G的标准配置。相当于你一共部署了100 * 20 = 2000个服务实例,有2000台机器。
每台机器上的服务实例内部都有一个Eureka Client组件,它会每隔30秒请求一次Eureka Server,拉取变化的注册表。此外,每个服务实例上的Eureka Client都会每隔30秒发送一次心跳请求给Eureka Server。
- 按标准的算法,每个服务实例每分钟请求2次拉取注册表,每分钟请求2次发送心跳。
- 这样一个服务实例每分钟会请求4次,2000个服务实例每分钟请求8000次。
- 换算到每秒,则是8000 / 60 = 133次左右,我们就大概估算为Eureka Server每秒会被请求150次。
- 那一天的话,就是8000 * 60 * 24 = 1152万,也就是每天千万级访问量。
所以通过设置一个适当的拉取注册表以及发送心跳的频率,可以保证大规模系统里对Eureka Server的请求压力不会太大。
源码剖析
内存注册表类.png- 如上图所示,图中的这个名字叫做registry的CocurrentHashMap,就是注册表的核心结构。
- 从代码中可以看到,Eureka Server的注册表直接基于纯内存,即在内存里维护了一个数据结构。
- 各个服务的注册、服务下线、服务故障,全部会在内存里维护和更新这个注册表。
- 各个服务每隔30秒拉取注册表的时候,Eureka Server就是直接提供内存里存储的有变化的注册表数据给他们就可以了。
- 同样,每隔30秒发起心跳时,也是在这个纯内存的Map数据结构里更新心跳时间。
registry的数据结构
- 首先,这个ConcurrentHashMap的key就是服务名称,比如“xxx-service”,就是一个服务名称。
- value则代表了一个服务的多个服务实例。
- 举例:比如“xxx-service”是可以有3个服务实例的,每个服务实例部署在一台机器上。
作为value的这个Map
Map<String, Lease<InstanceInfo>>
- 这个Map的key就是服务实例的id
- value是一个叫做Lease的类,它的泛型是一个叫做InstanceInfo的东东。
- InstanceInfo,我们见名知义,这个InstanceInfo就代表了服务实例的具体信息,比如机器的ip地址、hostname以及端口号。
- Lease,里面会维护每个服务最近一次发送心跳的时间
Eureka Server端多级缓存机制
Eureka Server为了避免同时读写内存数据结构造成的并发冲突问题,采用了多级缓存机制来进一步提升服务请求的响应速度。
拉取注册表的步骤:
- 首先从ReadOnlyCacheMap里查缓存的注册表。
- 若没有,就找ReadWriteCacheMap里缓存的注册表。
- 如果还没有,就从内存中获取实际的注册表数据。
注册表发生变更的步骤:
- 会在内存中更新变更的注册表数据,同时过期掉ReadWriteCacheMap。
- 此过程不会影响ReadOnlyCacheMap提供人家查询注册表。
- 一段时间内(默认30秒),各服务拉取注册表会直接读ReadOnlyCacheMap。
- 30秒过后,Eureka Server的后台线程发现ReadWriteCacheMap已经清空了,也会清空ReadOnlyCacheMap中的缓存。
- 下次有服务拉取注册表,又会从内存中获取最新的数据了,同时填充各个缓存。
多级缓存机制的优点是什么?
- 尽可能保证了内存注册表数据不会出现频繁的读写冲突问题。
-
并且进一步保证对Eureka Server的大量请求,都是快速从纯内存走,性能极高。
多级缓存机制.png
总结
- Eureka通过设置适当的请求频率(拉取注册表30秒间隔,发送心跳30秒间隔),可以保证一个大规模的系统每秒请求Eureka Server的次数在几百次。
- 同时通过纯内存的注册表,保证了所有的请求都可以在内存处理,确保了极高的性能。
- 另外,多级缓存机制,确保了不会针对内存数据结构发生频繁的读写并发冲突操作,进一步提升性能。