springboot项目中redis连接关闭

问题描述:
学习使用redis的stream实现消息队列的时候,写完了代码进行运行,但是在登录界面获取验证码的时候控制台收不到验证码。

验证码界面与发送验证码代码:

img

    @Override
    public Result sendCode(String phone, HttpSession session) {
       
         //1.校验手机号
        if (RegexUtils.isPhoneInvalid(phone)){
            //2.如果校验不成功,返回错误信息
            return Result.fail("手机号格式错误");
        }
        //3.校验成功生成验证码
        String code = RandomUtil.randomNumbers(6);

        //4.保存验证码到redis
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code,LOGIN_CODE_TTL, TimeUnit.MINUTES);

        //session.setAttribute("code",code);

        //5.发送验证码
        log.info("code success:::::::::{}",code);

        //如果都没问题,返回成功
        return Result.ok();
    }

但是此时控制台收不到任何消息,redis中也没有存入数据,前端页面会显示localhost拒绝了我们的连接请求

并且在停止项目后报错:

img

报错部分的代码(idea提示位置在两处获取消息队列中的订单信息处):

//创建线程任务
    private class VoucherOrderHandler implements Runnable{
        String queueName = "stream.orders";
        @Override
        public void run() {
            while (true){
                try {
                    //1.获取消息队列中的订单信息
                   List<MapRecord<String, Object, Object>> list = stringRedisTemplate.opsForStream().read(
                            Consumer.from("g1", "c1"),
                            StreamReadOptions.empty().count(1).block(Duration.ofSeconds(2)),
                            StreamOffset.create(queueName, ReadOffset.lastConsumed())
                    );
                    //2判断消息获取是否成功
                    //2.1获取失败,说明此时队列中没有消息,下一次循环
                    if (list == null || list.isEmpty()){
                        continue;
                    }

                    //2.2到这里说明取到了消息,对消息进行解析
                    MapRecord<String, Object, Object> record = list.get(0);
                    Map<Object, Object> value = record.getValue();
                    VoucherOrder voucherOrder = BeanUtil.fillBeanWithMap(value, new VoucherOrder(), true);
                    //2.3获取成功,可以下单
                    //3创建订单
                    handleVoucherOrder(voucherOrder);
                    //4.ACK确认
                   stringRedisTemplate.opsForStream().acknowledge(queueName,"g1",record.getId());
                } catch (Exception e) {
                    log.error("处理订单异常",e);
                    handlePendingList();
                }
            }
        }
        private void handlePendingList() {
            while (true){
                try {
                    //1.获取pending-list队列中的订单信息
                    List<MapRecord<String, Object, Object>> list = stringRedisTemplate.opsForStream().read(
                            Consumer.from("g1", "c1"),
                            StreamReadOptions.empty().count(1),
                            StreamOffset.create(queueName, ReadOffset.from("0"))
                    );
                    //2判断消息获取是否成功
                    if (list == null || list.isEmpty()){
                        //2.1获取失败,说明此时pending-list中没有异常消息,结束循环
                        break;
                    }

                    //2.2到这里说明取到了消息,对消息进行解析
                    MapRecord<String, Object, Object> record = list.get(0);
                    Map<Object, Object> value = record.getValue();
                    VoucherOrder voucherOrder = BeanUtil.fillBeanWithMap(value, new VoucherOrder(), true);
                    //2.3获取成功,可以下单
                    //3创建订单
                    handleVoucherOrder(voucherOrder);
                    //4.ACK确认
                    stringRedisTemplate.opsForStream().acknowledge(queueName,"g1",record.getId());
                } catch (Exception e) {
                    log.error("处理pending-list异常",e);
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }
    }

在使用redis的stream实现消息队列之前代码和功能都是正常的,但是我也尝试过还原代码,还原后控制台不会报错,但是前端页面会变成这个样子

img

请各位为我指正,谢谢各位

redis测试过是否可以连接上吗?
还原后,项目启动应该失败了,导致访问报错。

项目还原不成功,应该是没有真正还原到之前的代码,如果无法做到,还是在新代码的基础上解决当前的问题。你可以尝试在 String code = RandomUtil.randomNumbers(6);这句代码后面打印输出下验证码,或者打断点调试到这里,看下后端是否接收到了请求并进入了该方法。

我还不确定问题在哪里,但有一个地方提示一下:

img


因为你是while(true),图中所示的地方,从列表中获取消息不知道是不是阻塞式的,如果是非阻塞的,那么在没有消息时,就容易占用100%CPU。通常在这里会有sleep来释放cpu的占用。

不是找到问题了吗?

Spring Boot Redis 在开发或者本地没有redis数据库时,控制台会一直报连接超时的日志,可以通过配置取消:

spring:  
    data:
        redis:
          repositories:
            enabled: false

Redis使用完之后,要释放连接,避免连接池耗尽