springboot dubbo seata nacos集成 分布式事务seata实现

news2024/11/15 21:49:13

文章目录

  • Seata介绍
  • dubbo介绍
  • 目标
  • 版本说明和代码地址
  • pom.xml
  • 验证模块
    • microservice-boot-common
    • microservice-boot- plat
  • 验证结果
  • 注意事项

Seata介绍

官网:http://seata.io/zh-cn/docs/overview/what-is-seata.html
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

在这里插入图片描述

dubbo介绍

官网;https://cn.dubbo.apache.org/zh-cn/overview/what/
Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。
在云原生时代,Dubbo 相继衍生出了 Dubbo3、Proxyless Mesh 等架构与解决方案,在易用性、超大规模微服务实践、云原生基础设施适配、安全性等几大方向上进行了全面升级。

目标

我们先说目标,为各位看官节省不匹配的时间
1、使用nacos做配置中心
2、使用nacos做注册中心
3、微服务模块化
4、使用dubbo作为服务管理
5、使用springboot做脚手架
6、使用seata做分布式事务

版本说明和代码地址

Dubbo :3.1.0
Springboot:2.3.1.RELEASE
Seata:1.6.1
Nacos-config:0.2.10

实现源代码地址
分支:microservice-boot-1.0.4-seata
代码演示和测试:
microservice-boot-common模块
microservice-boot-plat模块

pom.xml

直接上pom文件吧

  
          <dubbo.version>3.1.0</dubbo.version>
          <spring-boot.version>2.3.1.RELEASE</spring-boot.version>
          <spring-context-support.version>1.0.11</spring-context-support.version>
  
          <!-- 微服务相关 -->
          <nacos-config.version>0.2.10</nacos-config.version>
          <io.seata.version>1.6.1</io.seata.version>
  
  
  
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

 <!-- Dubbo Spring Boot Starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.spring</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

        <!--nacos config -->
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>nacos-config-spring-boot-starter</artifactId>
            <version>${nacos-config.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </dependency>

验证模块

两个模块
microservice-boot-common
microservice-boot- plat
模拟:
plat中controller请求,本地服务(此服务使用分布式事务),本地服务调用dubbo服务(包括palt的保存数据和common的保存日志)

microservice-boot-common

1、yaml配置

  # seata 配置
seata:
  application-id: ${spring.application.name}
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: fb91b495-9490-436f-b9cd-023f2ca42b08
      group: SEATA_GROUP
      username: nacos
      password: nacos
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties
  # 默认就是这个额,可以不配置
  tx-service-group: default_tx_group
  registry:
    custom:
      name: ${spring.application.name}
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      application: seata-server
      group: SEATA_GROUP
      namespace: 920bb73f-17da-4128-9de0-41893097ce38
      username: nacos
      password: nacos

2、dubbo服务代码

package org.lwd.microservice.boot.common.service.dubbo;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.lwd.microservice.boot.common.api.dto.VisitDubboDTO;
import org.lwd.microservice.boot.common.api.dubbo.VisitDubboService;
import org.lwd.microservice.boot.common.entity.dto.VisitDTO;
import org.lwd.microservice.boot.common.service.VisitService;
import org.lwd.microservice.boot.core.constant.HttpStatusEnum;
import org.lwd.microservice.boot.core.entity.BaseResult;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * @author weidong
 * @version V1.0.0
 * @since 2023/6/28
 */
@Slf4j
@DubboService
public class VisitDubboServiceImpl implements VisitDubboService {

    @Autowired
    VisitService visitService;

    /**
     * 保存
     *
     * @return
     */
    @Override
    public BaseResult<Integer> saveVisitDubboService(VisitDubboDTO visitDubboDTO) {
        log.info("----i am do saveVisitDubboService-----:{}", JSON.toJSONString(visitDubboDTO));
        BaseResult<Integer> baseResult = BaseResult.success();
        VisitDTO visitDTO = new VisitDTO();
        BeanUtils.copyProperties(visitDubboDTO, visitDTO);
        BaseResult<Integer> result = visitService.saveVisit(visitDTO);
        if (result.isSuccess()) {
            baseResult.setData(baseResult.getData());
        } else {
            baseResult.setCode(HttpStatusEnum.REQUEST_FAIL.getCode());
            baseResult.setMessage("保存日志失败");
        }

        return baseResult;
    }
}

microservice-boot- plat

1、yaml配置

# seata 配置
seata:
  application-id: ${spring.application.name}
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: fb91b495-9490-436f-b9cd-023f2ca42b08
      group: SEATA_GROUP
      username: nacos
      password: nacos
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties
  # 默认就是这个额,可以不配置
  tx-service-group: default_tx_group
  registry:
    custom:
      name: ${spring.application.name}
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      application: seata-server
      group: SEATA_GROUP
      namespace: 920bb73f-17da-4128-9de0-41893097ce38
      username: nacos
      password: nacos


2、dubbo服务实现

package org.lwd.microservice.boot.plat.service.dubbo;

import org.apache.dubbo.config.annotation.DubboService;
import org.lwd.microservice.boot.core.entity.BaseResult;
import org.lwd.microservice.boot.plat.api.dto.UserLoginDubboDTO;
import org.lwd.microservice.boot.plat.api.dubbo.UserLoginDubboService;
import org.lwd.microservice.boot.plat.entity.dto.UserLoginDTO;
import org.lwd.microservice.boot.plat.service.UserLoginService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 登录基本服务
 * @author weidong
 * @version V1.0.0
 * @since 2023/7/3
 */
@DubboService
public class UserLoginDubboServiceImpl implements UserLoginDubboService {

    @Autowired
    UserLoginService userLoginService;

    @Override
    public BaseResult<Integer> saveUserLoginDubbo(UserLoginDubboDTO userLoginDubboDTO) {
        BaseResult<Integer> result = BaseResult.success();
        UserLoginDTO userLoginDTO = new UserLoginDTO();
        BeanUtils.copyProperties(userLoginDubboDTO,userLoginDTO);
        BaseResult<Integer> baseResult = userLoginService.saveUserLogin(userLoginDTO);
        if(baseResult.isSuccess()){
            result.setData(baseResult.getData());
        }
        return result;
    }
}

3、分布式事务服务实现

package org.lwd.microservice.boot.plat.service.impl;

import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.lwd.microservice.boot.common.api.dto.VisitDubboDTO;
import org.lwd.microservice.boot.common.api.dubbo.VisitDubboService;
import org.lwd.microservice.boot.core.constant.HttpStatusEnum;
import org.lwd.microservice.boot.core.entity.BaseResult;
import org.lwd.microservice.boot.plat.api.dto.UserLoginDubboDTO;
import org.lwd.microservice.boot.plat.api.dubbo.UserLoginDubboService;
import org.lwd.microservice.boot.plat.entity.dto.UserLoginDTO;
import org.lwd.microservice.boot.plat.service.UserLoginSeataService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

/**
 * @author weidong
 * @version V1.0.0
 * @since 2023/7/3
 */
@Slf4j
@Service
public class UserLoginSeataServiceImpl implements UserLoginSeataService {

    @DubboReference
    UserLoginDubboService userLoginDubboService;
    @DubboReference
    VisitDubboService visitDubboService;

    @Override
    @GlobalTransactional(timeoutMills = 30000, name = "default_tx_group")
    public BaseResult<Integer> saveUserLoginSeata(UserLoginDTO dto) throws Exception {
        BaseResult<Integer> result = BaseResult.success();
        log.info("开始全局事务:xid=" + RootContext.getXID());
        log.info("begin userLogin: " + dto);

        //保存登录信息
        UserLoginDubboDTO userLoginDubboDTO = new UserLoginDubboDTO();
        BeanUtils.copyProperties(dto, userLoginDubboDTO);
        BaseResult<Integer> userResult = userLoginDubboService.saveUserLoginDubbo(userLoginDubboDTO);
        if (userResult.isSuccess()) {
            result.setData(userResult.getData());
        } else {
            result.setCode(HttpStatusEnum.REQUEST_FAIL.getCode());
            throw new Exception("登录信息保存系统异常");
        }
        if (!result.isSuccess()) {
            return result;
        }

        //保存日志
        VisitDubboDTO visitDubboDTO = new VisitDubboDTO();
        visitDubboDTO.setServerIpAddress("3.3.3.3");
        if (dto.getEnabled().equals(1)) {
            visitDubboDTO.setCreateTime(dto.getCreateTime());
        }
        BaseResult<Integer> visitResult = visitDubboService.saveVisitDubboService(visitDubboDTO);
        if (visitResult.isSuccess()) {
            log.info("visit info pk:{}", visitResult.getData());
            result.setData(visitResult.getData());
        } else {
            result.setCode(HttpStatusEnum.REQUEST_FAIL.getCode());
            throw new Exception("日志保存系统异常");
        }

        return result;
    }
}

验证结果

在这里插入图片描述

注意事项

1、seata在注册到nacos时,订阅端的应用名称为unknown
临时解决方案:

package org.lwd.microservice.boot.common;

import org.lwd.microservice.boot.middle.runtime.util.YmlUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 *
 * @author weidong
 * @version V1.0.0
 * @since 2023/4/7
 */
@SpringBootApplication
public class CommonApplication {
    public static void main(String[] args) {
        //TODO 这块有一个问题,seata在注册到nacos时,订阅端的应用名称为unknown,经验证是获取不到ProjectNameConfig中设置的${spring.application.name}
        //估计是加载顺序获取其他问题,现在这获取数据,优先处理
        System.setProperty("project.name", YmlUtils.getApplicationName());
        SpringApplication.run(CommonApplication.class, args);
    }
}


2、分布式事务默认AT模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零开始 Spring Boot 63:Hibernate 继承映射

从零开始 Spring Boot 63&#xff1a;Hibernate 继承映射 图源&#xff1a;简书 (jianshu.com) 关系型数据库设计中是不存在继承概念的&#xff0c;但实体类可以用继承来组织代码结构&#xff0c;所以需要用一种方式将实体类的继承结构映射到表结构。 本文将介绍几种在 JPA&a…

LCD1602显示屏只亮不显示字符

代码能在普中的板子能正常显示&#xff0c;但是换了块板子就不行&#xff1a; 调节显示屏下方的可调电阻 在调试中找到自己适合的值&#xff0c;就可以看见字符了

5、加载3dtileset模型并定位到模型

这一节使用CCesium加载3dtiles模型&#xff0c;3dtiles模型使用ceisum官网示例中的模型&#xff0c;加载3dtiles功能目前只能添加没有压缩的模型&#xff0c;draco或其他解压缩功能没有写。 1、在上一个例子的基础上&#xff0c;将鼠标事件改成右键的鼠标事件Cesium::ScreenSp…

科研热点|重磅!华为,唯一单位首发Nature!

今日&#xff0c;国际顶级学术期刊《自然》(Nature)杂志正刊发表了华为云盘古大模型研发团队研究成果——《三维神经网络用于精准中期全球天气预报》&#xff08;《Accurate medium-range global weather forecasting with 3D neural networks》&#xff09;。数据显示&#xf…

医学报告怎样翻译效果好?

我们知道&#xff0c;医学报告是医学翻译领域比较重要的一个项目&#xff0c;许多国际医学期刊和杂志都要求医学报告必须是英语的&#xff0c;促使医学报告翻译的需求量越来越大。那么&#xff0c;怎样翻译医学报告&#xff0c;医学报告中译英哪里比较专业&#xff1f; 据了解&…

Java类加载深度剖析-大白话

Java类加载深度剖析 1.类加载的入口2.AppClassLoader、ExtClassLoader、BootstrapClassLoader的血脉渊源3.ExtClassLoader究竟是不是孙大圣4.为什么自定义类加载器的父类加载器是AppClassLoader呢&#xff1f;5.我们应该如何打破双亲委派机制呢&#xff1f;6.如何保证同class对…

实现UDP通信

UDP通信的实现过程 write/read到send/recv 函数原型&#xff1a; ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags); 前三个参数同read/write一样&#xff1b; ssize_t read(int fd, void *bu…

滚珠螺杆的基本知识点

滚珠螺杆具有定位精度高、高寿命、低污染和可做高速正逆向的传动及变换传动等特性&#xff0c;因具上述特性&#xff0c;滚珠螺杆已成为近来精密科技产业及精密机械产业的定位及测量系统上的重要零组件之一。 滚珠螺杆主要由螺杆、螺帽、钢珠、固定座、刮刷器及回流管所构成的&…

thinkphp开发宠物领养商城系统 金融投资理财源码 中英文语言 支持增加多种语言

程序代码里面 除了线下支付&#xff0c;增加了4个线上支付方式 1、新增短信接口&#xff1a;短信宝、云片短信、网建短信。 2、新增阿里API实名认证&#xff0c;支持开启或关闭。 3、新增阿里API银行卡实名认证&#xff0c;支持开启或关闭。 4、新增项目分类开关、支付宝和微信…

基于springboot+vue框架的电影订票系统_wqc3k

随着网络科技的不断发展以及人们经济水平的逐步提高&#xff0c;计算机如今已成为人们生活中不可缺少的一部分&#xff0c;为电影订票方便管理&#xff0c;基于java技术设计与实现了一款简洁、轻便的管理系统。本系统解决了电影订票事务中的主要问题&#xff0c;包括个人中心、…

微服务拆分原则

库存供应链服务 交易和订单服务 用户服务 1. 业务之间耦合降低 相互调用较少 进行拆分 2.修改频率区分不同服务

Qlib全新升级:强化学习能否重塑金融决策模式?

编者按&#xff1a;2020年&#xff0c;微软亚洲研究院开源了金融 AI 通用技术平台 Qlib。Qlib 以金融 AI 研究者和金融行业 IT 从业者为用户&#xff0c;针对金融场景研发了一个适应人工智能算法的高性能基础设施和数据、模型管理平台。一经开源&#xff0c;Qlib 便掀起了一阵热…

对话罗氏中国:数字化创新驱动下的高效运营与合规实践

上海斯歌与罗氏中国已合作十余年&#xff0c;罗氏几乎见证了上海斯歌发展的全过程。近日&#xff0c;斯歌与罗氏 China Market Domain 架构负责人—— Brian Yang&#xff0c;就企业数字化探索、新技术的展望及斯歌产品等话题展开了探讨。 罗氏中国简介 罗氏&#xff08;Roche&…

Nacos启动报错

错误如下 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name communicationController defined in URL [jar:file:/D:/apache/maven/vip/xiaonuo/nacos/nacos-config/2.1.2.GA/nacos-config-2.1.2.GA.jar!/com/alibaba/nacos…

前后端实现mqtt物联网消息互通对话(图文详解)

需求&#xff1a;前端使用mqtt订阅主题和硬件设备进行通讯功能&#xff0c;不走后端&#xff0c;前端操作可以控制。从部署到对话&#xff0c;跟着图文一套下来你也可以学会。很简单的。后端用node&#xff0c;前端就用原生的js&#xff0c;如果要使用vue&#xff0c;可以看我另…

OpenCV4使用applyColorMap()函数,可以将灰度图或彩色图转换成自定义的彩色图,或opencv提供的20多种色彩值

文章目录 1、applyColorMap()函数的使用&#xff1a;&#xff08;1&#xff09;函数原型&#xff1a;void applyColorMap(InputArray src, OutputArray dst, int colormap)void applyColorMap(InputArray src, OutputArray dst, InputArray userColor) &#xff08;2&#xff0…

记录CompletableFuture使用遇到的坑-多数据源

现象&#xff1a;使用了allof().get()去阻塞线程等待子线程跑完&#xff0c;但子线程还是没跑完就结束了。 代码如图&#xff1a; 如果您熟悉CompletableFuture的.allOf方法应该知道题主是想等3个异步任务完成再往下执行&#xff0c;但事实是3个异步任务执行到最后 "好像…

2023年最新全国分省、市路网数据shp

最新全国分省、市路网数据 2023年 ​ 最近有小伙伴反应无法进入OSM地图官网下载数据&#xff0c;所以这次带来全国路网数据shp文件。获取时间&#xff1a;2023年5月 数据格式&#xff1a;shp 坐标系&#xff1a;GCJ-02 数据概览 分省如下&#xff1a; ​ 例如河北&#xff…

DDR3 控制器 MIG IP 详解完整版 (nativeVIVADOVerilog)

文章目录 前言一、MIG IP 核的配置二、MIG 交互的接口三、常用IP例化值四、小实验传图 前言 本节主要是介绍 Xilinx DDR 控制器 IP 的创建流程、IP 用户使用接口 native 协议介绍和IP 对应的 Example Design 的仿真和上板验证。。 提示&#xff1a;以下是本篇文章正文内容&…

开放式耳机哪个好?综合性能不错的开放式耳机推荐

传统入耳式耳机容易滑落&#xff0c;而且戴久了耳朵疼&#xff0c;开放式耳机的出现就避免了这个问题的出现&#xff0c;本文就为大家推荐几款使用感较好的开放式耳机&#xff0c;一起来看看吧~ 一、NANK南卡OE Pro开放式耳机 南卡OE Pro凭借着顶级的佩戴体验和极高的音质水准…