20200523 尚硅谷2020最新版SpringCloud【笔记】1
尚硅谷2020最新版SpringCloud【笔记】1
2.从2.2.x和H版开始说起
技术 | 版本 |
---|---|
Spring Cloud | Hoxton.SR1 |
Spring Boot | 2.2.2.RELEASE |
Spring Cloud Alibaba | 2.1.0.RELEASE |
4.微服务架构编码构建
配置热部署Devtools
-
改 POM,添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
-
在父工程中添加 Maven 插件
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.2.2.RELEASE</version> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> </plugins> </build>
-
IDEA 设置
- File | Settings | Build, Execution, Deployment | Compiler 中,全部勾选
- 快捷键 Ctrl+Shift+Alt+/ -> 1.Registry... -> 勾选 compiler.automake.allow.when.app.running 和 actionSystem.assertFocusAccessFromEdt
-
重启 IDEA
开启 Run Dashboard
Services 视图中添加 Run Configuration Type,选择 Spring Boot
遵循原则
约定 > 配置 > 编码
创建父工程 Project
创建步骤:
- New Project
- 聚合总工程名字
- Maven选版本
- 工程名字
- 字符编码
- 注解生效激活
- java编译版本选8
- File Type过滤(可选)
父工程 POM
<?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>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>mycloud2020</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cloud-provider-payment8001</module>
...
</modules>
<!-- 统一管理jar包版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.2.RELEASE</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 注意其中的 packaging 标签值为 pom
创建 cloud-provider-payment8001 微服务提供者支付Module模块,即生产者
创建步骤:
- 建 module,名为 cloud-provider-payment8001
- 改 POM
- 写 YML
- 主启动类
- 业务类
创建 cloud-consumer-order80 微服务消费者订单Module模块,即
工程重构
创建 cloud-api-commons Module模块
-
将重复代码放入此模块
-
打包此模块,maven命令clean install
-
在其他模块中删除重复代码,添加此模块依赖
<dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency>
5.Eureka 服务注册与发现
定位
Eureka 类比物业公司,服务类比入驻企业
单机 Eureka 服务中心构建
-
建Module,cloud-eureka-server7001
-
改POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
-
写 YML
eureka: instance: hostname: localhost # eureka服务端的实例名字 client: register-with-eureka: false # 表示不向注册中心注册自己 fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务 # 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
-
主启动,添加
@EnableEurekaServer
业务模块配置 Eureka 客户端
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
改 YML
eureka: client: # 表示是否将自己注册进EurekaServer默认为true。 register-with-eureka: true # 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 fetchRegistry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
-
主启动类,添加注解
@EnableEurekaClient
集群 Eureka 服务中心构建
-
新建 cloud-eureka-server7002 模块
-
修改 hosts 文件
hosts 文件路径为
C:\Windows\System32\drivers\etc\hosts
127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com
-
改 YML
eureka: instance: hostname: eureka7001.com # eureka服务端的实例名字 client: register-with-eureka: false # 表示不向注册中心注册自己 fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务 service-url: # 7001 配置 7002,7002 配置7001 defaultZone: http://eureka7002.com:7002/eureka/
-
业务模块改 YML
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
生产者模块配置集群
-
复制生产者模块,cloud-provider-payment8002
-
注意 YML 配置中,应用名称保持一致
spring: application: name: cloud-payment-service
消费者模块配置负载均衡
-
修改配置类
@Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); }
-
修改 Controller
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE"; return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
-
测试负载均衡
actuator微服务信息完善
-
改 POM ,添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
主机名称:服务名称修改
eureka: instance: # 服务实例 ID instance-id: payment8001
-
访问信息有ip信息提示
eureka: instance: # 访问路径可以显示IP地址 prefer-ip-address: true
服务发现 Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
-
主启动类,添加注解
@EnableDiscoveryClient
-
业务代码
@Autowired private DiscoveryClient discoveryClient; @GetMapping("/discovery") public Object discovery() { List<String> services = discoveryClient.getServices(); for (String service : services) { log.info("service *** {}" + service); List<ServiceInstance> instances = discoveryClient.getInstances(service); for (ServiceInstance instance : instances) { log.error("instance *** {}", instance); } } return discoveryClient; }
Eureka自我保护
某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存
属于CAP里面的AP分支
禁止自我保护
-
Eureka 服务中心配置
eureka: server: enable-self-preservation: false # 关闭自我保护机制,保证不可用服务被及时踢除 eviction-interval-timer-in-ms: 2000
-
Eureka 客户端配置
eureka: instance: # Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒) lease-renewal-interval-in-seconds: 1 # Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务 lease-expiration-duration-in-seconds: 2
6.Zookeeper服务注册与发现
结论
服务在 Zookeeper 中创建的是临时节点,一旦服务停止,一段时间后,节点被 Zookeeper 删除。
SpringCloud整合Zookeeper代替Eureka
注册中心Zookeeper
-
启动 Zookeeper
-
在 Windows 服务中开启 VMware DHCP Service 和 VMware NAT Service
-
关闭虚拟机中的防火墙
systemctl stop firewalld.service
-
启动 Zookeeper
# 启动服务 ./zkServer.sh start # 验证状态 ./zkServer.sh status # 启动客户端 ./zkCli.sh
-
服务提供者
-
创建生产者服务
-
建 Module,cloud-provider-payment8004
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> </dependency>
如果启动时报错,可能是依赖的 ZooKeeper 的 jar 包与使用的 ZooKeeper 版本不一致,可以通过调整依赖解决:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> <!--先排除自带的zookeeper3.5.3--> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <!--添加zookeeper3.4.9版本--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> </dependency>
-
改 YML
#8004表示注册到zookeeper服务器的支付服务提供者端口号 server: port: 8004 #服务别名----注册zookeeper到注册中心名称 spring: application: name: cloud-provider-payment cloud: zookeeper: connect-string: 192.168.181.128:2181
-
主启动类,添加注解
@EnableDiscoveryClient
-
-
验证
- 启动无报错
- Zookeeper 客户端中查看,会产生新的节点
services
,services
下有cloud-provider-payment
节点
服务消费者
- 建 Module ,cloud-consumerzk-order80
- 改 POM,同上
- 改 YML,同上
- 主启动类,同上
- 测试
- Zookeeper 客户端中查看,
services
节点下有新的节点cloud-consumer-order
- Zookeeper 客户端中查看,
7.Consul服务注册与发现
Consul简介
功能
- 服务发现
提供HTTP和DNS两种发现方式 - 健康监测
支持多种协议,HTTP、TCP、Docker、Shell脚本定制化 - KV存储
key , Value的存储方式 - 多数据中心
Consul支持多数据中心 - 可视化Web界面
安装并运行Consul
-
下载 Windows 64位程序;
-
查看版本信息
.\consul.exe --version
-
使用开发模式启动
consul agent -dev
-
访问Consul的首页
http;//localhost:8500
服务提供者
-
建 Module,cloud-providerconsul-payment8006
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
-
改 YML
###服务端口号 server: port: 8006 spring: application: name: consul-provider-payment ####consul注册中心地址 cloud: consul: host: localhost port: 8500 discovery: #hostname: 127.0.0.1 service-name: ${spring.application.name}
-
主启动类,添加注解
@EnableDiscoveryClient
-
测试
- Consul 的图形化界面中出现新的 Service,consul-provider-payment
服务消费者
- 建 Module ,cloud-consumerconsul-order80
- 改 POM,同上
- 改 YML,同上
- 主启动类,同上
- 测试
- Consul 的图形化界面中出现新的 Service,cloud-consumer-order
三个注册中心异同点
组件名 | 语言 | CAP | 健康检查 | 对外暴露接口 | Spring Cloud 集成 |
---|---|---|---|---|---|
Eureka | Java | AP | 可配支持 | HTTP | 已集成 |
Consul | Go | CP | 支持 | HTTP/DNS | 已集成 |
ZooKeeper | Java | CP | 支持 | 客户端 | 已集成 |
8.Ribbon负载均衡服务调用
概述
是什么
客户端 负载均衡 的工具
主要功能是提供客户端的软件负载均衡算法和服务调用
Ribbon目前也进入维护模式,未来可以使用 Spring Cloud LoadBalancer 替代
能干吗
LB(负载均衡)
-
集中式LB
即在消费方和服务方之间使用独立的 LB 设施
例如 Nginx,Nginx 是服务器负载均衡,客户端所有请求都会交给 Nginx ,然后由 Nginx 实现转发请求。即负载均衡是由服务端实现的。
-
进程内LB
将 LB 逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后从这些地址中选择一个合适的服务器。
Ribbon 本地负载均衡,在调用微服务接口时,会在注册中心上获取注册信息服务列表之后缓存到 JVM 本地,从而在本地实现 RPC 远程服务调用技术。
负载均衡+RestTemplate调用
Ribbon负载均衡演示
总结:Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。
POM
spring-cloud-starter-netflix-eureka-client
依赖中自带了 spring-cloud-starter-netflix-ribbon
,所以无需手动引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
二说RestTemplate的使用
-
getForObject:返回对象
CommonResult commonResult = restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
-
getForEntity:返回 ResponseEntity
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
Ribbon核心组件IRule
com.netflix.loadbalancer.IRule
IRule:根据特定算法从服务列表中选取一个要访问的服务
com.netflix.loadbalancer.RoundRobinRule
轮询com.netflix.loadbalancer.RandomRule
随机com.netflix.loadbalancer.RetryRule
先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试WeightedResponseTimeRule
对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择BestAvailableRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务AvailabilityFilteringRule
先过滤掉故障实例,再选择并发较小的实例ZoneAvoidanceRule
默认规则,复合判断server所在区域的性能和server的可用性选择服务器
替换负载均衡算法
注意:算法的配置类不能位于包扫描范围内,需要独立出来。例如,启动类在包 com.atguigu.springcloud
下,算法的配置类就不能位于此包及其子包下,可以位于包 com.atguigu.myrule
下。
替换步骤:
-
新建配置类,
com.atguigu.myrule.MySelfRule
@Configuration public class MySelfRule { @Bean public IRule myRule() { return new RandomRule(); //定义为随机 } }
-
主启动类,配置
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration= MySelfRule.class)
9.OpenFeign服务接口调用
概述
Feign是一个声明式的web服务客户端,让编写web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可
OpenFeign 依赖 Ribbon,自带负载均衡功能
服务消费者使用 OpenFeign 步骤
-
建 Module,cloud-consumer-feign-order80
-
改 POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
改 YML
-
主启动类,添加注解
@EnableFeignClients
-
业务类,Feign 接口类
@Component @FeignClient(value = "CLOUD-PAYMENT-SERVICE") public interface PaymentFeignService { @GetMapping(value = "/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id); }
-
调用 Feign 接口类
@Resource private PaymentFeignService paymentFeignService; @GetMapping(value = "/consumer/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) { return paymentFeignService.getPaymentById(id); }
OpenFeign超时控制
改 YML:
#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间,默认为1s
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间,默认为1s
ConnectTimeout: 5000
OpenFeign日志打印功能
日志级别
级别 | 描述 |
---|---|
NONE | 默认,不显示任何日志 |
BASIC | 仅记录请求方法、URL、响应状态码及执行时间 |
HEADERS | 除了 BASIC 中定义的信息之外,还有请求和相应的头信息 |
FULL | 除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据 |
配置步骤
-
新建配置类
@Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
-
改 YML
logging: level: # feign日志以什么级别监控哪个接口 com.atguigu.springcloud.service.PaymentFeignService: debug