开源php企业网站,软件开发流程图软件,网络上市场推广,注册公司代理费用标准原作者#xff1a;3. SpringCloud - 快速通关
前置知识#xff1a;
Java17及以上、MavenSpringBoot、SpringMVC、MyBatisLinux、Docker
1. 分布式基础
1.1. 微服务
微服务架构风格#xff0c;就像是把一个单独的应用程序开发为一套小服务#xff0c;每个小服务运行在自…原作者3. SpringCloud - 快速通关
前置知识
Java17及以上、MavenSpringBoot、SpringMVC、MyBatisLinux、Docker
1. 分布式基础
1.1. 微服务
微服务架构风格就像是把一个单独的应用程序开发为一套小服务每个小服务运行在自己的进程中并使用轻量级机制通信通常是 HTTP API。这些服务围绕业务能力来构建 并通过完全自动化部署机制来独立部署。这些服务使用不同的编程语言书写以及不同数据存储技术并保持最低限度的集中式管理。
简而言之拒绝大型单体应用基于业务边界进行服务微化拆分各个服务独立部署运行。 1.2. 集群分布式节点
集群是个物理形态分布式是个工作方式。
只要是一堆机器就可以叫集群他们是不是一起协作着干活这个谁也不知道
《分布式系统原理与范型》定义
“分布式系统是若干独立计算机的集合这些计算机对于用户来说就像单个相关系统”分布式系统distributed system是建立在网络之上的软件系统。 分布式是指将不同的业务分布在不同的地方。
集群指的是将几台服务器集中在一起实现同一业务。 例如京东是一个分布式系统众多业务运行在不同的机器所有业务构成一个大型的业务集群。每一个小的业务比如用户系统访问压力大的时候一台服务器是不够的。我们就应该将用户系统部署到多个服务器也就是每一个业务系统也可以做集群化
分布式中的每一个节点都可以做集群。 而集群并不一定就是分布式的。
节点集群中的一个服务器 1.3. 远程调用
在分布式系统中各个服务可能处于不同主机但是服务之间不可避免的需要互相调用我们称为远程调用。 SpringCloud 中使用 HTTPJSON 的方式完成远程调用 1.4. 负载均衡
分布式系统中A 服务需要调用 B 服务B 服务在多台机器中都存在A 调用任意一个服务器均可完成功能。 为了使每一个服务器都不要太忙或者太闲我们可以负载均衡的调用每一个服务器提升网站的健壮性。
常见的负载均衡算法
轮询为第一个请求选择健康池中的第一个后端服务器然后按顺序往后依次选择直到最后一个然后循环。
最小连接优先选择连接数最少也就是压力最小的后端服务器在会话较长的情况下可以考虑采取这种方式。
散列根据请求源的 IP 的散列hash来选择要转发的服务器。这种方式可以一定程度上保证特定用户能连接到相同的服务器。如果你的应用需要处理状态而要求用户能连接到和之前相同的服务器可以考虑采取这种方式。 1.5. 服务注册/发现注册中心
A 服务调用 B 服务A 服务并不知道 B 服务当前在哪几台服务器有哪些正常的哪些服务已经下线。解决这个问题可以引入注册中心 如果某些服务下线我们其他人可以实时的感知到其他服务的状态从而避免调用不可用的服务 1.6. 配置中心
每一个服务最终都有大量的配置并且每个服务都可能部署在多台机器上。我们经常需要变更配置我们可以让每个服务在配置中心获取自己的配置。
配置中心用来集中管理微服务的配置信息 1.7. 服务熔断服务降级
在微服务架构中微服务之间通过网络进行通信存在相互依赖当其中一个服务不可用时有可能会造成雪崩效应。要防止这样的情况必须要有容错机制来保护服务。 1、服务熔断
设置服务的超时当被调用的服务经常失败到达某个阈值我们可以开启断路保护机制后来的请求不再去调用这个服务。本地直接返回默认的数据
2、服务降级
在运维期间当系统处于高峰期系统资源紧张我们可以让非核心业务降级运行。降级某些服务不处理或者简单处理【抛异常、返回 NULL、调用 Mock 数据、调用 Fallback 处理逻辑】 1.8. API 网关
在微服务架构中API Gateway 作为整体架构的重要组件它抽象了微服务中都需要的公共功能同时提供了客户端负载均衡服务自动熔断灰度发布统一认证限流流控日志统计等丰富的功能帮助我们解决很多 API 管理难题。 2. Spring Cloud
2.1. 技术配置
Spring Cloud 系列
官网Spring Cloud远程调用OpenFeign
网关Gateway Spring Cloud Alibaba 系列
官网Spring Cloud Alibaba官网_基于Springboot的微服务教程-阿里云
注册中心/配置中心Nacos服务保护Sentinel分布式事务Seata 2.2. 版本 2.3. 实践
创建父项目引入公共依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion3.3.4/versionrelativePath/ !-- lookup parent from repository --/parentmodelVersion4.0.0/modelVersiongroupIdcom.atguigu/groupIdartifactIdspring-cloud-demo/artifactIdversion1.0-SNAPSHOT/versionpackagingpom/packagingpropertiesmaven.compiler.source17/maven.compiler.sourcemaven.compiler.target17/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncodingspring-cloud.version2023.0.3/spring-cloud.versionspring-cloud-alibaba.version2023.0.3.2/spring-cloud-alibaba.version/propertiesdependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependencydependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion${spring-cloud-alibaba.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagement/project 3. Nacos - 注册/配置中心
3.1. 基础入门
3.1.1. 简介
官网Nacos 快速开始 | Nacos 官网
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 3.1.2. 安装
Docker 安装
docker run -d -p 8848:8848 -p 9848:9848 -e MODEstandalone --name nacos nacos/nacos-server:v2.4.3
下载软件包nacos-server-2.4.3.zip启动startup.cmd -m standalone 3.2. 注册中心
3.2.1. 依赖引入
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId
/dependency
3.2.2. 整合配置
1、在 application.properties中配置如下
spring.cloud.nacos.discovery.server-addr127.0.0.1:8848#暂未用到配置中心功能需要关闭配置检查
#spring.cloud.nacos.config.import-check.enabledfalse
2、开启服务注册/发现功能
EnableDiscoveryClient //核心注解
SpringBootApplication
public class OrderMainApplication {public static void main(String[] args) {SpringApplication.run(OrderMainApplication.class, args);}}
3.2.3. 服务注册
3.2.3.1. 查看效果
访问http://localhost:8848/nacos 可以看到服务已经注册上来 3.2.3.2. 注册更多
创建 service-product服务引入 nacos依赖配置 nacos地址信息 注意每个微服务端口不一样
启动应用查看是否注册成功 3.2.3.3. 启动集群
以 service-order为例启动 movie 的三个服务。
idea 搜索 services面板添加 SpringBoot 项目。
复制 OrderMainApplication三份每个启动命令重新指定端口 3.2.3.4. 查看集群 3.2.4. 服务发现
3.2.4.1. DiscoveryClient
Autowired
DiscoveryClient discoveryClient;
Test
void discoveryClientTest(){for (String service : discoveryClient.getServices()) {System.out.println(service service);//获取ipportListServiceInstance instances discoveryClient.getInstances(service);for (ServiceInstance instance : instances) {System.out.println(ipinstance.getHost()port instance.getPort());}}
} 3.2.4.2. NacosServiceDiscovery
Autowired
NacosServiceDiscovery nacosServiceDiscovery;
Test
void nacosServiceDiscoveryTest() throws NacosException {for (String service : nacosServiceDiscovery.getServices()) {System.out.println(service service);ListServiceInstance instances nacosServiceDiscovery.getInstances(service);for (ServiceInstance instance : instances) {System.out.println(ipinstance.getHost()port instance.getPort());}}
} 3.2.4.3. 模拟掉线
随机中断一个服务运行代码或在界面查看效果 3.2.5. 远程调用
3.2.5.1. 配置 RestTemplate
Configuration
public class UserConfiguration {BeanRestTemplate restTemplate() {return new RestTemplate();}
} 3.2.5.2. 测试调用 AutowiredRestTemplate restTemplate;Testvoid testRestTemplate() {String forObject restTemplate.getForObject(http://localhost:8080/movie, String.class);System.out.println(forObject);System.out.println(-----------------------------);} 3.2.5.3. 小结
使用 RestTemplate 可以获取到远程数据必须精确指定地址和端口如果远程宕机将不可用
期望可以负载均衡调用不用担心远程宕机
3.2.6. 负载均衡
3.2.6.1. 依赖导入
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId
/dependency 3.2.6.2. LoadBalancerClient // 进阶2完成负载均衡发送请求private Product getProductFromRemoteWithLoadBalance(Long productId){//1、获取到商品服务所在的所有机器IPportServiceInstance choose loadBalancerClient.choose(service-product);//远程URLString url http://choose.getHost() : choose.getPort() /product/productId;log.info(远程请求{},url);//2、给远程发送请求Product product restTemplate.getForObject(url, Product.class);return product;} 3.2.6.3. 注解式负载均衡
Configuration
public class UserConfiguration {LoadBalancedBeanRestTemplate restTemplate() {return new RestTemplate();}} // 进阶3基于注解的负载均衡private Product getProductFromRemoteWithLoadBalanceAnnotation(Long productId){String url http://service-product/product/productId;//2、给远程发送请求 service-product 会被动态替换Product product restTemplate.getForObject(url, Product.class);return product;} 3.2.6.4. 小结
负载均衡调用只需要传入服务名请求发起之前会自动去注册中心确定微服务地址如果微服务宕机会自动剔除在线名单请求将不会发过去 3.2.7. 深入探索
经典面试题
如果注册中心宕机远程调用是否可以成功
从未调用过如果宕机调用会立即失败调用过如果宕机因为会缓存名单调用会成功调用过如果注册中心和对方服务宕机因为会缓存名单调用会阻塞后失败Connection Refused 3.3. 配置中心
主要提示 3.3.1. 整合配置
3.3.1.1. 依赖引入
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-config/artifactId
/dependency
3.3.1.2. 配置文件
application.properties
# 指定配置中心地址
spring.cloud.nacos.server-addrlocalhost:8848
spring.config.importnacos:service-order.properties 3.3.1.3. 配置集-dataId 3.3.2. 动态刷新
3.3.2.1. RefreshScope
RefreshScope//自动刷新
RestController
public class OrderController {AutowiredOrderService orderService;Value(${order.timeout})String orderTimeout;Value(${order.auto-confirm})String orderAutoConfirm;AutowiredOrderProperties orderProperties;GetMapping(/config)public String config(){return order.timeoutorderProperties.getTimeout() order.auto-confirmorderProperties.getAutoConfirm() order.db-urlorderProperties.getDbUrl();}
} 3.3.2.2. ConfigurationProperties
无需 RefreshScope自动绑定配置动态更新
Component
ConfigurationProperties(prefix order) //配置批量绑定在nacos下可以无需RefreshScope就能实现自动刷新
Data
public class OrderProperties {String timeout;String autoConfirm;String dbUrl;
} 3.3.3. NacosConfigManager BeanApplicationRunner applicationRunner(NacosConfigManager manager){return args - {ConfigService configService manager.getConfigService();configService.addListener(service-order.properties, DEFAULT_GROUP, new Listener() {Overridepublic Executor getExecutor() {return Executors.newFixedThreadPool(4);}Overridepublic void receiveConfigInfo(String configInfo) {System.out.println(configInfo configInfo);}});};} 3.3.4. namespace、dataId、group
3.3.4.1. namespace
命名空间实现多环境隔离如开发、测试、预发、生产等 3.3.4.2. dataId
数据集id就是以前配置文件的名字。完整写法名字.后缀 如common.properties 3.3.4.3. groupId
分组id一般可以用微服务的名字作为自己的组。 3.3.4.4. 推荐用法 4. OpenFeign - 远程调用
4.1. 基础入门
官网Spring Cloud OpenFeign Features :: Spring Cloud Openfeign
4.1.1. 简介
OpenFeign 是一个声明式远程调用客户端 4.1.2. 引入依赖
由于大型项目中每个项目都可能需要使用远程调用。所以我们可以在父项目中统一引入
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId
/dependency 4.1.3. 开启功能
SpringBootApplication
EnableFeignClients
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}} 4.1.4. 远程调用
FeignClient(stores)
public interface StoreClient {RequestMapping(method RequestMethod.GET, value /stores)ListStore getStores();GetMapping(/stores)PageStore getStores(Pageable pageable);PostMapping(value /stores/{storeId}, consumes application/json,params modeupsert)Store update(PathVariable(storeId) Long storeId, Store store);DeleteMapping(/stores/{storeId:\\d})void delete(PathVariable Long storeId);
}
注意用法
EnableFeignClients
EnableFeignClients(basePackages com.example.clients) 4.2. 进阶配置
4.2.1. 开启日志
logging:level:com.atguigu.order.feign: debug
Bean
Logger.Level feignLoggerLevel() {return Logger.Level.FULL;
} 4.2.2. 超时控制
spring:cloud:openfeign:client:config:default:logger-level: fullconnect-timeout: 1000read-timeout: 2000service-product:logger-level: fullconnect-timeout: 3000read-timeout: 5000 4.2.3. 重试机制
Bean
Retryer retryer(){return new Retryer.Default();
}4.2.4. fallback - 兜底返回
引入 sentinel dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId/dependency
开启熔断
feign:sentinel:enabled: true 编写 fallback 函数
FeignClient(value service-product,fallback ProductFeignClientFallback.class) // feign客户端
public interface ProductFeignClient {//mvc注解的两套使用逻辑//1、标注在Controller上是接受这样的请求//2、标注在FeignClient上是发送这样的请求GetMapping(/product/{id})Product getProductById(PathVariable(id) Long id);} Component
public class ProductFeignClientFallback implements ProductFeignClient {Overridepublic Product getProductById(Long id) {System.out.println(兜底回调....);Product product new Product();product.setId(id);product.setPrice(new BigDecimal(0));product.setProductName(未知商品);product.setNum(0);return product;}
}
5. Sentinel - 流量保护
5.1. 介绍
官网home | Sentinel
wikihttps://github.com/alibaba/Sentinel/wiki
下载控制台sentinel-dashboard-1.8.8.jar 随着微服务的流行服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
丰富的应用场景Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景例如秒杀即突发流量控制在系统容量可以承受的范围、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。完备的实时监控Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据甚至 500 台以下规模的集群的汇总运行情况。广泛的开源生态Sentinel 提供开箱即用的与其它开源框架/库的整合模块例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C 等多语言的原生实现。完善的 SPI 扩展机制Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。 5.2. 架构 5.3. 资源规则
定义资源
主流框架自动适配Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor所有Web接口均为资源编程式SphU API声明式SentinelResource
定义规则
流量控制规则熔断降级规则系统保护规则来源访问控制规则热点参数规则 5.4. 环境搭建
5.4.1. 依赖
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId
/dependency 5.4.2. 启动控制台
java -jar sentinel.jar 5.4.3. 配置连接
spring:cloud:sentinel:transport:dashboard: localhost:8080 5.5. 异常处理 5.5.1. 自定义 BlockExceptionHandler
Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {private ObjectMapper objectMapper new ObjectMapper();Overridepublic void handle(HttpServletRequest request, HttpServletResponse response,String resourceName, BlockException e) throws Exception {response.setStatus(429); //too many requestsresponse.setContentType(application/json;charsetutf-8);PrintWriter writer response.getWriter();R error R.error(500, resourceName 被Sentinel限制了原因 e.getClass());String json objectMapper.writeValueAsString(error);writer.write(json);writer.flush();writer.close();}
} 5.5.2. blockHandler SentinelResource(value createOrder,blockHandler createOrderFallback)Overridepublic Order createOrder(Long productId, Long userId) {
// Product product getProductFromRemoteWithLoadBalanceAnnotation(productId);//使用Feign完成远程调用Product product productFeignClient.getProductById(productId);Order order new Order();order.setId(1L);// 总金额order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName(zhangsan);order.setAddress(尚硅谷);//远程查询商品列表order.setProductList(Arrays.asList(product));return order;}//兜底回调public Order createOrderFallback(Long productId, Long userId, BlockException e){Order order new Order();order.setId(0L);order.setTotalAmount(new BigDecimal(0));order.setUserId(userId);order.setNickName(未知用户);order.setAddress(异常信息e.getClass());return order;} 5.5.3. OpenFeign - 兜底回调
FeignClient(value service-product,fallback ProductFeignClientFallback.class) // feign客户端
public interface ProductFeignClient {//mvc注解的两套使用逻辑//1、标注在Controller上是接受这样的请求//2、标注在FeignClient上是发送这样的请求GetMapping(/product/{id})Product getProductById(PathVariable(id) Long id);} Component
public class ProductFeignClientFallback implements ProductFeignClient {Overridepublic Product getProductById(Long id) {System.out.println(兜底回调....);Product product new Product();product.setId(id);product.setPrice(new BigDecimal(0));product.setProductName(未知商品);product.setNum(0);return product;}
}
5.6. 规则 - 流量控制 5.6.1. 阈值类型
QPS统计每秒请求数
并发线程数统计并发线程数 5.6.2. 流控模式 5.6.3. 流控效果 5.7. 规则 - 熔断降级
5.7.1. 断路器 5.7.2. 工作原理 5.7.3. 熔断与兜底 5.8. 规则 - 热点参数 5.8.1. 环境搭建 GetMapping(/seckill)SentinelResource(value seckill-order,fallback seckillFallback)public Order seckill(RequestParam(value userId,required false) Long userId,RequestParam(value productId,defaultValue 1000) Long productId){Order order orderService.createOrder(productId, userId);order.setId(Long.MAX_VALUE);return order;}public Order seckillFallback(Long userId,Long productId, BlockException exception){System.out.println(seckillFallback....);Order order new Order();order.setId(productId);order.setUserId(userId);order.setAddress(异常信息exception.getClass());return order;} 6. Gateway - 网关
官网Spring Cloud Gateway
6.1. 基础入门
6.1.1. 功能 6.1.2. HelloWorld
/api/order/**路由给订单
/api/product/**路由给商品
测试负载均衡 6.1.2.1. 创建项目
引入 spring-cloud-starter-gateway、spring-cloud-starter-alibaba-nacos-discovery
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId
/dependency
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId
/dependency 6.1.2.2. 改造微服务
为 service-order、service-prduct 添加 /api基础路径 6.1.2.3. 配置网关
创建 application.yml编写如下配置
spring:cloud:gateway:routes:- id: orderuri: lb://service-orderpredicates:- Path/api/order/**- id: producturi: lb://service-productpredicates:- Path/api/product/** 6.1.3. 原理 6.2. Predicate - 断言
spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- After2017-01-20T17:42:47.789-07:00[America/Denver] 名 参数个数/类型 作用 After 1/datetime 在指定时间之后 Before 1/datetime 在指定时间之前 Between 2/datetime 在指定时间区间内 Cookie 2/string,regexp 包含cookie名且必须匹配指定值 Header 2/string,regexp 包含请求头且必须匹配指定值 Host N/string 请求host必须是指定枚举值 Method N/string 请求方式必须是指定枚举值 Path 2/ListString,bool 请求路径满足规则是否匹配最后的/ Query 2/string,regexp 包含指定请求参数 RemoteAddr 1/ListString 请求来源于指定网络域(CIDR写法) Weight 2/string,int 按指定权重负载均衡 XForwardedRemoteAddr 1/Liststring 从X-Forwarded-For请求头中解析请求来源并判断是否来源于指定网络域 6.3. Filter - 过滤器 名 参数个数/类型 作用 AddRequestHeader 2/string 添加请求头 AddRequestHeadersIfNotPresent 1/Liststring 如果没有则添加请求头key:value方式 AddRequestParameter 2/string、string 添加请求参数 AddResponseHeader 2/string、string 添加响应头 CircuitBreaker 1/string 仅支持forward:/inCaseOfFailureUseThis方式进行熔断 CacheRequestBody 1/string 缓存请求体 DedupeResponseHeader 1/string 移除重复响应头多个用空格分割 FallbackHeaders 1/string 设置Fallback头 JsonToGrpc 请求体Json转为gRPC LocalResponseCache 2/string 响应数据本地缓存 MapRequestHeader 2/string 把某个请求头名字变为另一个名字 ModifyRequestBody 仅 Java 代码方式 修改请求体 ModifyResponseBody 仅 Java 代码方式 修改响应体 PrefixPath 1/string 自动添加请求前缀路径 PreserveHostHeader 0 保护Host头 RedirectTo 3/string 重定向到指定位置 RemoveJsonAttributesResponseBody 1/string 移除响应体中的某些Json字段多个用,分割 RemoveRequestHeader 1/string 移除请求头 RemoveRequestParameter 1/string 移除请求参数 RemoveResponseHeader 1/string 移除响应头 RequestHeaderSize 2/string 设置请求大小超出则响应431状态码 RequestRateLimiter 1/string 请求限流 RewriteLocationResponseHeader 4/string 重写Location响应头 RewritePath 2/string 路径重写 RewriteRequestParameter 2/string 请求参数重写 RewriteResponseHeader 3/string 响应头重写 SaveSession 0 session保存配合spring-session框架 SecureHeaders 0 安全头设置 SetPath 1/string 路径修改 SetRequestHeader 2/string 请求头修改 SetResponseHeader 2/string 响应头修改 SetStatus 1/int 设置响应状态码 StripPrefix 1/int 路径层级拆除 Retry 7/string 请求重试设置 RequestSize 1/string 请求大小限定 SetRequestHostHeader 1/string 设置Host请求头 TokenRelay 1/string OAuth2的token转发 6.4. CORS - 跨域处理
全局跨域
spring:cloud:gateway:globalcors:cors-configurations:[/**]:allowedOrigins: https://docs.spring.ioallowedMethods:- GET 局部跨域
spring:cloud:gateway:routes:- id: cors_routeuri: https://example.orgpredicates:- Path/service/**metadata:cors:allowedOrigins: *allowedMethods:- GET- POSTallowedHeaders: *maxAge: 30 6.5. GlobalFilter
Bean
public GlobalFilter customFilter() {return new CustomGlobalFilter();
}public class CustomGlobalFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info(custom global filter);return chain.filter(exchange);}Overridepublic int getOrder() {return -1;}
} 7. Seata - 分布式事务
官网Apache Seata
7.1. 环境搭建
7.1.1. 微服务
下载 seata 工程文件导入到项目中并在 services中添加module聚合
seata-demo.zip
7.1.2. SQL
启动一个数据库然后运行如下sql文件
CREATE DATABASE IF NOT EXISTS storage_db;
USE storage_db;
DROP TABLE IF EXISTS storage_tbl;
CREATE TABLE storage_tbl (id int(11) NOT NULL AUTO_INCREMENT,commodity_code varchar(255) DEFAULT NULL,count int(11) DEFAULT 0,PRIMARY KEY (id),UNIQUE KEY (commodity_code)
) ENGINEInnoDB DEFAULT CHARSETutf8;
INSERT INTO storage_tbl (commodity_code, count) VALUES (P0001, 100);
INSERT INTO storage_tbl (commodity_code, count) VALUES (B1234, 10);-- 注意此处0.3.0 增加唯一索引 ux_undo_log
DROP TABLE IF EXISTS undo_log;
CREATE TABLE undo_log (id bigint(20) NOT NULL AUTO_INCREMENT,branch_id bigint(20) NOT NULL,xid varchar(100) NOT NULL,context varchar(128) NOT NULL,rollback_info longblob NOT NULL,log_status int(11) NOT NULL,log_created datetime NOT NULL,log_modified datetime NOT NULL,ext varchar(100) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY ux_undo_log (xid,branch_id)
) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8;CREATE DATABASE IF NOT EXISTS order_db;
USE order_db;
DROP TABLE IF EXISTS order_tbl;
CREATE TABLE order_tbl (id int(11) NOT NULL AUTO_INCREMENT,user_id varchar(255) DEFAULT NULL,commodity_code varchar(255) DEFAULT NULL,count int(11) DEFAULT 0,money int(11) DEFAULT 0,PRIMARY KEY (id)
) ENGINEInnoDB DEFAULT CHARSETutf8;
-- 注意此处0.3.0 增加唯一索引 ux_undo_log
DROP TABLE IF EXISTS undo_log;
CREATE TABLE undo_log (id bigint(20) NOT NULL AUTO_INCREMENT,branch_id bigint(20) NOT NULL,xid varchar(100) NOT NULL,context varchar(128) NOT NULL,rollback_info longblob NOT NULL,log_status int(11) NOT NULL,log_created datetime NOT NULL,log_modified datetime NOT NULL,ext varchar(100) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY ux_undo_log (xid,branch_id)
) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8;CREATE DATABASE IF NOT EXISTS account_db;
USE account_db;
DROP TABLE IF EXISTS account_tbl;
CREATE TABLE account_tbl (id int(11) NOT NULL AUTO_INCREMENT,user_id varchar(255) DEFAULT NULL,money int(11) DEFAULT 0,PRIMARY KEY (id)
) ENGINEInnoDB DEFAULT CHARSETutf8;
INSERT INTO account_tbl (user_id, money) VALUES (1, 10000);
-- 注意此处0.3.0 增加唯一索引 ux_undo_log
DROP TABLE IF EXISTS undo_log;
CREATE TABLE undo_log (id bigint(20) NOT NULL AUTO_INCREMENT,branch_id bigint(20) NOT NULL,xid varchar(100) NOT NULL,context varchar(128) NOT NULL,rollback_info longblob NOT NULL,log_status int(11) NOT NULL,log_created datetime NOT NULL,log_modified datetime NOT NULL,ext varchar(100) DEFAULT NULL,PRIMARY KEY (id),UNIQUE KEY ux_undo_log (xid,branch_id)
) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8; 7.1.3. seata-server
下载Seata Java Download | Apache Seata
apache-seata-2.1.0-incubating-bin.tar.gz 解压并启动seata-server.bat 7.1.4. 微服务配置
7.1.4.1. 依赖
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactId
/dependency
7.1.4.2. 配置
每个微服务创建 file.conf文件完整内容如下
【微服务只需要复制 service 块配置即可】
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the License); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#transport {# tcp, unix-domain-sockettype TCP#NIO, NATIVEserver NIO#enable heartbeatheartbeat true# the tm client batch send request enableenableTmClientBatchSendRequest false# the rm client batch send request enableenableRmClientBatchSendRequest true# the rm client rpc request timeoutrpcRmRequestTimeout 2000# the tm client rpc request timeoutrpcTmRequestTimeout 30000# the rm client rpc request timeoutrpcRmRequestTimeout 15000#thread factory for nettythreadFactory {bossThreadPrefix NettyBossworkerThreadPrefix NettyServerNIOWorkerserverExecutorThread-prefix NettyServerBizHandlershareBossWorker falseclientSelectorThreadPrefix NettyClientSelectorclientSelectorThreadSize 1clientWorkerThreadPrefix NettyClientWorkerThread# netty boss thread sizebossThreadSize 1#auto default pin or 8workerThreadSize default}shutdown {# when destroy server, wait secondswait 3}serialization seatacompressor none
}
service {#transaction service group mappingvgroupMapping.default_tx_group default#only support when registry.typefile, please dont set multiple addressesdefault.grouplist 127.0.0.1:8091#degrade, current not supportenableDegrade false#disable seatadisableGlobalTransaction false
}client {rm {asyncCommitBufferLimit 10000lock {retryInterval 10retryTimes 30retryPolicyBranchRollbackOnConflict true}reportRetryCount 5tableMetaCheckEnable falsetableMetaCheckerInterval 60000reportSuccessEnable falsesagaBranchRegisterEnable falsesagaJsonParser fastjsonsagaRetryPersistModeUpdate falsesagaCompensatePersistModeUpdate falsetccActionInterceptorOrder -2147482648 #Ordered.HIGHEST_PRECEDENCE 1000sqlParserType druidbranchExecutionTimeoutXA 60000connectionTwoPhaseHoldTimeoutXA 10000}tm {commitRetryCount 5rollbackRetryCount 5defaultGlobalTransactionTimeout 60000degradeCheck falsedegradeCheckPeriod 2000degradeCheckAllowTimes 10interceptorOrder -2147482648 #Ordered.HIGHEST_PRECEDENCE 1000}undo {dataValidation trueonlyCareUpdateColumns truelogSerialization jacksonlogTable undo_logcompress {enable true# allow zip, gzip, deflater, lz4, bzip2, zstd default is ziptype zip# if rollback info size threshold, then will be compress# allow k m g tthreshold 64k}}loadBalance {type XIDvirtualNodes 10}
}
log {exceptionRate 100
}
tcc {fence {# tcc fence log table namelogTableName tcc_fence_log# tcc fence log clean periodcleanPeriod 1h}
} 7.2. 事务模式
7.2.1. AT
二阶提交协议原理 7.2.2. XA 7.2.3. TCC 7.2.4. Saga 8. 总结