微服务分布式事务解决方案-springboot整合分布式seata1.3.0

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: springcloud-alibaba的分布式事务解决方案本文项目地址:https://github.com/longxiaonan/springcloud-demo

概述

Seat是蚂蚁金服和阿里巴巴联合推出的一个开源的分布式事务框架,在阿里云商用的叫做GTS。
项目地址:https://github.com/longxiaonan/springcloud-demo

官网:http://seata.io/zh-cn/index.html

一个XID和三个概念:

  • Transaction ID (XID) : 全局唯一的事务ID
  • Transaction Coordinator (TC) : 事务协调器,维护全局事务的运行状态
  • Transaction Manager (TM):控制全局事务的边界,负责开启一个全局事务
  • Resource Manager (RM):控制分支事务,负责分支注册、状态汇报,并接受TC的提交或者回滚操作

事务分为全局事务和本地事务。

全局事务通过XID(全局唯一事务id)来标识。分支通过分支id和资源id来标识,标签每个分支事务都标有XID来标识是属于哪个全局事务。

事务流程如下:

image.png

  1. TM向TC申请开启一个全局事务,全局事务创建成功并且生成一个全局唯一的XID;
  2. XID在微服务调用链路的上下文中传播;
  3. RM向TC注册分支事务,汇报事务资源准备状态,将其纳入XID对应全局事务的管辖;
  4. RM执行业务逻辑;
  5. TM结束分布式事务,事务一阶段结束,通知TC针对XID的全局提交或回滚决议;
  6. TC汇总事务信息,决定分布式事务是提交还是回滚;
  7. TC调度XID下管辖的RM的分支事务完成提交或者回滚请求,事务二阶段结束。

TC,TM和RM对应到实际服务节点

全局事务需要在服务调用方的service上开启,服务调用方就是TM,其他被调用方就是RM。

image.png

两段提交的详细过程

一阶段加载:
image.png

二阶段提交
image.png

二阶段提交失败,则进行回滚

image.png

image.png

下载seata

下载地址:http://seata.io/zh-cn/blog/download.html

本文采用的是 seata 1.3.0 (2020-07-14)

和springCloudAlibaba版本支持说明:

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

添加seata依赖(建议单选)

  • 依赖seata-all
  • 依赖seata-spring-boot-starter,支持yml、properties配置(.conf可删除),内部已依赖seata-all
  • 依赖spring-cloud-alibaba-seata,内部集成了seata,并实现了xid传递

因为是微服务方式,故添加依赖:

  • spring-cloud-starter-alibaba-seata推荐依赖配置方式
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-spring-boot-starter</artifactId>
                <version>最新版</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
                <version>2.2.1.RELEASE</version>
                <exclusions>
                    <exclusion>
                        <groupId>io.seata</groupId>
                        <artifactId>seata-spring-boot-starter</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>

文件配置

修改registry.type、config.type

文件在下载的seata包下

启动包: seata-->conf-->file.conf,修改store.mode="db或者redis"
源码: 根目录-->seata-server-->resources-->file.conf,修改store.mode="db或者redis"

启动包: seata-->conf-->file.conf,修改store.db或store.redis相关属性。
源码: 根目录-->seata-server-->resources-->file.conf,修改store.db或store.redis相关属性。

registry.conf

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "file"

  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
  ...
  config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "file"

  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "SEATA_GROUP"
    username = ""
    password = ""
  }
 }

改成

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    application = "seata-server"
    serverAddr = "localhost:8848"
    namespace = "public"
    cluster = "default"
    username = ""
    password = ""
  }
...
  config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  nacos {
    serverAddr = "localhost:8848"
    namespace = "public"
    group = "SEATA_GROUP"
    username = ""
    password = ""
  }
}

store.mode 和 对应的nacos和db连接配置

file.conf

注意数据源类型,比如springboot的默认数据源是hikari而不是druid

store {
  ## store mode: file、db、redis
  mode = "file"
  ...
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "mysql"
    password = "mysql"
  }
 ...
}

修改为:

store {
  ## store mode: file、db、redis
  mode = "db"
  
  ...

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "root"
    password = "123456"
  }
  ...
}

配置nacos-config.txt

文件地址:https://github.com/seata/seata/blob/1.3.0/script/config-center/config.txt

官网seata-server-0.9.0的conf目录下有该文件,官网seata-server-0.9.0的conf目录下有该文件,后面的版本无该文件需要手动下载执行。

修改为自己的服务组名,各个微服务之间使用相同的服务组名,务必保持一致!

service.vgroupMapping.my_test_tx_group=default
service.vgroupMapping.my_test_tx_group1=default
service.vgroupMapping.my_test_tx_group2=default
service.vgroupMapping.my_test_tx_group3=default

配置seata服务器mysql链接信息,注意数据源类型,比如springboot的默认数据源是hikari而不是druid

store.mode=db
...
store.db.datasource=druid
store.db.dbType=mysql
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
store.db.user=root
store.db.password=123456

执行nacos-config.sh脚本

脚本地址:https://github.com/seata/seata/blob/1.3.0/script/config-center/nacos/nacos-config.sh

官网seata-server-0.9.0的conf目录下有该文件,后面的版本无该文件需要手动下载执行。

如果本地是windows,使用git工具git bash执行nacos-config.sh脚本:

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -u nacos -w nacos

执行完成后nacos会新增seata配置。

需要注意config.txt中目录的对应关系,否则可能提示finished,其实未执行成功!

$ sh nacos-config.sh -h localhost -p 8848
set nacosAddr=localhost:8848
set group=SEATA_GROUP
cat: /d/soft/config.txt: No such file or directory
=========================================================================
 Complete initialization parameters,  total-count:0 ,  failure-count:0
=========================================================================
 Init nacos config finished, please start seata-server.

Seata Server需要依赖的表

表的地址:https://github.com/seata/seata/blob/develop/script/server/db/mysql.sql

新建数据库seata, 创建如下三个表,用于seata服务, 0.0.9版本才有这个文件1.0.0版本后需要手动添加。

-- the table to store GlobalSession data
DROP TABLE IF EXISTS `global_table`;
CREATE TABLE `global_table` (
  `xid` VARCHAR(128)  NOT NULL,
  `transaction_id` BIGINT,
  `status` TINYINT NOT NULL,
  `application_id` VARCHAR(32),
  `transaction_service_group` VARCHAR(32),
  `transaction_name` VARCHAR(128),
  `timeout` INT,
  `begin_time` BIGINT,
  `application_data` VARCHAR(2000),
  `gmt_create` DATETIME,
  `gmt_modified` DATETIME,
  PRIMARY KEY (`xid`),
  KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
  KEY `idx_transaction_id` (`transaction_id`)
);

-- the table to store BranchSession data
DROP TABLE IF EXISTS `branch_table`;
CREATE TABLE `branch_table` (
  `branch_id` BIGINT NOT NULL,
  `xid` VARCHAR(128) NOT NULL,
  `transaction_id` BIGINT ,
  `resource_group_id` VARCHAR(32),
  `resource_id` VARCHAR(256) ,
  `lock_key` VARCHAR(128) ,
  `branch_type` VARCHAR(8) ,
  `status` TINYINT,
  `client_id` VARCHAR(64),
  `application_data` VARCHAR(2000),
  `gmt_create` DATETIME,
  `gmt_modified` DATETIME,
  PRIMARY KEY (`branch_id`),
  KEY `idx_xid` (`xid`)
);

-- the table to store lock data
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table` (
  `row_key` VARCHAR(128) NOT NULL,
  `xid` VARCHAR(96),
  `transaction_id` LONG ,
  `branch_id` LONG,
  `resource_id` VARCHAR(256) ,
  `table_name` VARCHAR(32) ,
  `pk` VARCHAR(36) ,
  `gmt_create` DATETIME ,
  `gmt_modified` DATETIME,
  PRIMARY KEY(`row_key`)
);

AT模式下每个业务数据库需要创建undo_log表,用于seata记录分支的回滚信息

表的地址:https://github.com/seata/seata/blob/1.3.0/script/client/at/db/mysql.sql

-- 注意此处0.3.0+ 增加唯一索引 ux_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`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

运行 Seata-server

Linux/Unix/Mac

sh seata-server.sh -p $LISTEN_PORT -m $STORE_MODE -h $IP(此参数可选)

Windows

cmd seata-server.bat -p $LISTEN_PORT -m $STORE_MODE -h $IP(此参数可选)

$LISTEN_PORT: Seata-Server 服务端口
$STORE_MODE: 事务操作记录存储模式:file、db
$IP(可选参数): 用于多 IP 环境下指定 Seata-Server 注册服务的IP,配置自己的ip即可

测试的时候 直接双击运行seata-server.bat 即可。

# linux
nohup ./seata-server.sh -h 192.168.1.4 -p 8092 &
# windows cmd
seata-server.bat -m file -h 192.168.1.4 -p 8092 

用例

参考官网中用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持:

  • 存储服务:扣除给定商品的存储数量。
  • 订单服务:根据购买请求创建订单。
  • 帐户服务:借记用户帐户的余额。

项目地址:

https://github.com/longxiaonan/springcloud-demo

添加依赖:

<!-- 分布式事务seata包 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-all</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

配置seata:

seata:
  enabled: true
  application-id: ${spring.application.name}
  txServiceGroup: my_test_tx_group
  # 是否开启数据源自动代理 如果不开启设置为false
  enable-auto-data-source-proxy: true
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: localhost:8848
      namespace:
  #      userName: "nacos"
  #      password: "nacos"
  config:
    type: nacos
    nacos:
      namespace:
      serverAddr: localhost:8848
      group: SEATA_GROUP
#      userName: "nacos"
#      password: "nacos"

在代码中通过注解开启:

@GlobalTransactional(rollbackFor = Exception.class)

请求逻辑

image.png

commint测试接口:http://127.0.0.1:8008/purchase/commit接口是可以正常执行完成的方法

rollback测试接口:http://127.0.0.1:8008/purchase/rollback接口是会发生异常并正常回滚的方法

测试

当未开启seata服务rollback测试:

未开启seata服务,启动业务服务节点, 业务节点的console log如下提示:

2020-07-25 10:59:50.492 ERROR 11284 --- [eoutChecker_1_1] i.s.c.r.netty.NettyClientChannelManager : no available service 'default' found, please make sure registry config correct
2020-07-25 10:59:50.654 ERROR 11284 --- [eoutChecker_2_1] i.s.c.r.netty.NettyClientChannelManager : no available service 'default' found, please make sure registry config correct

此时,访问rollback测试接口,controller不能进入加了@GlobalTransitional的service,无任何服务被执行和调用。console log如下报错:

io.seata.common.exception.FrameworkException: No available service
     at io.seata.core.rpc.netty.AbstractNettyRemotingClient.loadBalance(AbstractNettyRemotingClient.java:257)
     at io.seata.core.rpc.netty.AbstractNettyRemotingClient.sendSyncRequest(AbstractNettyRemotingClient.java:133)
     at io.seata.tm.DefaultTransactionManager.syncCall(DefaultTransactionManager.java:95)
     at io.seata.tm.DefaultTransactionManager.begin(DefaultTransactionManager.java:53)
     at io.seata.tm.api.DefaultGlobalTransaction.begin(DefaultGlobalTransaction.java:104)
     at io.seata.tm.api.TransactionalTemplate.beginTransaction(TransactionalTemplate.java:175)

开启seata服务rollback测试

双击 `` 启动seata服务

业务服务console提示如下log,说明注册成功

2020-07-25 11:08:31.599  INFO 11284 --- [eoutChecker_1_1] i.s.c.rpc.netty.TmNettyRemotingClient    : register TM success. client version:1.3.0, server version:1.3.0,channel:[id: 0xdd694462, L:/169.254.249.134:3959 - R:/169.254.249.134:8091]
2020-07-25 11:08:31.618  INFO 11284 --- [eoutChecker_2_1] i.s.c.rpc.netty.RmNettyRemotingClient    : register RM success. client version:1.3.0, server version:1.3.0,channel:[id: 0x5ece5f24, L:/169.254.249.134:3960 - R:/169.254.249.134:8091]
2020-07-25 11:08:31.624  INFO 11284 --- [eoutChecker_2_1] i.s.core.rpc.netty.NettyPoolableFactory  : register success, cost 264 ms, version:1.3.0,role:RMROLE,channel:[id: 0x5ece5f24, L:/169.254.249.134:3960 - R:/169.254.249.134:8091]
2020-07-25 11:08:31.624  INFO 11284 --- [eoutChecker_1_1] i.s.core.rpc.netty.NettyPoolableFactory  : register success, cost 263 ms, version:1.3.0,role:TMROLE,channel:[id: 0xdd694462, L:/169.254.249.134:3959 - R:/169.254.249.134:8091]

rollback接口在执行到account服务的时候会抛异常:

java.lang.RuntimeException: account branch exception
    at com.javasea.account.service.AccountService.debit(AccountService.java:34) ~[classes/:na]
    at com.javasea.account.service.AccountService$$FastClassBySpringCGLIB$$e3edd550.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]

order服务作为account服务的调用方,会知道account服务发生了异常:

feign.FeignException$InternalServerError: [500] during [GET] to [http://account-service/debit/1002/10] [AccountFeignClient#debit(String,Integer)]: [{"timestamp":"2020-07-25T03:36:18.494+0000","status":500,"error":"Internal Server Error","message":"account branch exception","path":"/debit/1002/10"}]
    at feign.FeignException.serverErrorStatus(FeignException.java:231) ~[feign-core-10.7.4.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:180) ~[feign-core-10.7.4.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:169) ~[feign-core-10.7.4.jar:na]
    at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92) ~[feign-core-10.7.4.jar:na]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:156) ~[feign-core-10.7.4.jar:na]
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:80) ~[feign-core-10.7.4.jar:na]
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-10.7.4.jar:na]
    at com.sun.proxy.$Proxy89.debit(Unknown Source) ~[na:na]
    at com.javasea.order.service.OrderService.create(OrderService.java:38) ~[classes/:na]

business服务log如下:

2020-07-25 11:36:18.288  INFO 11284 --- [nio-8008-exec-4] i.seata.tm.api.DefaultGlobalTransaction  : Begin new global transaction [169.254.249.134:8091:30253423644925952]
2020-07-25 11:36:18.289  INFO 11284 --- [nio-8008-exec-4] c.j.business.service.BusinessService     : 开始全局事务,XID = 169.254.249.134:8091:30253423644925952
2020-07-25 11:36:18.627  INFO 11284 --- [nio-8008-exec-4] i.seata.tm.api.DefaultGlobalTransaction  : [169.254.249.134:8091:30253423644925952] rollback status: Rollbacked
feign.FeignException$InternalServerError: [500] during [GET] to [http://order-service/order/1002/2001/1] [OrderFeignClient#create(String,String,Integer)]: [{"timestamp":"2020-07-25T03:36:18.530+0000","status":500,"error":"Internal Server Error","message":"[500] during [GET] to [http://account-service/debit/1002/10] [AccountFeignClient#debit(String,Intege... (405 bytes)]
    at feign.FeignException.serverErrorStatus(FeignException.java:231)
    at feign.FeignException.errorStatus(FeignException.java:180)
    at feign.FeignException.errorStatus(FeignException.java:169)

storage服务的扣减库存已经提交,因为全局事务没成功,故触发回滚:

2020-07-25 11:36:18.303  INFO 5924 --- [io-8010-exec-10] c.j.storage.service.StorageService       : 开始分支事务,XID = 169.254.249.134:8091:30253423644925952
2020-07-25 11:36:18.400  WARN 5924 --- [io-8010-exec-10] c.a.c.seata.web.SeataHandlerInterceptor  : xid in change during RPC from 169.254.249.134:8091:30253423644925952 to null
2020-07-25 11:36:18.543  INFO 5924 --- [ch_RMROLE_1_7_8] i.s.c.r.p.c.RmBranchRollbackProcessor    : rm handle branch rollback process:xid=169.254.249.134:8091:30253423644925952,branchId=30253423821086720,branchType=AT,resourceId=jdbc:mysql://localhost:3306/seata_storage,applicationData=null
2020-07-25 11:36:18.544  INFO 5924 --- [ch_RMROLE_1_7_8] io.seata.rm.AbstractRMHandler            : Branch Rollbacking: 169.254.249.134:8091:30253423644925952 30253423821086720 jdbc:mysql://localhost:3306/seata_storage
2020-07-25 11:36:18.618  INFO 5924 --- [ch_RMROLE_1_7_8] i.s.r.d.undo.AbstractUndoLogManager      : xid 169.254.249.134:8091:30253423644925952 branch 30253423821086720, undo_log deleted with GlobalFinished
2020-07-25 11:36:18.619  INFO 5924 --- [ch_RMROLE_1_7_8] io.seata.rm.AbstractRMHandler            : Branch Rollbacked result: PhaseTwo_Rollbacked

遇到的问题:

console一直提示如下error log:

00:46:38.070 ERROR 10652 --- [imeoutChecker_2] i.s.c.r.n.NettyClientChannelManager - no available service 'default' found, please make sure registry config correct
00:46:47.729 ERROR 10652 --- [imeoutChecker_1] i.s.c.r.n.NettyClientChannelManager - no available service 'default' found, please make sure registry config correct

一直百事不得其解。后面突然发现会不会是jar包问题。

查看在父项目的pom配置:

<!-- 分布式事务seata包 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-all</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

到本项目分析pom.xml的依赖关系,发现jia包竟然是1.1.0的,在父项目不是引入的1.3.0吗?

image.png

去文档中查找发现1.1.0是默认 spring-cloud-starter-alibaba-seata 2.2.1.RELEASE 内嵌的,也就是pom依赖关系基础问题。

image.png

先不管pom依赖的继承问题。将pom依赖分别添加到子项目即可。

然后重启,RM注册成功:

00:49:17.541 INFO  13260 --- [eoutChecker_1_1] i.s.c.rpc.netty.NettyPoolableFactory - NettyPool create channel to transactionRole:TMROLE,address:169.254.249.134:8091,msg:< RegisterTMRequest{applicationId='lmwy-flow-longxiaonan', transactionServiceGroup='my_test_tx_group'} >
00:49:17.557 INFO  13260 --- [eoutChecker_1_1] i.s.c.r.netty.TmNettyRemotingClient - register TM success. client version:1.3.0, server version:1.3.0,channel:[id: 0x1d35034a, L:/169.254.249.134:9977 - R:/169.254.249.134:8091]
00:49:17.557 INFO  13260 --- [eoutChecker_1_1] i.s.c.rpc.netty.NettyPoolableFactory - register success, cost 8 ms, version:1.3.0,role:TMROLE,channel:[id: 0x1d35034a, L:/169.254.249.134:9977 - R:/169.254.249.134:8091]
00:49:32.077 INFO  13260 --- [.12.11.240_8848] c.a.n.c.config.impl.ClientWorker - get changedGroupKeys:[]
00:49:38.880 INFO  13260 --- [.12.11.240_8848] c.a.n.c.config.impl.ClientWorker - get changedGroupKeys:[]
00:50:01.684 INFO  13260 --- [.12.11.240_8848] c.a.n.c.config.impl.ClientWorker - get changedGroupKeys:[]

本文项目地址:https://github.com/longxiaonan/springcloud-demo

参考:

http://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html

https://sourcegraph.com/github.com/seata/seata-samples@master/-/blob/springcloud-nacos-seata/README.md

目录
相关文章
|
3月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
4天前
|
运维 监控 Java
为何内存不够用?微服务改造启动多个Spring Boot的陷阱与解决方案
本文记录并复盘了生产环境中Spring Boot应用内存占用过高的问题及解决过程。系统上线初期运行正常,但随着业务量上升,多个Spring Boot应用共占用了64G内存中的大部分,导致应用假死。通过jps和jmap工具排查发现,原因是运维人员未设置JVM参数,导致默认配置下每个应用占用近12G内存。最终通过调整JVM参数、优化堆内存大小等措施解决了问题。建议在生产环境中合理设置JVM参数,避免资源浪费和性能问题。
22 3
|
26天前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
87 5
|
25天前
|
存储 运维 数据可视化
如何为微服务实现分布式日志记录
如何为微服务实现分布式日志记录
47 1
|
1月前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
54 6
|
1月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
43 5
|
2月前
|
消息中间件 存储 负载均衡
微服务与分布式系统设计看这篇就够了!
【10月更文挑战第12天】 在现代软件架构中,微服务和分布式系统设计已经成为构建可扩展、灵活和可靠应用程序的主流方法。本文将深入探讨微服务架构的核心概念、设计原则和挑战,并提供一些关于如何在分布式系统中实现微服务的实用指导。
84 2
|
2月前
|
Java Docker 微服务
SpringBoot微服务打包Docker镜像
SpringBoot微服务打包Docker镜像
84 11
|
2月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
188 1