撸代码这么久,从之前简单的脚本,到单体应用,到最后的微服务,我们的应用总会因为各种奇奇怪怪的原因罢工,有些错误显而易见,而有些错误也会让人一时摸不到头脑。究其原因,还是需要加强自己的修养,多多总结,就能做到防患于未然。
下面老高会总结一些平时遇到的问题,以及对应的解决思路和方法,同事也欢迎大家补充!
环境问题是一个比较宽泛的概念,如果把一个应用比作一个人,程序的运行就比作去工作,对应人类的办公室。
最常见的办公室就是你的开发机了,可以理解为应用在在家办公。
有钱的公司会给自己的所有应用租一栋大楼,然后把应用合理规划到大楼的各个办公室,而像老高这种码农,也就租的起一个路边摊了。。。
这二者的差别在哪儿呢?打个比方,如果大楼失火了,如果是大公司,有自己的灭火团队,可能作为员工的"应用",感知到的是个别办公室暂时无法使用,被分配到别的场地办公,等火灭了,就自动回迁。如果是老高的路边摊出了问题,那我的网站你都打不开了(不会自动恢复)。
系统决定了你的应用的办公舒适度,他可以为应用提供各种支持,比如大仓库(大硬盘),24小时监控、保安巡逻(监控告警) 等等。
如果服务突然出现了应用卡顿,首先应该排查应用使用的磁盘空间是否已经所剩无几。
原因有:
解决方案:
df -h
查看磁盘使用df -i
查看inode使用情况# 寻找当前目录下大于1G的文件
find . -type f -size +1G
# 寻找当前目录下大于1G的文件并排序
find . -type f -size +1G -print0 | xargs -0 du -h | sort -nr
# 查看最大深度为2的文件夹大小
du -h --max-depth=2
logging:
driver: “json-file”
options:
max-size: “3m”
说到内存,老高第一个想到的就是OOM了。。。但是想把OOM讲清楚不是本文的目的。这里就像说一个点,在编程的时候,一定要尽量节省内存,Linux虽然是无私的(Memory Overcommit),你申请的内存的时候"满口答应",但真的等到系统内存不够用的时候,别忘了OMM Killer会来嘎嘎乱杀。
举个golang的demo
# snippet 1
response, err = ioutil.ReadAll(resp.Body)
# snippet 2
response := bytes.NewBuffer(make([]byte, 4096))
io.Copy(response, resp.Body)
不知道大家看出来代码1和2的区别没,如果resp.Body
投毒,返回会来一个10G的文件,那么代码1会让你的内存瞬间爆掉,而代码二会更加柔性(这种情况在下载文件的时候十分明显)。
内存对齐
老高的业务中不同的环境有不同配置文件,有时会出现某项配置在开发环境,但是测试环境中丢失的问题。
业务中有时候会填写DSN(数据源名称),比如:
mysql:
dsn://user:password@tcp(localhost:3306)/your_db?charset=xxx
redis://password@127.0.0.1:6379/0
但是密码中可能会出现 =
、?
、:
等特殊字符,这些字符可能会导致DSN无法解析,比如dsn://user:localhost:3306@tcp(localhost:3306)/your_db?charset=xxx
这种,就会比较难解析。
此处就很容易发生错误。