• springCloudeAlibaba的使用


    父pom文件:

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0modelVersion>
    6. <modules>
    7. <module>ordermodule>
    8. <module>commonmodule>
    9. <module>usermodule>
    10. <module>openFeignOrdermodule>
    11. modules>
    12. <groupId>org.examplegroupId>
    13. <artifactId>springCloudAlibabaartifactId>
    14. <version>1.0-SNAPSHOTversion>
    15. <packaging>pompackaging>
    16. <parent>
    17. <groupId>org.springframework.bootgroupId>
    18. <artifactId>spring-boot-starter-parentartifactId>
    19. <version>2.3.11.RELEASEversion>
    20. <relativePath/>
    21. parent>
    22. <dependencies>
    23. <dependency>
    24. <groupId>org.projectlombokgroupId>
    25. <artifactId>lombokartifactId>
    26. <version>1.18.30version>
    27. dependency>
    28. dependencies>
    29. <dependencyManagement>
    30. <dependencies>
    31. <dependency>
    32. <groupId>com.alibaba.cloudgroupId>
    33. <artifactId>spring-cloud-alibaba-dependenciesartifactId>
    34. <version>2.2.5.RELEASEversion>
    35. <type>pomtype>
    36. <scope>importscope>
    37. dependency>
    38. <dependency>
    39. <groupId>org.springframework.cloudgroupId>
    40. <artifactId>spring-cloud-dependenciesartifactId>
    41. <version>Hoxton.SR8version>
    42. <type>pomtype>
    43. <scope>importscope>
    44. dependency>
    45. dependencies>
    46. dependencyManagement>
    47. <properties>
    48. <skywalking.version>8.5.0skywalking.version>
    49. <maven.compiler.source>8maven.compiler.source>
    50. <maven.compiler.target>8maven.compiler.target>
    51. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    52. properties>
    53. <build>
    54. <plugins>
    55. <plugin>
    56. <groupId>org.springframework.bootgroupId>
    57. <artifactId>spring-boot-maven-pluginartifactId>
    58. plugin>
    59. plugins>
    60. build>
    61. project>

    (一定要遵从springcloude版本约定的各个组件版本号,直接往上搜来看版本发布说明 | Spring Cloud Alibaba (aliyun.com))首先原来的服务注册与发现eureka被替代为nacos,直接下载运行 startup.cmd ,要改成单机运行:

    set MODE="standalone"

    然后配置文件这样配置yml:

    1. server:
    2. port: 8001
    3. spring:
    4. application:
    5. #注册成功后,这就是你的服务名
    6. name: user-server
    7. cloud:
    8. nacos:
    9. # nacos服务ip
    10. server-addr: 192.168.126.1:8848
    11. discovery:
    12. # 空间id
    13. namespace: c1102e00-c947-4d0c-8320-b98dc7fae641
    14. # 分组
    15. group: TEST

     调用方式:

    1. package com.stockServer.controller;
    2. import com.common.util.MyServerNameUtil;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.web.bind.annotation.PostMapping;
    5. import org.springframework.web.bind.annotation.RequestMapping;
    6. import org.springframework.web.bind.annotation.RestController;
    7. import org.springframework.web.client.RestTemplate;
    8. /**
    9. * @program: springCloudAlibaba
    10. * @author: quxiao
    11. * @create: 2024-02-03 12:57
    12. **/
    13. @RequestMapping("/dingDan")
    14. @RestController
    15. public class DingDanController {
    16. @Autowired
    17. RestTemplate restTemplate;
    18. @PostMapping("/xiadan")
    19. public String xiadan() {
    20. String template = restTemplate.postForObject("http://" + "user-server" + "/XiaDab/jianKuChun", null, String.class);
    21. return template;
    22. }
    23. }

    就不再需要指定完全的url地址,还有就是默认集成了ribbon调用方式,也就是说,可以自己设定调用的方式,轮询、随机。。。。

    1. package com.stockServer.config;
    2. import com.alibaba.cloud.nacos.ribbon.NacosRule;
    3. import com.netflix.loadbalancer.IRule;
    4. import com.netflix.loadbalancer.RandomRule;
    5. import org.springframework.boot.web.client.RestTemplateBuilder;
    6. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    7. import org.springframework.context.annotation.Bean;
    8. import org.springframework.context.annotation.Configuration;
    9. import org.springframework.web.client.RestTemplate;
    10. /**
    11. * @program: springCloudAlibaba
    12. * @author: quxiao
    13. * @create: 2024-02-03 13:00
    14. **/
    15. @Configuration
    16. public class SpringConfig {
    17. @Bean
    18. @LoadBalanced
    19. public RestTemplate getRestTemplate(RestTemplateBuilder builder) {
    20. return builder.build();
    21. }
    22. @Bean
    23. public IRule getRule() {
    24. // 随机掉用
    25. return new RandomRule();
    26. }
    27. }

    使用open-fegin进行调用,不再需要使用url的方式,直接声明接口(请直接创建一个新的模块,不要再图方便,直接修改能跑的模块了!!!!!!!!!):

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <parent>
    6. <artifactId>springCloudAlibabaartifactId>
    7. <groupId>org.examplegroupId>
    8. <version>1.0-SNAPSHOTversion>
    9. parent>
    10. <modelVersion>4.0.0modelVersion>
    11. <artifactId>openFeignOrderartifactId>
    12. <dependencies>
    13. <dependency>
    14. <groupId>com.alibaba.cloudgroupId>
    15. <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    16. dependency>
    17. <dependency>
    18. <groupId>org.examplegroupId>
    19. <artifactId>commonartifactId>
    20. <version>1.0-SNAPSHOTversion>
    21. <scope>compilescope>
    22. dependency>
    23. <dependency>
    24. <groupId>org.springframework.bootgroupId>
    25. <artifactId>spring-boot-starter-webartifactId>
    26. dependency>
    27. <dependency>
    28. <groupId>org.springframework.cloudgroupId>
    29. <artifactId>spring-cloud-starter-openfeignartifactId>
    30. dependency>
    31. dependencies>
    32. <properties>
    33. <maven.compiler.source>8maven.compiler.source>
    34. <maven.compiler.target>8maven.compiler.target>
    35. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    36. properties>
    37. project>
    1. package com.stockServer.fegin;
    2. import com.common.dto.MsgData;
    3. import org.springframework.cloud.openfeign.FeignClient;
    4. import org.springframework.web.bind.annotation.PostMapping;
    5. //指定远程接口的服务名,path是@RequestMapping的地址
    6. @FeignClient(name = "user-server", path = "XiaDab")
    7. public interface openFeginOrder {
    8. @PostMapping("/jianKuChun")
    9. public String jianKuChun();
    10. @PostMapping("/quxiao")
    11. //方法名可以不同,但是 @PostMapping("/quxiao")必须完全一样!
    12. public MsgData quxiao();
    13. }

    调用方式:

    1. package com.stockServer.controller;
    2. import com.stockServer.fegin.openFeginOrder;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.web.bind.annotation.PostMapping;
    5. import org.springframework.web.bind.annotation.RequestMapping;
    6. import org.springframework.web.bind.annotation.RestController;
    7. /**
    8. * @program: springCloudAlibaba
    9. * @author: quxiao
    10. * @create: 2024-02-03 12:57
    11. **/
    12. @RequestMapping("/dingDan")
    13. @RestController
    14. public class DingDanController {
    15. //直接注入这个接口,调用它的方法
    16. @Autowired
    17. openFeginOrder openFeginOrder;
    18. @PostMapping("/xiadan")
    19. public String xiadan() {
    20. String template = openFeginOrder.quxiao1().toString();
    21. return template;
    22. }
    23. }

    记得开启fegin哦(我在项目上就是因为没开启,导致一直走降级方法。。。。)

    开启:

    1. package com.stockServer;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    5. import org.springframework.cloud.openfeign.EnableFeignClients;
    6. @SpringBootApplication
    7. @EnableDiscoveryClient
    8. //开启fegin调用
    9. @EnableFeignClients
    10. public class fenginOrderApplication {
    11. public static void main(String[] args) {
    12. SpringApplication.run(fenginOrderApplication.class);
    13. }
    14. }

    也就是说,相当于再我这个服务写一个调用另一个服务的controller,标记了url地址。

    (另一种方式是直接在每一个服务上写一个api模块,每一个服务都有)

    然后实现对外的接口,具体逻辑写好,另一个模块引入然后调用。

    还有另一种远程调用的方式:

     专门用一个api模块来表示是这个服务对外接口。

    具体实现由server来实现。

     启动类将对外的接口加载进来

    Sentinel限流,容灾等使用:

    1. <dependency>
    2. <groupId>com.alibaba.cloudgroupId>
    3. <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
    4. dependency>
    1. private static final String T1 = "t1";
    2. //注解方式
    3. //blockHandlerClass 将限流的方法写在指定的类中,静态,公共的
    4. //blockHandler 指定达到限流后执行的方法
    5. //fallback 发生异常后,容灾方法
    6. //fallbackClass 将容灾的方法写在指定的类中,静态,公共的
    7. @GetMapping("/t1")
    8. @SentinelResource(value = T1, blockHandlerClass = test.class, blockHandler = "t1cw", fallback = "t1rz", fallbackClass = test.class)
    9. public String t1() {
    10. //代码的方式添加限流,或者容灾
    11. // Entry entry = null;
    12. // try {
    13. // entry = SphU.entry("t1");
    14. // } catch (BlockException e) {
    15. // return "被限流了";
    16. // } catch (Exception e) {
    17. // Tracer.traceEntry(e, entry);
    18. // } finally {
    19. // if (entry != null) {
    20. // entry.exit();
    21. // }
    22. // }
    23. // int a = 0 / 1;
    24. // a = 1 / 0;
    25. return "t1";
    26. }
    27. @PostConstruct
    28. private static void init() {
    29. List rules = new ArrayList<>();
    30. FlowRule rule = new FlowRule();
    31. //接口名
    32. rule.setResource("t1");
    33. //限流策略
    34. rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    35. rule.setCount(1);
    36. rules.add(rule);
    37. FlowRuleManager.loadRules(rules);
    38. }

    Sentinel有一个网页界面,拿来查看具体数据:

    需要去官网相爱一个jar包,然后运行。并且在需要监听的心目中指定页面的端口

    java -jar sentinel-dashboard-1.8.0.jar --server.port=8002

    (dashboard: localhost:8002):

    1. server:
    2. port: 8011
    3. spring:
    4. application:
    5. name: stock1-server
    6. cloud:
    7. sentinel:
    8. transport:
    9. dashboard: localhost:8002
    10. nacos:
    11. server-addr: 192.168.126.1:8848
    12. discovery:
    13. namespace: c1102e00-c947-4d0c-8320-b98dc7fae641
    14. group: TEST

    限流、降级方法的指定方式:

    1、直接在接口的同一个类里指定:参数名,返回值相同,多一个异常

    BlockException类

    1. @GetMapping("getStock2/{id}")
    2. @SentinelResource(value = "getStock2", blockHandler = "getStock2err")
    3. public String getStock2(@PathVariable("id") long id) {
    4. return "" + id;
    5. }
    6. public String getStock2err(@PathVariable("id") Long id, BlockException e) {
    7. return "限流操作";
    8. }
     2、放在指定的类里面:
    1. public class test {
    2. public static String t1cw(BlockException e) {
    3. return "流控方法";
    4. }
    5. public static String t1rz(Throwable e) {
    6. return "发生错误方法";
    7. }
    1. /**
    2. * blockHandlerClass 流控方法类
    3. * blockHandler 流控方法名
    4. * fallbackClass 降级(发生异常)方法类
    5. * fallback 降级(发生异常)方法名
    6. */
    7. @GetMapping("/t2")
    8. @SentinelResource(value = "t2", blockHandlerClass = test.class, blockHandler = "t1cw", fallback = "t1rz", fallbackClass = test.class)
    9. public String t2() {
    10. return "t2";
    11. }

    将需要调用的方法放在其他类中,是有约定的,方法必须是static的,因为这个方法必须比接口对应的方法先加载到jvm中。

    3、全局管理:
    1. package com.stock1Server.ecception;
    2. import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
    3. import com.alibaba.csp.sentinel.slots.block.BlockException;
    4. import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
    5. import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
    6. import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
    7. import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
    8. import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
    9. import org.springframework.stereotype.Component;
    10. import javax.servlet.http.HttpServletRequest;
    11. import javax.servlet.http.HttpServletResponse;
    12. @Component
    13. public class MyBlockExceptionHandler implements BlockExceptionHandler {
    14. @Override
    15. public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
    16. String rs = null;
    17. if (e instanceof FlowException)
    18. rs = "接口限流了";
    19. else if (e instanceof DegradeException)
    20. rs = "服务降级了";
    21. else if (e instanceof ParamFlowException)
    22. rs = "参数限流了";
    23. else if (e instanceof AuthorityException)
    24. rs = "权限规则不通过";
    25. else if (e instanceof SystemBlockException)
    26. rs = "系统保护";
    27. httpServletResponse.setContentType("application/json;charset=utf-8");
    28. httpServletResponse.getWriter().write(rs);
    29. }
    30. }

    流控规则介绍:

    直接:

    达到流控要求是,直接进行流控(执行流控方法)、

    关联:

    意识是不在为自己设置流控,而是为他人,只要他人达到流控约束条件,我就执行流控方法。

    链路模式不做介绍,用的太少了。

    流控效果

    快速失败就是达到流控时,直接调用流控方法
    warm up

    是预热模式,就是处理能力会越来越强,适合激增请求的场景。

    排队等待

    就是有心跳式的访问,一下子多,停一会,又一下子变多。中间有一定的等待时间,这一段时间就可以拿来让服务器处理。

     降级规则:

    慢调用比例

    最小5此请求,达到10%次执行时间超过1000毫秒,持续10秒开始执行降级方法,10秒后,若第一次执行时间超过1000毫米,又持续10秒开始执行降级方法(半开状态)直到新的一次调用小于1000毫秒。

    异常比例:

    最小5此请求,达到10%次异常,持续10秒开始执行降级方法,10秒后,若第一次执行时间超过1000毫米,又持续10秒开始执行降级方法(半开状态)直到新的一次调用小于1000毫秒。

    异常数:

    最小5此请求,达到1次异常,持续10秒开始执行降级方法,10秒后,若第一次执行时间超过1000毫米,又持续10秒开始执行降级方法(半开状态)直到新的一次调用小于1000毫秒。

    结合openfigen

    要在配置文件中开启sentinel和openfigen的使用

    1. feign:
    2. sentinel:
    3. enabled: true

    然后再提供方,调用方都加上:依赖,并且开启上面的两个框架的集成。

    热点规则使用:

    一句话:给方法参数的某个数据添加流控,例如:给id为1、2、3添加流控,1秒2次就开启流控。其他数据1秒5次开启流控。

    用sentinel页面这玩意看运气,我添加了一下午才成功这一次,用代码添加如下:

    1. @PostConstruct
    2. public static void initParamFlowRule() {
    3. //使用这个方式,居然没有调用我指定的限流方法,待解决
    4. List rules = new ArrayList<>();
    5. ParamFlowRule rule = new ParamFlowRule();
    6. //阈值类型:只支持QPS
    7. rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    8. //其它参数调用次数
    9. rule.setCount(10);
    10. //接口名
    11. rule.setResource("getStock2");
    12. //第几个参数,0为第一个
    13. rule.setParamIdx(0);
    14. //约定时间
    15. rule.setDurationInSec(1);
    16. List items = new ArrayList<>();
    17. ParamFlowItem item1 = new ParamFlowItem();
    18. item1.setClassType(long.class.getName());
    19. //超过约定时间访问参数
    20. item1.setCount(2);
    21. //具体参数值
    22. item1.setObject("1");
    23. items.add(item1);
    24. rule.setParamFlowItemList(items);
    25. rules.add(rule);
    26. ParamFlowRuleManager.loadRules(rules);
    27. }

     持久化sentinel配置:

    就是将图形化界面的配置,用json的格式,挨个挨个配置到nacos的config中,我在想,高版本的sentinel应该会出现直接保存到nacos的mysql数据库中,然后直接快熟导入。

    1. com.alibaba.csp
    2. sentinel-datasource-nacos
    3. com.alibaba.cloud
    4. spring-cloud-starter-alibaba-nacos-config

    一个是持久化依赖,一个是nacos配置中心的依赖,再配置中心手动加上配置:

    代码项目中使用:

    1. server:
    2. port: 8011
    3. spring:
    4. application:
    5. name: stock1-server
    6. cloud:
    7. sentinel:
    8. transport:
    9. dashboard: localhost:8002
    10. datasource:
    11. flow-rule:
    12. nacos:
    13. server-addr: 192.168.126.1:8848
    14. data-id: stock1-server-sentinel-config
    15. ruleType: flow
    16. nacos:
    17. server-addr: 192.168.126.1:8848
    18. discovery:
    19. namespace: c1102e00-c947-4d0c-8320-b98dc7fae641
    20. group: TEST
    21. feign:
    22. sentinel:
    23. enabled: true

    seata分布式事务搭建:

    首先需要下载对应的steta版本,并且记得把源码版也下上,后面将配置导入nacos需要用:

    修改配置:

    file.con文件

    1. ## transaction log store, only used in seata-server
    2. store {
    3. ## store mode: file、db、redis
    4. mode = "db"
    5. db {
    6. datasource = "druid"
    7. dbType = "mysql"
    8. driverClassName = "com.mysql.cj.jdbc.Driver"
    9. url = "jdbc:mysql://192.168.126.128:3306/seata?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true"
    10. user = "root"
    11. password = "123456"
    12. minConn = 5
    13. maxConn = 30
    14. globalTable = "global_table"
    15. branchTable = "branch_table"
    16. lockTable = "lock_table"
    17. queryLimit = 100
    18. maxWait = 5000
    19. }
    20. }

    就是指定自己的mysql数据库地址,外加三张必须得表:

    源码文件的这里:

    然后是配置到nacos的文件:

    registry.conf

    1. registry {
    2. # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
    3. type = "nacos"
    4. nacos {
    5. application = "seata-server"
    6. serverAddr = "192.168.126.1:8848"
    7. group = "SEATA_GROUP"
    8. namespace = ""
    9. cluster = "default"
    10. username = "nacos"
    11. password = "nacos"
    12. }
    13. file {
    14. name = "file.conf"
    15. }
    16. }
    17. config {
    18. # file、nacos 、apollo、zk、consul、etcd3
    19. type = "nacos"
    20. nacos {
    21. serverAddr = "192.168.126.1:8848"
    22. namespace = ""
    23. group = "SEATA_GROUP"
    24. username = "nacos"
    25. password = "nacos"
    26. }
    27. file {
    28. name = "file.conf"
    29. }
    30. }

    就是指定nacos的地址,加载到nacos后seata的基本信息。

    导入配置到nacos中:

    既然是使用nacos的配置,就得把配置放进nacos配置源中,在seata的源码文件中,有快速将配置加载到nacos配置源中的方法:

    1. transport.type=TCP
    2. transport.server=NIO
    3. transport.heartbeat=true
    4. transport.enableClientBatchSendRequest=false
    5. transport.threadFactory.bossThreadPrefix=NettyBoss
    6. transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
    7. transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
    8. transport.threadFactory.shareBossWorker=false
    9. transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
    10. transport.threadFactory.clientSelectorThreadSize=1
    11. transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
    12. transport.threadFactory.bossThreadSize=1
    13. transport.threadFactory.workerThreadSize=default
    14. transport.shutdown.wait=3
    15. service.vgroupMapping.my_test_tx_group=default
    16. service.default.grouplist=127.0.0.1:8091
    17. service.enableDegrade=false
    18. service.disableGlobalTransaction=false
    19. client.rm.asyncCommitBufferLimit=10000
    20. client.rm.lock.retryInterval=10
    21. client.rm.lock.retryTimes=30
    22. client.rm.lock.retryPolicyBranchRollbackOnConflict=true
    23. client.rm.reportRetryCount=5
    24. client.rm.tableMetaCheckEnable=false
    25. client.rm.sqlParserType=druid
    26. client.rm.reportSuccessEnable=false
    27. client.rm.sagaBranchRegisterEnable=false
    28. client.tm.commitRetryCount=5
    29. client.tm.rollbackRetryCount=5
    30. client.tm.degradeCheck=false
    31. client.tm.degradeCheckAllowTimes=10
    32. client.tm.degradeCheckPeriod=2000
    33. store.mode=db
    34. store.file.dir=file_store/data
    35. store.file.maxBranchSessionSize=16384
    36. store.file.maxGlobalSessionSize=512
    37. store.file.fileWriteBufferCacheSize=16384
    38. store.file.flushDiskMode=async
    39. store.file.sessionReloadReadSize=100
    40. store.db.datasource=druid
    41. store.db.dbType=mysql
    42. store.db.driverClassName=com.mysql.cj.jdbc.Driver
    43. store.db.url=mysql://192.168.126.128:3306/seata?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
    44. store.db.user=root
    45. store.db.password=123456
    46. store.db.minConn=5
    47. store.db.maxConn=30
    48. store.db.globalTable=global_table
    49. store.db.branchTable=branch_table
    50. store.db.queryLimit=100
    51. store.db.lockTable=lock_table
    52. store.db.maxWait=5000
    53. store.redis.host=127.0.0.1
    54. store.redis.port=6379
    55. store.redis.maxConn=10
    56. store.redis.minConn=1
    57. store.redis.database=0
    58. store.redis.password=null
    59. store.redis.queryLimit=100
    60. server.recovery.committingRetryPeriod=1000
    61. server.recovery.asynCommittingRetryPeriod=1000
    62. server.recovery.rollbackingRetryPeriod=1000
    63. server.recovery.timeoutRetryPeriod=1000
    64. server.maxCommitRetryTimeout=-1
    65. server.maxRollbackRetryTimeout=-1
    66. server.rollbackRetryTimeoutUnlockEnable=false
    67. client.undo.dataValidation=true
    68. client.undo.logSerialization=jackson
    69. client.undo.onlyCareUpdateColumns=true
    70. server.undo.logSaveDays=7
    71. server.undo.logDeletePeriod=86400000
    72. client.undo.logTable=undo_log
    73. client.log.exceptionRate=100
    74. transport.serialization=seata
    75. transport.compressor=none
    76. metrics.enabled=false
    77. metrics.registryType=compact
    78. metrics.exporterList=prometheus
    79. metrics.exporterPrometheusPort=9898

    修改这几个地方:

    store.mode=db

    store.db.driverClassName=com.mysql.cj.jdbc.Driver
    store.db.url=mysql://192.168.126.128:3306/seata?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
    store.db.user=root
    store.db.password=123456

    和前面的file.con文件保持一致,唯一不同的就是这个store.db.url的连接方式,我用和file.con文件一样的,它就报错,连接不上后来差了资料,改了链接语句。

    然后必须有git软件在电脑上,它可以运行bash语句,也就是linux的。

    有python也可以。

    项目配置:

    然后在需要使用seata全局事务配置文件中,加上对seata的配置:

    1. server:
    2. port: 8011
    3. spring:
    4. application:
    5. name: stock1-server
    6. cloud:
    7. sentinel:
    8. transport:
    9. dashboard: localhost:8002
    10. datasource:
    11. flow-rule:
    12. nacos:
    13. server-addr: 192.168.126.1:8848
    14. data-id: stock1-server-sentinel-config
    15. ruleType: flow
    16. nacos:
    17. server-addr: 192.168.126.1:8848
    18. discovery:
    19. namespace: c1102e00-c947-4d0c-8320-b98dc7fae641
    20. group: TEST
    21. alibaba:
    22. seata:
    23. tx-service-group: my_test_tx_group #事务分组
    24. datasource:
    25. driver-class-name: com.mysql.cj.jdbc.Driver
    26. type: com.alibaba.druid.pool.DruidDataSource
    27. url: jdbc:mysql://192.168.126.128:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    28. username: root
    29. password: 123456
    30. feign:
    31. sentinel:
    32. enabled: true
    33. mybatis-plus:
    34. configuration:
    35. map-underscore-to-camel-case: true
    36. auto-mapping-behavior: full
    37. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    38. seata:
    39. registry:
    40. type: nacos
    41. nacos:
    42. server-addr: 192.168.126.1:8848 #nacos地址
    43. application: seata-server #在nacos中的服务名
    44. username: nacos #nacos账号密码
    45. password: nacos
    46. group: SEATA_GROUP #在nacos中的分组名
    47. config:
    48. nacos:
    49. server-addr: 192.168.126.1:8848

    添加这两个地方:

    seata分组是在上面config.txt中配置的:

    service.vgroupMapping.my_test_tx_group=default

    使用 :my_test_tx_group

    使用全局事务处理:

    1. @GlobalTransactional
    2. @GetMapping("getStock1/{code}")
    3. @GlobalLock
    4. @SentinelResource(value = "getStock1", fallback = "getStock1err")
    5. public MsgTxt getStock1(@PathVariable("code") String code) {
    6. MsgTxt print = stock1FeignClient.print(code, 14);//扣除数量
    7. worktableService.updateByIdTest1();//保存单号
    8. int a = 1 / 0;//发生异常
    9. return print;
    10. }

    扣除数量就是一个远程方法,扣除数据。

    然后本服务发生异常,就会通知seata回滚,本方法修改了的表也会回滚,seata现在使用的是AT管理,自动事务。

    当开启分布式事务时,调用sql方法,就会在seata的数据库中保留回滚的数据,如下:

    global_table表就是存放执行分布式方法时,进入全局方法,就会生产它,这个方法的全局信息。

    lock_table表是运行数据库操作后,生产一个表信息。操作一个表,增加一个信息。如下:

    我就执行了远程服务的方法,里面操作了两个表,seata就生成了两条数据:

    branch_table表存放的是涉及到了多少个服务。很明显我调用了两个服务,所以两条数据,并且保存各自的服务信息。

    undo_log表就是存放执行情况,只要是修改了的数据,都会保存在这,里面包含了修改前数据,修改后数据。

    1. 修改前数据:
    2. "beforeImage": {
    3. "@class": "io.seata.rm.datasource.sql.struct.TableRecords",
    4. "tableName": "worktable",
    5. "rows": [
    6. "java.util.ArrayList",
    7. [
    8. {
    9. "@class": "io.seata.rm.datasource.sql.struct.Row",
    10. "fields": [
    11. "java.util.ArrayList",
    12. [
    13. {
    14. "@class": "io.seata.rm.datasource.sql.struct.Field",
    15. "name": "i1",
    16. "keyType": "PRIMARY_KEY",
    17. "type": 4,
    18. "value": 1
    19. },
    20. {
    21. "@class": "io.seata.rm.datasource.sql.struct.Field",
    22. "name": "i2",
    23. "keyType": "NULL",
    24. "type": 12,
    25. "value": "123321"
    26. }
    27. ]
    28. ]
    29. }
    30. ]
    31. ]
    32. }
    33. 修改后数据
    34. "afterImage": {
    35. "@class": "io.seata.rm.datasource.sql.struct.TableRecords",
    36. "tableName": "worktable",
    37. "rows": [
    38. "java.util.ArrayList",
    39. [
    40. {
    41. "@class": "io.seata.rm.datasource.sql.struct.Row",
    42. "fields": [
    43. "java.util.ArrayList",
    44. [
    45. {
    46. "@class": "io.seata.rm.datasource.sql.struct.Field",
    47. "name": "i1",
    48. "keyType": "PRIMARY_KEY",
    49. "type": 4,
    50. "value": 1
    51. },
    52. {
    53. "@class": "io.seata.rm.datasource.sql.struct.Field",
    54. "name": "i2",
    55. "keyType": "NULL",
    56. "type": 12,
    57. "value": "20212904"
    58. }
    59. ]
    60. ]
    61. }
    62. ]
    63. ]
    64. }

    保存的发生修改sql之前的数据,和修改之后的数据。如果发生异常,就根据这里保存的数据,执行反向sql回滚

    还有另一个注解,分布式数据库锁:

    @GlobalLock

    一旦标识了这个,该方法在执行时,就回去获取锁,如果正好这条数据库数据还在分布式事务中,就会报错,不允许修改。读取不受限制。

    1. Creating a new SqlSession
    2. SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@55b12ac0] was not registered for synchronization because synchronization is not active
    3. 2024-03-09 16:18:42.997 WARN 2780 --- [nio-8011-exec-4] c.a.druid.pool.DruidAbstractDataSource : discard long time none received connection. , jdbcUrl : jdbc:mysql://192.168.126.128:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC, version : 1.2.4, lastPacketReceivedIdleMillis : 433818
    4. JDBC Connection [io.seata.rm.datasource.ConnectionProxy@5b76de06] will not be managed by Spring
    5. ==> Preparing: UPDATE user SET user_code=? WHERE (id = ?)
    6. ==> Parameters: 新数据(String), 14(Integer)
    7. <== Updates: 1
    8. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@55b12ac0]
    9. Creating a new SqlSession
    10. Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e4aeaba]
    11. JDBC Connection [io.seata.rm.datasource.ConnectionProxy@3c86fa5a] will be managed by Spring
    12. ==> Preparing: UPDATE worktable SET i2=? WHERE (i1 = ?)
    13. ==> Parameters: 多了一个表(String), 2(Integer)
    14. <== Updates: 1
    15. Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e4aeaba]
    16. Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e4aeaba]
    17. Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e4aeaba]
    18. Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e4aeaba]
    19. Creating a new SqlSession
    20. SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3c0e5228] was not registered for synchronization because synchronization is not active
    21. JDBC Connection [io.seata.rm.datasource.ConnectionProxy@7dbe36da] will not be managed by Spring
    22. ==> Preparing: UPDATE user SET user_code=? WHERE (id = ?)
    23. ==> Parameters: er(String), 14(Integer)
    24. 2024-03-09 16:18:46.397 ERROR 2780 --- [nio-8011-exec-5] i.s.r.d.exec.AbstractDMLBaseExecutor : execute executeAutoCommitTrue error:Global lock wait timeout
    25. io.seata.rm.datasource.exec.LockWaitTimeoutException: Global lock wait timeout
    26. at io.seata.rm.datasource.exec.LockRetryController.sleep(LockRetryController.java:52) ~[seata-all-1.3.0.jar:1.3.0]
    27. at io.seata.rm.datasource.ConnectionProxy$LockRetryPolicy.doRetryOnLockConflict(ConnectionProxy.java:302) ~[seata-all-1.3.0.jar:1.3.0]
    28. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor$LockRetryPolicy.execute(AbstractDMLBaseExecutor.java:155) ~[seata-all-1.3.0.jar:1.3.0]
    29. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor.executeAutoCommitTrue(AbstractDMLBaseExecutor.java:110) [seata-all-1.3.0.jar:1.3.0]
    30. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor.doExecute(AbstractDMLBaseExecutor.java:74) [seata-all-1.3.0.jar:1.3.0]
    31. at io.seata.rm.datasource.exec.BaseTransactionalExecutor.execute(BaseTransactionalExecutor.java:115) [seata-all-1.3.0.jar:1.3.0]
    32. at io.seata.rm.datasource.exec.ExecuteTemplate.execute(ExecuteTemplate.java:113) [seata-all-1.3.0.jar:1.3.0]
    33. at io.seata.rm.datasource.exec.ExecuteTemplate.execute(ExecuteTemplate.java:51) [seata-all-1.3.0.jar:1.3.0]
    34. at io.seata.rm.datasource.PreparedStatementProxy.execute(PreparedStatementProxy.java:55) [seata-all-1.3.0.jar:1.3.0]
    35. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
    36. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
    37. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    38. at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    39. at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59) [mybatis-3.5.7.jar:3.5.7]
    40. at com.sun.proxy.$Proxy123.execute(Unknown Source) [na:na]
    41. at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47) [mybatis-3.5.7.jar:3.5.7]
    42. at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74) [mybatis-3.5.7.jar:3.5.7]
    43. at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50) [mybatis-3.5.7.jar:3.5.7]
    44. at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) [mybatis-3.5.7.jar:3.5.7]
    45. at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) [mybatis-3.5.7.jar:3.5.7]
    46. at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194) [mybatis-3.5.7.jar:3.5.7]
    47. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
    48. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
    49. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    50. at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    51. at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) [mybatis-spring-2.0.6.jar:2.0.6]
    52. at com.sun.proxy.$Proxy82.update(Unknown Source) [na:na]
    53. at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:288) [mybatis-spring-2.0.6.jar:2.0.6]
    54. at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:64) [mybatis-plus-core-3.4.3.jar:3.4.3]
    55. at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) [mybatis-plus-core-3.4.3.jar:3.4.3]
    56. at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) [mybatis-plus-core-3.4.3.jar:3.4.3]
    57. at com.sun.proxy.$Proxy83.update(Unknown Source) [na:na]
    58. at com.baomidou.mybatisplus.extension.service.IService.update(IService.java:167) [mybatis-plus-extension-3.4.3.jar:3.4.3]
    59. at com.baomidou.mybatisplus.extension.service.IService.update(IService.java:157) [mybatis-plus-extension-3.4.3.jar:3.4.3]
    60. at com.stock1Server.service.impl.UserServiceImpl.updateTest(UserServiceImpl.java:24) [classes/:na]
    61. at com.stock1Server.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$3e673818.invoke() [classes/:na]
    62. at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) [spring-core-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    63. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    64. at com.stock1Server.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$c2539cd9.updateTest() [classes/:na]
    65. at com.stock1Server.controller.stockController.t6(stockController.java:118) [classes/:na]
    66. at com.stock1Server.controller.stockController$$FastClassBySpringCGLIB$$ae77ee83.invoke() [classes/:na]
    67. at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) [spring-core-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    68. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    69. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    70. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    71. at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    72. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    73. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    74. at io.seata.spring.annotation.GlobalTransactionalInterceptor.lambda$handleGlobalLock$0(GlobalTransactionalInterceptor.java:134) [seata-all-1.3.0.jar:1.3.0]
    75. at io.seata.rm.GlobalLockTemplate.execute(GlobalLockTemplate.java:48) ~[seata-all-1.3.0.jar:1.3.0]
    76. at io.seata.spring.annotation.GlobalTransactionalInterceptor.handleGlobalLock(GlobalTransactionalInterceptor.java:132) [seata-all-1.3.0.jar:1.3.0]
    77. at io.seata.spring.annotation.GlobalTransactionalInterceptor.invoke(GlobalTransactionalInterceptor.java:124) [seata-all-1.3.0.jar:1.3.0]
    78. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    79. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    80. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) [spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    81. at com.stock1Server.controller.stockController$$EnhancerBySpringCGLIB$$e2df0638.t6() ~[classes/:na]
    82. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
    83. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
    84. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    85. at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    86. at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    87. at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    88. at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    89. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    90. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    91. at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    92. at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    93. at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    94. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    95. at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    96. at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
    97. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    98. at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
    99. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    100. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    101. at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.46.jar:9.0.46]
    102. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    103. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    104. at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    105. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    106. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    107. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    108. at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    109. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    110. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    111. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    112. at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    113. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    114. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    115. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    116. at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    117. at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    118. at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    119. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    120. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    121. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    122. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    123. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    124. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    125. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    126. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    127. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    128. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_171]
    129. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_171]
    130. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    131. at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_171]
    132. Caused by: io.seata.rm.datasource.exec.LockConflictException: null
    133. at io.seata.rm.datasource.ConnectionProxy.checkLock(ConnectionProxy.java:119) ~[seata-all-1.3.0.jar:1.3.0]
    134. at io.seata.rm.datasource.ConnectionProxy.processLocalCommitWithGlobalLocks(ConnectionProxy.java:205) ~[seata-all-1.3.0.jar:1.3.0]
    135. at io.seata.rm.datasource.ConnectionProxy.doCommit(ConnectionProxy.java:198) ~[seata-all-1.3.0.jar:1.3.0]
    136. at io.seata.rm.datasource.ConnectionProxy.lambda$commit$0(ConnectionProxy.java:184) ~[seata-all-1.3.0.jar:1.3.0]
    137. at io.seata.rm.datasource.ConnectionProxy$LockRetryPolicy.execute(ConnectionProxy.java:289) ~[seata-all-1.3.0.jar:1.3.0]
    138. at io.seata.rm.datasource.ConnectionProxy.commit(ConnectionProxy.java:183) ~[seata-all-1.3.0.jar:1.3.0]
    139. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor.lambda$executeAutoCommitTrue$0(AbstractDMLBaseExecutor.java:112) [seata-all-1.3.0.jar:1.3.0]
    140. at io.seata.rm.datasource.ConnectionProxy$LockRetryPolicy.doRetryOnLockConflict(ConnectionProxy.java:299) ~[seata-all-1.3.0.jar:1.3.0]
    141. ... 104 common frames omitted
    142. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3c0e5228]
    143. 2024-03-09 16:18:46.466 ERROR 2780 --- [nio-8011-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.QueryTimeoutException:
    144. ### Error updating database. Cause: io.seata.rm.datasource.exec.LockWaitTimeoutException: Global lock wait timeout
    145. ### The error may exist in com/stock1Server/mapper/UserMapper.java (best guess)
    146. ### The error may involve com.stock1Server.mapper.UserMapper.update-Inline
    147. ### The error occurred while setting parameters
    148. ### SQL: UPDATE user SET user_code=? WHERE (id = ?)
    149. ### Cause: io.seata.rm.datasource.exec.LockWaitTimeoutException: Global lock wait timeout
    150. ; Global lock wait timeout; nested exception is io.seata.rm.datasource.exec.LockWaitTimeoutException: Global lock wait timeout] with root cause
    151. io.seata.rm.datasource.exec.LockConflictException: null
    152. at io.seata.rm.datasource.ConnectionProxy.checkLock(ConnectionProxy.java:119) ~[seata-all-1.3.0.jar:1.3.0]
    153. at io.seata.rm.datasource.ConnectionProxy.processLocalCommitWithGlobalLocks(ConnectionProxy.java:205) ~[seata-all-1.3.0.jar:1.3.0]
    154. at io.seata.rm.datasource.ConnectionProxy.doCommit(ConnectionProxy.java:198) ~[seata-all-1.3.0.jar:1.3.0]
    155. at io.seata.rm.datasource.ConnectionProxy.lambda$commit$0(ConnectionProxy.java:184) ~[seata-all-1.3.0.jar:1.3.0]
    156. at io.seata.rm.datasource.ConnectionProxy$LockRetryPolicy.execute(ConnectionProxy.java:289) ~[seata-all-1.3.0.jar:1.3.0]
    157. at io.seata.rm.datasource.ConnectionProxy.commit(ConnectionProxy.java:183) ~[seata-all-1.3.0.jar:1.3.0]
    158. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor.lambda$executeAutoCommitTrue$0(AbstractDMLBaseExecutor.java:112) ~[seata-all-1.3.0.jar:1.3.0]
    159. at io.seata.rm.datasource.ConnectionProxy$LockRetryPolicy.doRetryOnLockConflict(ConnectionProxy.java:299) ~[seata-all-1.3.0.jar:1.3.0]
    160. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor$LockRetryPolicy.execute(AbstractDMLBaseExecutor.java:155) ~[seata-all-1.3.0.jar:1.3.0]
    161. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor.executeAutoCommitTrue(AbstractDMLBaseExecutor.java:110) ~[seata-all-1.3.0.jar:1.3.0]
    162. at io.seata.rm.datasource.exec.AbstractDMLBaseExecutor.doExecute(AbstractDMLBaseExecutor.java:74) ~[seata-all-1.3.0.jar:1.3.0]
    163. at io.seata.rm.datasource.exec.BaseTransactionalExecutor.execute(BaseTransactionalExecutor.java:115) ~[seata-all-1.3.0.jar:1.3.0]
    164. at io.seata.rm.datasource.exec.ExecuteTemplate.execute(ExecuteTemplate.java:113) ~[seata-all-1.3.0.jar:1.3.0]
    165. at io.seata.rm.datasource.exec.ExecuteTemplate.execute(ExecuteTemplate.java:51) ~[seata-all-1.3.0.jar:1.3.0]
    166. at io.seata.rm.datasource.PreparedStatementProxy.execute(PreparedStatementProxy.java:55) ~[seata-all-1.3.0.jar:1.3.0]
    167. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
    168. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
    169. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    170. at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    171. at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59) ~[mybatis-3.5.7.jar:3.5.7]
    172. at com.sun.proxy.$Proxy123.execute(Unknown Source) ~[na:na]
    173. at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47) ~[mybatis-3.5.7.jar:3.5.7]
    174. at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74) ~[mybatis-3.5.7.jar:3.5.7]
    175. at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50) ~[mybatis-3.5.7.jar:3.5.7]
    176. at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.5.7.jar:3.5.7]
    177. at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) ~[mybatis-3.5.7.jar:3.5.7]
    178. at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194) ~[mybatis-3.5.7.jar:3.5.7]
    179. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
    180. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
    181. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    182. at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    183. at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) ~[mybatis-spring-2.0.6.jar:2.0.6]
    184. at com.sun.proxy.$Proxy82.update(Unknown Source) ~[na:na]
    185. at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:288) ~[mybatis-spring-2.0.6.jar:2.0.6]
    186. at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:64) ~[mybatis-plus-core-3.4.3.jar:3.4.3]
    187. at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) ~[mybatis-plus-core-3.4.3.jar:3.4.3]
    188. at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) ~[mybatis-plus-core-3.4.3.jar:3.4.3]
    189. at com.sun.proxy.$Proxy83.update(Unknown Source) ~[na:na]
    190. at com.baomidou.mybatisplus.extension.service.IService.update(IService.java:167) ~[mybatis-plus-extension-3.4.3.jar:3.4.3]
    191. at com.baomidou.mybatisplus.extension.service.IService.update(IService.java:157) ~[mybatis-plus-extension-3.4.3.jar:3.4.3]
    192. at com.stock1Server.service.impl.UserServiceImpl.updateTest(UserServiceImpl.java:24) ~[classes/:na]
    193. at com.stock1Server.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$3e673818.invoke() ~[classes/:na]
    194. at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    195. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    196. at com.stock1Server.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$c2539cd9.updateTest() ~[classes/:na]
    197. at com.stock1Server.controller.stockController.t6(stockController.java:118) ~[classes/:na]
    198. at com.stock1Server.controller.stockController$$FastClassBySpringCGLIB$$ae77ee83.invoke() ~[classes/:na]
    199. at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    200. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    201. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    202. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    203. at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    204. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    205. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    206. at io.seata.spring.annotation.GlobalTransactionalInterceptor.lambda$handleGlobalLock$0(GlobalTransactionalInterceptor.java:134) ~[seata-all-1.3.0.jar:1.3.0]
    207. at io.seata.rm.GlobalLockTemplate.execute(GlobalLockTemplate.java:48) ~[seata-all-1.3.0.jar:1.3.0]
    208. at io.seata.spring.annotation.GlobalTransactionalInterceptor.handleGlobalLock(GlobalTransactionalInterceptor.java:132) ~[seata-all-1.3.0.jar:1.3.0]
    209. at io.seata.spring.annotation.GlobalTransactionalInterceptor.invoke(GlobalTransactionalInterceptor.java:124) ~[seata-all-1.3.0.jar:1.3.0]
    210. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    211. at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    212. at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    213. at com.stock1Server.controller.stockController$$EnhancerBySpringCGLIB$$e2df0638.t6() ~[classes/:na]
    214. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171]
    215. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171]
    216. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171]
    217. at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171]
    218. at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    219. at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    220. at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    221. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    222. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    223. at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    224. at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    225. at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    226. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    227. at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    228. at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
    229. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    230. at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.46.jar:4.0.FR]
    231. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    232. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    233. at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.46.jar:9.0.46]
    234. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    235. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    236. at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    237. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    238. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    239. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    240. at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    241. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    242. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    243. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    244. at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    245. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.15.RELEASE.jar:5.2.15.RELEASE]
    246. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    247. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    248. at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    249. at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.46.jar:9.0.46]
    250. at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.46.jar:9.0.46]
    251. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.46.jar:9.0.46]
    252. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.46.jar:9.0.46]
    253. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.46.jar:9.0.46]
    254. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.46.jar:9.0.46]
    255. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) [tomcat-embed-core-9.0.46.jar:9.0.46]
    256. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.46.jar:9.0.46]
    257. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.46.jar:9.0.46]
    258. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) [tomcat-embed-core-9.0.46.jar:9.0.46]
    259. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.46.jar:9.0.46]
    260. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
    261. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
    262. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.46.jar:9.0.46]
    263. at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]

    gateway路由网关:

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-gatewayartifactId>
    4. dependency>

    gateway是springcloud发出的,由于Netflix组件没有继续维护了,所以spring官方就开发了一个网关路由。

    使用起来也是很简单,直接在配置文件中配置:

    1. server:
    2. port: 8080
    3. spring:
    4. application:
    5. name: gateway-server
    6. cloud:
    7. gateway:
    8. routes:
    9. - id: oder_route
    10. uri: lb://order1-server
    11. predicates:
    12. - Path=/oder/**
    13. filters:
    14. - StripPrefix=1
    15. nacos:
    16. server-addr: 192.168.126.1:8848
    17. discovery:
    18. namespace: c1102e00-c947-4d0c-8320-b98dc7fae641
    19. group: TEST

    Path=/oder/**是将路径前面加一个前缀,用于区分服务之间的路径。

    StripPrefix=1是切割掉上面的前缀

    lb://order1-server是指定这个配置代理的服务。

    也可以直接开启自动代理,直接用服务名取调用:

    1. server:
    2. port: 8080
    3. spring:
    4. application:
    5. name: gateway-server
    6. cloud:
    7. gateway:
    8. discovery:
    9. locator:
    10. enabled: true
    11. nacos:
    12. server-addr: 192.168.126.1:8848
    13. discovery:
    14. namespace: c1102e00-c947-4d0c-8320-b98dc7fae641
    15. group: TEST

    localhost:8080/order1-server/order1/getOder2/10010

    order1-server就是服务名。

    gateway全局过滤器

    1. package com.gateway.config;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    4. import org.springframework.cloud.gateway.filter.GlobalFilter;
    5. import org.springframework.stereotype.Component;
    6. import org.springframework.web.server.ServerWebExchange;
    7. import reactor.core.publisher.Mono;
    8. /**
    9. * @program: springCloudAlibaba
    10. * @author: quxiao
    11. * @create: 2024-03-11 21:04
    12. **/
    13. @Component
    14. @Slf4j
    15. public class GatewayFilter implements GlobalFilter {
    16. @Override
    17. public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    18. //输出访问路径
    19. log.info(exchange.getRequest().getPath().value());
    20. return chain.filter(exchange);
    21. }
    22. }

    集合sentinen:

    1. com.alibaba.cloud
    2. spring-cloud-alibaba-sentinel-gateway
    3. com.alibaba.cloud
    4. spring-cloud-starter-alibaba-sentinel

    另一个要注意的是,这个可以根据api分组来限流熔断:

    只定义返回消息:

    1. package com.gateway.config;
    2. import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
    3. import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
    4. import org.springframework.context.annotation.Configuration;
    5. import org.springframework.http.HttpStatus;
    6. import org.springframework.http.MediaType;
    7. import org.springframework.web.reactive.function.BodyInserters;
    8. import org.springframework.web.reactive.function.server.ServerResponse;
    9. import javax.annotation.PostConstruct;
    10. @Configuration
    11. public class SentinelConfiguration {
    12. @PostConstruct
    13. private void initBlockHandler() {
    14. BlockRequestHandler blockRequestHandler = (exchange, t) ->
    15. ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
    16. .contentType(MediaType.APPLICATION_JSON)
    17. .body(BodyInserters.fromValue("限流了")
    18. );
    19. GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    20. }
    21. }

    skywalking链路追踪

    ksysalking可以查看服务中的调用路径,可以清楚看清服务之间的依赖。

    需要下载ksysalking的服务启动包:

    链接: https://pan.baidu.com/s/1-icaoGf_CLY2PYF2D6lbEg

    提取码: xrix 复制这段内容后打开百度网盘手机App,操作更方便哦

    然后修改配置文件:

    修改一个端口:

    然后启动服务:

    然后在配置文件中配置依赖:

    1. <dependency>
    2. <groupId>org.apache.skywalkinggroupId>
    3. <artifactId>apm-toolkit-logback-1.xartifactId>
    4. <version>${skywalking.version}version>
    5. dependency>
    6. <dependency>
    7. <groupId>org.apache.skywalkinggroupId>
    8. <artifactId>apm-toolkit-traceartifactId>
    9. <version>${skywalking.version}version>
    10. dependency>

    连接skywalking

    在运行之前,加上VM配置:

    1. -javaagent:D:\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
    2. -DSW_AGENT_NAME=gateway-server
    3. -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800

    是skywalking服务文件中的探针服务:

    -javaagent:D:\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar

    服务名称
    -DSW_AGENT_NAME=gateway-server

    ksysalking的服务端口号
    -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800

    然后再代码中指定接口链路:

    1. @Trace
    2. @Tags(value = {
    3. @Tag(key = "print", value = "returnedObj")
    4. , @Tag(key = "print", value = "arg[0]")
    5. })
    6. public MsgTxt print(String txt, int id) {
    7. boolean b = userService.updateTest(txt, id);
    8. return new MsgTxt(txt, b);
    9. }

        @Trace

    标识查看调用这个方法的链路

        @Tags(value = {
                @Tag(key = "print", value = "returnedObj")
                , @Tag(key = "print", value = "arg[0]")
        })

    print是方法名

    returnedObj标识在skywalking查看是显示方法的返回值:

    arg[0]标识第一个参数

    性能剖析

    点击接口的调用,然后分析,能看见哪一句代码耗时最长:

    集成logback日志:

    上面已经导入了jar包,之后需要配置logback-spring.xml日志输出格式:

    1. "1.0" encoding="UTF-8"?>
    2. "FILE_LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] %green(%-5level) [%thread] %yellow([%tid]) %cyan(%logger{50}) : %msg%n" />
    3. "STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    4. "ch.qos.logback.core.encoder.LayoutWrappingEncoder">
    5. "org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
    6. ${FILE_LOG_PATTERN}
    7. "ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
    8. 0
    9. 256
    10. "STDOUT"/>
    11. "GRPC_LOG" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
    12. "ch.qos.logback.core.encoder.LayoutWrappingEncoder">
    13. "org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
    14. ${FILE_LOG_PATTERN}
    15. "info">
    16. "ASYNC_STDOUT"/>
    17. "GRPC_LOG"/>
    18. "info">
    19. "ASYNC_STDOUT"/>

    skywalking警告

    这几配置了一些调用约束,一旦达成,就会发出skywalking警告消息,基本上都是时间段内调用时间、失败次数等的约束,而且还是调用指定的回调函数,方便发生警告后,执行一些自定义的方法:

    1. package com.stock1Api.api;/*
    2. * Licensed to the Apache Software Foundation (ASF) under one or more
    3. * contributor license agreements. See the NOTICE file distributed with
    4. * this work for additional information regarding copyright ownership.
    5. * The ASF licenses this file to You under the Apache License, Version 2.0
    6. * (the "License"); you may not use this file except in compliance with
    7. * the License. You may obtain a copy of the License at
    8. *
    9. * http://www.apache.org/licenses/LICENSE-2.0
    10. *
    11. * Unless required by applicable law or agreed to in writing, software
    12. * distributed under the License is distributed on an "AS IS" BASIS,
    13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14. * See the License for the specific language governing permissions and
    15. * limitations under the License.
    16. *
    17. */
    18. import lombok.Getter;
    19. import lombok.Setter;
    20. /**
    21. * Alarm message represents the details of each alarm.
    22. */
    23. @Setter
    24. @Getter
    25. public class AlarmMessage {
    26. private int scopeId;
    27. private String scope;
    28. private String name;
    29. private String id0;
    30. private String id1;
    31. private String ruleName;
    32. private String alarmMessage;
    33. private long startTime;
    34. private transient boolean onlyAsCondition;
    35. @Override
    36. public String toString() {
    37. return "AlarmMessage{" +
    38. "scopeId=" + scopeId +
    39. ", scope='" + scope + '\'' +
    40. ", name='" + name + '\'' +
    41. ", id0='" + id0 + '\'' +
    42. ", id1='" + id1 + '\'' +
    43. ", ruleName='" + ruleName + '\'' +
    44. ", alarmMessage='" + alarmMessage + '\'' +
    45. ", startTime=" + startTime +
    46. ", onlyAsCondition=" + onlyAsCondition +
    47. '}';
    48. }
    49. }
    1. @PostMapping("/ksysalkingMessage")
    2. public void ksysalkingMessage(@RequestBody List mesgs) {
    3. log.info(mesgs.toString());
    4. }

  • 相关阅读:
    JDK21来了!附重要更新说明
    Linux安装MongoDB(简单详细)
    JS 对象总结
    SpringBoot项目本机和Linux环境部署
    NPM配置阿里云(淘宝)镜像仓库
    理解编辑距离算法
    Day 48 MySQL
    什么是Mirai僵尸网络
    Java设计模式-结构型模式-适配器模式
    nginx负载均衡配置及常见负载均衡策略
  • 原文地址:https://blog.csdn.net/qx020814/article/details/136284929