今天我们说说Springcloud中的第一个组件——Eureka。
Eureka是什么? |
Eureka是微服务框架中负责完成服务治理的组件。简单来说,既然微服务中各服务之间是相互独立的,那他们如果想相互调用接口,就需要用到Eureka。
Eureka就相当于dubbo+zk。
其中,注册中心是Eureka的服务端,服务提供者和消费者是Eureka的客户端。下面我们就来看看Eureka的服务治理机制。
服务提供者 |
B服务(服务提供者)在启动的时候,会通过发送REST请求的方式将自己注册到Eureka Server(服务注册中心)上。注册中心收到这个REST请求之后,将相关信息存储在一个双层结构Map中,这个Map是服务名+具体服务的实例名。
服务名 | 位置 |
服务B | 192.168.0.100:8000、192.168.0.101:8000 |
服务D | 192.168.0.100:9000、192.168.0.101:9000、192.168.0.102:9000、 |
可以看到,B服务和D服务均为服务提供者,均为集群部署。B服务部署在100、101两台服务器上,它的端口号为8000。D服务部署在100、101、102三台服务器上,它的端口号为9000。
值得一提的是,我们可以在配置文件中修改如下参数来启动和关闭注册功能。
eureka.client.register-with-eureka=true
我们在图中也可以看到,不光是对服务提供者和消费者做了集群部署,对注册中心也做了集群部署。服务提供者将注册请求发送到其中一个注册中心时,此注册中心会将该请求转发给集群中的其它注册中心,从而实现服务同步。
服务同步的前提是注册中心之间已经相互注册为服务。
服务提供者会维护一个心跳来持续告诉注册中心:“我还活着”,这就叫服务续约。如下有两个参数需要我们注意:
eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=90
前者代表服务提供者每隔30s给注册中心发送一次心跳,后者表示如果90s内都没收到注册中心的心跳,就认为它死了,就会在注册清单中将其“剔除”。这两个时间是系统默认的,也可以根据实际情况进行修改。
服务消费者 |
服务消费者启动时,会发送一个REST请求给注册中心,注册中心会把服务清单发送过来。此服务清单对于服务消费者来说,是只读的,而且每隔30s更新一次。
开启获取服务功能:
eureka.client.fetch-registry=true
修改缓存清单的更新时间:
eureka.client.registry-fetch
服务消费者获取到服务清单后,会通过服务名来找到服务提供者的服务器地址。因为服务提供者是集群的形式,所以有多个服务器地址。默认是采用轮询的方式进行调用。
当服务消费者或提供者要关闭时,会发送一个服务下线的REST请求给注册中心,注册中心在收到请求后,会将该服务状态置为下线,并把该下线事件传播出去。
服务注册中心 |
前面我们讲服务续约的时候说过,如果超过90s没有发送心跳检测,会被注册中心剔除。注册中心在启动时,会创建一个定时任务,每隔一段时间(默认为60s)将当前清单中超时(默认为90s)没有续约的服务剔除出去。
为避免“自杀式剔除”,注册中心有自我保护机制。啥叫自杀式剔除?试想,如果因为网络不稳定,在90秒内注册清单上的服务都没有按时将心跳发送过来,那注册中心要把它们全部剔除吗?NO,注册中心才没有那么傻。
如果心跳失败的比例在15分钟之内高于了85%,注册中心就会将当前的实例注册信息保护起来,不再进行剔除。
进一步想,即使不再剔除,那消费者还是调用不成功呀,怎么办?这就涉及到了断路器等容错机制,日后再谈。
和zk的区别 |
(1)ZK更偏向于一致性,Eureka更偏向于高可用。
zk中有master和follower之分,而且当进入选举模式时,无法对外提供服务。Eureka是集群形式的,各服务器的地位相同,不会出现不可用的情况。
(2)Eureka有自我保护机制,ZK没有。
小结 |
(1)关于服务治理机制给大家画了个丑帅丑帅的图,可供参考:
(2)深层次想一个问题,我们知道,Eureka是为了各独立的服务之间的接口调用,那如果是服务内部各文件之间的接口调用呢,应该怎么调用?
答:有两种方式:直接new或者用Spring的IOC技术。服务内部之间的调用就相当于service层调dao层,在service层这样写即可:
①直接new的方式
UserDao userdao=new UserDao();
②用Spring的IOC技术
@Autowired
UserDao userdao;