最近线上发生的两个坑爹锅!

Java后端技术

共 1927字,需浏览 4分钟

 ·

2021-01-17 14:36

往期热门文章:

1、往期精选优秀博文都在这里了!

2、为什么我不建议你用去 “ ! = null " 做判空?

3、这四种情况下,才是考虑分库分表的时候!

4、线上 4 台机器同一时间全部 OOM,到底发生了什么?

5爽啊!Intellij IDEA 神器居然还藏着这些实用小技巧 !

最近由于在技改,发生了不少问题,前文中说的缓存穿透只是其中之一,想了想,虽然都是比较简单的问题,但是应该实际中还是有不少人碰到过,这些问题看似很简单,但是你绝对应该踩过。

==和equals

关于==和equals区别,我相信稍微做过一两年开发的同学都应该很清楚,可是,然而,这个坑在很多开发的时候仍然频繁出现,为什么?因为有时候有的同学认为没什么区别,就用==吧,然而,一些意外总是如期而至。
不久前,由于线上RPC框架切换,我们就发生了一点小问题。
本来,线上的接口是这样定义的:
然后,接口查询中使用到了一个枚举类型,根据id获取枚举值,只不过这里使用的是==号来判断。
调用方的写法:
本来,这个代码在线上跑了两年了,一点问题没有,怎么就突然不行了呢?
但是,切换框架之后,这个接口报错了,当时我也看了这个地方半天,猜测是这里的问题,但是想了想貌似又不应该啊。
结果最后发现,原来的RPC框架传输中使用的是valueOf,从缓存中取值,加上自动装箱拆箱,判断可以通过。但是,新的框架使用的是new Byte(),所以这个老代码就永远无法通过了,因为这是一个新的对象。
看看这个测试的结果。
后面,通过安装Alibaba Java Coding Guidelines插件统一扫描所有代码,还又发现了一个坑爹的问题。
这个写法又不太一样,这个枚举只是单纯的把code成员变量定义成了byte基础类型,不是包装类型。这样,代码用==判断又都OK了。
坑爹1
想象一下,因为是基础数据类型,拆箱后==判断当然是通过的。
还有更奇葩的写法,成员变量是Byte包装类型,getEnumByCode(byte code)这里用的又是基础类型,当然,这种写法也能判断通过。
坑爹2
所以,心累... ...
最后,我想再补充一下关于基础数据类型缓存的知识。能用==判断的原因也都是依赖于缓存的原因。

最后,奉劝大家一句,千万,千万,在项目中判断包装数据类型都用equals,因为就算这段代码你很确信现在是对的,然而鬼都不知道后面会发生什么!不要抱有侥幸心理。

日志打满

项目技改上线后不久,发现接口成功率直接跌0(跌0的告警监控必须得有,不然死都不知道怎么死的)。排查了很久,看其他都是正常的,最后发现GC耗时狂增,登录服务器一看,居然是硬盘被打满了。
然后果断去看日志,因为我们的硬盘实际上很小,先怀疑日志,果不其然,日志炸了。通过ls -lht查看文件大小。
通过rm -rf删除后发现硬盘空间并没有释放。正常情况下是不会出现这个问题的,但是如果文件被锁定或者有另外的进程在向文件写数据的话就会有问题了。
在Linux中,一个文件在文件系统中存放包含两个部分:
  1. 指针部分:指针位于文件系统的meta-data中,在将数据删除后,这个指针就从meta-data中清除了。
  2. 数据部分:而数据部分存储在磁盘中。
像上面的情况,虽然我们删除了service.log,但是由于进程锁定,指针部分没有从meta-data中删除,所以也就看到存储空间没有释放的问题。
解决办法有两种:
  1. 使用lsof -n |grep delete查看什么进程在写service.log,通过命令发现是我们的java进程在一直写文件,然后通过后台工具直接重启应用,重启之后发现恢复正常。

  2. 清空日志文件,执行命令echo "">/service.log,这个方法可以立刻释放磁盘空间,进程继续写入日志也不会受到影响。

往期热门文章:

1、历史文章分类导读列表!精选优秀博文都在这里了!》

2、万亿级数据应该怎么迁移?
3、从应用到底层 36张图带你进入Redis世界
4、写代码有这16个好习惯,可以减少80%非业务的bug
5、顺丰快递:请签收MySQL灵魂十连

6一个基于SpringBoot + MyBatis + Vue的代码生成器
7Redis 分布式锁使用不当,超卖了100瓶飞天茅台!!!

8、如何设计订单系统?这篇写得太好了!
9如果MySQL磁盘满了,会发生什么?还真被我遇到了!
10、阿里开源的27个项目,值得收藏!
浏览 20
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报