• SpringCloud系列之Nacos+Dubbo+Seata应用篇


    前言

    本文接上篇文章《SpringCloud系列之Nacos+Dubbo应用篇》继续展开,本次在原先集成Nacos和Dubbo基础上增加分布式事务Seata组件,之前在《SpringCloud系列之集成分布式事务Seata应用篇》中也提及到Seata的集成,只不过原先Seata使用都是基于“file”展开,在本篇中将介绍如何基于nacos进行配置以及Dubbo和Seata的集成验证。

    项目版本

    spring-boot.version:2.2.5.RELEASE
    spring-cloud.version:Hoxton.SR3
    nacos.version:1.3.2
    dubbo.version:2.6.9/2.7.6
    seata.version:1.3.0

    关注本文末尾微信公众号,回复“666”获取常用开发工具包,内含常用开发组件(Nacos,Seata等),节省FQ下载时间。

    项目说明

    项目模块说明如下:

    前端请求接口请求cloud-web模块保留接口,从而调用相应业务微服务模块,执行业务逻辑后响应前端请求。

    支付模块对外提供Dubbo服务,其余服务采用Feign进行通讯,用户模块示例中未涉及相关业务调用。

    Dubbo 2.6.x 和 Dubbo 2.7.x 除了依赖不一样,其余配置项基本一样,这边就不再单独进行区分说明,详情请查阅本文文末项目源码,有进行区分说明。

    Nacos服务

    Nacos服务端部署请查阅《SpringCloud系列之Nacos应用篇》

    Seata服务

    进入Seata配置目录下,编辑registry.conf配置文件,将registry配置项中type配置项配置成"nacos",并配置nacos相关配置,具体如下

    registry {
      # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
      type = "nacos"
    
      nacos {
        application = "seata-server"
        serverAddr = "127.0.0.1:8848"
        group = "SEATA_GROUP"
        namespace = "public"
        cluster = "default"
        username = ""
        password = ""
      }
    }  
    

    配置完registry配置项后将config配置项也配置成“nacos”,具体如下

    config {
      # file、nacos 、apollo、zk、consul、etcd3
      type = "nacos"
    
      nacos {
        serverAddr = "127.0.0.1:8848"
        namespace = "public"
        group = "SEATA_GROUP"
        username = ""
        password = ""
      }
    }
    

    调整完后启动Seata服务即可在Nacos后台看到已注册的服务,如下图

    订单模块

    其余模块本次未进行任何调整,只在订单模块中增加Dubbo相关配置
    部分pom.xml如下,完整信息请查阅本文文末项目源码
    pom.xml

            <!--nacos discovery-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.alibaba.nacos</groupId>
                        <artifactId>nacos-client</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--nacos config-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>com.alibaba.nacos</groupId>
                        <artifactId>nacos-client</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--dubbo-->
            <dependency>
                <groupId>com.alibaba.boot</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>0.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>2.6.9</version>
            </dependency>
            <!--dubbo nacos-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo-registry-nacos</artifactId>
                <version>2.6.7</version>
                <exclusions>
                    <exclusion>
                        <groupId>com.alibaba.nacos</groupId>
                        <artifactId>nacos-client</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--nacos-->
            <dependency>
                <groupId>com.alibaba.nacos</groupId>
                <artifactId>nacos-client</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.31.Final</version>
            </dependency>
            <!-- seata-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-seata</artifactId>
                <version>2.2.0.RELEASE</version>
                <exclusions>
                    <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>
    

    application.properties

    dubbo.application.name=order-service
    # dubbo扫描包路径
    dubbo.scan.base-packages=com.chinawu.cloud.order.service
    # dubbo协议
    dubbo.protocol.name=dubbo
    # 随机端口
    dubbo.protocol.port=-1
    # zookeeper地址
    dubbo.registry.address=nacos://127.0.0.1:8848
    
    spring.main.allow-bean-definition-overriding=true
    

    OrderService.java

    @RestController
    public class OrderService implements OrderFacade {
    
        @Autowired
        private TbOrderMapper tbOrderMapper;
        @Autowired
        private CartFacade cartFacade;
        @Autowired
        private GoodsFacade goodsFacade;
        @Autowired
        private WalletFacade walletFacade;
    
        // Dubbo服务消费
        @Reference(check = false)
        DPayFacade dPayFacade;
    
        /**
         * <p >
         * 功能:新增订单
         * </p>
         * @param cartId 购物车ID
         * @author wuyubin
         * @date  2020年05月22日
         * @return
         */
        @Override
        public void addOrder(Long cartId) {
            CartDTO cart = cartFacade.getCartById(cartId);
            TbOrder order = new TbOrder();
            order.setUserId(cart.getUserId());
            order.setGoodsId(cart.getGoodsId());
            order.setOrderNo(String.valueOf(System.currentTimeMillis()));
            order.setCreateTime(System.currentTimeMillis());
            order.setUpdateTime(order.getCreateTime());
            order.setIsDeleted(Byte.valueOf("0"));
            // 新增订单
            tbOrderMapper.insert(order);
            // 删除购物车(Feign)
            cartFacade.deleteCartById(cartId);
            GoodsDTO goods = goodsFacade.getByGoodsId(cart.getGoodsId());
            // 扣减库存(Feign)
            goodsFacade.substractStock(goods.getId());
            // 扣减金额(Feign)
            walletFacade.substractMoney(cart.getUserId(),goods.getMoney());
            // 记录支付消息(Dubbo调用)
            dPayFacade.goToPay("wuyubin");
            throw new RuntimeException();
        }
    }
    

    新增引用支付模块Dubbo服务,dPayFacade.goToPay("wuyubin");

    支付模块

    支付模块在原先基础上增加Seata依赖,部分pom信息如下
    pom.xml

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-seata</artifactId>
                <version>2.2.0.RELEASE</version>
                <exclusions>
                    <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>
    

    application.properties

    # seata配置
    seata.enabled=true
    #seata.excludes-for-auto-proxying=firstClassNameForExclude,secondClassNameForExclude
    seata.application-id=pay-service
    # 事务分组名
    seata.tx-service-group=pay-service_tx_group
    # 默认开启数据源自动代理
    seata.enable-auto-data-source-proxy=true
    seata.use-jdk-proxy=false
    
    seata.config.type=nacos
    seata.registry.type=nacos
    seata.registry.nacos.server-addr=127.0.0.1:8848
    

    DPayService.java

    @Service
    public class DPayService implements DPayFacade {
    
        @Autowired
        TbPayMapper tbPayMapper;
    
        @Override
        public String goToPay(String userName) {
            String xid = RootContext.getXID();
            System.out.println("pay.seata.xid:"+xid);
            System.out.println("dubbo.method:goToPay request "+userName);
            TbPay pay = new TbPay();
            pay.setMoney(new BigDecimal("5"));
            pay.setStatus(Byte.valueOf("1"));
            tbPayMapper.insert(pay);
            return "dubbo.method:goToPay result:" + userName + " pay success";
        }
    }
    

    调整完启动支付模块后,启动过程中发现一行报错日志,信息如下
    no available service 'null' found, please make sure registry config correct

    其余正常,但心里还是有点担忧,其他服务模块启动后试一下再说
    http://localhost:9100/order/add?cartId=1

    请求后果然在支付模块报如下错误
    Caused by: io.seata.core.exception.RmTransactionException: Runtime
    Caused by: io.seata.common.exception.FrameworkException: No available service
    看信息应该是缺少服务,后来经过一点点排查后,最终确认是这一行配置项导致,将
    seata.config.type=nacos调整至file时并把这行配置项打开即可(用nacos时其余seata配置项都注释掉了)

     seata.service.vgroup-mapping.pay-service_tx_group=default
    

    先了解下该行配置项主要作用,原来是靠此配置项用于查询TC服务的。

    那是不是只要添加这行配置就可以了呢,重新将seata配置信息调整至“nacos”,根据命名规则尝试创建以下配置项

    配置创建成功后,在支付模块后台立马看到有日志输出

    2020-09-14 15:58:43.284 ERROR 28292 --- [eoutChecker_2_1] i.s.c.r.netty.NettyClientChannelManager  : no available service 'null' found, please make sure registry config correct
    2020-09-14 15:58:53.252 ERROR 28292 --- [eoutChecker_1_1] i.s.c.r.netty.NettyClientChannelManager  : no available service 'null' found, please make sure registry config correct
    2020-09-14 15:58:53.285 ERROR 28292 --- [eoutChecker_2_1] i.s.c.r.netty.NettyClientChannelManager  : no available service 'null' found, please make sure registry config correct
    2020-09-14 15:59:02.853  INFO 28292 --- [-localhost_8848] c.a.n.client.config.impl.ClientWorker    : [fixed-localhost_8848] [polling-resp] config changed. dataId=service.vgroupMapping.pay-service_tx_group, group=SEATA_GROUP
    2020-09-14 15:59:02.853  INFO 28292 --- [-localhost_8848] c.a.n.client.config.impl.ClientWorker    : get changedGroupKeys:[service.vgroupMapping.pay-service_tx_group+SEATA_GROUP]
    2020-09-14 15:59:02.857  INFO 28292 --- [-localhost_8848] c.a.n.client.config.impl.ClientWorker    : [fixed-localhost_8848] [data-received] dataId=service.vgroupMapping.pay-service_tx_group, group=SEATA_GROUP, tenant=null, md5=c21f969b5f03d33d43e04f8f136e7682, content=default, type=text
    2020-09-14 15:59:02.857  INFO 28292 --- [-localhost_8848] c.a.nacos.client.config.impl.CacheData   : [fixed-localhost_8848] [notify-context] dataId=service.vgroupMapping.pay-service_tx_group, group=SEATA_GROUP, md5=c21f969b5f03d33d43e04f8f136e7682
    2020-09-14 15:59:02.858  INFO 28292 --- [-localhost_8848] c.a.nacos.client.config.impl.CacheData   : [fixed-localhost_8848] [notify-ok] dataId=service.vgroupMapping.pay-service_tx_group, group=SEATA_GROUP, md5=c21f969b5f03d33d43e04f8f136e7682, listener=io.seata.config.nacos.NacosConfiguration$NacosListener@37dd83b6 
    2020-09-14 15:59:02.858  INFO 28292 --- [-localhost_8848] c.a.nacos.client.config.impl.CacheData   : [fixed-localhost_8848] [notify-listener] time cost=1ms in ClientWorker, dataId=service.vgroupMapping.pay-service_tx_group, group=SEATA_GROUP, md5=c21f969b5f03d33d43e04f8f136e7682, listener=io.seata.config.nacos.NacosConfiguration$NacosListener@37dd83b6 
    2020-09-14 15:59:03.253  INFO 28292 --- [eoutChecker_1_1] com.alibaba.nacos.client.naming          : new ips(1) service: SEATA_GROUP@@seata-server@@default -> [{"instanceId":"192.168.2.241#8091#default#SEATA_GROUP@@seata-server","ip":"192.168.2.241","port":8091,"weight":1.0,"healthy":true,"enabled":true,"ephemeral":true,"clusterName":"default","serviceName":"SEATA_GROUP@@seata-server","metadata":{},"ipDeleteTimeout":30000,"instanceHeartBeatInterval":5000,"instanceIdGenerator":"simple","instanceHeartBeatTimeOut":15000}]
    2020-09-14 15:59:03.254  INFO 28292 --- [eoutChecker_1_1] com.alibaba.nacos.client.naming          : current ips:(1) service: SEATA_GROUP@@seata-server@@default -> [{"instanceId":"192.168.2.241#8091#default#SEATA_GROUP@@seata-server","ip":"192.168.2.241","port":8091,"weight":1.0,"healthy":true,"enabled":true,"ephemeral":true,"clusterName":"default","serviceName":"SEATA_GROUP@@seata-server","metadata":{},"ipDeleteTimeout":30000,"instanceHeartBeatInterval":5000,"instanceIdGenerator":"simple","instanceHeartBeatTimeOut":15000}]
    2020-09-14 15:59:03.254  INFO 28292 --- [eoutChecker_1_1] com.alibaba.nacos.client.naming          : [LISTENER] adding SEATA_GROUP@@seata-server with default to listener map
    2020-09-14 15:59:03.256  INFO 28292 --- [eoutChecker_1_1] i.s.c.r.netty.NettyClientChannelManager  : will connect to 192.168.2.241:8091
    2020-09-14 15:59:03.258  INFO 28292 --- [eoutChecker_1_1] i.s.core.rpc.netty.NettyPoolableFactory  : NettyPool create channel to transactionRole:TMROLE,address:192.168.2.241:8091,msg:< RegisterTMRequest{applicationId='pay-service', transactionServiceGroup='pay-service_tx_group'} >
    2020-09-14 15:59:03.281  INFO 28292 --- [eoutChecker_2_1] i.s.c.r.netty.NettyClientChannelManager  : will connect to 192.168.2.241:8091
    2020-09-14 15:59:03.281  INFO 28292 --- [eoutChecker_2_1] i.s.c.rpc.netty.RmNettyRemotingClient    : RM will register :jdbc:mysql://127.0.0.1:3306/spring-cloud
    2020-09-14 15:59:03.283  INFO 28292 --- [eoutChecker_2_1] i.s.core.rpc.netty.NettyPoolableFactory  : NettyPool create channel to transactionRole:RMROLE,address:192.168.2.241:8091,msg:< RegisterRMRequest{resourceIds='jdbc:mysql://127.0.0.1:3306/spring-cloud', applicationId='pay-service', transactionServiceGroup='pay-service_tx_group'} >
    2020-09-14 15:59:03.305  INFO 28292 --- [eoutChecker_2_1] i.s.c.rpc.netty.RmNettyRemotingClient    : register RM success. client version:1.3.0, server version:1.3.0,channel:[id: 0x15ef339d, L:/192.168.2.241:64550 - R:/192.168.2.241:8091]
    2020-09-14 15:59:03.305  INFO 28292 --- [eoutChecker_1_1] i.s.c.rpc.netty.TmNettyRemotingClient    : register TM success. client version:1.3.0, server version:1.3.0,channel:[id: 0xd4e407be, L:/192.168.2.241:64548 - R:/192.168.2.241:8091]
    2020-09-14 15:59:03.313  INFO 28292 --- [eoutChecker_1_1] i.s.core.rpc.netty.NettyPoolableFactory  : register success, cost 39 ms, version:1.3.0,role:TMROLE,channel:[id: 0xd4e407be, L:/192.168.2.241:64548 - R:/192.168.2.241:8091]
    2020-09-14 15:59:03.313  INFO 28292 --- [eoutChecker_2_1] i.s.core.rpc.netty.NettyPoolableFactory  : register success, cost 26 ms, version:1.3.0,role:RMROLE,channel:[id: 0x15ef339d, L:/192.168.2.241:64550 - R:/192.168.2.241:8091]
    
    

    感觉有戏,再次请求接口,果然不再报错,提示事务回滚成功,其余模块也提示回滚成功,另外数据也正常,至此就可以使用啦。

    pay.seata.xid:192.168.2.241:8091:48803259719028736
    dubbo.method:goToPay request wuyubin
    2020-09-14 16:06:44.006  INFO 28292 --- [ch_RMROLE_1_1_8] i.s.c.r.p.c.RmBranchRollbackProcessor    : rm handle branch rollback process:xid=192.168.2.241:8091:48803259719028736,branchId=48803260146847744,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/spring-cloud,applicationData=null
    2020-09-14 16:06:44.010  INFO 28292 --- [ch_RMROLE_1_1_8] io.seata.rm.AbstractRMHandler            : Branch Rollbacking: 192.168.2.241:8091:48803259719028736 48803260146847744 jdbc:mysql://127.0.0.1:3306/spring-cloud
    2020-09-14 16:06:44.061  INFO 28292 --- [ch_RMROLE_1_1_8] i.s.r.d.undo.AbstractUndoLogManager      : xid 192.168.2.241:8091:48803259719028736 branch 48803260146847744, undo_log deleted with GlobalFinished
    2020-09-14 16:06:44.063  INFO 28292 --- [ch_RMROLE_1_1_8] io.seata.rm.AbstractRMHandler            : Branch Rollbacked result: PhaseTwo_Rollbacked
    
    

    参考资料

    Seata事务分组专题
    源码分析Seata-XID传递 Dubbo篇

    系列文章

    SpringCloud系列之配置中心(Config)使用说明

    SpringCloud系列之服务注册发现(Eureka)应用篇

    SpringCloud系列之网关(Gateway)应用篇

    SpringCloud系列之集成Dubbo应用篇

    SpringCloud系列之集成分布式事务Seata应用篇

    SpringCloud系列之Nacos应用篇

    SpringCloud系列之Nacos+Dubbo应用篇

    项目源码

    在这里插入图片描述

  • 相关阅读:
    Queries about less or equal elements CodeForces
    Session in BSU CodeForces
    基环树
    骑士 HYSBZ
    Valid BFS? CodeForces
    Trips CodeForces
    The writing on the wall 南京网络赛2018B题
    Building a Space Station
    Constructing Roads
    Networking
  • 原文地址:https://www.cnblogs.com/chinaWu/p/13671620.html
Copyright © 2020-2023  润新知