文章目录
SpringCloud介绍
Spring cloud是一个基于Spring Boot实现的服务治理工具包,在微服务架构中用于管理和协调服务的
微服务:是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着基本业务进行构建,并且能够被独立的部署到生成环境。
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
SpringCloud采用了英国伦敦地铁站的名称来命名,并且由地铁站名称字母A-Z依次类推的形式发布迭代版本。SpringCloud的发布内容积累到临界点或者一个重大BUG被解决后,会发布一个“service releases”版本,简称“SRX”版本。
SpringCloud和SpringBoot版本选择:https://spring.io/projects/spring-cloud#overview
更细致的版本对应:https://start.spring.io/actuator/info
访问的页面返回是json串,找个在线json工具转换一下就可以看到对应的版本,转换后的json有点长,下图只是截取的SpringCloud对应的SpringBoot的版本
SpringCloud各个组件功能:
可能看Spring官网都是英文看不懂或者看不明白,下面附上中文链接:https://www.bookstack.cn/read/spring-cloud-docs/docs-user-guide-eureka.md
关于Spring各种组件的停更/升级/替换:Spring Cloud其实就是一套规范,而Spring Cloud Netflix、Spring Cloud Alibaba才是SpringCloud规范的实现
Eureka(服务注册中心)
SpringCloud Eureka是SpringCloud Netflix服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。
Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是极为重要的,有了服务发现与注册,只需要使用服务标识符就可以访问到服务,而不需要修改服务调用的配置文件。功能类似于Dubbo的注册中心,比如Zookeeper。
Eureka既包含了服务端组件,也包含了客户端组件,并且服务端与客户端均采用java编写,所以Eureka主要适用于通过java实现的分布式系统,或是JVM兼容语言构建的系统。Eureka的服务端提供了较为完善的REST API,所以Eureka也支持将非java语言实现的服务纳入到Eureka服务治理体系中来,只需要其他语言平台自己实现Eureka的客户端程序。
Eureka包含两个组件:Eureka Server
和Eureka Client
。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)
Eureka在Spring官方已经停止更新了,但还可以使用,不过有许多可以替代Eureka的组件,比如Zookeeper、Consul、Nacos
EurekServer单机
pom依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
启动类:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer7001.class,args);
}
}
yml配置文件:
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #fasle表示自己就是服务注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url: #如果是集群这里写其他集群的地址,这里是单机写自己的地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
启动访问localhost:7001即可
EurekaClient注册单机EurekaServer
pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
启动类:
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
yml配置文件:
server:
port: 8001
spring:
application:
name: cloud-payment-service
eureka:
client:
register-with-eureka: true #表示是否将自己注册进EurekaSever,默认为true
fetch-registry: true #是否从EurekaServer抓取已有的注册信息,默认为true,单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
service-url: #注册进名字叫localhost端口为7001的EuerkaServer里
defaultZone: http://localhost:7001/eureka
instance:
instance-id: payment8001 #在EurekaClient上显示的Server名称
prefer-ip-address: true #点击EurekaClient上的服务名,访问显示ip
访问localhost:7001
EurekaServer集群搭建(三台)
三台机器大部分相同,下面只写不同的yml文件
第一台机器7001yml配置文件:
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #fasle表示自己就是服务注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url: #另外两台的地址
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
第二台机器7002yml配置文件:
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #fasle表示自己就是服务注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url: #另外两台的地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
第三台机器7003yml配置文件:
server:
port: 7003
eureka:
instance:
hostname: eureka7003.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #fasle表示自己就是服务注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url: #另外两台的地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
分别启动即可,结果如下图,这里是访问7001的截图:
服务发现 Discovery
1.在启动类上加@EnableDiscoveryClient注解
2.在Controller中加个测试方法
import org.springframework.cloud.client.discovery.DiscoveryClient;
@Autowired
private DiscoveryClient discoveryClient;//这里有两个DiscoveryClient,一个是Eureka下的一个是spring下的,这里导包小心导错
@GetMapping(value = "payment/discovery")
public Object discovery(){
//获取EurekaServer上都有哪些服务
List<String> services = discoveryClient.getServices();
for (String s : services) {
log.info("服务Server:"+s);
}
//CLOUD-PAYMENT-SERVICE:注册到Eureka上的Client服务名
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance : instances) {
log.info("服务名:"+instance.getServiceId()+";ip:"+instance.getHost()+";端口:"+instance.getPort()+";url:"+instance.getUri());
}
return this.discoveryClient;
}
EurekaServer如下:
Controller方法中输出结果如下:
Eureka自我保护机制
先回顾一下分布式环境中经常提及的一个东西 - CAP
C - consistency 强一致性
A - availability 可用性
P - partition tolerance 分区容错性
CAP核心理论:一个分布式系统不可能同时很好的满足一致性,可用性,和分区容错性三个需求
CA - 单点集群,满足一致性,可用性,通常在可拓展性上不太强大
CP - 满足一致性,分区容错性的系统,通常性能不是特别的高
AP - 满足可用性,分区容错性,通过对数据一致性要求低一些。
分布式系统考虑到集群的拓展,只能选择CP 或者 AP
Eureka在设计上遵循AP原则
回归话题:为什么产生 Eureka 自我保护机制
为了防止 EurkaClient 可以正常运行,但是EurkaServer 网络不通的情况下,EurkeServer 不会即刻 将 EurekaClient 服务剔除。
什么是自我保护模式
默认情况,如果EurekaServer 在一定时间内没有接收到某个微服务实例的心跳,EurkaServer会注销该实例(默认90秒)。但是当网络分区故障发生(延迟、卡顿、拥挤)时,微服务与 EurekaServer 之间无法正常通讯。以上行为可能变得非常危险了-- 因为微服务本身是健康的,此时不应该注销这个微服务。 Eureka 通过“自我保护模式” 来解决这个问题 – 当 EurekaServer 节点在短时间内丢失过多客户端时(可能发生了网络分我去故障),那么这个节点就会进入自我保护模式。
在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例。
它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。
综上,自我保护模式是一种应对网络异常的安全保护措施,它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的我服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让 Eureka 集群更加的稳健、稳定。
Eureka默认是开启自我保护机制的
EurekaServer端:
eureka.server.enable-self-preservation=true #false是关闭自我保护机制
eureka.server.eviction-interval-timer-in-ms=5000 #eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒
EurekaClient端:
eureka.client.registry-fetch-interval-seconds=5 #表示EurekaClient端向服务端(EurekaServer)发送心跳的时间间隔,单位为秒,默认30S
eureka.instance.lease-expiration-duration-in-seconds=15 #EurekaServer端在收到最后一次心跳后等待时间上限,单位为秒.默认90秒,超时将移除Client
eureka.instance.lease-renewal-interval-in-seconds=5 #每个多久主动心跳一次 单位为秒,默认30秒
Eureka停止更新:https://github.com/Netflix/eureka/wiki
Zookeeper服务注册中心(用的相对比较少)
pom依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<version>版本</version>
</dependency>
注意:依赖的版本不要比zookeeper的版本高,不然会报错
yml配置文件:
server:
port: 8003
spring:
application:
name: cloud-provider-payment #注册到zookeeper上的服务名称
cloud:
zookeeper:
connect-string: #zookeeper地址加端口号,多个用英文逗号分隔
#数据库连接配置和其他配置省略
启动类:
@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
public class paymentZk8003 {
public static void main(String[] args) {
SpringApplication.run(paymentZk8003.class,args);
}
}
此时启动Zookeeper和启动类 就可以看到Zookeeper下注册进的服务
zookeeper具备的服务节点是临时的
Consul
Consul 是一套开源的分布式发现和配置管理系统,由 HashiCorp 公司用 Go 语言开发,
提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以更具需要单独使用, 也可以一起使用构建全方位的服务网格总之 Consul 提供了一宗完整的服务网格解决方案。
它具有很多优点, 包括: 基于 raft 协议,比较简洁; 支持健康检查,同时支持 HTTP 和DNS 协议支持跨数据中心的WAN 集群 提供图形化界面,跨平台,支持 Linux 、Max 、Windows
Consul下载地址,安装步骤,与 spring-cloud 整合参考
Windows版单机搭建
Windows版下载后直接解压,只有一个exe文件
进入解压路径:cmd窗口查看consul版本:consul --version
开发模式运行consul:consul agent -dev 出现Consul agent running说明运行成功
访问localhost:8500
服务注册进单机Consul
pom依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
yml配置:
server:
port: 8004
spring:
application:
name: payment-service
#Consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
consul的其他一些配置
spring.cloud.consul.host:配置consul地址
spring.cloud.consul.port:配置consul端口
spring.cloud.consul.discovery.enabled:启用服务发现
spring.cloud.consul.discovery.register:启用服务注册
spring.cloud.consul.discovery.deregister:服务停止时取消注册
spring.cloud.consul.discovery.prefer-ip-address:表示注册时使用IP而不是hostname
spring.cloud.consul.discovery.health-check-interval:健康检查频率
spring.cloud.consul.discovery.health-check-path:健康检查路径
spring.cloud.consul.discovery.health-check-critical-timeout:健康检查失败多长时间后,取消注册
spring.cloud.consul.discovery.instance-id:服务注册标识
主启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class payment8004 {
public static void main(String[] args) {
SpringApplication.run(payment8004.class,args);
}
}
这样服务就注册进consul了
Eureka、Zookeeper、Consul的异同点
组件名 | 语言 | CAP | 服务健康检查 | 对外暴露接口 | SpringCloud集成 |
---|---|---|---|---|---|
Eureka | Java | AP | 可配支持 | HTTP | 已集成 |
Consul | Go | CP | 支持 | HTTP/DNS | 已集成 |
Zookeeper | Java | CP | 支持 | 客户端 | 已集成 |