springboot + seata + httpclient调用
Posted cn_yaojin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot + seata + httpclient调用相关的知识,希望对你有一定的参考价值。
三个项目,彼此使用seata自带的httpclient来完成相互调用,三个项目分别是:seata_user、seata_msg、seata_online,对应三个数据库。其中seata_online是调用入口,分别调用seata_user、seata_msg,其中当参数等于5的时候,会抛出异常,3个数据库均回滚事务;参数不等于5的时候,3个数据库正常保存数据。
三个项目引入seata的版本如下
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-core</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.2.0</version>
</dependency>
一、seata_user
1、application.yml
server:
port: 40023
undertow:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
io-threads: 4
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
# 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8
worker-threads: 200
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 1024
# 是否分配的直接内存
direct-buffers: true
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
config-location: classpath:mapper/config/sqlMapConfig.xml
spring:
servlet:
multipart:
enabled: true
max-file-size: 100MB
max-request-size: 100MB
application:
name: seata_user
datasource:
dynamic:
primary: user #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
user:
url: jdbc:mysql://127.0.0.1:3306/business_platform_demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
database: 0
host: 127.0.0.1
port: 6379
password:
max-active: 100
max-wait: 1000
management:
endpoints:
web:
exposure:
include: '*'
swagger:
title: app端
scanpackages: com.cn
logging:
level:
com.cn: info
servlet:
multipart:
enabled: true
max-file-size: 100MB
max-request-size: 100MB
# seata配置
seata:
enabled: true
# Seata 应用编号,默认为 $spring.application.name
application-id: $spring.application.name
# Seata 事务组编号,用于 TC 集群名
tx-service-group: $spring.application.name-group
# 开启自动代理
enable-auto-data-source-proxy: true
# 服务配置项
service:
# 虚拟组和分组的映射
vgroup-mapping:
gulimall-order-group: default
grouplist:
default: 192.168.3.21:8091
config:
type: nacos
nacos:
serverAddr: 192.168.3.133:8848
group: SHOP_GROUP
namespace: 53e24698-1032-41cc-966f-129931d10ec9
registry:
type: nacos
nacos:
application: seata-server
server-addr: 192.168.3.133:8848
namespace: 53e24698-1032-41cc-966f-129931d10ec9
group: SHOP_GROUP
2. 在nacos上新建如下配置:service.vgroupMapping.seata_user-group
3. 新建mapper
@Mapper
public interface IUserMapper extends BaseMapper<PortalUserEntity>
4. 新建service
@Service
@Slf4j
public class UserService
@Autowired
private IUserMapper userMapper;
@Transactional
public void saveTmp(PortalUserEntity info)
info.setId(SnowflakeIdWorkerUtil.getId());
info.setAddTime(DateUtil.getTime("yyyy-MM-dd HH:mm:ss"));
this.userMapper.insert(info);
5. 新建controller
@RestController
@RequestMapping(value = "mobile/demo")
@Api(tags = "Demo")
public class DemoController
@Autowired
private UserService userService;
@ApiOperation(value = "saveUser")
@PostMapping(value = "saveUser")
public ResultMsg saveUser(
@RequestBody PortalUserEntity user
)
this.userService.saveTmp(user);
return ResultMsg.builder();
6. 启动,启动后的地址及端口:http://127.0.0.1:40023/mobile/demo/saveUser
二、seata_msg
1、application.yml
server:
port: 40024
undertow:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
io-threads: 4
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
# 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8
worker-threads: 200
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 1024
# 是否分配的直接内存
direct-buffers: true
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
config-location: classpath:mapper/config/sqlMapConfig.xml
spring:
servlet:
multipart:
enabled: true
max-file-size: 100MB
max-request-size: 100MB
application:
name: seata_msg
datasource:
dynamic:
primary: company #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
company:
url: jdbc:mysql://127.0.0.1:3306/business_company_demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
seata: true
redis:
database: 0
host: 127.0.0.1
port: 6379
password:
max-active: 100
max-wait: 1000
management:
endpoints:
web:
exposure:
include: '*'
swagger:
title: seata_user
scanpackages: com.cn
logging:
level:
com.cn: info
servlet:
multipart:
enabled: true
max-file-size: 100MB
max-request-size: 100MB
# seata配置
seata:
enabled: true
# Seata 应用编号,默认为 $spring.application.name
application-id: $spring.application.name
# Seata 事务组编号,用于 TC 集群名
tx-service-group: $spring.application.name-group
# 开启自动代理
enable-auto-data-source-proxy: true
# 服务配置项
service:
# 虚拟组和分组的映射
vgroup-mapping:
gulimall-order-group: default
grouplist:
default: 192.168.3.21:8091
config:
type: nacos
nacos:
serverAddr: 192.168.3.133:8848
group: SHOP_GROUP
namespace: 53e24698-1032-41cc-966f-129931d10ec9
registry:
type: nacos
nacos:
application: seata-server
server-addr: 192.168.3.133:8848
namespace: 53e24698-1032-41cc-966f-129931d10ec9
group: SHOP_GROUP
2、在nacos上加入以下配置:service.vgroupMapping.seata_msg-group
3、新建mapper
@Mapper
public interface IMsgMapper extends BaseMapper<MsgEntity>
4、新建service
@Service
@Slf4j
public class MsgService
@Autowired
private IMsgMapper msgMapper;
@Transactional
public void saveTmp(MsgEntity info)
info.setId(SnowflakeIdWorkerUtil.getId());
info.setCreateTime(DateUtil.getTime("yyyy-MM-dd HH:mm:ss"));
this.msgMapper.insert(info);
5、新建controller
@RestController
@RequestMapping(value = "mobile/demo")
public class Demo2Controller
@Autowired
private MsgService msgService;
@ApiOperation(value = "saveMsg")
@PostMapping(value = "saveMsg")
public ResultMsg saveMsg(
@RequestBody MsgEntity msg
)
this.msgService.saveTmp(msg);
return ResultMsg.builder();
6、启动后的访问地址:http://127.0.0.1:40024/mobile/demo/saveMsg
三、seata_online
1、application.yml
server:
port: 40025
undertow:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
io-threads: 4
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
# 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8
worker-threads: 200
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 1024
# 是否分配的直接内存
direct-buffers: true
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
config-location: classpath:mapper/config/sqlMapConfig.xml
spring:
servlet:
multipart:
enabled: true
max-file-size: 100MB
max-request-size: 100MB
application:
name: seata_online
datasource:
dynamic:
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/business_portal_demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
seata: true
redis:
database: 0
host: 127.0.0.1
port: 6379
password:
max-active: 100
max-wait: 1000
management:
endpoints:
web:
exposure:
include: '*'
swagger:
title: seata_user
scanpackages: com.cn
logging:
level:
com.cn: info
servlet:
multipart:
enabled: true
max-file-size: 100MB
max-request-size: 100MB
# seata配置
seata:
enabled: true
# Seata 应用编号,默认为 $spring.application.name
application-id: $spring.application.name
# Seata 事务组编号,用于 TC 集群名
tx-service-group: $spring.application.name-group
# 开启自动代理
enable-auto-data-source-proxy: true
# 服务配置项
service:
# 虚拟组和分组的映射
vgroup-mapping:
gulimall-order-group: default
grouplist:
default: 192.168.3.21:8091
config:
type: nacos
nacos:
serverAddr: 192.168.3.133:8848
group: SHOP_GROUP
namespace: 53e24698-1032-41cc-966f-129931d10ec9
registry:
type: nacos
nacos:
application: seata-server
server-addr: 192.168.3.133:8848
namespace: 53e24698-1032-41cc-966f-129931d10ec9
group: SHOP_GROUP
2、在nacos上加入以下配置:service.vgroupMapping.seata_online-group
3、新建mapper
@Mapper
public interface IOnmessageMapper extends BaseMapper<OnlineMessageEntity>
4、新建service
@Service
@Slf4j
public class OnMessageService
@Autowired
private IOnmessageMapper onmessageMapper;
@Transactional
public void add(OnmessageEdit info)
OnlineMessageEntity msg = new OnlineMessageEntity();
BeanUtils.copyProperties(info, msg);
msg.setId(SnowflakeIdWorkerUtil.getId());
msg.setCreateDate(DateUtil.getTime("yyyy-MM-dd HH:mm:ss"));
if (StringUtils.isEmpty(msg.getImgs()))
msg.setImgs("");
this.onmessageMapper.insert(msg);
import com.alibaba.fastjson.JSONObject;
import com.cn.exception.MyException;
import com.cn.msg.ResultMsg;
import com.cn.util.JsonUtil;
import com.cn.web.portal.vo.OnmessageEdit;
import io.seata.integration.http.DefaultHttpExecutor;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service
public class DemoService
@Autowired
private OnMessageService onMessageService;
private void saveUser() throws IOException
// 参数拼接
JSONObject params = new JSONObject().fluentPut("title", "我爱我的祖国")
.fluentPut("content", "通知们好,我爱我的祖国");
// 执行调用
HttpResponse response = DefaultHttpExecutor.getInstance().executePost("http://127.0.0.1:40024", "/mobile/demo/saveMsg",
params, HttpResponse.class);
// 解析结果
ResultMsg result = JsonUtil.fromJson(EntityUtils.toString(response.getEntity()), ResultMsg.class);
if (!result.isSuccess())
throw new MyException(result.getMsg());
private void saveMsg() throws IOException
// 参数拼接
JSONObject params = new JSONObject().fluentPut("phone", "13909384351")
.fluentPut("userName", "cn_yang").fluentPut("userType", "0").fluentPut("userStatus", 0);
// 执行调用
HttpResponse response = DefaultHttpExecutor.getInstance().executePost("http://127.0.0.1:40023", "/mobile/demo/saveUser",
params, HttpResponse.class);
ResultMsg result = JsonUtil.fromJson(EntityUtils.toString(response.getEntity()), ResultMsg.class);
if (!result.isSuccess())
throw new MyException(result.getMsg());
@GlobalTransactional
public void save0(Long id) throws IOException
saveUser();
saveMsg();
OnmessageEdit lineMsg = new OnmessageEdit();
lineMsg.setTitle("标题").setContent("alsdkfja").setMsgType("0");
onMessageService.add(lineMsg);
if (id == 5)
throw new MyException("尝试跑出异常");
以上DemoService中,注意一下4个依赖
import io.seata.integration.http.DefaultHttpExecutor; // seata自带的httpclient执行器
import io.seata.spring.annotation.GlobalTransactional; // 全局事务
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
5、新建controller
@RestController
@RequestMapping(value = "mobile/demo")
public class Demo2Controller
@Autowired
private DemoService demoService;
@ApiOperation(value = "save2")
@GetMapping(value = "save2")
public ResultMsg save2(
@ApiParam(name = "id") @RequestParam Long id
)
try
this.demoService.save0(id);
catch (IOException e)
e.printStackTrace();
return ResultMsg.builder();
6、启动后的访问地址:http://127.0.0.1:40025/mobile/demo/save2?id=3 当id=5的时候,抛出异常,事务回滚,三个库里面的数据均恢复原样;当id不等于5的时候,正常插入数据。
SpringBoot集成nacos+seata1.5.1相关注意事项
1. 客户端配置:在项目的yml配置文件中,以下标红的两个地方要一致,并且和server。
seata:
enabled: true
application-id: $spring.application.name
tx-service-group: demo-seata-service-group # 事务群组(可以每个应用独立取名,也可以使用相同的名字)
service:
vgroup-mapping:
demo-seata-service-group: default # TC 集群(必须与seata-server保持一致)
disable-global-transaction: false # 禁用全局事务(默认false)
registry:
type: nacos
nacos:
application: seata-server
server-addr: xx.xx.xx.xx:8848
namespace: platform
group: DEFAULT_GROUP
cluster: default
2. 设置seata注册到nacos上的ip为外网ip
设置环境变量 SEATA_IP = 外网IP,如在/etc/profile 中增加一行
export SEATA_IP= xx.xx.xx.xx
生效环境变量
source /etc/profile
再用 sh seata-server.sh 命令启动seata服务即可。
以上是关于springboot + seata + httpclient调用的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot+SpringCloud+Seata配置
分布式事务:SpringBoot+Dubbo+Seata+Nacos 实现案例
SpringBoot集成nacos+seata1.5.1相关注意事项