记一次dubbo接口调用造成的数据插入重复问题

项目近期要上线,这段时间改bug改的躁动不安的,也没时间好好写点东西了。本篇文章想给大家分享的是昨天调试改bug碰到的一个大坑。dubbo的重试配置。
问题出现的原因是,我在服务端接口里加了一段逻辑,导致程序执行时间增加了一些,消费端调用接口的时候超时了,导致触发的重试机制,数据重复推送到
服务端,重复生成三条数据。

大坑模拟复现

简单搭建一下dubbo环境 dubbo-service dubbo-service-sdk dubbo-service-web
1、新建module dubbo-service-sdk 定义服务接口

/**
 * @author v_liuwen
 * @date 2019-07-24
 */
public interface AsoService {

    void saveAso(AsoInfoDto asoInfoDto) throws InterruptedException;
}
/**
 * @author v_liuwen
 * @date 2019-07-24
 */
@Data
public class AsoInfoDto implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long asoId;

    private String asoNo;

    private String linkOrderNo;

    private Date createTime;

}

2、新建module dubbo-service 实现sdk的接口
依赖

       <dependency>
            <groupId>top.qrainly</groupId>
            <artifactId>dubbo-service-sdk</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.13</version>
        </dependency>
/**
 * @author v_liuwen
 * @date 2019-07-24
 */
@Service(version = "1.0", interfaceClass = AsoService.class)
@Component
@Slf4j
public class AsoServiceImpl implements AsoService {

    @Override
    public void saveAso(AsoInfoDto asoInfoDto) throws InterruptedException {
        //模拟阻塞超时
        Thread.sleep(5000);

        log.info("插入售后单信息-->{}", JSONObject.toJSONString(asoInfoDto));
    }
}

3、新建module dubbo-service-web
依赖

        <dependency>
            <groupId>top.qrainly</groupId>
            <artifactId>dubbo-service-sdk</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.13</version>
        </dependency>

定义业务接口

/**
 * @author v_liuwen
 * @date 2019-07-24
 */
public interface CreateAsoService {

    void saveAso();
}

定义业务实现

/**
 * @author v_liuwen
 * @date 2019-07-24
 */
@Service
@Slf4j
public class CreateAsoServiceImpl implements CreateAsoService {

    @Reference(version = "1.0",check = false)
    private AsoService asoService;
    @Override
    public void saveAso() {
        AsoInfoDto mock = JMockData.mock(AsoInfoDto.class);
        try {
            asoService.saveAso(mock);
        } catch (InterruptedException e) {
            log.error("异常-->{}",e.getMessage());
        }
    }
}

测试类

  @RunWith(SpringRunner.class)
  @SpringBootTest
  public class DubboWebApplicationTests {
  
      @Autowired
      private CreateAsoService createAsoService;
  
      @Test
      public void contextLoads() {
          createAsoService.saveAso();
      }
  
  }

启动dubbo-service 运行测试方法
控制台输出

2019-07-25 21:03:24.655  INFO 6720 --- [:20880-thread-5] t.q.dubboservice.impl.AsoServiceImpl     : 插入售后单信息-->{"asoId":8248,"asoNo":"aQg","createTime":2995060930132,"linkOrderNo":"zDv2"}
2019-07-25 21:03:27.603  INFO 6720 --- [:20880-thread-6] t.q.dubboservice.impl.AsoServiceImpl     : 插入售后单信息-->{"asoId":8248,"asoNo":"aQg","createTime":2995060930132,"linkOrderNo":"zDv2"}
2019-07-25 21:03:30.616  INFO 6720 --- [:20880-thread-7] t.q.dubboservice.impl.AsoServiceImpl     : 插入售后单信息-->{"asoId":8248,"asoNo":"aQg","createTime":2995060930132,"linkOrderNo":"zDv2"}

完美复现问题 刚开始就怀疑是不是重试配置导致的,但是看了一下@Reference的retries默认也是0,也就是说不配置的话默认重试0次,也就是不重试。
那为啥还调了三次。于是尝试配置了重试次数为-1

@Reference(version = “1.0”,retries = -1,check = false)

再次操作 控制台输出


果然!真是重试配置搞的鬼!后来我们的处理方案并不是把重试次数设为-1,而是配置的超时时间为30000ms。毕竟在网络抖动以及异常情况下,重试确实是
一个很好的弥补措施。配置超时时间也一样可以解决问题。至于服务超时处理,这个,也确实要优化一下。

总结:

dubbo接口的注入可以通过xml的方式和声明注解的方式注入
针对业务场景,配置合理的重试次数和超时时间,可以有效避免接口调用的问题
能配置超时时间尽量不要屏蔽重试机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qrainly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值