Eureka

Eureka两个核心功能,一个是服务注册与发现,一个是心跳故障检测

(一)服务注册中心原理


Eureka内部核心有个服务注册表这个数据结构,
在服务一启动的时候就给自己的ip端口注册到服务注册表里面

在服务进行服务发现的时候就不断的去Eureka里面的服务注册表里面拉取服务,这个你可以自己配置每隔10秒或者20秒拉取一次.

服务注册表有两级缓存,一个是ReadOnly缓存,一个是ReadWrite缓存,一开始服务发现拉取的时候先去ReadOnly缓存拉取,如果是空的就去ReadWrite缓存拉取,如果还是空的就去服务注册表里面拉取数据,然后再依次把拉取的最新数据放入到ReadWrite和ReadOnly缓存里面来.
这样的好处就是优化冲突,如果读写都去服务注册表的话,就会出现写和读的锁冲突,所以就设计了一套缓存.在进行服务注册的时候,如果修改服务注册表的以后,会立马给数据同步到ReadWrite缓存里面.然后后台会有个线程会定时(时间可以手动配置,比如说30秒)给ReadWrite和ReadOnly两个缓存的数据做对比,如果不一样的话,就从ReadWrite缓存里面放到ReadOnly里面.

此时就会有个问题,新注册的一个服务A在服务发现的时候可能会获取不到,因为服务发现在拉取ReadOnly缓存里面的数据的话,可能不是最新的.
SpringCloud原理[笔记] - 图1

(二)心跳故障检测

SpringCloud原理[笔记] - 图2


每个服务会定时往服务注册表里面发送心跳,这个发送频率可以自己去设计的,比如30秒发送一次, 然后Eureka内部会有一个线程每个几十秒(时间可以用户去设置)定时检查服务注册表里面的数据心跳频率,如果发现有个服务在过去的可能60秒,可能90秒内(这个时间是可以程序员自己配置的)都没有发送心跳,此时Eureka就会认为这个服务发生故障了,这个时候这个服务器的ip和端口就会被服务注册表删除掉. 同时会给ReadWrite缓存全部清理掉,此时消费者里面的服务数据还是旧的数据,在访问生产者的时候如果访问到挂掉的生产者的话,就会出现调用失败情况,
Eureka后台线程发现ReadOnly和ReadWrite缓存的数据不一样的话就会给ReadOnly缓存也删除掉,然后消费者在服务发现的时候再去拉取服务信息的时候,发现ReadOnly是空的话,就去ReadWrite拉取,还是空的, 最后就去服务注册表里面拉取最新的服务了.

(三)集群架构原理


Eureka集群起码也两台做冗余处理

SpringCloud原理[笔记] - 图3

(四)Zookeeper和Eureka对比

1.集群问题


Eureka集群每个机器都是对等的,各个服务可以向任何一个Eureka实例注册服务和服务发现,集群里任何一个Eureka实例接收到写请求之后都会自动同步给其它的所有Eureka实例.

2.可用性和一致性问题


Zookeeper保证了强一致性,一旦Leader挂了,重新Leader选举的期间是不可用的.
Eureka是peer模式,可能还没有同步数据Eureka自己就挂掉了,此时还可以继续从别的机器上拉取服务注册表,但是看到的不是最新的数据,但是保证了可用性.

Eureka能保证可用,Zookeeper能保证强一致性.

3.同步问题

Zookeeper注册和同步是秒级别的,也就是说生产者一上线消费者立马就能感知到,如果生产者挂掉了,Zookeeper集群能立马感知到并且同步到消费者,还是秒级别的.

而Eureka时效性是非常差的,生产者部署之后消费者要过好几十秒才能发现到,如果生产者挂掉了,消费者也得好几十秒才能发现,如果再配合Ribbon的话,那么时效性是更差的,因为Ribbon内部也有自己的服务注册表缓存.

如果服务故障的话,假设Eureka 60秒检查一次心跳,发现生产者死了,然后可能一个线程每隔30秒发现ReadOnly缓存和ReadWrite缓存不一样,就同步一下,可能最后得两分钟左右消费者才能发现生产者已经挂了.

4.容量问题


Zookeeper和Eureka都不是和大规模的服务实例,
Zookeeper在服务上下线问题,要同时通知上千个机器,占用网络带宽非常大.
一般Zookeeper同时支撑1000个服务器就差不多了.

而Eureka也很难承受的住大量机器的心跳检测等等.









Ribbon




Feign


Feign是对一个接口打了一个注解,Feign一定会针对这个注解标注的接口生成动态代理,然后针对Feign的动态代理去调用它的方法的时候,此时会在底层生成Http协议格式的请求,底层的话,使用Http通讯的框架组件,比如说HttpClient,先得让Ribbon从Eureka的本地注册表缓存里面获取出来对方机器的列表,然后进行选择一台机器出来,接着针对那台机器发送http请求过去即可.

Zuul

配置一下不同的请求路径和服务的对应关系,你的请求到对应的网关,Zuul直接查找到匹配的服务,然后就直接把请求转发给那个服务的某台机器.