- 前言
- Eureka简介
- Eureka简单案例
- 代码版本
- 概况
- 新建项目的方式
- springcloud-eureka
- pom.xml
- springcloud-eureka-server
- pom.xml
- EurekaServerApplication
- application.yml
- springcloud-eureka-client-provider
- pom.xml
- application.yml
- EurekaClientProviderApplication
- UserController
- springcloud-eureka-client-consumer
- pom.xml
- application.xml
- EurekaClientConsumerApplication
- LoginController
- 演示效果
- Eureka的自我保护机制
- Eureka Server 集群
- 项目地址
Eureka简介对于一名Java开发而言,不停的学习技术是必须的,同时也需要有一些文档的积累。
于我而言,某项技术使用的少,很快就会遗忘。大概两三年,曾经学习过SpringCloud的相关知识,但缺乏实战,也没有文档资料的积累,早已忘记了大半。Spring官方推荐的组件也发生了不小的变动,比如zuul被gateway替代。
因此,重新学习一下,并形成资料文档是很有必要的。
与Dubbo+Zookeeper的RPC结构类似,Eureka在SpringCloud的中是一个⽤于服务注册和服务发现的组件。其中涉及到的三大角色为:注册中心、服务提供者、服务消费者。
三个角色间逻辑大致如下图
Eureka简单案例 代码版本上图只是一个简单的样例,经常都会存在客户端既是服务提供者又是服务消费者的情况
- jdk:11
- springboot:2.5.6
- springcloud:2020.0.4
此版本非硬性要求,可根据自己的需求改动,springboot、springcloud的版本对应关系可在spring官网查看
新建项目的方式为了演示Eureka的效果,需要建多个springboot。多个springboot之间可以相互独立,也可以用父子项目的结构,不影响效果。
此处使用的是父子项目结构,后续的SpringCloud学习篇章不再详细展示
- 使用Spring Initializr的方式,选择需要的组件(如Eureka Server),自动生成项目
- 使用Maven的方式,自行修改pom文件增加依赖
案例最终的层级效果如下图,非硬性要求,只是为了层级分明而已。
springcloud-eureka-server4.0.0 com.cloud springcloud-eureka 1.0-SNAPSHOT pom springcloud-eureka-server springcloud-eureka-client-provider springcloud-eureka-client-consumer SpringCloud学习样例 org.springframework.boot spring-boot-starter-parent 2.5.6 11 2020.0.4 org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import
结构如下
EurekaServerApplicationspringcloud-eureka com.cloud 1.0-SNAPSHOT 4.0.0 springcloud-eureka-server org.springframework.cloud spring-cloud-starter-netflix-eureka-server
如果是使用Maven生成的项目,可使用JBLSpringBootAppGen插件生成Application类、application.yml
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
application.yml
server: port: 10001
此时启动springboot,访问http://localhost:10001/,即可看到如下图的界面
此时application.yml还有一些eureka的相关参数未进行设置,此处说明一部分,其呈现的效果稍后再展示
application.yml如下
server:
port: 10001
spring:
application:
name: eureka-server # 在Eureka注册的服务名称
eureka:
client:
service-url:
# eureka的服务地址,如果是集群,需要指定其他eureka server的地址
defaultZone: http://127.0.0.1:10001/eureka
# 不注册服务
register-with-eureka: false
# 不拉取服务列表
fetch-registry: false
springcloud-eureka-client-provider
pom.xml若仅仅要看Eureka界面,无需额外新建模块,springcloud-eureka-client-provider、springcloud-eureka-client-consumer这两个模块只是为了简单演示服务调用。
可跳转至Eureka界面演示效果、Eureka的自我保护、Eureka集群
application.ymlspringcloud-eureka com.cloud 1.0-SNAPSHOT 4.0.0 springcloud-eureka-client-provider org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-web
server:
port: 10002
spring:
application:
name: eureka-client-provider # 在Eureka注册的服务名称
eureka:
client:
service-url:
# eureka的服务地址,如果是集群,需要指定其他eureka server的地址
defaultZone: http://127.0.0.1:10001/eureka
EurekaClientProviderApplication
@SpringBootApplication
// Eureka客户端
@EnableDiscoveryClient
public class EurekaClientProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientProviderApplication.class, args);
}
}
UserController
由于只作演示用,为避免重复造实体类User,或依赖公共子模块,使用Map类模拟为实体类
@RestController
@RequestMapping("user")
public class UserController {
@GetMapping("info/{id}")
public Map info(@PathVariable(name = "id") Long id) {
Map user = new HashMap<>();
user.put("id", id);
user.put("name", "用户" + id);
user.put("gender", id % 2 == 0 ? "男" : "女");
return user;
}
}
springcloud-eureka-client-consumer
pom.xml
application.xmlspringcloud-eureka com.cloud 1.0-SNAPSHOT 4.0.0 springcloud-eureka-client-consumer org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-web
server:
port: 10003
spring:
application:
name: eureka-client-consumer # 在Eureka注册的服务名称
eureka:
client:
service-url:
# eureka的服务地址,如果是集群,需要指定其他eureka server的地址
defaultZone: http://127.0.0.1:10001/eureka
EurekaClientConsumerApplication
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientConsumerApplication.class, args);
}
@Bean
@LoadBalanced // 用于负载均衡,下一节再详细说明
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
LoginController
@RestController
public class LoginController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("loginInfo/{id}")
public ResponseEntity info(@PathVariable(name = "id") Long id) {
// 使用eureka中注册的服务名称
String url = "http://eureka-client-provider/user/info/" + id;
Map user = restTemplate.getForObject(url, Map.class);
return ResponseEntity.ok(user);
}
}
演示效果
微服务有序启动后,可查看到如下界面
可以看到,只显示了EUREKA-CLIENT-CONSUMER、EUREKA-CLIENT-PROVIDER,没有EUREKA-SERVER。
这就是application.yml 文件中eureka.client.register-with-eureka属性的效果,默认为true,若设置为false,则不会将服务注册到Eureka中
此时调用消费者的接口http://localhost:10003/loginInfo/72,即可看到如下效果(显示效果受浏览器插件影响,如无插件,则为json格式的字符串)
Eureka界面有时候会显示如下红字提示信息
这是触发了Eureka的自我保护机制,该机制是针对网络异常波动的保护措施。如果再15分钟内超过85%的客户端节点都没有正常的心跳,那么就会认为客户端与服务端之间出现了网络故障,此时会出现以下几种情况:
- 服务端不再移除注册列表中因为长时间没收到心跳而过期的服务
- 服务端仍然能够接收新服务的注册和查询,但是不会同步到其他节点上,保证当前节点依然可用(Eureka集群,稍后演示)
- 当网络稳定时,关闭自我保护机制,将新的注册信息同步到其他节点
以下说明自我保护机制相关的配置说明:
eureka:
# 配置在Eureka客户端中
instance:
# 心跳间隔时间(默认为30秒)
lease-renewal-interval-in-seconds: 30
# 没收到心跳多长时间剔除(默认为90秒)
lease-expiration-duration-in-seconds: 90
# 配置在Eureka服务端中
server:
# 启动自我保护的比例(默认为0.85)
renewal-percent-threshold: 0.85
# 关闭自我保护机制(默认为打开)
enable-self-preservation: false
# 扫描失效服务的间隔时间(默认为60*1000ms)
eviction-interval-timer-in-ms: 1000
Eureka Server 集群开发过程中,微服务必然是经常重启的,此时自我保护机制就比较碍事,关闭自我保护机制,有利于看到服务信息的实时变动。
生产环境中不建议关闭保护机制。
上述案例中,Eureka Server是单体的,而在生产环境中,需要高可用,那么就可以通过集群实现高可用。
在 springcloud-eureka-server的application.yml中加入以下配置
---
spring:
config:
activate:
on-profile: peer1
server:
port: 20001
eureka:
instance:
hostname: peer1
client:
service-url:
defaultZone: http://peer1:20001/eureka,http://peer2:20002/eureka,http://peer3:20003/eureka
---
spring:
config:
activate:
on-profile: peer2
server:
port: 20002
eureka:
instance:
hostname: peer2
client:
service-url:
defaultZone: http://peer1:20001/eureka,http://peer2:20002/eureka,http://peer3:20003/eureka
---
spring:
config:
activate:
on-profile: peer3
server:
port: 20003
eureka:
instance:
hostname: peer3
client:
service-url:
defaultZone: http://peer1:20001/eureka,http://peer2:20002/eureka,http://peer3:20003/eureka
注意: 在yaml单⼀配置⽂件中,可⽤连续三个连字号(- - -)区分多个⽂件
为了在同一IP下正确演示集群效果,需修改C:WindowsSystem32driversetc下的hosts文件,在文件内容末位加入以下内容
# Eureka Server 127.0.0.1 peer1 127.0.0.1 peer2 127.0.0.1 peer3
springcloud-eureka-client-provider的application.yml修改为
server:
port: 10002
spring:
application:
name: eureka-client-provider # 在Eureka注册的服务名称
eureka:
client:
service-url:
defaultZone: http://peer1:20001/eureka # 为演示集群效果,只注册在其中一个Eureka Server中
需新增如下的启动配置,使其按照对应的profile配置启动,peer2、peer3类似
启动3个服务端,及1个客户端
可看到服务端http://peer1:20001/如下的界面效果
其他服务端http://peer2:20002/、http://peer3:20003/
由上图可见,EUREKA-CLIENT-PROVIDER服务只注册在peer1中,但由于集群效果,peer2,peer3中同样存在该服务的注册信息
如有需要,可查看SpringCloud组件使用样例



