这个是本系列的第三个文章,主要用于记录一下几个边缘业务的线上问题/核心业务的小问题的排查方案与解决
基本上排查思路就是技术保证基础参数的排查诊断,业务能力保证排查的流程思路是清晰的,精确找到对应出问题的业务节点进行解决。
我所在的业务组,除了一些关键业务我没有参与外(我参与了云存储和告警)其他的像是webRTC,信息平台,cdn这些都算是小业务点,这些有一些也有线上问题
系列文章见 【实践】2025年线上问题解决与总结-1
三元运算符NPE问题
背景
环境上线发生NPE报错,造成紧急回退

有以下两方面需要查看
若connectMode.contains(1)报NPE,代表需要查看stream运算是否返回nullproductDocDO.getApScanCapacity()可能会有三元运算符的自动拆装箱产生的NPE
根因分析
触发了自动拆装箱,但是Integer对象是null,触发了NPE开发时在环境中配置了MySQL字段的非空默认值,但是测试完沟通后直接将默认值删除,没有验证没有默认值的情况,造成了NPE
-
stream操作是否会引起NPE或者返回null对象?
-
Arrays.stream(...):将数组转换为流。不会返回 null。productDocDO.getConnectMode():如果这个方法返回 null 或者 productDocDO 是 null,那么整个表达式将会抛出 NullPointerException。.split(SEMICOLON):将字符串按分号分割成数组。如果结果是空字符串(""),则会生成一个包含单个空字符串的数组([""])。.map(Integer::parseInt):将每个字符串转换为整数。如果遇到非数字字符串,会抛出 NumberFormatException。.collect(Collectors.toList()):将流中的元素收集到一个列表中。不会返回 null。
-
要看stream是否返回一个null对象,则可以直接看stream流表达式中的最后一个操作,也就是输出操作,其他的可以不用关注,stream流详细设置可以单独写一篇文档进行讲解
代表stream流不会返回null对象,信息来源Collectors(Java Platform SE 8)。
- Collect.toList()方法只会返回一个新的List对象,因此使用stream流开发时不需要考虑会产生null对象,但是stream操作过程中可能会产生NPE或其他问题
三元运算符是否会引起NPE?
三元运算符在使用时会自动触发数据类型的拆装箱,如会将Integer变成int类型,如果对象数据类型是null,在拆装箱时会出现NPE问题
信息来源
自动拆装箱的原因为三目运算符两侧数据类型不一样时,为了确保信息一致,会进行拆装箱,这是为了确保三目运算符的结果类型一致。
信息来源 docs.oracle.com/javase/spec...
解决方案
三目运算符两侧类型保持一致/非空校验或填充默认值

-
不要在测试完成后随意修改一切相关文本,包括但不限于代码、表结构、配置文件信息等,如果修改则代表需要重新进行测试!
-
开发过程中如果使用基本数据类型,在调用链路中(如函数嵌套,对象在多个语句中等)需要尽量避免自动拆装箱三元运算符,要么冒号两侧类型是相同类型,如都是Integer或者都是int,或者是对象类型使用Optional进行包装
-
不太熟的API使用前需要详细查看使用时容易出现的问题
其他的小bug
-
【云存储】云存储套餐状态下发,有时会有状态异常,通过定时任务,对设备状态和套餐状态进行对比,发现异常
原因是kafka下发乱序,比如我们这边有业务是通过kafka先下发关闭再下发开启,如果乱序,最终状态时关闭,与实际业务不符合,通过把deviceid作为kafka消息的key+粘性分区
后续解决方案是对于顺序性要求高的,重要的业务,一律使用key+粘性分区
-
【云存储】云存储有时候有状态问题,造成脏数据(比如开启的套餐触发归档流程)
解决方案是 通过幂等+状态机,解决该问题

通过严格的状态调整,避免异常状态转换,避免后续脏数据的人工介入
-
【告警】告警的入库率有问题,也有重复
因为主要是通过kafka进行消费,网关性能较好暂未关注,所以需要保证
kafka生产->broker存储->consumer消费->进行业务处理->存储数据库这个链路不会有重复或者丢失
-
【云存储】批处理只有一个pod执行,且长时间执行,中途任务中断会导致进度丢失,影响业务
解决方案:一个是对批处理任务进行进行存储,按照业务点(如我这边进行套餐的状态更新、将套餐和设备进行校验,基准是套餐,所以可以通过单次查询1000个套餐,进行业务处理),每完成一个小型批处理任务则可以往数据库中记录
任务,处理量,完成时间,任务对应日期等信息,这样重启尝试重新查看是否有遗漏时,可以直接通过这张表即时回溯,快速恢复到任务失败之前的状态为了解决多个pod进行批处理业务,通过redisson锁+偏移量实现,redisson表示记录偏移量时只能有一个pod修改,偏移量代表这个长时间任务的执行进度