rabbitmq异步消息传递的使用

2021SC@SDUSC

rabbitmq异步消息传递的使用

配置rabbitmq

通过配置rabbitmq的config以及rabbitmq的templete实现更自由的定制,实现重发机制等

@Configuration
public class RabbitMqConfig {
    //空字符串是默认交换机
//    static final String SOLVED_EXCHANGE_NAME = "";
    public static final String SOLVED_QUEUE = "rabbitmq-to-reply-queue";
    //空字符串是默认交换机
//    static final String NEED_SOLVE_EXCHANGE_NAME = "";
    public static final String NEED_SOLVE_QUEUE = "rabbitmq-to-handle-queue";
    // 同步消息
    public static final String SYNC_SOLVE_QUEUE = "rabbitmq-sync-judge";

    @Bean
    Queue solvedQueue() {
        return new Queue(SOLVED_QUEUE, true);
    }

    @Bean
    Queue needSolveQueue() {
        return new Queue(NEED_SOLVE_QUEUE, true);
    }

    @Bean
    RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> System.out.println(cause));
        rabbitTemplate.setReturnsCallback(System.out::println);
        return rabbitTemplate;
    }

    @Bean
    AsyncRabbitTemplate asyncRabbitTemplate(RabbitTemplate rabbitTemplate){
        return new AsyncRabbitTemplate(rabbitTemplate);
    }
}

建立实体类

public class JudgeMessage {
    //处理类型
    private String procedure;
    //请求头
    private Header header;
    //请求实体
    private RequestBody requestBody;
    //响应实体
    private ResponseBody responseBody;
    //未用
    private String testData;
}

 public static class Header {
        //消费者
        private String custom;
        //时间发起的server
        private String server;
        //信息传递的时间,unix时间
        private long date;
        //唯一表示,uuid
        private String id;
}
    public static class Body {
        //请求唯一标识
        private String requestID;
        //唯一问题标识号
        private String problemID;
        private List<String> pointList;
        //代码实体
        private Code code;
        //请求限制
        private JudgeLimit judgeLimit;

        //返回值结果
        private String judgeResult;
        //判题端运行的结果
        private Map<String, JudgeResponse> pointJudgeResponseMap;
    }
    public static class JudgeLimit {
        private Integer maxCPUTime;
        private Integer maxRealTime;
        private Integer maxMemory;
        private Integer maxStack;
        private Integer maxProcessNumber;
        private Integer maxOutputSize;
    }
    public static class RunningDetail {
        private int time;
        private int memory;
    }

service

判题采用异步机制,因为多个测试点可能花费许多时间,所以异步传输机制

@Transactional
    public Integer trySolveProblem(Solve solve) throws DataIntegrityViolationException {
        //不存在对应题目直接返回
        if (!problemMapper.exists(solve.getProblemId())) {
            return null;
        }
        if (!solveMapper.insertSolve(solve)) {
            throw new RuntimeException();
        }
        ProblemLimit problemLimit = problemLimitMapper.getProblemLimitById(solve.getId());
        List<TestPoint> testPoints = testPointMapper.getTestPointByProblemId(solve.getProblemId());
        List<String> pointList = new ArrayList<>();
        // 只取/分割的最后部分的结果
        for (TestPoint testPoint : testPoints) {
            String lastName = testPoint.getInPath().split("/")[1];
            pointList.add(lastName);
            solveTestPointMapper.insertSolveTestPoint(solve.getId(), lastName);
        }
        String json = JSON.toJSONString(new JudgeMessage(solve, problemLimit, pointList));
        System.out.println(json);
        rabbitTemplate.convertAndSend("rabbitmq-to-handle-queue", json);
        return solve.getId();
    }

receiver

注册receiver,实现异步消息的接受

@Component
@RabbitListener(queues = "rabbitmq-to-reply-queue")
public class SolveReceive {
    @Autowired
    SolveService solveService;
    @Autowired
    SolveTestPointMapper solveTestPointMapper;

    @RabbitHandler
    @Transactional
    public void receiveMessage(String message) {
        try {
            JudgeMessage judgeMessage = JSON.parseObject(message, JudgeMessage.class);
            JudgeMessage.Body body;
            int solveId = Integer.parseInt(judgeMessage.getHeader().getId());
            Solve solve = solveService.adminSelectSolveRecord(solveId);
            solve.setPass(true);

            if (judgeMessage.getResponseBody().getStatus().equals("ClientError")) {  //客户端格式错误
                List<SolveTestPoint> solveTestPoints = solveTestPointMapper.selectSolvePointResultBySolveId(solveId);
                for (SolveTestPoint solveTestPoint : solveTestPoints) {
                    solveTestPoint.setDetailOfError(message);
                    solveTestPoint.setResult("CLIENT_ERROR");
                    solveTestPoint.setMemory(-1);
                    solveTestPoint.setTime(-1);
                    solveTestPointMapper.updateRowBySolveIdAndTestPointId(solveTestPoint);
                }
                solve.setPass(false);
                solve.setResult("CLIENT_ERROR");
                if (!solveService.adminUpdateSolveRecordStatus(solve)) {
                    //更新失败回退状态
                    solveService.adminDeleteSolveRecord(solve.getId());
                }
            } else if (judgeMessage.getResponseBody().getStatus().equals("InternalError")) { //判题端错误
                List<SolveTestPoint> solveTestPoints = solveTestPointMapper.selectSolvePointResultBySolveId(solveId);
                for (SolveTestPoint solveTestPoint : solveTestPoints) {
                    solveTestPoint.setDetailOfError(message);
                    solveTestPoint.setResult("INTERNAL_ERROR");
                    solveTestPoint.setMemory(-1);
                    solveTestPoint.setTime(-1);
                    solveTestPointMapper.updateRowBySolveIdAndTestPointId(solveTestPoint);
                }
                solve.setPass(false);
                solve.setResult("INTERNAL_ERROR");
                if (!solveService.adminUpdateSolveRecordStatus(solve)) {
                    //更新失败回退状态
                    solveService.adminDeleteSolveRecord(solve.getId());
                }
            } else { //正常情况
                body = JSON.parseObject(judgeMessage.getResponseBody().getBody(), JudgeMessage.Body.class);
                boolean partlySolved = false;
                //遍历多测试点结果并保存
                for (Map.Entry<String, JudgeMessage.JudgeResponse> res : body.getPointJudgeResponseMap().entrySet()) {
                    SolveTestPoint solveTestPoint = new SolveTestPoint();
                    solveTestPoint.setSolveId(solveId);
                    solveTestPoint.setTestPointId(res.getKey());
                    String result = res.getValue().getJudgeResult();
                    solveTestPoint.setResult(result);

                    if (result.equals("ACCEPT")) {
                        JudgeMessage.RunningDetail detail = res.getValue().getRunningDetails();
                        solveTestPoint.setMemory(detail.getMemory());
                        solveTestPoint.setTime(detail.getTime());
                        partlySolved = true;
                    } else {
                        solveTestPoint.setMemory(-1);
                        solveTestPoint.setTime(-1);
                        if (res.getValue().getDetailOfError() != null) {
                            solveTestPoint.setDetailOfError(res.getValue().getDetailOfError().toString());
                        }
                        solve.setPass(false);
                    }
                    solveTestPointMapper.updateRowBySolveIdAndTestPointId(solveTestPoint);
                }
                if (solve.isPass()) {
                    solve.setResult("ACCEPT");
                } else {
                    if (partlySolved) {
                        solve.setResult("PARTLY_ACCEPT");
                    } else {
                        solve.setResult("WRONG_ANSWER");
                    }
                }
                //保存最终结果
                if (!solveService.adminUpdateSolveRecordStatus(solve)) {
                    //更新失败回退状态
                    solveService.adminDeleteSolveRecord(solve.getId());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用异步消息接受机制,减少了服务器的压力,更便于逻辑的实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值