轻境界的可用性与性能优化记

sorra 发表于 03/31 14:18 修改于 04/03 13:15 阅读数517

问题

昨天凌晨1点多,可能是V友太热情,或者爬虫太勤奋,轻境界的服务器宕机了,悄悄地,没有留下错误日志。

我上午收到用户反馈,赶快先重启服务器压压惊,再来分析原因。

连错误日志都没有,这是什么程度的问题呢?

最大的可能性是 JVM内存不够用 或 线程数过多。需要调整相关参数。

另外还需要让服务器能自动恢复。

内存

在调整JVM内存前,先看看系统内存使用情况:

$ free -m

​              total        used        free      shared  buff/cache   available

Mem:           1696        1336          68          20         291         155

Swap:             0           0           0

空闲(free)内存几乎没有了。

再看看哪些进程吃了内存:

11869 sorrada+  20   0 2438544 *417292  15332 S  0.7 24.0   1:24.82 java

 5442 sorrada+  20   0 2420764 *353808      0 S  0.0 20.4 278:47.83 java

 3876 mysql     20   0 1111688 *203020      0 S  0.3 11.7  18:38.52 mysqld

2026 sorrada+  20   0 3118488 *313664      0 S  0.0 18.1 580:09.45 java

第1个是轻境界本体 (417M),第2个是一个无关紧要的程序 (353M),第3个是MySQL (203M),第4个是ElasticSearch (313M)。

于是我kill了那个无关紧要的程序,现在内存情况是:

$ free -m

              total        used        free      shared  buff/cache   available

Mem:           1696         986         431          20         277         505

Swap:             0           0           0

然后要调整JVM最大内存的参数,给它1个G吧~ -Xmx1024m

关于线程数,我查了一下文档:

  • Tomcat的NIO模式的maxThreads默认值为10000,这么大!

改成多少好呢?我算了一下,假设最坏情况下平均每个线程吃5MB,100线程就是500MB,加上已经占用的大约400MB,再加上JVM后台线程和MetaSpace,差不多用完了1G,没有空间留给缓存了,而且会频繁触发Full GC,变成龟速。那就把上限设为60线程吧!

修改Spring Boot的application.properties server.tomcat.max-threads = 60

维持可用(keep alive)

Keepalived这个工具适合维持集群的高可用,我只有一台服务器,就只写了一套shell脚本来确保进程处于运行状态:

https://github.com/sorra/sage-system/tree/master/production-files

日志优化

虽然给Logback配置了异步文件输出,但为了开发方便,并没有启用它,而是用了同步文件输出和控制台输出。

这次必须改进了,利用Spring的Profile功能根据环境来加载不同的Logback配置。例如,当profile=production时,启用异步文件输出,关闭同步文件输出,关闭控制台输出。

我在src/main/resources/application.properties文件中存放了默认配置项,包括这一行,把环境设为了开发环境:

spring.profiles.active = dev
# ... other properties ...

我又建了一个只有一行的application.properties文件,存放在源代码的production-files目录内,部署脚本会自动把它copy到生产环境的应用根目录。它有更高优先级,会覆盖前面那个文件的配置:

spring.profiles.active = production

总结

全文介绍了这些改进:调整JVM内存上限、调整Tomcat线程数上限、支持自动恢复、日志优化。

缓存方面:现在只有首页的数据做了缓存,还需要进一步运用缓存,以减少SQL查询,尤其是要避免触发全表扫描。