问题起源
Spring Cloud架构体系中,Eureka是一个至关重要的组件,它扮演着微服务注册中心的角色,所有的服务注册与服务发现,都是依赖Eureka的。
面试有时会碰到如下问题:
Eureka注册中心使用什么样的方式来储存各个服务注册时发送过来的机器地址和端口号?
各个服务找Eureka Server拉取注册表的时候,是什么样的频率?
各个服务是如何拉取注册表的?
一个几百服务,部署上千台机器的大型分布式系统,会对Eureka Server造成多大的访问压力?
Eureka Server从技术层面是如何抗住日千万级访问量的?
带着这几个问题,我们来了解下Eureka作为微服务注册中心的核心原理。
先说一个基本的知识点,各个服务内的Eureka Client组件,默认情况下,每隔30秒会发送一个请求到Eureka Server,来拉取最近有变化的服务信息
举个例子:库存服务原本部署在1台机器上,现在扩容了,部署到了3台机器,并且均注册到了Eureka Server上。然后订单服务的Eureka Client会每隔30秒去找Eureka Server拉取最近注册表的变化,看看其他服务的地址有没有变化。
除此之外,Eureka还有一个心跳机制,各个Eureka Client每隔30秒会发送一次心跳到Eureka Server,通知人家这个服务实例还活着!
如果某个Eureka Client很长时间没有发送心跳给Eureka Server,那么就说明这个服务实例已经挂了。
上述整个过程如下图:
Eureka设计精妙的注册表存储结构
现在假设手头有一套大型的分布式系统,一共100个服务,每个服务部署在20台机器上,机器是4核8G的标准配置。相当于你一共部署了100 * 20 = 2000
个服务实例,有2000台机器。
每台机器上的服务实例内部都有一个Eureka Client组件,它会每隔30秒请求一次Eureka Server,拉取变化的注册表。此外,每个服务实例上的Eureka Client都会每隔30秒发送一次心跳请求给Eureka Server。
那么算算,Eureka Server作为一个微服务注册中心,每秒钟要被请求多少次?一天要被请求多少次?
按标准的算法,每个服务实例每分钟请求2次拉取注册表,每分钟请求2次发送心跳,这样一个服务实例每分钟会请求4次,2000个服务实例每分钟请求8000次,换算到每秒,则是8000 / 60 = 133次左右,我们就大概估算为Eureka Server每秒会被请求150次,那一天的话,就是8000 * 60 * 24 = 1152万,也就是每天千万级访问量。
按照我们的测算,一个上百个服务,几千台机器的系统,按照这样的频率请求Eureka Server,日请求量在千万级,每秒的访问量在150次左右。即使算上其他一些额外操作,我们姑且就算每秒钟请求Eureka Server在200次~300次吧。
所以通过设置一个适当的拉取注册表以及发送心跳的频率,可以保证大规模系统里对Eureka Server的请求压力不会太大。
关键问题来了,Eureka Server是如何保证轻松抗住这每秒数百次请求,每天千万级请求的呢?
要搞清楚这个,首先得清楚Eureka Server到底是用什么来存储注册表的,如下源码:
一句话概括:维护注册表、拉取注册表、更新心跳时间,全部发生在内存里!这是Eureka Server非常核心的一个点。
举例:比如“inventory-service”是可以有3个服务实例的,每个服务实例部署在一台机器上。
Eureka 优秀的多级缓存机制
Eureka Server为了避免同时读写内存数据结构造成的并发冲突问题,采用了多级缓存机制来进一步提升服务请求的响应速度。
多级缓存机制的优点是什么?
- 尽可能保证了内存注册表数据不会出现频繁的读写冲突问题。
- 并且进一步保证对Eureka Server的大量请求,都是快速从纯内存走,性能极高。
整个过程如下图:
总结
通过上面的分析可以看到,Eureka通过设置适当的请求频率(拉取注册表30秒间隔,发送心跳30秒间隔),可以保证一个大规模的系统每秒请求Eureka Server的次数在几百次。
同时通过纯内存的注册表,保证了所有的请求都可以在内存处理,确保了极高的性能。
另外,多级缓存机制,确保了不会针对内存数据结构发生频繁的读写并发冲突操作,进一步提升性能。