微服务因为一个项目就是一个功能的实现,所以对于整个体统来说,最重要的就是服务之间的通信,需要知道服务之间调用的通信地址,还需要对上线服务添加、下线服务的剔除,如果微服务较多的情况下,手工管理这些微服务是不现实的,这时候我们需要借助一个强大的工具帮我们实现这一功能 - Eureka,同类型的组件还有 zookeeper、consul等
Eureka包括注册于发现组件,简单说就是用来统一管理微服务的通信地址的组件,可以看成是一个系统的花名册,它包含了EurekaServer 服务端(也叫注册中心)和EurekaClient客户端两部分组成,EurekaServer是独立的服务,而EurekaClient需要集成到每个微服务中
微服务(EurekaClient)在启动的时候会向EurekaServer提交自己的服务信息(通信地址如:服务名、ip、端口等),在 EurekaServer会形成一个微服务的通信地址列表存储起来(形成服务花名册)
微服务(EurekaClient)会定期(RegistryFetchIntervalSeconds:默认30s)的从EurekaServer拉取一份微服务通信地址列表缓存到本地。当一个微服务在向另一个微服务发起调用的时候会根据目标服务的服务名找到其通信地址,然后基于HTTP协议向目标服务发起请求
微服务(EurekaClient)采用定时(LeaseRenewalIntervalInSeconds:默认30s)发送“心跳”请求向EurekaServer发请求进行服务续约,一种长链接状态,其实就是定时向 EurekaServer发请求报告自己的健康状况,告诉EurekaServer自己还活着,不要把自己从服务地址清单中剔除掉,那么当微服务(EurekaClient)宕机未向EurekaServer续约,或者续约请求超时,注册中心机会从服务地址清单中剔除该续约失败的服务
微服务(EurekaClient)关闭服务前向注册中心发送下线请求,注册中心(EurekaServer)接受到下线请求负责将该服务实例从注册列表剔除
下面会通过三个微服务来做演示
为了方便演示SpringCloud的各个组件,我这里采用多模块的方式搭建项目,所有的jar包交给父工程来管理,搭建好的项目结构如下:
<groupId>cn.itsourcegroupId>
<artifactId>springcloud-wlk-parentartifactId>
<version>1.0-SNAPSHOTversion>
<modules>
<module>server-eurekamodule>
<module>springcloud-user-server-1020module>
<module>springcloud-order-server-1030module>
modules>
在springcloud-wlk-parent父工程下面搭建好子工程server-eureka
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-wlk-parentartifactId>
<groupId>cn.itsourcegroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>server-eurekaartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
project>
注意:spring-cloud-starter-netflix-eureka-server作为EurekaServer端的基础依赖,但同时这个包也把EurekaClient端的以来也导入进来了,spring-boot-starter-web作为web服务的基础依赖是不可缺少的
@SpringBootApplication
@EnableEurekaServer //服务端标签
@EnableEurekaClient //客户端标签可以省略
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class, args);
}
}
server:
port: 1010 #端口
eureka:
instance:
hostname: localhost #主机名
client: #客户端配置
registerWithEureka: false #不需要向注册中心进行注册,因为自己本身就是注册中心
fetchRegistry: false #不需要向注册中心拉去注册表,因为自己本身就是注册中心
serviceUrl: #注册中心地址
# 下面的等价于http://localhost:1010/eureka/
defaultZone: http://${
eureka.instance.hostname}:${
server.port}/eureka/
server:
enable-self-preservation: false #关闭自我保护警告
注意:因为我们导入了spring-cloud-starter-netflix-eureka-server所以此时server-eureka即使服务端又是客户端,我们这里暂时把EurekaClient的功能屏蔽掉 ,即关闭它的服务注册和发现功能,让他做好EurekaServer该做的事情即可
启用server-eureka进行测试,浏览器访问 http://localhost:1010
默认情况下,当EurekaServer接收到服务续约的心跳失败比例在15分钟之内低于85%,EurekaServer会把这些服务保护起来,即不会把该服务从服务注册地址清单中剔除掉,但是在此种情况下有可能会出现服务下线,那么消费者就会拿到一个无效的服务,请求会失败,那我们需要对消费者服务做一些重试,或者熔断策略。
我们在配置文件中可以通过 server:enable-self-preservation: false #关闭自我保护警告
进行关闭,这样可以确保注册中心中不可用的实例被及时的剔除,但是不推荐(这里先关闭,方便后续演示)
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
导入EurekaClient基础依赖:spring-cloud-starter-netflix-eureka-client,导入web的基础依赖:spring-boot-starter-web
@SpringBootApplication
@EnableEurekaClient //开启Eureka客户端
public class UserServerApplication1020 {
public static void main(String[] args) {
SpringApplication.run(UserServerApplication1020.class);
}
}
#注册到EurekaServer
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/
instance:
prefer-ip-address: true #使用ip地址进行注册
instance-id: user-server:1020 #实例ID
spring:
application:
name: user-server-1020
server:
port: 1020
浏览器再次访问http://localhost:1010
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApplication1030 {
public static void main(String[] args) {
SpringApplication.run(OrderServerApplication1030.class);
}
}
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/
instance:
prefer-ip-address: true #使用ip地址进行注册
instance-id: order-server:1030 #实例ID
spring:
application:
name: order-server-1030
server:
port: 1030