# 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部署在多台服务器上并作为一个整体提供一类服务,这个整体称为集群 ![image-20260618100328025](assets/image-20260618100328025.png) * 正向代理: 系统内部要访问外部网络时,统一通过一个代理服务器 把请求转发出去,在外部网络看来就是代理服务器发起的访问,此时代理服务器实现的是正向代理; * 反向代理 当外部请求进入系统时,代理服务器把该请求转发到系统中的某台服务器上,对外部请求来说,与之交互的只有代理服务器,此时代理服务器实现的是反向代理。 ## 分布式 系统中的多个模块在不同服务器上部署,即可称为分布式系统 ![image-20260618100913187](assets/image-20260618100913187.png) ![image-20260618101502967](assets/image-20260618101502967.png) ## 单体 ![image-20260618104705941](assets/image-20260618104705941.png) ## 垂直拆分 将系统拆分成多个子系统 分别独立运行 按业务拆分 ![image-20260618110221412](assets/image-20260618110221412.png) ## SOA ![image-20260618111313583](assets/image-20260618111313583.png) ## 微服务 ![image-20260618113438863](assets/image-20260618113438863.png) ![image-20260618114126292](assets/image-20260618114126292.png) ![image-20260618114402966](assets/image-20260618114402966.png) # 分布式框架 * 第一代 Spring Cloud Netflix * 第二代 Spring Cloud Aibaba ![image-20260618162751096](assets/image-20260618162751096.png) # 版本 ![image-20260618163042042](assets/image-20260618163042042.png) # Nacos注册中心 ## 微服务通信 服务: * 订单服务 -------订单数据库 * 库存服务 ------ 库存数据库 服务通信: Spring MVC提供的网络请求工具: RestTemplate 服务注册 > 最早: eureka ![image-20260622101310500](assets/image-20260622101310500.png) ## 服务注册 * 临时注册 默认的 如果服务关了 会从注册中心移除 通常的微服务都是这种 * 永久注册 需要手动移除 如网关 > 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 ## 认证 微服务之间如何进行权限认证? ## 超时 ![image-20260623161139570](assets/image-20260623161139570.png) ### 编程 ~~~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); } ~~~ ### 熔断 ![image-20260625161025134](assets/image-20260625161025134.png) # 分布式事务 * 订单服务 ----生成订单 * 商品服务 ---更新库存 ## 两段提交 ![image-20260626172437313](assets/image-20260626172437313.png)