seata1.4.0落地

1,简介

        由于项目功能已经开发完成,但是某些功能牵扯到的分布式事务没有处理,而在调研了一些分布式解决方案后,最终选择了当前比较流行,且对现有业务代码无侵入的seata。

        本项目情况:

        spring boot 2.0.9.RELEASE + sprong cloudFinchley.SR3 + nacos1.3.2作为注册中心+ oracle12C

        本次集成seata 1.4.0 : 需要单独部署TC(seata-server服务)

为防止部分资源无法下载,文末会附上相关下载资源

2,seata服务端安装

        仔细官方文档,很重要,能避免后期一些坑。

        2.1 seata官方文档路径:https://seata.io/zh-cn/index.html       

        2.2 seata下载路径:http://seata.io/zh-cn/blog/download.html

        2.3下载好1.4.0压缩

seata1.4.0落地_第1张图片

如果没有logs文件夹,则创建一个logs文件夹,并在logs文件夹里创建一个seata_gc.log文件

2.4打开目录seata/cof在README-zh.md中有一些资源github下载地址

seata1.4.0落地_第2张图片

2.5创建seata-server 数据库

本项目只有一个数据库所有在该项目的数据库里创建一个用户,作为seata的数据库,用户名叫seata

脚本:

CREATE TABLE global_table
(
    xid                       VARCHAR2(128) NOT NULL,
    transaction_id            NUMBER(19),
    status                    NUMBER(3)     NOT NULL,
    application_id            VARCHAR2(32),
    transaction_service_group VARCHAR2(32),
    transaction_name          VARCHAR2(128),
    timeout                   NUMBER(10),
    begin_time                NUMBER(19),
    application_data          VARCHAR2(2000),
    gmt_create                TIMESTAMP(0),
    gmt_modified              TIMESTAMP(0),
    PRIMARY KEY (xid)
);

CREATE INDEX idx_gmt_modified_status ON global_table (gmt_modified, status);
CREATE INDEX idx_transaction_id ON global_table (transaction_id);

-- the table to store BranchSession data
CREATE TABLE branch_table
(
    branch_id         NUMBER(19)    NOT NULL,
    xid               VARCHAR2(128) NOT NULL,
    transaction_id    NUMBER(19),
    resource_group_id VARCHAR2(32),
    resource_id       VARCHAR2(256),
    branch_type       VARCHAR2(8),
    status            NUMBER(3),
    client_id         VARCHAR2(64),
    application_data  VARCHAR2(2000),
    gmt_create        TIMESTAMP(6),
    gmt_modified      TIMESTAMP(6),
    PRIMARY KEY (branch_id)
);

CREATE INDEX idx_xid ON branch_table (xid);

-- the table to store lock data
CREATE TABLE lock_table
(
    row_key        VARCHAR2(128) NOT NULL,
    xid            VARCHAR2(128),
    transaction_id NUMBER(19),
    branch_id      NUMBER(19)    NOT NULL,
    resource_id    VARCHAR2(256),
    table_name     VARCHAR2(32),
    pk             VARCHAR2(36),
    gmt_create     TIMESTAMP(0),
    gmt_modified   TIMESTAMP(0),
    PRIMARY KEY (row_key)
);

CREATE INDEX idx_branch_id ON lock_table (branch_id);

2.6创建undo_log表

说明:该表在seata服务数据库创建一张,在相关业务库也都要创建,如果是多个业务库,每个业务库都要创建。

-- Create table
create table UNDO_LOG
(
  id            NUMBER(19) not null,
  branch_id     NUMBER(19) not null,
  xid           VARCHAR2(128) not null,
  context       VARCHAR2(128) not null,
  rollback_info BLOB not null,
  log_status    NUMBER(10) not null,
  log_created   TIMESTAMP(0) not null,
  log_modified  TIMESTAMP(0) not null
);
comment on table UNDO_LOG
  is 'AT transaction mode undo table';

2.7 更改seata服务相关配置文件

        2.7.1在根目录seata下创建config.txt文件

service.vgroupMapping.mjkf-agility-sys-manage_tx_group=default
service.vgroup_mapping.sys_tx_group=default
service.vgroup_mapping.mjkf-agility-sys-manage-htf-group=default
service.vgroupMapping.mjkf-agility-sys-manage-htf-group=default
service.vgroupMapping.sys_tx_group=default
service.vgroupMapping.sys_group=default
service.vgroupMapping.mjkf-agility-dbmodel_tx_group=default
service.vgroupMapping.mjkf-agility-code_tx_group=default
service.default.grouplist=10.1.5.98:8091
service.disableGlobalTransaction=false
store.mode=db
store.db.datasource=druid
store.db.dbType=oracle
store.db.driverClassName=oracle.jdbc.OracleDriver
store.db.url=jdbc:oracle:thin:@10.1.5.98:1521/bxpdb
store.db.user=seata
store.db.password=seata
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

以下是需要自行更改的内容,包含数据库连接信息,自行修改

seata1.4.0落地_第3张图片

2.7.2在seata/conf/文件夹下增加nacos-config.sh 文件 内容如下:

#!/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

urlencode() {
  for ((i=0; i < ${#1}; i++))
  do
    char="${1:$i:1}"
    case $char in
    [a-zA-Z0-9.~_-]) printf $char ;;
    *) printf '%%%02X' "'$char" ;;
    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=$(urlencode $1)&group=$group&content=$(urlencode $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

2.7.3更改seata/cong文件夹下的registry.conf,修改两处

    1注册中心类型及注册中西配置

seata1.4.0落地_第4张图片

2,配置中心类型及相关参数

seata1.4.0落地_第5张图片

2.7.4修改项目目录下的file.conf文件

更改数据库信息,如有redis更改redis相关配置

seata1.4.0落地_第6张图片

2.8将fonfig.txt上传至nacos

在seata/conf文件夹下执行如下上传命令:

sh nacos-config.sh -h 10.1.5.88 -p 8848 -g SEATA_GROUP -t 60e39b35-0229-4733-addf-fa9eedcd8e33 -u admin -w 123456

seata1.4.0落地_第7张图片

seata1.4.0落地_第8张图片seata1.4.0落地_第9张图片

2.9 启动seata服务,在seataa/bin 文件夹下执行,windows的话执行.bat  linux执行.sh文件

seata1.4.0落地_第10张图片

如下表示启动成功,可取nacos里去查看

seata1.4.0落地_第11张图片

seata1.4.0落地_第12张图片seata1.4.0落地_第13张图片

至此TC(服务端)配置启动完成

2.9客户端配置(自己的服务)

2.9.1 引入依赖,

注意引入依赖这一步可能会有些模范,首先官网提供了依赖版本说明

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

可参考官网提供的版本配置方式。

可能我项目内spring boot cloud版本比较老所有几番尝试之后使用了如下配置:

主项目:


    com.alibaba.cloud
    spring-cloud-alibaba-dependencies
    2.0.4.RELEASE
    pom
    import

子项目:


   io.seata
   seata-spring-boot-starter
   1.4.0

seata1.4.0落地_第14张图片

2.9.2yml配置,增加如下配置

seata:
  enabled: true
  application-id: mjkf-agility-sys-manage-htf
  tx-service-group: mjkf-agility-sys-manage-group
  data-source-proxy-mode: AT
  use-jdk-proxy: true
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 10.1.5.88:8848
      username: admin
      password: 123456
  config:
    type: nacos
    nacos:
      server-addr: 10.1.5.88:8848
      group: SEATA_GROUP
      username: admin
      password: 123456
      namespace: 60e39b35-0229-4733-addf-fa9eedcd8e33
      #data-id: seata.properties
      #namespace: 5342dc77-dbb7-4ac7-ad72-9f65b71b1e94
  service:
    vgroupMapping:
      mjkf-agility-sys-manage-group: default
  client:
    rm:
      report-success-enable: false
  grouplist:
    default: 10.1.5.98:8091

seata1.4.0落地_第15张图片seata1.4.0落地_第16张图片2.10,业务代码增加配置

@GlobalTransactional(rollbackFor = Exception.class)

seata1.4.0落地_第17张图片

注意:完成上述工作后,因为fegin调用需要绑定XID的传递,以下附上绑定代码

新建一个配置类

import feign.RequestInterceptor;
import feign.RequestTemplate;
import io.seata.core.context.RootContext;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author htf
 * @description
 * @date 2021-7-12 10:56
 */

@Configuration
public class FeignSupportConfig implements RequestInterceptor {
    /**
     * 解决服务直接调用请求头不传递的问题
     * @param template
     */
    @Override
    public void apply(RequestTemplate template) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            Enumeration headerNames = request.getHeaderNames();
            if (headerNames != null) {
                Map> resolvedHeaders = new CaseInsensitiveKeyMap<>();
                resolvedHeaders.putAll(template.headers());

                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    if (!resolvedHeaders.containsKey(name)) {
                        String values = request.getHeader(name);
                        List headers = new ArrayList();
                        headers.addAll(Arrays.asList(values));
                        resolvedHeaders.put(name, headers);
                    }
                }
                template.headers(null);
                template.headers(resolvedHeaders);
            }
        }
        String xid = RootContext.getXID();
        if (StringUtils.isNotBlank(xid)) {
            template.header(RootContext.KEY_XID, xid);
        }
    }
}

然后再feigin调用server处添加此配置类就可以

seata1.4.0落地_第18张图片

 

至此客户端也配置完成。  一定要自己查看官方文档,避免踩空

过程中可能出现问题:

因为本人已经踩过很多坑,给出的配置文件基本上已经是更改过的,此前出现过的一些报错信息及解决记录:

1,客户端服务一致起不起来 一致报错

   Could not generate CGLIB subclass of class com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper: 
   Common causes of this problem include using a final class or a non-visible class; 
   
   nested exception is org.springframework.cglib.core.CodeGenerationException: 
   java.lang.reflect.InvocationTargetException-->null

解决:yml配置文件增加use-jdk-proxy: true  解决

2,seata服务端已启动,客户端还是一直报错:

no available service found in cluster ‘default’, please make sure registry config correct and keep your seata server running

或者

can not get cluster name in registry config 'service.vgroupMapping.my_test_tx_group', please make sure registry config correct

解决:注意在nacos的seata-server服务与 nacos的配置中心分组保持一致,都使用SEATA_GROUP

这个分组是在配置文件里 registry.conf配置文件里

seata1.4.0落地_第19张图片seata1.4.0落地_第20张图片

关于这个报错  还需要注意:config.txt里的service.vgroupMapping.mjkf-agility-sys-manage-group=default(注:mjkf-agility-sys-manage-group 为自定义)这个配置即为nacos里的配置

seata1.4.0落地_第21张图片

与yml文件里的这两处一定要保持一致,否在会此错误。

seata1.4.0落地_第22张图片

-----------------------------------------------------------------------------------------

相关资源:

https://download.csdn.net/download/u010185947/20065800

你可能感兴趣的:(seata,分布式,分布式,java,spring)