SpringCloud | 第一篇:Eureka(Greenwich SR1)

Spring Cloud 为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理、服务发现、断路器、智能路由、微代理、控制总线)。分布式系统的协调导致了样板式的模式,使用Spring Cloud 开发人员可以快速地支持实现这些模式的服务和应用程序。

[TOC]

Eureka

服务发现是基于微服务的体系结构的关键原则之一。Eureka 是 Netflix 服务发现的服务器 Eureka Server 和客户端 Eureka Client。它支持通过 Eureka Server 的配置和部署实现高可用,每个 Server 都将注册服务的状态复制到其他 Server。

Eureka Server没有后端存储,所以注册表中的服务实例都必须以发送心跳的方式使其注册信息保持最新(这样的功能可以在内存中完成);默认情况下,Eureka 通过Client 心跳来确定 Client 是否启动的。Client的内存也有一部分是用来存放 Eureka 注册表 的缓存(因此他们不必每个对服务的请求都去注册中心)。

Eureka Server

Eureka Server 提供服务注册与发现,各个 client 启动后,会向 Eureka Server 注册自己的信息,Eureka Server注册表中将会存储所有可用服务节点的信息。

Eureka Client

Eureka Client 分为 服务供应商 和 服务消费者

Eureka High Availability

Eureka Server 通过运行多个相互注册的实例,可以变得更具弹性和可用性的。

你可以向系统添加多个 peer(对等点),而且,只要他们通过至少一个边彼此连接,它们就可以在彼此之间同步注册信息。如果peer(对等点)在物理上是分开的,那么,在原则上,这个系统可以在“宕(dàng)机”类型的故障中存活下来。您可以向一个系统中添加多个对等点,只要它们都直接连接在一起,它们就可以在彼此之间同步注册,从而实现高可用。

环境/版本一览:

  • 开发工具:Intellij IDEA 2018.3.2
  • springboot: 2.1.5.RELEASE
  • jdk:1.8.0_171
  • maven:3.3.9
  • springcloud:Greenwich.SR1

1. eureka-server(Standalone Mode)

创建一个子工程作为注册中心,需要选择的依赖如下:

Spring Cloud Discovery -> Eureka Server

1560160700879

pom.xml

创建完的 pom.xml 文件如下:

1
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
<?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 http://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>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.fatal</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server</name>
<description>Eureka Server(注册中心)</description>

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</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>${spring-cloud.version}</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>

</project>

application.yml

单机版测试下很多东西只需要选择默认即可。

1
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
server:
port: 8761

# eureka 配置
eureka:
# Eureka Server 的默认值看 EurekaServerConfigBean
server:
# 是否开启自我保护(生产环境建议修改为 true)
enable-self-preservation: false
# 清理间隔计时器(毫秒)默认值为 60 * 1000
# eviction-interval-timer-in-ms: 60000
# instance:
# hostname: localhost
# Eureka Client 的默认值看 EurekaClientConfigBean
client:
# 指定是否向` Eureka 服务器(由 defaultZone 配置,可以多个)`注册`本 Eureka 客户端`
#(单个 Eureka Server 没必要,设置为 false;`注册中心高可用配置`则必须设置为 true)
# 默认值为 true
register-with-eureka: false
# 表示此客户端是否应从 Eureka 服务器获取 Eureka 注册表信息。默认值为 true
# fetch-registry: true
# 表示从 Eureka 服务器获取注册表信息的频率(秒)。默认值为 30
registry-fetch-interval-seconds: 5
# service-url:
# defaultZone 在 `Eureka 服务器配置`中,一般用于高可用配置,Eureka 服务器之间相互注册。
#(Eureka Server 也是一个 Eureka Client,官网说的)
# defaultZone 是个Map。默认值为 http://localhost:8761/eureka
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka

注:生产环境建议 Eureka Server 开启自我保护

EurekaServerApplication.java

在启动类上添加@EnableEurekaServer开启 Eureka 服务器相关配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.fatal;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
// 开启 Eureka 服务器相关配置
@EnableEurekaServer
public class EurekaServerApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}

}

2. eureka-client

创建一个子工程作为服务提供者,需要 引入的依赖如下:

Web -> Spring Web Start

Spring Cloud Discovery -> Eureka Discovery Client

1560161210458

pom.xml

创建完的 pom.xml 文件如下:

1
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
<?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 http://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>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.fatal</groupId>
<artifactId>eureka-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-client</name>
<description>Eureka Client</description>

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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>${spring-cloud.version}</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>

</project>

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
application:
name: eureka-client

# eureka 配置
eureka:
instance:
hostname: fatal
# 该属性用在 Client 端,设置为 true,则表示使用IP向注册中心注册;否则使用主机名注册
prefer-ip-address: true
client:
service-url:
defaultZone: http://localhost:8761/eureka
# defaultZone: http://192.168.0.107:8761/eureka

注:defaultZone 指定注册的 Eureka 服务器 URL

EurekaClientApplication.java

在启动类上添加@EnableEurekaClient开启 Eureka 服务器相关配置。

1
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
package com.fatal;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* 注册中心是eureka,那么就推荐@EnableEurekaClient;
* 如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。
*/
@SpringBootApplication
// 开启发现 Eureka 客户端相关配置
@EnableEurekaClient
@RestController
public class EurekaClientApplication {

@RequestMapping("/client")
public String client() {
return "this is eureka client";
}

public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}

}

注:注册中心是eureka,那么就推荐@EnableEurekaClient;如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

3. eureka-high-availability-server

创建一个子工程作为 Eureka Server 来测试 高可用

pom.xml 和 EurekaHighAvailabilityServerApplication.java 参考上面的 eureka-server(Standalone Mode)。唯一有区别的就是 application.yml

pom.xml

和上面 eureka-server 一样的

application.yml

1
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
########################       Eureka Server 高可用      ########################


######################## Eureka 本地测试 ########################

spring:
profiles:
active: peer1
application:
name: eureka-server
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/, http://peer2:8762/eureka/, http://peer3:8763/eureka/


---

server:
port: 8761
spring:
profiles: peer1
eureka:
instance:
hostname: peer1

---

server:
port: 8762
spring:
profiles: peer2
eureka:
instance:
hostname: peer2

---

server:
port: 8763
spring:
profiles: peer3
eureka:
instance:
hostname: peer3

######################## Eureka 本地测试(end) ########################



######################## Eureka 模拟生产测试 ########################

#server:
# port: 8761
#
#spring:
# application:
# name: eureka-server
#
#eureka:
# instance:
# prefer-ip-address: true
# client:
# serviceUrl:
# defaultZone: http://192.168.0.107:8761/eureka/, http://192.168.0.108:8761/eureka/, http://192.168.0.109:8761/eureka/

######################## Eureka 模拟生产测试(end) ########################

注:在 Eureka 高可用配置中,如果本地测试的话,defaultZone 上的 URL 不允许出现 ip,只能使用域名,否则都会出现在 unavailable-replicas (不可用的副本)上。这里 defaultZone 的值中出现的 peer1、peer2、peer3 指的是域名(当然,本地测试需要你自己去 hosts 文件中设置映射)。

EurekaHighAvailabilityServerApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.fatal;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
// 开启 Eureka 服务器相关配置
@EnableEurekaServer
public class EurekaHighAvailabilityServerApplication {

public static void main(String[] args) {
SpringApplication.run(EurekaHighAvailabilityServerApplication.class, args);
}

}

4. 测试

4.1. Eureka 服务注册与发现

4.1.1. step

首先启动 eureka-server

然后启动 eureka-client

浏览器上访问 http://localhost:8761/ ,可以看到结果如下:

1560218715224

4.1.2. 测试 prefer-ip-address

应用程序使用eureka注册,它使用的是其 IP 地址,而不是其主机名。所以 Eureka Client 的 prefer-ip-address 建议为 true

点击访问Instances currently registered with Eureka上的 EUREKA-CLIENT 服务

1560219026109

true

使用IP向注册中心注册(推荐)

你可以看到访问该服务的 URL 上显示的是 IP 地址

1560219713962

false

使用主机名向注册中心注册

你可以看到访问该服务的 URL 上显示的是主机名

1560219828218

4.2. Eureka 高可用

4.2.1. Eureka 本地测试(defaultZone 使用域名)

4.2.1.1. step
  1. 打开 application.yml 中 Eureka 本地测试 的注释,同时关闭 Eureka 模拟生产测试的注释

  2. 在操作栏上选择 Edit Configurations

    1560185087148

  3. 选中左侧框中的 EurekaHighAvailabilityServerApplication,点击两次上方的复制图标

  4. 将三个 EurekaHighAvailabilityServerApplication 分别修改为 EurekaHighAvailabilityServerApplication 1,EurekaHighAvailabilityServerApplication 2,EurekaHighAvailabilityServerApplication 3,点击 OK

    1560185179454

  5. 选中操作栏 EurekaHighAvailabilityServerApplication 1 ,对应设置 application.yml 文件上的 spring.profiles.active 的值为 peer1,然后启动;再以这种方式启动 2 和 3 的即可。

    1
    2
    3
    // EurekaHighAvailabilityServerApplication 1	->	peer1
    // EurekaHighAvailabilityServerApplication 2 -> peer2
    // EurekaHighAvailabilityServerApplication 3 -> peer3
  6. 配置 hosts 。路径:C:\Windows\System32\drivers\etc

    1
    2
    3
    127.0.0.1 peer1
    127.0.0.1 peer2
    127.0.0.1 peer3
4.2.1.2. show

访问 http://localhost:8761/

1560212843320

访问 http://localhost:8762/

1560212863974

访问 http://localhost:8763/

1560212880992

4.2.1.3. 测试同步

eureka-client配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
application:
name: eureka-client

# eureka 配置
eureka:
instance:
# 该属性用在 Client 端,设置为 true,则表示使用IP向注册中心注册;否则使用主机名注册
prefer-ip-address: true
client:
service-url:
defaultZone: http://localhost:8761/eureka
# defaultZone: http://192.168.0.107:8761/eureka

启动 eureka-client,只向 http://localhost:8761/eureka 注册服务

在 8761,8762,8763 端口上的注册中心我们都可以看到 Instances currently registered with Eureka 多了个 Application: EUREKA-CLIENT。三个注册中心可以在彼此之间同步注册信息,所以 Eureka 高可用实现了~~

结果如下:

访问 http://localhost:8762/

1560213952271

访问 http://localhost:8762/

1560214043790

访问 http://localhost:8763/

1560213986803

4.2.2. Eureka 模拟生产测试(defaultZone 使用 IP)

4.2.2.1. step
  1. 打开 application.yml 中 Eureka 模拟生产测试 的注释,同时关闭 Eureka本地测试的注释
  2. 启动了三台虚拟机,地址分别是 192.168.0.107,192.168.0.108,192.168.0.109。将虚拟机的的8761端口对外开放(/sbin/iptables -I INPUT -p tcp --dport 8761 -j ACCEPT)。
  3. 在 IDEA中,选择下方菜单栏的 Terminal,进入eureka-high-availability-server根目录下,输入 mvn package打包,分别部署即可到三台虚拟机即可。
4.2.2.2. show

访问 http://192.168.0.107:8761/

1560266351071

访问 http://192.168.0.108:8761/

1560266383536

访问 http://192.168.0.109:8761/

1560266429514

4.2.2.3. 测试同步

eureka-client配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
application:
name: eureka-client

# eureka 配置
eureka:
instance:
# 该属性用在 Client 端,设置为 true,则表示使用IP向注册中心注册;否则使用主机名注册
prefer-ip-address: true
client:
service-url:
# defaultZone: http://localhost:8761/eureka
defaultZone: http://192.168.0.107:8761/eureka

启动 eureka-client

在192.168.0.107,192.168.0.108,192.168.0.109上的注册中心我们都可以看到 Instances currently registered with Eureka 多了个 Application: EUREKA-CLIENT。三个注册中心可以在彼此之间同步注册信息,所以 Eureka 高可用实现了~~

结果如下:

访问 http://192.168.0.107:8761/

1560266970045

访问 http://192.168.0.108:8761/

1560266987893

访问 http://192.168.0.109:8761/

1560267006461

笔记

  1. eureka.instance.prefer-ip-address: true 在 Client 端使用时,表示使用IP向注册中心注册;在 Server 端使用(一般用于生产环境高可用场景),表示 注册中心 作为客户端时,使用IP向其它注册中心注册
  1. 如果你的 Instances currently registered with Eureka 上 Status 中,服务实例名前缀如果是 localhost,而不是主机名(也叫实例名, instance-id,没设置的话自动生成的),像下图

    1565859773347

    那么你可以选择 Reimport All Maven Projects,反正我重新引入之后就正常了

参考资料

Spring Cloud (Greenwich.SR1)

  • 12.5 Peer Awareness

一起来学Spring Cloud(F版) | 第一篇:认识Eureka

SpringCloud教程第1篇:Eureka(F版本)

总结

SpringCloud的知识已经有前辈在我们之前探索了。比较喜欢的博主有:唐亚峰 | Battcn、方志朋的专栏、程序猿DD、纯洁的微笑。对这门技术感兴趣的可以去他们的博客逛逛。谢谢他们的分享~~

以上文章是我用来学习的Demo,都是基于 SpringCloud(Greenwich.SR1) 版本。

源码地址: https://github.com/ynfatal/springcloud-learning/tree/master/chapter1

学习 唐亚峰、方志朋 前辈的经验