Docker部署seata Nacos作为注册配置中心
一、Seata服务端安装
1.1 要注意和spring-cloud、boot、 alibaba等版本对应上 ,避免出现版本不兼容问题
//拉去docker镜像
docker pull seataio/seata-server:1.3.0
//启动临时容器
docker run --name seata-server -p 8091:8091 -p 7091:7091 -d seataio/seata-server:1.3.0
//创建启动容器挂在目录
mkdir -p /home/seata
//复制文件
docker cp seata-server:/seata-server /home/seata
//停止删除临时容器
docker stop seata-server
docker rm seata-server
//正式启动seata-server容器
docker run -d --restart always \
--name seata-server -p 8091:8091 \
-p 7091:7091 \
-v /home/seata:/seata-server \
-e SEATA_IP=容器宿主机ip地址 \
-e SEATA_PORT=8091 \
seataio/seata-server:1.3.0
seata-server 参数说明:
-
SEATA_IP 可选, 指定seata-server启动的IP, 该IP用于向注册中心注册时使用, 如eureka等
-
SEATA_PORT 可选, 指定seata-server启动的端口, 默认为 8091
-
STORE_MODE 可选, 指定seata-server的事务日志存储方式, 支持db ,file,redis(Seata-Server 1.3及以上版本支持), 默认是 file
-
SERVER_NODE 可选, 用于指定seata-server节点ID, 如 1,2,3…, 默认为 根据ip生成
-
SEATA_ENV 可选, 指定 seata-server 运行环境, 如 dev, test 等, 服务启动时会使用 registry-dev.conf 这样的配置
-
SEATA_CONFIG_NAME 可选, 指定配置文件位置, 如 file:/root/registry, 将会加载/root/registry.conf 作为配置文件,如果需要同时指定 file.conf文件,需要将registry.conf的config.file.name的值改为类似file:/root/file.conf
1.2 修改seata配置文件
# 此处修改seata 注册中心为nacos
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
application = "seata-server"
serverAddr = "192.168.32.128:8848"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
}
# 此处修改seata配置中心nacos
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "192.168.32.128:8848"
namespace = "7fd09be2-e979-4593-9840-9a8bf8bc2765"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
}
//新建配置文件 添加如下配置信息(个人的有点简单)
//需要注意的是事务分组:vgroupMapping 这个在clint使用的时候需要配置在application.yml中
//service.default.grouplist=192.168.32.132:8091 这里的ip地址需要使用容器宿主机的ip地址
touch /home/seata/config.txtZ
vi config.txt
service.vgroupMapping.my_test_tx_group=default
service.default.grouplist=192.168.32.132:8091
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://47.92.82.183:3306/seata?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
store.db.user=seata
store.db.password=k8YGyRtEJ5j28FEp
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
//新建脚本文件 目的:把config.txt中的配置 增加到nacos配置中心中去
touch /home/seata/nacos-config.sh
//修改脚本执行权限
chmod u+x nacos-config.sh
//脚本文件内容
//注意:$(dirname "$PWD")/seata/config.txt 这里要写成自己的文件路径
#!/usr/bin/env bash
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at、
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
while getopts ":h:p:g:t:u:w:" opt
do
case $opt in
h)
host=$OPTARG
;;
p)
port=$OPTARG
;;
g)
group=$OPTARG
;;
t)
tenant=$OPTARG
;;
u)
username=$OPTARG
;;
w)
password=$OPTARG
;;
?)
echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "
exit 1
;;
esac
done
if [[ -z ${host} ]]; then
host=localhost
fi
if [[ -z ${port} ]]; then
port=8848
fi
if [[ -z ${group} ]]; then
group="SEATA_GROUP"
fi
if [[ -z ${tenant} ]]; then
tenant=""
fi
if [[ -z ${username} ]]; then
username=""
fi
if [[ -z ${password} ]]; then
password=""
fi
nacosAddr=$host:$port
contentType="content-type:application/json;charset=UTF-8"
echo "set nacosAddr=$nacosAddr"
echo "set group=$group"
failCount=0
tempLog=$(mktemp -u)
function addConfig() {
curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$1&group=$group&content=$2&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null
if [[ -z $(cat "${tempLog}") ]]; then
echo " Please check the cluster status. "
exit 1
fi
if [[ $(cat "${tempLog}") =~ "true" ]]; then
echo "Set $1=$2 successfully "
else
echo "Set $1=$2 failure "
(( failCount++ ))
fi
}
count=0
for line in $(cat $(dirname "$PWD")/config.txt | sed s/[[:space:]]//g); do
(( count++ ))
key=${line%%=*}
value=${line#*=}
addConfig "${key}" "${value}"
done
echo "========================================================================="
echo " Complete initialization parameters, total-count:$count , failure-count:$failCount "
echo "========================================================================="
if [[ ${failCount} -eq 0 ]]; then
echo " Init nacos config finished, please start seata-server. "
else
echo " init nacos config fail. "
fi
//执行脚本文件 -t :指定 namespace 命名空间
sh nacos-config.sh -h 192.168.32.128 -p 8848 -g SEATA_GROUP -u nacos -w nacos -t 7fd09be2-e979-4593-9840-9a8bf8bc2765
1.3 查看容器信息成功
//查看日志
docker logs -f 3e09de888d2f
一、Seata clint使用
1.1 假设 服务A接口调用微服务 B 和 C
分别在服务中增加依赖
<!--seata依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
在application.yml中增加seata配置
spring:
cloud:
#默认使用的Ribbon负载均衡器调用的
nacos:
discovery:
username: nacos
password: nacos
namespace: public
server-addr: 192.168.32.128:8848,192.168.32.129:8848
alibaba:
seata:
#事务分组 此处注意要和配置文件中ervice.vgroupMapping一致
tx-service-group: my_test_tx_group
seata:
registry:
#配置seata注册中心 告诉clint 访问seata server
type: nacos
nacos:
username: nacos
password: nacos
server-addr: 192.168.32.128:8848,192.168.32.129:8848
application: seata-server #注册中心中的服务名称
group: SEATA_GROUP
config:
#配置seata配置中心
nacos:
server-addr: 192.168.32.128:8848
username: nacos
password: nacos
group: SEATA_GROUP
namespace: 7fd09be2-e979-4593-9840-9a8bf8bc2765
/*
* 模拟分布式事务
* updateProduct 报错就会回滚事务
* */
@GlobalTransactional //加上此注解 分布式事务生效
@RequestMapping(value = "/addOrder")
public Result<Object> addOrder() {
String res = stockSeataFeignService.updateStock(2,99);
String res1 = productSeataFeignService.updateProduct(1,88);
return Result.success( res + " ========= " + res1 );
}