0%

SpringCloud基础大全-服务注册中心

一、Eureka

1.1 概述

服务提供者越多就需要用到C/S架构来对服务消费者和服务提供者进行统一管理

服务消费者:可以通过eureka注册中心获取到服务提供者的信息,经过负载均衡选择后即可进行远程调用

服务注册中心:存放服务消费者和服务提供者的信息,并进行管理,注册中心也可以有多个

1.2 环境搭建

1.2.1 服务端

创建Maven项目作为Eureka服务注册中心(服务端),命名为cloud-eureka-server7001

pom文件依赖配置如下:

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
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>3.1.2</version>
</dependency>

<dependency>
<groupId>org.example</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>

yml配置如下:

1
2
3
4
5
6
7
8
9
10
11
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

主启动类中需要添加EnableEurekaServer注解如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.atguigu.springcloud;

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

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class,args);
}
}

1.2.2 客户端

客户端要做的就是将微服务注册进eureka中

以cloud-provider-payment8001工程为例,eureka依赖包导入如下:

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.1.2</version>
</dependency>

yml配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
eureka:
client:
register-with-eureka: true #false表示不向注册中心注册自己。
fetch-registry: true #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://localhost:7001/eureka/

spring:
application:
name: cloud-order-service #注册进eureka的服务名称

主启动类添加注解@EnableEurekaClient

1
2
3
4
5
6
7
8
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(OrderMain8080.class,args);
}

}

这些配置完成之后即可运行,并访问http://localhost:7001/,访问成功后就可以在页面中看到服务的注册信息

同理,其他服务的注册步骤也是一样的,导包->yml配置->主启动类注解

1.3 Eureka集群构建

如果Eureka注册中心只有一个,并且发生故障的话,会导致整个服务环境不可用,所以要构建Eureka集群

多个注册中心要满足规定:互相注册,相互守望。但对外是一个整体

注:负载均衡是对某一个微服务中的不同端口进行一种选择调用的机制,默认的是轮询,即在通过消费者端8080访问支付服务时会先访问某一端口,如8001,那么下次再进行访问时就会访问8002端口,依次循环下去

1.3.1 注册中心集群构建

  • 构建多个注册中心maven项目,取不同端口号,如7001、7002、7003
  • 修改yml配置,满足互相注册,相互守望的规则
1
2
3
4
5
6
7
8
9
10
11
server:
port: 7001 # 端口号为7001的注册中心
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称,集群要保证每个注册中心名字不同
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
# 互相注册,注意下面的地址端口
defaultZone: http://eureka7002.com:7002/eureka/
  • 同时微服务的yml配置也需要修改
1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 8001
servlet:
context-path: /

eureka:
client:
register-with-eureka: true #false表示不向注册中心注册自己。
fetch-registry: true #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
# 多个注册中心地址都要写上
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

1.3.2 微服务集群构建

  • 构建多个相同模块的微服务项目,取不同的端口号,如8001、8002、8003
  • 消费者端的RestTemplate服务调用地址修改为微服务的名称
1
2
3
4
5
6
7
8
9
10
11
@RestController
@Slf4j
public class OrderController {
// private static final String PAYMENT_URL = "http://localhost:8001";
private static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

@Resource
private RestTemplate restTemplate;

// ...
}
  • 在消费者端的配置类中,为RestTemplate添加负载均衡注解@LoadBalanced
1
2
3
4
5
6
7
8
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced // 为服务调用提供负载均衡的能力
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}

1.4 actuator微服务信息

打开eureka注册中心后,可以看到微服务的链接状态,可以通过修改yml来对链接信息进行修改

修改微服务的yml配置,如8001的yml配置如下:

1
2
3
4
eureka:
instance:
instance-id: payment8001
prefer-ip-address: true # 访问路径可以显示IP地址

修改完成后,访问地址可以显示ip信息,显示效果如下:

1.5 服务发现Discovery

服务发现可以通过Discovery对象来获取微服务的信息,如微服务名称、访问地址、端口等

以8001为例,先修改其controller

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
@RestController
@Slf4j
public class PaymentController {
// 注入DiscoveryClient用于获取微服务信息,注意DiscoveryClient导入的是Spring的包
@Resource
private DiscoveryClient discoveryClient;

// ...
// 微服务信息获取接口
@GetMapping("/payment/discovery")
public Object discovery(){
// 获取所有微服务名称,并打印到终端
List<String> services = discoveryClient.getServices();
for (String service: services) {
log.info(service);
}

// 获取支付微服务的所有主机信息,并打印到终端
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance:instances) {
log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
}

/*返回结果:
{"services":["cloud-payment-service","cloud-order-service"],"order":0}
*/
return this.discoveryClient;
}
}

再修改8001的启动类,添加注解@EnableDiscoveryClient,开启服务发现功能

1
2
3
4
5
6
7
8
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}

1.6 Eureka自我保护理论

Eureka自我保护:一旦某个微服务不可用了,Eureka会启动保护机制,将该微服务信息保留一段时间,默认是开启的,注册中心会有以下提示信息:

可以通过修改注册中心,比如7001的yml配置关闭Eureka自我保护

1
2
3
4
5
6
eureka:
server:
# 关闭Eureka自我保护机制
enable-self-preservation: false
# 让服务端每隔2秒扫描一次,是服务能尽快的剔除,单位为ms
eviction-interval-timer-in-ms: 2000

除此之外,每个客户端微服务都会定时向服务端注册中心发送心跳,类似物业费的概念,即续费服务。服务发送心跳的时间间隔也可以通过服务的yml进行配置,以8001服务的yml配置如下:

1
2
3
4
5
6
eureka:
instance:
# Eureka客户端向服务端发送心跳的时间间隔,单位为s(默认为30s)
lease-renewal-interval-in-seconds: 1
# Eureka服务端在收到最后一次心跳后等待时间上限,单位为s(默认为90s),超时将剔除服务
lease-expiration-duration-in-seconds: 2

1.7 注意

  • Eureka自发布2.x版本后就停止维护了
  • 后面会进入到其它服务注册架构的学习

二、Zookeeper

zookeeper需要先在Linux下进行安装,再在微服务中进行配置才能使用

2.1 安装

2.1.1 单机版

  • zookeeper下载地址
  • 通过tar命令解压后,需要做两件事情
    • 重命名文件夹为zk,进入conf文件夹,复制其中的zoo_sample.cfg为zoo_cfg
    • 修改zoo.cfg中的数据文件夹地址,最后就可以进入zk/bin中启动zookeeper了
  • zookeeper启动命令:./zkServer.sh start
  • zookeeper客户端启动命令:./zkCli.sh

2.1.2 集群版

2.2 微服务构建

2.2.1 服务提供者

  • 首先肯定需要创建maven工程,命名为cloud-provider-payment8004
  • 接着就是配置yml,如下所示
1
2
3
4
5
6
7
8
9
10
11
server:
port: 8004
servlet:
context-path: /

spring:
application:
name: cloud-payment-service
cloud:
zookeeper:
connect-string: 192.168.41.199:2181 #配置单机版的zookeeper服务器地址
  • 然后就是pom文件的配置
1
2
3
4
5
<!-- zookeeper依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
  • 启动类注意添加@EnableDiscoveryClient注解
  • 最后就是创建类,一个启动类和一个controller分别用于启动和测试
1
2
3
4
5
6
7
8
9
10
11
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverPort;

@RequestMapping(value = "/payment/zk")
public String paymentzk(){
return "springcloud with zookeeper:"+serverPort+"\t"+ UUID.randomUUID().toString();
}
}
  • 最后直接运行启动类,如果配置zookeeper的信息没有问题,就可以打开zookeeper客户端,输入ls /命令查看到对应的服务节点

2.2.2 临时与持久节点

三、Consul

3.1 安装

  • Consul下载地址:Consul官网下载
  • 解压安装包后,直接可以通过cmd运行
  • 开发模式启动:consul agent -dev
  • 服务管理地址:localhost:8500

3.2 配置

  • 和之前几个服务注册中心一样,新建一个maven模块cloud-providerconsul-payment

  • pom引入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
  • yml配置
1
2
3
4
5
6
7
8
9
server:
port: 8006

cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}

3.3 三个服务注册中心的区别

组件名 语言 CAP 服务健康检查 对外暴露接口
Eureka Java AP 可配支持 Http
Consul Go CP 支持 Http/DNS
Zookeeper Java CP 支持 客户端
  • C:Consistency强一致性
  • A:Availability可用性
  • P:Partition tolerance分区容错性