java - SpringCloud从0-1基础教学
一、概念讲解
1.1微服务
把一个大型的单一应用程序,拆分成一组小而独立的服务,每个服务都围绕特定的业务功能运行,可以独立开发、部署和扩展。(单一职责、独立自治、轻量级通信、技术多样性)
举例:将银行系统划分为:客服部、接待部、管理部、安保部等各个部门,各自负责各自的业务,协同完成银行工作。
1.2分布式概念
分布式系统是多台计算机(节点)通过网络连接,协同工作,共同完成一个任务的系统。对用户来说,它就像一个统一的整体。
举例:将银行分为多个分部,可以在北京存款甘肃取款。
1.2.1集群
集群就是将多台计算机(服务器)组合起来,共同完成同一项任务,对外如同一台机器。(分布式中的每一个节点,都可以做集群。 而集群并不一定就是分布式的。)
1.2.2服务之间的交互方式
RPC:Netty(Socket)+自定义序列化
RestAPI:HTTP+JSON(springCloud交互方式)
1.3微服务架构
Spring Cloud 是一套用于快速构建微服务架构的“工具箱”或“全家桶”。(而 微服务架构 本身是一种 分布式系统。)
1.4.spring cloud相关组件
- 注册中心:Eureka
- 负载均衡:Ribbon
- 声明式调用远程方法:OpenFeign(包含ribbon)
- 熔断、降级、监控:Hystrix
- 网关:Gateway
- 链路跟踪:Sleuth
- 服务注册和配置中心:Spring Cloud Alibaba Nacos
- 熔断、降级、限流:Spring Cloud Alibaba Sentinel
二、基础服务搭建示例(。。。。。。该示例由:父工程(规定依赖版本) + 子工程())
服务层级:父工程(规定依赖版本) + 子工程(引入父工程)
服务链路:公共服务 + 服务提供者(含mysql) + 服务调用者(使用restTemplate进行交互(原理-HTTP+JSON格式))
业务链路:用户 -> 页面 -> 调用order-cloud服务 -> 调用pay-cloud服务 -> 数据库
2.1 父工程搭建(demo-cloud)
2.1.1创建新maven项目
2.1.2字符编码设置
2.1.3注解生效激活
2.1.4pom文件
⚠️注意dependencyManagement(仅规定版本)和dependencies(实际引入)区别!!!!
<?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.demo.cloud</groupId>
<artifactId>demo-cloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>pay-cloud</module>
<module>order-cloud</module>
<module>api-cloud</module>
<module>eureka-cloud</module>
<module>order-feign-cloud</module>
</modules>
<!-- pom代表是父类pom文件 -->
<packaging>pom</packaging>
<!-- 统一管理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>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!-- dependencyManagement:仅规定版本,不实际引入jar,子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version -->
<!-- dependency:实际引入jar -->
<dependencyManagement>
<dependencies>
<!-- springBoot核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springCloud核心依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springCloud Alibaba核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Mysql JDBC驱动 -->
<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>
<!-- mybatis依赖 -->
<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>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.1.5install工程
2.2 公共服务搭建(api-cloud)
2.2.1 创建子Modlue(仅输入名称即可)
2.2.2 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">
<parent>
<artifactId>demo-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-cloud</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- 热加载工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- java工具类库 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</project>
2.2.3创建公共实体bean
⚠️注意:使用方服务的文件夹路径(com.ai.springcloud)需要和api的保持一致,否则扫描不到!!!

2.2.4install工程
2.3服务提供者搭建(pay-cloud,面向接口编程)
2.3.1服务架构总览
⚠️注意:1. 前置路径通api-cloud保持一致(com.ai.springcloud)
2.mapper:mapper文件同yml中配置的路径一致 
2.3.2创建子项目(同上)
2.3.3pom文件
⚠️注意:引入公共服务api-cloud!!!
<?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">
<parent>
<artifactId>demo-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pay-cloud</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- web项目启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 应用监控和管理(监控检查等) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- Mysql JDBC驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- spring JDBC,提供事务等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 热部署工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试类启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<!-- 引入公共API文件jar -->
<dependency>
<artifactId>api-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
2.3.4yml配置文件(主义mysql相关配置和特殊文件指定扫描路径)
server:
port: 8081
spring:
application:
name: pay-cloud
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: cb19980702
mybatis:
mapperLocations: classpath:/mapper/*.xml # mapper映射文件存放位置
type-aliases-package: com.ai.springcloud.entities # 实体 bean文件存放位置
2.3.5创建启动类
package com.ai.springcloud;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@MapperScan("com.ai.springcloud.dao")
public class PayMentMain {
public static void main(String[] args) {
SpringApplication.run(PayMentMain.class, args);
}
}
2.3.6创建dao层
package com.ai.springcloud.dao;
import com.ai.springcloud.entities.PayMent;
import org.apache.ibatis.annotations.Param;
public interface PayMentDao {
int create(PayMent payMent);
PayMent getPaymentById(@Param("id") Long id);
}
2.3.7创建service层
package com.ai.springcloud.service;
import com.ai.springcloud.entities.PayMent;
public interface PayMentService {
int create(PayMent payMent); //写
PayMent getPaymentById(Long id); //读取
}
2.3.8创建imp实现(面向接口编程)
⚠️注意:此处Autowired爆红是因为MapperScan是运行时扫描的,而Mapper是编译时扫描,所以如果在PayMentDao加Mapper注解就不会爆红,在启动类加MapperScan就会爆红。!!!
package com.ai.springcloud.service.impl;
import com.ai.springcloud.dao.PayMentDao;
import com.ai.springcloud.entities.PayMent;
import com.ai.springcloud.service.PayMentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PayMentServiceImpl implements PayMentService {
// 用Autowired爆红是因为MapperScan是运行时扫描的,而Mapper是编译时扫描,所以如果在PayMentDao加Mapper注解就不会爆红,在启动类加MapperScan就会爆红
// @Autowired
@Resource
private PayMentDao payMentDao;
@Override
public int create(PayMent payment){
return payMentDao.create(payment);
}
@Override
public PayMent getPaymentById( Long id){
return payMentDao.getPaymentById(id);
}
}
2.3.9创建mapper映射文件
⚠️注意:<mapper namespace="com.ai.springcloud.dao.PayMentDao">,需要配置dao文件路径进行扫描!!!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ai.springcloud.dao.PayMentDao">
<insert id="create" >
insert into payment(serial) values(#{serial});
</insert>
<select id="getPaymentById" parameterType="Long" resultType="com.ai.springcloud.entities.PayMent">
select * from payment where id=#{id}
</select>
</mapper>
2.3.10创建controller层
package com.ai.springcloud.controller;
import com.ai.springcloud.entities.CommonResult;
import com.ai.springcloud.entities.PayMent;
import com.ai.springcloud.service.PayMentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.alibaba.fastjson.JSON;
@RestController
@Slf4j
public class PayMentController {
@Autowired
private PayMentService payMentService;
@PostMapping(value = "/payment/create")
public CommonResult<Integer> create(@RequestBody PayMent payMent){
log.info("请求参数payMent:{}", JSON.toJSONString(payMent));
int result = payMentService.create(payMent);
log.info("*****插入结果:"+result);
if (result>0){ //成功
return new CommonResult(200,"插入数据库成功",result);
}else {
return new CommonResult(444,"插入数据库失败",null);
}
}
@GetMapping(value = "/payment/get/{id}")
// @PathVariable 从路径中获取参数
public CommonResult<PayMent> getPaymentById(@PathVariable("id") Long id){
PayMent payMent = payMentService.getPaymentById(id);
log.info("*****查询结果:"+payMent);
if (payMent!=null){ //说明有数据,能查询成功
return new CommonResult(200,"查询成功",payMent);
}else {
return new CommonResult(444,"没有对应记录,查询ID:"+id,null);
}
}
}
2.3.11install工程
2.3.12创建mysql表并进行服务接口测试
2.4restTemplate
2.4.1介绍
spring提供的一种包含多种便捷访问远程Http服务的方法,也属于Restful方式,即HTTP+JSON。
2.4.2使用方式
1.创建配置类
2.注入restTemplate后调用相关方法实现http服务调用(具体查看2.4.6、2.4.7)
2.5服务调用者搭建(order-cloud)
2.5.1服务架构总览
2.5.2创建子项目(同上)
2.5.3pom文件
⚠️注意:引入公共服务api-cloud!!!
<?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">
<parent>
<artifactId>demo-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-cloud</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- web项目启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 应用监控和管理(监控检查等) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 热部署工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 引入公共API文件jar -->
<dependency>
<artifactId>api-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
2.5.4yml配置文件(注意mysql相关配置和特殊文件指定扫描路径)
server:
port: 8080
spring:
application:
name: order-cloud
2.5.5创建启动类
package com.ai.springcloud;
import com.ai.ribbon.RibbonConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
2.5.6创建restTemplate配置类
package com.ai.springcloud.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootConfiguration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
2.5.7创建controller层
package com.ai.springcloud.controller;
import com.ai.springcloud.entities .CommonResult;
import com.ai.springcloud.entities.PayMent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class OrderController {
public static final String PAYMENT_URL = "http://localhost:8081";
@Resource
private RestTemplate restTemplate; // Spring所有,典型的RestFull风格,由HTTP+JSON组成,且使用RestTemplate则不需要实现序列化,但最好加上,避免后续使用redis等
@PostMapping("/consumer/payment/create")
public CommonResult<Integer> create(@RequestBody PayMent payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class); //写操作
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<PayMent> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
}
2.5.8install工程
2.5.9服务接口测试
三、Euerka介绍及集成
3.1介绍
Eureka是服务注册中心,采用了CS的设计架构。(检测服务心跳,便于监控和运维)
3.2两大组件
Eureka Server:服务端,提供服务的注册能力
Eureka Client:客户端,服务通过客户端进行注册
3.3示例(改造pay-cloud及order-cloud服务)
3.3.1 综述
搭建euerka注册中心服务端 -> pom文件添加euerka依赖 -> yml增加euerka配置 -> 启动类添加euerka启动注解 -> 重启服务,打开注册中心进行测试
3.3.1.1 依赖
<!-- rureka核心pom文件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.3.1.1 配置
eureka:
instance:
hostname: localhost # 注册中心服务地址
client:
register-with-eureka: false # 是否从注册中心注册自己的信息(此处不注册,因为自己就是注册中心)
fetchRegistry: false # 是否从注册中心获取信息(此处不获取,因为自己就是注册中心)
service-url:
defaultZone: http://localhost:8082/eureka # 注册中心访问全路径
3.3.1.1 注解
@EnableEurekaServer
3.3.2 搭建Euerka服务端(euerka-cloud)

3.3.2.1 创建子项目(同上)
3.3.2.2 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">
<parent>
<artifactId>demo-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-cloud</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- rureka核心pom文件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<artifactId>api-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
3.3.2.3 yml文件
server:
port: 8082 # 注册中心端口号
eureka:
instance:
hostname: localhost # 注册中心服务地址
client:
register-with-eureka: false # 是否从注册中心注册自己的信息(此处不注册,因为自己就是注册中心)
fetchRegistry: false # 是否从注册中心获取信息(此处不获取,因为自己就是注册中心)
service-url:
defaultZone: http://localhost:8082/eureka # 注册中心访问全路径
3.3.2.4 启动类
package com.ai.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer // 启动euerka服务端
public class EuerkaApplication {
public static void main(String[] args) {
SpringApplication.run(EuerkaApplication.class,args);
}
}
3.3.2.5 install工程
3.3.3 pay-cloud服务改造
3.3.3.1 pom新增euerka依赖
<!-- rureka核心pom文件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.3.3.2 yml文件
server:
port: 8081
spring:
application:
name: pay-cloud
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: cb19980702
mybatis:
mapperLocations: classpath:/mapper/*.xml # mapper映射文件存放位置
type-aliases-package: com.ai.springcloud.entities # 实体 bean文件存放位置
eureka: # 新增euerka客户端配置
client:
register-with-eureka: true # 是否从注册中心注册自己的信息
fetchRegistry: true # 是否从注册中心获取信息
service-url:
defaultZone: http://localhost:8082/eureka # 注册中心访问全路径
3.3.3.3 启动类
package com.ai.springcloud;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@MapperScan("com.ai.springcloud.dao")
@EnableEurekaServer
public class PayMentMain {
public static void main(String[] args) {
SpringApplication.run(PayMentMain.class, args);
}
}
3.3.3.4 install工程
3.3.4 order-cloud服务改造
步骤同3.3.3一致
3.4 示例演示
⚠️注意:浏览器访问地址为http://localhost:8082,不用带/eureka
pay-cloud有两个服务的原因是本地新增了一个副本服务。
四、Ribbon介绍及集成
4.1 介绍
客户端负载均衡工具,主要功能是提供客户端的软件负载均衡算法和服务调用。(nginx是服务端负载均衡,ribbon是本地负载均衡)
简单来说Ribbon=负载均衡+RestTemplate调用
4.2 核心组件Irule
com.netflix.loadbalancer.RoundRobinRule 轮询,默认策略。
com.netflix.loadbalancer.RandomRule 随机
com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
WeightedResponseTimeRule 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
AvailabilityFilteringRule 先过滤掉故障实例,再选择并发较小的实例
ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
4.3 示例(改造order-cloud服务调用端)
4.3.1 综述
新增ribbon依赖 -> 添加ribbon配置类 -> RestTemplate配置类新增注解 -> controller中修改RestTemplate公用调用路径 -> 启动类新增ribbon启动注解

4.3.2 POM
<!-- rureka核心pom文件,ribbon依赖在内 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
4.3.3 添加配置类,实现Irule组件
⚠️注意:配置类一定不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化订制的目的了。(此处放在com.ai.ribbon夹下)
package com.ai.ribbon;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
@SpringBootConfiguration
public class RibbonConfig {
@Bean
public IRule myRule(){
return new RoundRobinRule();//定义为轮询策略
}
}
4.3.4 RestTemplate配置类新增注解(@LoadBalanced)
package com.ai.springcloud.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootConfiguration
public class ApplicationContextConfig {
@Bean
@LoadBalanced // 让其自持负载均衡的方式,否则报错无法找到PAY-CLOUD,【无ribbon时不需要该注解】
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
4.3.5 修改RestTemplate公用调用路径
4.3.6 启动类新增ribbon启动注解(@RibbonClient)
package com.ai.springcloud;
import com.ai.ribbon.RibbonConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
@SpringBootApplication
@EnableEurekaServer
// 添加ribbon启动注解 他会自动去euerka里下载相关内容,【name = "ORDER-CLOUD"】代表euerka里注册的名称,【configuration = RibbonConfig.class】代表采用的个性化配置策略
@RibbonClient(name = "ORDER-CLOUD",configuration = RibbonConfig.class)
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
4.3.7 install工程
五、OpenFeign介绍及集成
5.1 介绍
Feign是一个声明式的web服务客户端,便于服务调用(也是http+json),其自身集成了ribbon。
5.2 OpenFeign及Feign区别
OpenFeign 是 Feign的升级版,OpenFeign目前仍然活跃开发,Feign目前已经进入维护状态
5.3 示例(重新搭建一套由openfeign进行交互的order-cloud工程,order-feign-cloud)
5.3.1 创建子工程(同上)
5.3.2 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">
<parent>
<artifactId>demo-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-feign-cloud</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--openfeign核心依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<artifactId>api-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
5.3.3 yml配置文件
server:
port: 8083
spring:
application:
name: order-feign-cloud
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8082/eureka
# 设置feign客户端超时时间
ribbon:
ReadTimeout: 3000
ConnectTimeout: 3000
5.3.4 启动类
package com.ai.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
// 开启euerka注解
@EnableEurekaClient
// 开启feign注解(不再需要ribbon注解,feign集成你了ribbon)
@EnableFeignClients
public class OrderFeignMain {
public static void main(String[] args) {
SpringApplication.run(OrderFeignMain.class,args);
}
}
5.3.5 openfeign接口
package com.ai.springcloud.service;
import com.ai.springcloud.entities.CommonResult;
import com.ai.springcloud.entities.PayMent;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
// 面向接口编程
@Component
// feign中继承了ribbon,这里实质相当于ribbon中的根据euerka里的注册名【PAY-CLOUD】获取其注册信息和访问地址
@FeignClient(name = "PAY-CLOUD")
public interface PayCloudFeignService {
@PostMapping(value = "/payment/create")
CommonResult<Integer> create(@RequestBody PayMent payMent);
@GetMapping(value = "/payment/get/{id}")
CommonResult<PayMent> getPaymentById(@PathVariable("id") Long id);
}
5.3.6 controller层
package com.ai.springcloud.controller;
import com.ai.springcloud.entities.CommonResult;
import com.ai.springcloud.entities.PayMent;
import com.ai.springcloud.service.PayCloudFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class OrderController {
@Autowired
PayCloudFeignService payCloudFeignService;
@PostMapping("/consumer/payment/create")
public CommonResult<Integer> create(@RequestBody PayMent payment){
return payCloudFeignService.create(payment);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<PayMent> getPayment(@PathVariable("id") Long id){
return payCloudFeignService.getPaymentById(id);
}
}
六、Hystrix介绍及集成(已经逐步淘汰,被Resilience4j取代)
6.1 介绍
断路器,通过断路器机制防止分布式系统中的级联故障和雪崩效应。
雪崩:A -> B -> C -> D,当C服务有问题时,A、B服务的请求都无法得到释放,当请求数越来越多就会导致整个链路雪崩。
6.2 功能
降级:超时、异常、线程池打满、熔断导致降级、人工降级
熔断:服务已达最大请求量、规定时间内异常数量超过阈值
限流:秒杀高并发等操作,N个请求/S
6.3 降级
【6.3.3为项目常用降级方式,euerka+openfeign(+ribbon)+hystrix。 】
6.3.1 单服务单方法降级处理(基础版-每个接口单独配置降级处理)
6.3.1.1 新增pom依赖
<!--新增hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
6.3.1.2 启动器新增注解
@EnableHystrix
6.3.1.3 yml配置文件
feign:
hystrix:
enabled: true # 为每个Feign客户端接口自动创建Hystrix包装器,当调用失败或超时时,能够执行降级逻辑。!!!只有服务调用者(包含feign)才需要该配置
6.3.1.4 业务层处理
配置@HystrixCommand注解并定义降级方法
@RestController
@Slf4j
public class OrderHystrixController {
@GetMapping("/hystrix/ok/{id}")
public String payOK(@PathVariable("id") Integer id){
return "测试ok";
}
//超时降级(【fallbackMethod = "payment_TimeoutHandler"】是降级兜底方法名,【name="execution.isolation.thread.timeoutInMilliseconds",value="5000"】设置超时时长,默认1S)
@HystrixCommand(fallbackMethod = "payment_TimeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")})
@GetMapping("/hystrix/timeout/{id}")
public String payTimeOut(@PathVariable("id") Integer id){
int timeNumber = 10; //模拟非正常情况
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "测试timeOut";
}
//兜底方法,上面方法出问题,我来处理,返回一个出错信息
public String payment_TimeoutHandler(Integer id) {
return "服务降级测试";
}
}
6.3.2 单服务单类公共降级处理(进阶版-每个class统一配置降级处理)
6.3.2.1 新增pom依赖(同上)
6.3.2.2 启动器新增注解(同上)
6.3.2.3 yml配置文件(同上)
6.3.2.4 业务层处理
配置@DefaultProperties全局注解、配置@HystrixCommand注解、定义公用降级方法
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_TimeoutHandler") //全局的
public class OrderHystrixController {
@GetMapping("/hystrix/ok/{id}")
public String payOK(@PathVariable("id") Integer id){
return "测试ok";
}
@HystrixCommand
@GetMapping("/hystrix/timeout/{id}")
public String payTimeOut(@PathVariable("id") Integer id){
int timeNumber = 10; //模拟非正常情况
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "测试timeOut";
}
//兜底方法,上面方法出问题,我来处理,返回一个出错信息
public String payment_TimeoutHandler(Integer id) {
return "服务降级测试";
}
}
6.3.3 单服务降级处理(常用版-调用者用降级接口对提供者进行统一处理)
6.3.3.1 新增pom依赖(同上)
6.3.3.2 启动器新增注解(同上)
6.3.3.3 yml配置文件(同上)
6.3.3.4 OpenFeign接口新增back属性

6.3.3.5 新增降级兜底类

6.3.4 @HystrixCommand降级时间及yml配置中降级时间区别
@HystrixCommand的时间:超时降级时间,默认1S,可自定义,如6.3.1、6.3.2。当单个接口、类进行降级处理时,走@HystrixCommand规定的时间。
yml配置中的降级时间:feign服务调用 http超时时间,6.3.3案例走yml的超时时间
6.3.5 服务熔断
当服务访问量上限/指定时间内失败次数上限
6.3.5.1 示例
pom、yml、注解等和上述一致
/*
* requestVolumeThreshold=10,10S内发送10个请求就打开断路
* errorThresholdPercentage=60,10S内发送10个请求,错误率达到60%就打开断路
*/
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"), //当在配置时间窗口内达到此数量,打开断路,默认20个
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //断路多久以后开始尝试是否恢复,默认5s
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"), //出错百分比阈值,当达到此阈值后,开始短路。默认50%
})
6.3.6 仪表盘搭建
6.3.6.1 pom
<!--新增hystrix dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
6.3.6.2 yml
hystrix:
dashboard:
proxy-stream-allow-list: localhost #仪表盘监控哪些服务
6.3.6.3 启动类新增注解
@EnableHystrixDashboard
6.3.6.4 工程install并启动,然后打开仪表盘

6.3.6.5 被监控工程pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
6.3.6.6 被监控工程的启动类新增内容
/**
*ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",为了设置被监控服务的访问路径,此服务是/hystrix.stream
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
6.3.6.6 添加访问被监控服务
http://localhost:xxxx/hystrix.stream
6.3.6.6 仪表盘讲解

七、网关gateway
7.1 概念
网关服务,类似于过滤器,对API进行路由,以及提供一些强大的过滤器功能,基于Spring5.X+SpringBoot2.X和Project Reactor等特定框架
7.2 作用
反向代理、过滤、鉴权、流量控制、熔断、日志监控等等
7.3 核心组成
Route(路由) -> Predicate(断言)、Filter(过滤)
7.4 官网
https://docs.spring.io/spring-cloud-gateway/docs/2.2.6.RELEASE/reference/html/

7.5 示例
搭建成功后,通过【http://localhost:9101/consumer/payment/get/60】访问即可,相当于面向用户的是9101端口,实际的8103端口被反向代理了,期间也配置了相关的断言和过滤条件。

7.5.1 创建子项目
7.5.2 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">
<parent>
<artifactId>demo-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>getway-cloud</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--新增gateway,不需要引入web和actuator模块-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<artifactId>api-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
7.5.3 yml文件
predicates断言共11种,具体查看官网
filters过滤同参考官网
server:
port: 9101
spring:
application:
name: gateway-gateway
cloud:
gateway:
routes: # 路由是个集合,- 代表集合元素
- id: orderment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8083 #predicates断言匹配后 提供服务的路由地址
predicates: # 断言类型有11种,具体参考官网文档
- Path=/consumer/payment/get/** #断言,路径匹配通过的 进行uri路由
- After=2025-10-08T10:59:34.102+08:00[Asia/Shanghai] # 指定时间之后的请求可以通过
# - Before=2025-10-08T10:59:34.102+08:00[Asia/Shanghai] # 指定时间之前的请求可以通过
# - Between=2025-10-08T10:59:34.102+08:00[Asia/Shanghai] , 2025-11-08T10:59:34.102+08:00[Asia/Shanghai] #指定时间区间内的请求可以通过
- id: orderment_routh2
uri: http://localhost:8083
# filters: #可设置已提供的过滤条件
predicates:
- Path=/consumer/payment/create/** #断言,路径相匹配的进行路由
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8082/eureka
7.5.4 启动类
package com.ai.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain {
public static void main(String[] args) {
SpringApplication.run(GateWayMain.class,args);
}
}
7.5.5 自定义全局过滤器(按需使用)
package com.ai.springcloud.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Date;
@Component
@Slf4j
public class GatewayConfig implements GlobalFilter, Ordered {
@Override
// 过滤内容
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("测试gateway:"+new Date());
String username = exchange.getRequest().getQueryParams().getFirst("username");
if(StringUtils.isEmpty(username)){
log.info("用户名为null");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
// 执行顺序,0最先执行
public int getOrder() {
return 0;
}
}
7.5.6 install工程
八、SpringCloud Sleuth(分布式链路请求跟踪)+ OpenZipkin(分布式跟踪平台)
8.1 概念
分布式服务调用链路跟踪监控并展示
8.2作用
监控服务调用链路,等同于pinpoint
8.3 Zipkin安装
8.3.1 下载
https://github.com/openzipkin/zipkin
8.3.2 本地安装
8.3.3 访问(http://ip地址:9411/zipkin/)

8.4 SpringCloud Sleuth集成(在已有的服务中集成)
8.4.1 添加pom依赖
<!--包含了sleuth+zipkin-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
8.4.2 新增yml配置(spring下层)
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
#采样率值介于0~1之间,1表示全部采样
probability: 1
8.4.3 重启工程并访问其中的接口
九、SpringCloud Alibaba Nacos
9.1 作用
注册中心+配置中心的组合,
9.2 安装nacos(nacos下载解压即可,不用像euerka进行部署)
9.2.1 官网下载
https://nacos.io/download/nacos-server/?spm=5238cd80.2ef5001f.0.0.3f613b7cVw55Dz
9.2.2 解压文件夹
9.2.3 变为单例模式进行启动(默认是集群模式)

9.2.4 访问
9.3 搭建提供者服务(注册中心)
9.3.1 父工程增加alibaba依赖
<!-- springCloud Alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
9.3.2 子工程添加nacos依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
9.3.3 yml配置
server:
port: 8084
spring:
application:
name: pay-nacos-cloud
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: cb19980702
mybatis:
mapperLocations: classpath:/mapper/*.xml # mapper映射文件存放位置
type-aliases-package: com.ai.springcloud.entities # 实体 bean文件存放位置
management:
endpoints:
web:
exposure:
include: '*' #默认只公开了/health和/info端点,要想暴露所有端点只需设置成星号
9.3.4 启动类增加注解
package com.ai.springcloud;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@MapperScan("com.ai.springcloud.dao")
// nacos启动注解
@EnableDiscoveryClient
public class PayMentMain {
public static void main(String[] args) {
SpringApplication.run(PayMentMain.class, args);
}
}
9.3.5 启动

9.4 搭建提供者服务(配置中心)
因环境不同(测试、生产等),可能存在多套配置文件,可用application.yml区分dev、pro的方式,也可用分组group的方式。
9.4.1 新增配置中心依赖
<!-- nacos配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- nacos注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
9.4.2 新增bookstrap.yml文件(主要增加nacos配置中心的配置)
bookstrap.yml作用同application.yml文件一致,只不过两者同时存在时,项目先加载bookstrap.yml
9.4.3 创建application.yml
9.4.4 启动类(同注册中心注解一样)
9.4.5 编写测试接口
9.4.6 nacos中心创建配置文件
⚠️注意:名称规则为(${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension})!!!
9.4.7 测试

9.5 nacos配置中心的名称空间
区分不同环境的配置文件,出了上述的配置文件区分、分组区分,还可以通过名称空间区分。
9.5.1 创建新的名称空间

9.5.2 增加相关配置


9.6 nacos配置中心持久化(数据库记录)
9.6.1 提取mysql表文件
9.6.2 数据库创建表
9.6.3 配置数据库连接

9.6.4 重启nacos
# 终端打开nacos的bin文件下
cd /path/to/nacos/bin
# nacos终止命令
sh shutdown.sh
# nacos启动命令
sh startup.sh -m standalone
9.6.5 测试


9.7 实际使用
nacos:多节点集群模式(cluster.conf【nacos所有节点配置文件】、application.properties【当前nacos端口号、数据库连接等配置】、startup.cmd【可配置当前nacos启动占用资源大小】)
nginx:代理访问nacos集群
工程:yml配置文件中配置nginx代理的nacos集群访问地址
十、SpringCloud Alibaba Sentinel
10.1 概念
分布式系统的流量防卫兵,作用同hystrix相似,提供限流、降级、熔断等功能。
10.2 与hystrix比较
1. hystrix目前处于维护状态,Sentinel由alibab提供,仍在更新
2. hystrix通过引入jar来使用,无可视化界面,降级、熔断等操作需要通过配置文件、注解来实现;Sentinel通过jar启动,有可视化界面,各类操作可以直接在客户端界面进行操作。
10.3 安装Sentinel
1.本地下载 Sentinel相关jar包

2.终端中启动Sentinel(java -jar sentinel-dashboard-1.8.2.jar )
3.访问(http://localhost:8080/)
10.4 搭建Sentinel工程
10.4.1 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">
<parent>
<artifactId>demo-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-cloud</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- 引入公共API文件jar -->
<dependency>
<artifactId>api-cloud</artifactId>
<groupId>com.demo.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- nacos注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- sentinel无法自主实现持久化,需要通过nacos连接数据库实现持久化 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
10.4.2 yml配置文件
server:
port: 9001
spring:
application:
name: sentinel-cloud
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719 #默认8719,应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用HttpServer
management:
endpoints:
web:
exposure:
include: '*'
10.4.3 启动类
package com.ai.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class SentinelMain {
public static void main(String[] args) {
SpringApplication.run(SentinelMain.class, args);
}
}
10.4.4 控制层
package com.ai.springcloud.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SentinelDemo {
@GetMapping("/testA")
public String testA() {
return "测试接口A";
}
@GetMapping("/testB")
public String testB() {
return "测试接口B";
}
}
10.4.5 测试(sentinel是实时的,需要服务有访问才会有显示)


10.5 流控规则 
QPS:每分钟请求参数
并发线程数:线程数
阈值:数量
直接:直接降级报错
关联:例如关联资源关联(/testA),则当A接口达到访问阈值时B接口也会降级报错
链路:家庭式链路
快速失败:直接降级报错
Warm Up:预热,前N秒将访问量控制在默认阈值/3,后续可以达到最大阈值,适用于秒杀活动
排队等待:超过阈值的接口请求会进行等待,超过等待时间仍未执行才会报错。

含义:A接口/B接口前2秒会进行预热,最大请求是3,2秒后最大请求可达到10次/秒,超过阈值时B接口报错。
10.6 熔断规则


含义:10S内当超过5个请求时,如果有一半的响应时常都超过200ms,则熔断2s

含义:10S内当超过5个请求时,如果10%的请求出现异常,则熔断2S

含义:10内当超过5个请求时,如果异常数量超过3个,则熔断2S
10.7 热点规则(需改造代码)
@RestController
public class SentinelDemo {
@GetMapping("/testA")
/*
1.SentinelResource - 热点规则处理注解
2.value - 资源名称|方法别名(例:热点规则名为testA,则触发规则时走block_testA方法,热点规则名为/testA,则触发热点规则时走默认兜底方法)
3.blockHandler - 热点规则兜底方法(降级处理)
4.fallback - 方法内部异常兜底方法(降级方法)
*/
@SentinelResource(value = "testA",blockHandler = "block_testA",fallback = "fall_testA")
public String testA(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2) {
return "测试接口A";
}
@GetMapping("/testB")
public String testB() {
return "测试接口B";
}
//热点规则兜底方法(返回类型一致、包含原有入参、包含异常对象BlockException)
public String block_testA (String p1, String p2, BlockException exception){
return "------testA,热点规则";
}
//方法内部异常兜底方法
public String fall_testA (String p1, String p2, Throwable throwable){
return "------testA,方法异常";
}
}


10.7.1 热点规则兜底方法提取(公共方法)


10.8 系统规则(用于对所有接口均统一进行规则判定,不常用)


10.9 持久化(配置数据入库)
目前sentinel暂无法直接实现持久化,而是通过nacos实现持久化(sentinel -> nacos配置中心 -> 入库)
10.9.1 新增pom
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
10.9.2 新增yml
server:
port: 9001
spring:
application:
name: sentinel-cloud
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719 #默认8719,应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用HttpServer
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: sentinel-cloud
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
10.9.3 新增nacos配置

十一、CAP讲解
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。
CAP至多同时满足两点,及CP、AP。
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

nacos支持CP和AP模式的切换,所以相较于其他控制中心使用更优。
更多推荐






















所有评论(0)