# Spring Cloud(Kilburn 2022.0.2版本)系列教程(一) 服务注册与发现(eureka)
为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000 (opens new window)
小景哥哥是一个追求完美的人,所以纵观各位大神的
SpringCloud
教程,发现版本都比较低,所以出于对新技术的追求,特出此最新版本(Spring Cloud(Kilburn 2022.0.2版本)截止写此博客时)的教程,如有错误恳请大家批评指正,与大家共同学习、一起成长,万分感谢。
# 一、构建环境
Spring Cloud
的构建工具可以使用Maven
或Gradle
,但Maven
任然是主流。本文档所使用的开发环境如下:
环境参数 | 版本 |
---|---|
JDK | 17 |
Maven | 3.9.1 |
Spring Cloud | 4.0.2 |
IDE | idea2023.1 U |
OS | Windows11 专业版 |
Spring Cloud
相关模块
模块 | 说明 |
---|---|
Eureka | 服务注册中心,用于服务管理 |
Ribbon | 基于客户端的负载均衡组件 |
Hystrix | 容错框架,能够防止服务的雪崩效应 |
Feign | Web服务客户端,能够简化HTTP接口的调用 |
Zuul | API网关,提供路由转发、请求过滤等功能 |
Config | 分布式配置管理 |
Sleuth | 服务跟踪 |
Stream | 构建消息驱动的微服务应用程序的框架 |
Bus | 消息代理的集群消息总线 |
但Spring Cloud
主要有5大组件,分别为服务发现组件Eureka
、Feign
、Ribbon
、Zuul
、Hystrix
。但很多都弃用了,比如Ribbon等。
注:SpringCloud
版本说明
英文 | 中文 | boot大版本 | boot代表 |
---|---|---|---|
Angel | 安吉尔 | 1.2.X | 1.2.8 |
Brixton | 布里克斯顿 | 1.3.X | 1.3.8 |
Camden | 卡梅登 | 1.4.X | 1.4.2 |
Dalston | 达斯顿 | 1.5.X | 1.5.0 |
Edgware | 艾奇韦尔 | 1.5.X | 1.5.19 |
Finchley | 芬奇利 | 2.0.X | 2.0.8 |
Greenwich | 格林威治 | 2.1.X | 2.1.2 |
Hoxton | 霍克斯顿 | 2.2.X | 2.2.6 |
2020.0.6-aka Ilford | 埃福的 | 2.5.7 | 2.5.7 |
2021.0.6 Jubilee | 朱比利 | 2.6.x | 2.6.1 |
2022.0.0 Kilburn | 基尔伯恩 | 3.0.x | 3.0.5 |
# 二、微服务注册与发现
Spring Cloud
提供了很多服务发现组件,比如:Eureka
、Consul
、ZooKeeper
等。而Eureka
是Netflix
开源的服务发现组件,它包含Server和Client两部分。Eureka Server
提供服务发现的能力,每个微服务启动时,都会向Eureka Server
注册自己的信息(IP、端口、微服务名称等),Eureka Server
存储记录每个微服务的这些信息。Eureka Client
是用于简化与Eureka Server
交互的Java客户端。微服务启动后,会周期性地(默认30s)向Eureka Server
发送心跳以续约自己的可用时间。如果Eureka Server
在规定的时间内没有接收到微服务实例的心跳,Eureka Server
则会将该实例注销(默认90s)。
常见的注册中心
组件名 | 语言 | CAP | 一致性算法 | 服务健康检查 | 对外暴露接口 |
---|---|---|---|---|---|
Eureka | Java | AP | 无 | 可配支持 | HTTP |
Consul | Go | CP | Raft | 支持 | HTTP/DNS |
Zookeeper | Java | CP | Paxos | 支持 | 客户端 |
Nacos | Java | AP | Raft | 支持 | HTTP |
# 2.1 创建EurekaServer
在idea中,创建一个名称为eurekaServer
的Maven
工程。
pom.xml
文件增加Eureka
依赖
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cc.huerpu</groupId>
<artifactId>eurekaServer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eurekaServer</name>
<description>eurekaServer</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>netflix-candidates</id>
<name>Netflix Candidates</name>
<url>https://artifactory-oss.prod.netflix.net/artifactory/maven-oss-candidates</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
修改EurekaServerApplication
启动类,增加@EnableEurekaServer
注解。
package cc.huerpu.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
创建application.yml
文件
server:
port: 8761 # 端口号
spring:
application:
name: eurekaServer # Eureka名称
eureka:
instance:
prefer-ip-address: false
hostname: eurekaServer
client:
fetch-registry: false # 表示是否从EurekaServer获取注册信息,默认为true。因为本应用是一个单点的EurekaServer,不需要同步其他的EurekaServer节点的数据,因此设为false。
register-with-eureka: false # 是否将自己注册到EurekaServer,默认为true。由于当前应用就是EurekaServer,因此设为false。
service-url:
defaultZone: http://eurekaServer:8761/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
修改系统的hosts
,Windows10
的hosts
文件路径为:C:\Windows\System32\drivers\etc\hosts
。Linux
和macOS
的文件路径为/etc/hosts
。增加一行:127.0.0.1 eurekaServer
。
启动项目,并测试访问
点击idea的项目启动按钮,并访问http:localhost:8761
查看Eureka首页。
# 2.2 创建EurekaClient
,并让它注册到EurekaServer
上。
复制eurekaServer
项目,修改artifactId
为EurekaClient
。修改application.yml
文件,端口号为8000,应用名称为eurekaClient
。
server:
port: 8000 # 端口号
spring:
application:
name: eurekaClient # Eureka名称
info:
app:
name: eurekaClient
encoding: "UTF-8"
java:
source: "17"
target: "17"
company:
name: www.huerpu.cc
management:
info:
env:
enabled: true
endpoints:
web:
exposure:
include: "*"
enabled-by-default: true
eureka:
instance:
prefer-ip-address: false
hostname: eurekaClient
client:
healthcheck:
enabled: true
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eurekaServer:8761/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
修改启动类,增加@EnableDiscoveryClient
注解。
package cc.huerpu.eurekaclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
编写一个测试接口,最简单的那种就好。
@RestController
public class UserController {
@RequestMapping("/getUserById")
public String getUserById(){
return "{id:1,name:jason,age:23}";
}
}
2
3
4
5
6
7
8
9
10
修改pom.xml
文件,把几处地方改为eurekaClient
,另外增加了一个actuator包。
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cc.huerpu</groupId>
<artifactId>eurekaClient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eurekaClient</name>
<description>eurekaClient</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>netflix-candidates</id>
<name>Netflix Candidates</name>
<url>https://artifactory-oss.prod.netflix.net/artifactory/maven-oss-candidates</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
启动项目,刷新http://localhost:8761/
会看到EurekaClient
注册上来了。
# 2.3 创建EurekaServer
集群
一般来说,EurekaServer
不会仅仅只有一个节点,都是用集群来达到高可用的,所以接下来创建有两个节点的EurekaServer
集群,让这两个节点互相注册,从而保证EurekaServer
的高可用。
①修改系统的hosts
,Windows10
的hosts
文件路径为:C:\Windows\System32\drivers\etc\hosts
。Linux
和macOS
的文件路径为/etc/hosts
。
增加一行:127.0.0.1 eurekaServerHA
。
②复制EurekaServer
项目,修改artifactId
为EurekaServerHA
。
③修改EurekaServerHA
的application.yml
文件,修改端口号为8762,应用名为eurekaServer
,和EurekaServer
的一样,defaultZone
为http://eurekaServer:8761/eureka/
。fetch-registry
和register-with-eureka
都改为true
。增加hostname: eurekaServerHA
、prefer-ip-address: false
。
server:
port: 8762 # 端口号
spring:
application:
name: eurekaServer # Eureka名称
eureka:
instance:
prefer-ip-address: false
hostname: eurekaServerHA
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eurekaServer:8761/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
④修改EurekaServer
的application.yml
文件,修改defaultZone
为http://eurekaServerHA:8762/eureka/
。fetch-registry
和register-with-eureka
都改为true
。
server:
port: 8761 # 端口号
spring:
application:
name: eurekaServer # Eureka名称
eureka:
instance:
prefer-ip-address: false
hostname: eurekaServer
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eurekaServerHA:8762/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
⑤修改EurekaClient
的application.yml
文件,修改defaultZone
为http://eurekaServer:8761/eureka/,http://eurekaServerHA:8762/eureka/
。由此,两个节点的EurekaServer
将会进行互相注册。访问第一个节点http://eurekaServer:8761
,可以看到有eurekaServer:8761
和eurekaServer:8762
。
访问第二个节点http://eurekaServerHA:8762
,可以看到有eurekaServer:8761
和eurekaServer:8762
。至此,搭建具有两个节点的EurekaServer
完毕。
# 2.4 添加EurekaServer
用户认证
在实际应用中,资源的访问都是需要认证的,接下来我们把EurekaServer
、EurekaServerHA
改造为需要认证的服务。
EurekaServer
、EurekaServerHA
添加security
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2
3
4
修改EurekaServer
的application.yml
文件,增加security
认证,增加spring.security.user.name
和spring.security.user.password
。并修改defaultZone
为http://eurekaha:eurekapwd@eurekaServerHA:8762/eureka/
。
server:
port: 8761 # 端口号
spring:
security:
user:
name: eureka
password: eurekapwd
application:
name: eurekaServer # Eureka名称
eureka:
instance:
prefer-ip-address: false
hostname: eurekaServer
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eureka:eurekapwd@eurekaServerHA:8762/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
修改EurekaServerHA
的application.yml
文件,增加security
认证,增加spring.security.user.name
和spring.security.user.password
。并修改defaultZone
为http://eureka:eureka@eurekaServer:8761/eureka/
。
server:
port: 8762 # 端口号
spring:
security:
user:
name: eureka
password: eurekapwd
application:
name: eurekaServer # Eureka名称
eureka:
instance:
prefer-ip-address: false
hostname: eurekaServerHA
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eureka:eurekapwd@eurekaServer:8761/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
修改EurekaClient
的application.yml
文件,defaultZone
为http://eureka:eurekapwd@eurekaServer:8761/eureka/,http://eureka:eurekapwd@eurekaServerHA:8762/eureka/
。
server:
port: 8000 # 端口号
spring:
application:
name: eurekaClient # Eureka名称
info:
app:
name: eurekaClient
encoding: "UTF-8"
java:
source: "17"
target: "17"
company:
name: www.huerpu.cc
management:
info:
env:
enabled: true
endpoints:
web:
exposure:
include: "*"
enabled-by-default: true
eureka:
instance:
prefer-ip-address: false
hostname: eurekaClient
client:
healthcheck:
enabled: true
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eureka:eurekapwd@eurekaServer:8761/eureka/,http://eureka:eurekapwd@eurekaServerHA:8762/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
分别在EurekaClient
、EurekaClientHA
的cc.huerpu.eurekaserver.security
包路径下创建WebSecurityConfig
类,关闭csrf,并开启httpBasic认证。
package cc.huerpu.eurekaserver.security;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@AutoConfigureAfter(WebSecurityConfig.class)
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig
{
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeHttpRequests().anyRequest().authenticated().and().httpBasic();
return http.build();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
重新启动项目,访问时需要认证登录。
输入配置文件里的账号/密码:eureka/eurekapwd
进行登录。
如果你的没有注册上来,耐心等一分钟就可以了。
# 三、创建一个eurekaClientConsumer调用eurekaClient服务
复制eurekaClient
项目,修改artifactId
为eurekaClientConsumer
。修改application.yml
文件,端口号为8001,应用名称为eurekaClientConsumer
(本机host中也增加这一个)。
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cc.huerpu</groupId>
<artifactId>eurekaClientConsumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eurekaClientConsumer</name>
<description>eurekaClientConsumer</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>netflix-candidates</id>
<name>Netflix Candidates</name>
<url>https://artifactory-oss.prod.netflix.net/artifactory/maven-oss-candidates</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
application.yml
server:
port: 8001 # 端口号
spring:
application:
name: eurekaClientConsumer # Eureka名称
info:
app:
name: eurekaClientConsumer
encoding: "UTF-8"
java:
source: "17"
target: "17"
company:
name: www.huerpu.cc
management:
info:
env:
enabled: true
endpoints:
web:
exposure:
include: "*"
enabled-by-default: true
eureka:
instance:
prefer-ip-address: false
hostname: eurekaClientConsumer
client:
healthcheck:
enabled: true
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eureka:eurekapwd@eurekaServer:8761/eureka/,http://eureka:eurekapwd@eurekaServerHA:8762/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
修改启动类名称为EurekaClientConsumerApplication
,并增加注入一个restTemplate
。
package cc.huerpu.eurekaclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在controller
包下创建一个ConsumerController
类,注入restTemplate
、eurekaClient
、discoveryClient
。
package cc.huerpu.eurekaclient.controller;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private EurekaClient eurekaClient;
@Autowired
private DiscoveryClient discoveryClient;
//获得eurekaClient的url
@RequestMapping("/eurekaClientServiceUrl")
private String eurekaClientServiceUrl() {
InstanceInfo instance = eurekaClient.getNextServerFromEureka("eurekaClient", false);
return instance.getHomePageUrl();
}
@RequestMapping("/consumerEurekaClient")
public String consumerEurekaClient(){
String eurekaClientURL = eurekaClientServiceUrl();
String res = restTemplate.getForObject(eurekaClientURL + "/getUserById",String.class);
return "consumerEurekaClient:" + res;
}
@RequestMapping("/eurekaClient-instance")
public List<ServiceInstance> showInfo() {
return this.discoveryClient.getInstances("eurekaClient");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
在没有服务注册中心的时候,eurekaClientConsumer服务调用eurekaClient服务,需要在eurekaClientConsumer服务代码里显式通过硬编码IP地址和端口号进行调用,也可以通过@Value注入配置的方式进行配置,但被调用方方的IP和端口号变化之后,调用方就必须进行修改,针对千千万万的接口来说,维护这些信息简直是场噩梦。
@RestController
public class ConsumerController {
@RequestMapping("/consumerEurekaClient")
public String consumerEurekaClient(){
String res = restTemplate.getForObject("http://localhost:8000/getUserById", String.class);
return "consumerEurekaClient:" + res;
}
}
2
3
4
5
6
7
8
9
10
@RestController
public class ConsumerController {
//通过配置文件中的hep.eurekaclient.userservice.url值进行配置
@Value("${hep.eurekaclient.userservice.url}")
private String eurekaClient;
@RequestMapping("/consumerEurekaClient")
public String consumerEurekaClient(){
String res = restTemplate.getForObject("http://localhost:8000/getUserById", String.class);
return "consumerEurekaClient:" + res;
}
}
2
3
4
5
6
7
8
9
10
11
但现在我们通过eureka就没有这个烦恼啦,只需要eurekaClient.getNextServerFromEureka("eurekaClient", false)
,就可以获得服务的调用地址,其中"eurekaClient"
是由spring.application.name
指定的,即使被调用方的IP和端口号变化,对我们来说都是无感的,调用方这边完全不用做任何修改,是不是很开心?
访问http://eurekaclientconsumer:8001/consumerEurekaClient
,就可以得到consumerEurekaClient:{id:1,name:jason,age:23}
,证明我们的消费方consumerEurekaClient
调用被消费方eurekaClient
成功了。
# 四、Eureka 的元数据
Eureka 的元数据有两种,标准元数据和自定义元数据。标准元数据有主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。自定义元数据可以使用eureka.instance.metadata-map
配置。
可以通过http://localhost:8761/eureka/apps
来查看eureka
中有哪些应用。
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_4_</apps__hashcode>
<application>
<name>EUREKASERVER</name>
<instance>
<instanceId>192.168.1.97:eurekaServer:8761</instanceId>
<hostName>eurekaServer</hostName>
<app>EUREKASERVER</app>
<ipAddr>192.168.1.97</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8761</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>5</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1681976869304</registrationTimestamp>
<lastRenewalTimestamp>1681976869304</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1681976869305</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8761</management.port>
</metadata>
<homePageUrl>http://eurekaServer:8761/</homePageUrl>
<statusPageUrl>http://eurekaServer:8761/actuator/info</statusPageUrl>
<healthCheckUrl>http://eurekaServer:8761/actuator/health</healthCheckUrl>
<vipAddress>eurekaServer</vipAddress>
<secureVipAddress>eurekaServer</secureVipAddress>
<isCoordinatingDiscoveryServer>true</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1681976869305</lastUpdatedTimestamp>
<lastDirtyTimestamp>1681976839602</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
<instance>
<instanceId>192.168.1.97:eurekaServer:8762</instanceId>
<hostName>eurekaServerHA</hostName>
<app>EUREKASERVER</app>
<ipAddr>192.168.1.97</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8762</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>5</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1681976841173</registrationTimestamp>
<lastRenewalTimestamp>1681976977251</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1681976841173</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8762</management.port>
</metadata>
<homePageUrl>http://eurekaServerHA:8762/</homePageUrl>
<statusPageUrl>http://eurekaServerHA:8762/actuator/info</statusPageUrl>
<healthCheckUrl>http://eurekaServerHA:8762/actuator/health</healthCheckUrl>
<vipAddress>eurekaServer</vipAddress>
<secureVipAddress>eurekaServer</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1681976841173</lastUpdatedTimestamp>
<lastDirtyTimestamp>1681976841049</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
<application>
<name>EUREKACLIENT</name>
<instance>
<instanceId>192.168.1.97:eurekaClient:8000</instanceId>
<hostName>eurekaClient</hostName>
<app>EUREKACLIENT</app>
<ipAddr>192.168.1.97</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8000</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>5</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1681976840091</registrationTimestamp>
<lastRenewalTimestamp>1681976981077</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1681976840091</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8000</management.port>
</metadata>
<homePageUrl>http://eurekaClient:8000/</homePageUrl>
<statusPageUrl>http://eurekaClient:8000/actuator/info</statusPageUrl>
<healthCheckUrl>http://eurekaClient:8000/actuator/health</healthCheckUrl>
<vipAddress>eurekaClient</vipAddress>
<secureVipAddress>eurekaClient</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1681976840092</lastUpdatedTimestamp>
<lastDirtyTimestamp>1681976839916</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
<application>
<name>EUREKACLIENTCONSUMER</name>
<instance>
<instanceId>192.168.1.97:eurekaClientConsumer:8001</instanceId>
<hostName>eurekaClientConsumer</hostName>
<app>EUREKACLIENTCONSUMER</app>
<ipAddr>192.168.1.97</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">8001</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>5</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1681976869305</registrationTimestamp>
<lastRenewalTimestamp>1681976869305</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1681976869305</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8001</management.port>
</metadata>
<homePageUrl>http://eurekaClientConsumer:8001/</homePageUrl>
<statusPageUrl>http://eurekaClientConsumer:8001/actuator/info</statusPageUrl>
<healthCheckUrl>http://eurekaClientConsumer:8001/actuator/health</healthCheckUrl>
<vipAddress>eurekaClientConsumer</vipAddress>
<secureVipAddress>eurekaClientConsumer</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1681976869305</lastUpdatedTimestamp>
<lastDirtyTimestamp>1681976840542</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
我们在上面也有写了一个接口,用来获得eurekaClient服务
的相关实例。
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping("/eurekaClient-instance")
public List<ServiceInstance> showInfo() {
return this.discoveryClient.getInstances("eurekaClient");
}
2
3
4
5
6
7
<List>
<item>
<scheme>http</scheme>
<host>eurekaClient</host>
<port>8000</port>
<uri>http://eurekaClient:8000</uri>
<secure>false</secure>
<metadata>
<management.port>8000</management.port>
</metadata>
<serviceId>EUREKACLIENT</serviceId>
<instanceId>192.168.1.97:eurekaClient:8000</instanceId>
<instanceInfo>
<instanceId>192.168.1.97:eurekaClient:8000</instanceId>
<app>EUREKACLIENT</app>
<appGroupName/>
<ipAddr>192.168.1.97</ipAddr>
<sid>na</sid>
<homePageUrl>http://eurekaClient:8000/</homePageUrl>
<statusPageUrl>http://eurekaClient:8000/actuator/info</statusPageUrl>
<healthCheckUrl>http://eurekaClient:8000/actuator/health</healthCheckUrl>
<secureHealthCheckUrl/>
<vipAddress>eurekaClient</vipAddress>
<secureVipAddress>eurekaClient</secureVipAddress>
<countryId>1</countryId>
<dataCenterInfo _class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<hostName>eurekaClient</hostName>
<status>UP</status>
<overriddenStatus>UNKNOWN</overriddenStatus>
<leaseInfo>
<renewalIntervalInSecs>5</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1681976866110</registrationTimestamp>
<lastRenewalTimestamp>1681976866110</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1681976866110</serviceUpTimestamp>
</leaseInfo>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<metadata>
<management.port>8000</management.port>
</metadata>
<lastUpdatedTimestamp>1681976866110</lastUpdatedTimestamp>
<lastDirtyTimestamp>1681976839916</lastDirtyTimestamp>
<actionType>ADDED</actionType>
<asgName/>
</instanceInfo>
</item>
</List>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 五、Eureka的健康检查
在pom文件中引入Spring Boot Actuator,它提供了/health端点,该端点可展示应用程序的健康信息。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2
3
4
引入Actuator后,在Eureka中开启健康检查。
eureka:
client:
healthcheck:
enabled: true #开启健康检查(依赖spring-boot-actuator)
2
3
4
访问http://localhost:8761/actuator/health
可以查看Eureka的状态。
若出现下面红色警告,其实是Eureka
进入自我保护模式。如果最近一分钟实际接收到的心跳值Renews除以期望的心跳阈值Renews threshold
小于等于0.85
,即 Renews/Renews threshold≤0.85
。
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE
可以把renewal-percent-threshold
调的小一些
eureka:
server:
renewal-percent-threshold: 0.49
2
3
或者暴力一点关闭自我保护模式
# 默认值是true
eureka:
server:
enable-self-preservation: false
2
3
4
默认情况下,服务注册到Eureka Server
的过程较慢。在开发或测试时,常常希望能够加速这一过程,从而提升工作效率。
##默认是30,单位秒。设成一个更小的值,该配置用于设置Eureka Client向Eureka Server发送心跳的时间间隔
eureka:
instance:
lease-renewal-interval-in-seconds: 5
2
3
4
本文参考SpringCloud官方文档:
https://docs.spring.io/spring-cloud-netflix/docs/4.0.1/reference/html/
# 六、上传到gitlab
# 6.1 gitlab创建空项目
# 6.2 idea上传项目到gitlab
idea设置git
上传项目到本地git仓库
# 6.3 项目上传到远程gitlab服务器
把复制过来的gitlab仓库地址贴过来。我这里是外网访问家里的服务器,用了往外的域名地址。
在gitlab页面就可以看到项目上传过来了。
可以让小伙伴去拉取项目进行开发与共享了。
代码共享地址:
http://www.huerpu.cc:2080/root/springcloud
# 七、部署eurekaserver到ubuntu22.04服务器
每次都启动eureka的项目,太繁琐了,我们把eureka部署到Ubuntu,就可以愉快的玩耍了。
# 7.1 配置文件设置
准备了三台机器192.168.31.31
、192.168.31.32
、192.168.31.33
ubuntu22.04
。
在eurekaserver
项目,创建application-text.yml
文件,内容如下
server:
port: 8761 # 端口号
spring:
security:
user:
name: eureka
password: eurekapwd
application:
name: eurekaServer # Eureka名称
eureka:
server:
enable-self-preservation: true
instance:
prefer-ip-address: ture
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eureka:eurekapwd@192.168.31.32:8761/eureka/,http://eureka:eurekapwd@192.168.31.33:8761/eureka/
#defaultZone: http://eureka:eurekapwd@192.168.31.31:8761/eureka/,http://eureka:eurekapwd@192.168.31.33:8761/eureka/
#defaultZone: http://eureka:eurekapwd@192.168.31.31:8761/eureka/,http://eureka:eurekapwd@192.168.31.32:8761/eureka/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
192.168.31.31
向192.168.31.32
、192.168.31.33
注册192.168.31.32
向192.168.31.31
、192.168.31.33
注册192.168.31.33
向192.168.31.31
、192.168.31.32
注册
application.properties
中增加让test生效配置。
spring.profiles.active=test
# 7.2 生成eurekaserver的jar包
生成eurekaserver的jar包:
或者更简单的使用install去生成,生成完成控制台有日志输出显示,生成的目录在哪里。
# 7.3 ubuntu安装jdk17
sudo su -
apt update
apt upgrade -y
apt install openjdk-17-jdk
java -version
2
3
4
5
6
7
8
9
# 7.4 运行eurekaServer-0.0.1-SNAPSHOT.jar包
我们把eurekaServer-0.0.1-SNAPSHOT.jar
包 放在/usr/software
目录下,根据个人喜好目录存放即可。使用MobaXterm
等SSH工具上传即可。
cd /usr
#创建software文件夹,在此文件夹下有我们的eurekaServer-0.0.1-SNAPSHOT.jar包,可以通过上传工具上传过来
mkdir software
#赋予权限
chmod -R 777 software
#进入到software目录
cd software
#运行jar包
nohup java -jar eurekaServer-0.0.1-SNAPSHOT.jar > log.txt &
#开放8761端口
ufw allow 8761
ufw enable
2
3
4
5
6
7
8
9
10
11
12
13
14
# 7.5 验证eurekaserver服务
可以看到三台机器,两两相互注册了。
# 八、eureka相关说明
# 8.1 EurekaServer REST API接口
POST /eureka/apps/{appId} 注册新的实例
DELETE /eureka/apps/{appId}/{instanceId} 注销应用实例
PUT /eureka/apps/{appId}/{instanceId} 应用实例发送心跳
GET /eureka/apps 查询所有的实例
GET /eureka/apps/{appId} 查询指定appId的实例
GET /eureka/apps/{appId}/{instanceId} 查询指定appId和instanceId的实例
GET /eureka/instances/{instanceId} 查询指定的instanceId的实例
PUT /eureka/apps/{appId}/{instanceId}/status?value=OUT_OF_SERVICE 暂停应用实例
PUT /eureka/apps/{appId}/{instanceId}/status?value=UP 恢复应用实例
PUT /eureka/apps/{appId}/{instanceId}/metadata?key=value 更新元数据信息
GET /eureka/vips/{vipAddress} 根据vip地址查询
GET /eureka/svips/{svipAddress} 根据svip地址查询
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 8.2 Client端参数
eureka.client.register-with-eureka: true 是否注册自己到Eureka Server上面
eureka.client.fetch-registry: true 是否从Eureka Server上面拉取服务信息
eureka.client.enable: true 是否启用Eureka客户端,不启用则不注册到Eureka Server
eureka.client.healthcheck.enable: true 是否启用Eureka健康检查
eureka.client.availability-zones: new HashMap<>() 告诉client有哪些可用的region和zone
eureka.client.filter-only-up-instances: true 是否过滤出InstanceStatus为UP的实例
eureka.client.region: us-east-1 指定该应用实例所在的region,AWS datacenters适用
eureka.client.prefer-same-zone-eureka: true 是否优先使用与该应用相同Zone的Eureka Server
eureka.client.cache-refresh-executor-thread-pool-size: 2 缓存刷新线程池CacheRefreshThread的初始化线程数
eureka.client.registry-fetch-interval-seconds: 30 Eureka client拉取服务注册信息间隔时间(s)
eureka.client.instance-info-replication-interval-seconds: 30 复制实例变化信息到Eureka服务器所需要的时间间隔(s)
eureka.client.eureka-service-url-poll-interval-seconds: 300 轮询Eureka服务端地址更改的间隔时间(s)
eureka.client.eureka-server-read-timeout-seconds: 8 读取Eureka Server信息的超时时间(s)
eureka.client.eureka-server-connect-timeout-seconds: 5 连接Eureka Server的超时时间(s)
eureka.client.eureka-server-total-connections: 200 从Eureka客户端到所有Eureka服务端的连接总数
eureka.client.eureka-server-total-connections-per-host: 50 从Eureka客户端到每个Eureka服务端主机的连接总数
eureka.client.eureka-connection-idle-timeout-seconds: 30 Eureka服务端连接的空闲关闭时间(s)
eureka.instance.metadata-map: new HashMap<>() 指定应用实例的元数据信息
eureka.instance.prefer-ip-address: false 是否优先使用ip地址来替代hostname作为实例hostname字段值
eureka.instance.lease-expiration-duration-in-seconds: 90 Eureka clent最后一次心跳后,Eureka Server剔除需要等待时间(s)
eureka.instance.lease-renewal-interval-in-seconds: 30 客户端向Eureka Server发送心跳周期(s)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 8.3 Server端参数
eureka.server.enable-self-preservation: true Eureka Server是否开启自我保护模式
eureka.server.renewal-percent-threshold: 0.85 指定每分钟需要收到的续约次数的阙值,如果阈值比最小值大,则自我保护模式开启
eureka.server.eviction-interval-timer-in-ms: 60*1000 指定EvictionTask定时任务的调度频率,用于剔除过期的实例
eureka.server.wait-time-in-ms-when-sync-empty: 1000*60*5 在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间
2
3
4