# SpringCloudDemo202606
**Repository Path**: nieps/spring-cloud-demo202606
## Basic Information
- **Project Name**: SpringCloudDemo202606
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-06-18
- **Last Updated**: 2026-06-26
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 目标
* 单体架构
* 分布式架构---微服务架构
最主要的分为4大部分:
* 单体
* 垂直拆分
* SOA
* 微服务
# 概念
## 集群
一套wms部署在多台服务器上并作为一个整体提供一类服务,这个整体称为集群

* 正向代理:
系统内部要访问外部网络时,统一通过一个代理服务器 把请求转发出去,在外部网络看来就是代理服务器发起的访问,此时代理服务器实现的是正向代理;
* 反向代理
当外部请求进入系统时,代理服务器把该请求转发到系统中的某台服务器上,对外部请求来说,与之交互的只有代理服务器,此时代理服务器实现的是反向代理。
## 分布式
系统中的多个模块在不同服务器上部署,即可称为分布式系统


## 单体

## 垂直拆分
将系统拆分成多个子系统 分别独立运行
按业务拆分

## SOA

## 微服务



# 分布式框架
* 第一代 Spring Cloud Netflix
* 第二代 Spring Cloud Aibaba

# 版本

# Nacos注册中心
## 微服务通信
服务:
* 订单服务 -------订单数据库
* 库存服务 ------ 库存数据库
服务通信:
Spring MVC提供的网络请求工具: RestTemplate
服务注册
> 最早: eureka

## 服务注册
* 临时注册 默认的 如果服务关了 会从注册中心移除 通常的微服务都是这种
* 永久注册 需要手动移除 如网关
> ephemeral:默认值是true 代表临时 , Nacos 专用,代表**会自动下线、依靠心跳保活**的临时服务
## 配置文件加载顺序
优先级从高到低:
1. 远程配置
2. bootstram.yaml (服务启动时 读取配置中的配置 必须在这个文件中配置)
3. applcation.yaml
## data-id配置
在 Nacos Server 中,配置的 dataId(即 Data ID)的完整格式如下:
~~~properties
${prefix}-${spring.profiles.active}.${file-extension}
~~~
dataId 格式中各参数说明如下:
- ${prefix}:默认取值为微服务的服务名,即配置文件中 spring.application.name 的值,我们可以在配置文件中通过配置 spring.cloud.nacos.config.prefix 来指定。
- ${spring.profiles.active}:表示当前环境对应的 Profile,例如 dev、test、prod 等。当没有指定环境的 Profile 时,其对应的连接符也将不存在, dataId 的格式变成 ${prefix}.${file-extension}。
- ${file-extension}:表示配置内容的数据格式,我们可以在配置文件中通过配置项 spring.cloud.nacos.config.file-extension 来配置,例如 properties 和 yaml。
## 配置自动更新
* @Value 注入 时, 需要注解 @RefreshScope 才能自动更新
* 使用属性的批量绑定 自动刷新
## 提交了解理论
* CAP 理论
* BASE 理论
# 负载均衡
什么是负载均衡?它的原理是什么?
### 启用负载均衡 算法
* @LoadBalancerClient
> 两个重要注解属性:
>
> 1. name 用于指定 负载均衡要调用的服务名(服务提供者)
>
> ~~~java
> @SpringBootApplication
> @LoadBalancerClient(name = "stock-service", configuration = CustomLoadBalancerConfiguration.class)
> public class OrderApp
> {
> public static void main( String[] args )
> {
> SpringApplication.run(OrderApp.class, args);
> ClientHttpRequestInterceptor interceptor;
> }
> }
>
> ~~~
>
> 如上,是订单服务的 启动类,要调用库存服务做负载均衡,所以Name的值是库存服务的 服务名
>
> 2. configuration 指定配置算法 的配置类
* @LoadBalancerClients 通过defaultConfiguration 指定配置类
# OpenFeign
调用远程像调用本地方法 一样。(RPC)
OpenFeign VS Feigin优势:
1. 支持Spring MVC注解
2. 支持负载均衡
3. 无缝对接中心
角色:
* 服务提供者 stock服务 -----由它提供feign接口
> 组织代码:
>
> 两部分:
>
> 1. stock服务本身------依赖库存api ----实现api接口 提供实现类
> 2. feign接口 专门提取出来 做为sdk 供 (库存api )
>
>
* 服务消费者 order服务 ---------依赖库存api
开发中使用:
### 步骤
1. 服务提供方
> 1. 抽取对外提供的接口 定义成一个模块 做为feign客户端
>
> > 1. 依赖openFeign
> >
> > ~~~xml
> >
> >
> > org.springframework.cloud
> > spring-cloud-starter-openfeign
> >
> > ~~~
> >
> > 2. 定义Feign接口 使用FeignClien注解 如下
> >
> > ~~~java
> > /**
> > * name 当前服务提供者的服务 名
> > */
> > @FeignClient(name = "sc03stock")
> > public interface StockApi {
> >
> > @GetMapping("/fegin/getGoodsById")
> > GoodsDto getGoodsById();
> > }
> > ~~~
>
> 2. 定义服务提供方本身的模块
>
> > 1. 依赖feign模块 同时提供对应的实现
> >
> > ~~~java
> > @RestController
> > @Slf4j
> > public class StockFeignController implements StockApi {
> >
> > @Override
> > public GoodsDto getGoodsById() {
> > log.info("查询商品");
> > return new GoodsDto(1, "iphone", 10);
> > }
> > }
> >
> > ~~~
> >
> >
2. 服务消费方
> 1. 依赖服务提供方 抽取的api模块 依赖负载均衡
>
> ~~~xml
>
> com.by
> sc04-stock-api
> 0.0.1-SNAPSHOT
>
>
>
> org.springframework.cloud
> spring-cloud-starter-loadbalancer
>
> ~~~
>
> 2. 启用对feign支持
>
> ~~~java
> @SpringBootApplication
> @EnableFeignClients // 开启feign
> public class Sc03Order
> {
> public static void main( String[] args )
> {
> SpringApplication.run(Sc03Order.class, args);
> }
> }
>
> ~~~
>
> 3. 依赖注解 在需要调用其它服务的地方 将fegin接口 注入后直接使用
>
> ~~~java
> @Autowired
> StockApi stockApi;
>
> @GetMapping("/order")
> public GoodsDto query() {
> log.info("查询订单");
> GoodsDto dto = stockApi.getGoodsById();
> return dto;
> }
> ~~~
>
>
## 日志配置
实现步骤:
1. 配置feign接口日志级别为debug 因为请求相关信息的日志级别是debug
~~~yaml
logging:
level:
com.by.feign.api: debug
~~~
2. 配置 Feign日志级别 用于说明请求过程输出内容详细程度
- NONE:不输出日志。
- BASIC:只输出请求方法的 URL 和响应的状态码以及接口执行的时间。
- HEADERS:将 BASIC 信息和请求头信息输出。
- FULL:输出完整的请求信息。
实现方式:
1. 配置类
~~~java
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
~~~
2. 使用yaml文件(推荐)
~~~yaml
spring:
cloud:
openfeign:
client:
config:
sc03stock: #feign接口中name指定的服务名
logger-level: full #feign日志级别
~~~
使用:
* 开发环境 使用 full
* 生产环境 BASIC
## 认证
微服务之间如何进行权限认证?
## 超时

### 编程
~~~java
@Bean
public Request.Options requestOptions(){
return new Request.Options(5, TimeUnit.SECONDS,10,TimeUnit.SECONDS, true);
}
~~~
### yaml配置
## spring mvc注解
### 一个参数
在声明方法时,要显示使用注解 @RequestParam指明参数
~~~java
@GetMapping("/fegin/getGoodsById")
GoodsDto getGoodsById(@RequestParam(name = "id") int id);
~~~
多个参数
~~~java
/**
* 冻结库存
* @param id
* @param num
* @return
*/
@PutMapping("/fegin/freezeStock")
int freezeStock(@RequestParam(name = "id") int id, @RequestParam(name = "num") int num);
~~~
## 关于@FeignClient注解属性
* value() /name() 远程接口调用 的目标服务名 sc04-stock
* contextId 上下文id 当有多个feign接口调用相同的服务时,就会报错,可以通过该属性指定不同的值来达到隔离
* configuration 指定当前feign接口对应的配置类 (注意 该配置类上不能用注解 交给spring管理 属于局部配置 )
* fallback 用于批定 实现当前feign接口的 降级处理类
* fallbackFactory 用于指定降级工厂类,里面可以获取调用远程失败的原图
# Gateway网关
## 路由
网关最基本的模块。它由一个 ID、一个目标 URI、一组断言(Predicate)和一组过滤器(Filter)组成。
* id 唯一标识
* 目标 URI-------真实的微服务地址
* 断言(Predicate) 条件
* 过滤器(Filter) 在请求的基础上增加或减少请求参数/请求头 ...
## 断言
### 关于时间的 (有时会用)
* After 在某个时间点之后 生效
> 时间类型是: ZonedDateTime
>
> 示例:
>
> ~~~yaml
> predicates:
> - After=2026-06-24T11:18:46.959822900+08:00[Asia/Shanghai] # 在11.18之后才能访问
> ~~~
* Before 在某个时间点之前 生效
* Between 在两个时间点之间 才生效
~~~yaml
predicates:
- Between =2026-06-24T11:18:46.959822900+08:00[Asia/Shanghai],2026-06-24T11:21:46.959822900+08:00[Asia/Shanghai]
~~~
### Cookie (一般不用)
~~~yaml
predicates:
- Path=/api/order/**
- Cookie=satoken,9911cb2d-f333-42d6-a157-403d7c0dc0ff # 请求必须有cookie 参数名是satoken value是9911cb2d-f333-42d6-a157-403d7c0dc0ff
~~~
### Header请求头
~~~yaml
predicates:
- Header=Authorization,Bearer 1234567890 # 请求头必须包含 Authorization 参数,且参数值为Bearer 1234567890
~~~
### Path 路径匹配
### Query
~~~yaml
predicates:
- Query=name,lily # 请求参数必须包含name,且值为lily 值是可选 的
~~~
### Weight
权重配置 通过group分组(即分组名一样就是是组)
## 过滤 器
主要常用 的:
* 添加或移除请求头
* 添加或移除响应头
* 添加或移除请求参数
* 添加或移除前缀
特殊过滤器:
default-filters: 会将过滤器应用到所有的路由上
~~~yaml
spring:
gateway:
default-filters: #应用到所有路由上的过滤器
- StripPrefix=1
- PrefixPath=/api
~~~
# sentinel 流量防卫兵
## 资源定义
资源可以是一段代码 、方法 ... 需要被保护的
* 手动定义 (了解)
> 1. SphU try--catch风格
> 2. SphO if--else 风格
* 注解
## 注解
### 限流方法与目标方法 同一类 且无参
返回类型需要与原方法相匹配;
参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException
~~~java
@SentinelResource(value = "根据id查询商品",blockHandler = "getGoodsBlockHandler")
@GetMapping("/goods")
public Map getGoods() {
return goodsService.getGoods(1);
}
//接收异常BlockException 该方法返回类型与原方法一致
public Map getGoodsBlockHandler(BlockException e) {
Map map=new HashMap();
map.put("code",0);
map.put("msg","被限流了....");
return map;
}
~~~
### 限流逻辑与目标方法不在一同类中
#### 限流类
要求:
返回类型需要与原方法相匹配;
参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException
**方法必须是static类型**
~~~java
public class GoodsLimit {
public static Map getGoodsBlockHandler(int id, BlockException e) {
Map map=new HashMap();
map.put("code",0);
map.put("msg",id+" ---被限流了....");
return map;
}
}
~~~
#### 注解使用
~~~java
@SentinelResource(value = "根据id查询商品",blockHandler = "getGoodsBlockHandler",blockHandlerClass = GoodsLimit.class)
@GetMapping("/goods")
public Map getGoods(int id) {
return goodsService.getGoods(id);
}
~~~
### 熔断

# 分布式事务
* 订单服务 ----生成订单
* 商品服务 ---更新库存
## 两段提交
