重试机制@Retryable

<dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
</dependency>
import com.example.cesium.service.IRetryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.time.LocalTime;

@Service
@Slf4j
public class IRetryServiceImpl implements IRetryService {

    @Override
    @Retryable(value=Exception.class,maxAttempts = 3,backoff = @Backoff(value = 2000,multiplier = 1.5))
    public int test(Integer code) throws Exception {
        log.info("testRetry时间:" + LocalTime.now());
        if (code == 0) {
            throw new Exception("出现异常!");
        }
        log.info("testRetry 成功调用!");
        return 200;
    }
}

value:抛出指定异常才会重试

include:除指定异常意外都重试

maxAttempts:最大重试次数。默认3次

backoff:重试等待策略,默认使用@Backoff , @Backoff的value默认为1000L,

mutiplier为指定延迟倍数 

value = 2000,multiplier = 1.5  第一次重试2秒 , 第二次3秒, 第三次 4.5秒

场景: 交通规则触发时,需要下发指令,但网络可能会抖动等异常情况,会导致车辆无法及时控制车辆。
优化: 网络抖动时,多次请求重试,保证下发指令有效执行。
实现:
    /**
     * 发送交通控制解除指令
     *
     * @param traffic
     * @param cmd
     */
    @Retryable(include = {RetryException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000L, multiplier = 2))
    @Override
    @Async
    public Boolean sendOperationCommand(TrafficVehiclesVo traffic, int cmd) {
        //拼接前车指令参数
        String code = traffic.getCode();
        BogieTrafficVo command = new BogieTrafficVo();
        command.setDeviceId(code);
        command.setOrder(cmd);
        command.setPointLongitude(traffic.getLongitude());
        command.setPointLatitude(traffic.getLatitude());
        command.setPointAltitude(traffic.getAltitude());
        // 根据规则引擎返回 下发车端指令 进行交通控制 增加判断条件限制重复下发相同指令
        log.info("车辆:{} 进行交通控制 {}", command.getDeviceId(), command);
        if (cmd == 1) {
            Double score = stringRedisTemplate.opsForZSet().score(DispatchRedisConstant.DISPATCH_CONTROL_URGENT, code);
            stringRedisTemplate.opsForSet().remove(DispatchRedisConstant.DISPATCH_CONTROL_FIXED, code);
            if (null != score && !Double.isNaN(score)) {
                log.error("-------------车辆:{} 已经紧急停车,交通控制无法执行放行指令", code, cmd);
                return false;
            }
        } else if (cmd == 3) {//定点停车缓存中增加车辆code
            stringRedisTemplate.opsForSet().add(DispatchRedisConstant.DISPATCH_CONTROL_FIXED, code);
        }
        R result = bogieIotDispathClient.bogieDispatchTraffic(command);
        //stringRedisTemplate.opsForHash().put(DispatchRedisConstant.DISPATCH_TRAFFIC_CONTROL, command.getDeviceId() + "-" + command.getOrder(), command.toString());
        if (result.getCode() == 200 && command.getDeviceId().equals(code)) {
            return true;
        }
        throw new RetryException("run contrl fail");
    }

    /**
     * 下发指令
     *
     * @param traffic
     * @param cmd
     * @return
     */
    @Retryable(include = {RetryException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000L, multiplier = 2))
    @Override
    @Async
    public Boolean sendRelieveCommad(TrafficVehiclesVo traffic, int cmd) {
        log.info("before:{}", traffic);
        String code = traffic.getCode();
        BogieTrafficVo freeCommand = new BogieTrafficVo();
        freeCommand.setDeviceId(code);
        freeCommand.setOrder(cmd);

        if (cmd == 1) {
            Double score = stringRedisTemplate.opsForZSet().score(DispatchRedisConstant.DISPATCH_CONTROL_URGENT, code);
            stringRedisTemplate.opsForSet().remove(DispatchRedisConstant.DISPATCH_CONTROL_FIXED, code);
            if (null != score && !Double.isNaN(score)) {
                log.error("-------------车辆:{} 已经紧急停车,交通控制无法执行放行指令", code, freeCommand);
                return false;
            }
        }

        R result = bogieIotDispathClient.bogieDispatchTraffic(freeCommand);// 下发解除控制指令后移除redis中设置主车的下发指令缓存
//stringRedisTemplate.opsForHash().put(DispatchRedisConstant.DISPATCH_TRAFFIC_CONTROL, command.getDeviceId() + "-" + command.getOrder(), command.toString());
        if (result.getCode() == 200 && freeCommand.getDeviceId().equals(code)) {
            log.info("车辆:{} 进行解除交通控制 {}", freeCommand.getDeviceId(), freeCommand);
            return true;
        }
        throw new RetryException("stop contrl fail");
    }

    @Recover
    public void recover(RetryException e) {
        log.error("recovery,{}", e.getMessage());
    }

 


posted @ 2022-12-15 17:07  蔡徐坤1987  阅读(261)  评论(0编辑  收藏  举报