最近给公司的华硕服务器做了一次性能调优,把接口平均响应时间从500ms降到了100ms,降幅80%。

这台服务器是华硕的RS700-E9系列,跑的是一个Java Web应用,用的是Spring Boot + MySQL。随着用户量增长,接口响应越来越慢,高峰期甚至能到2秒。老板下了死命令,必须在一周内把响应时间降下来。

我花了三天时间,从硬件到软件,从系统到应用,做了一次全面的性能调优。最终效果不错,平均响应时间从500ms降到了100ms,高峰期也能稳定在200ms以内。

本文分享这次调优的完整过程,包括问题定位、BIOS设置、系统优化、应用优化、数据库优化、监控验证等。不只是华硕服务器,这些调优思路对任何服务器都适用。

一、问题定位

调优的第一步,不是上来就改配置,而是先定位问题。

1. 建立性能基线

首先,我建立了性能基线,知道当前的性能是什么水平。

  • 平均响应时间:500ms
  • P95响应时间:1200ms
  • P99响应时间:2000ms
  • CPU使用率:高峰期85%
  • 内存使用率:70%
  • 磁盘IO:util 60%
  • 数据库连接数:高峰期接近上限

有了基线,调优之后才能对比效果。

2. 找到瓶颈

然后,我用各种工具找瓶颈。

  • 用top看CPU和内存
  • 用iostat看磁盘IO
  • 用netstat看网络连接
  • 用jstack看Java线程状态
  • 用慢查询日志看数据库

经过分析,发现了几个瓶颈:

  1. CPU:高峰期CPU使用率高,其中系统态占比大(sys% > 30%)
  2. 磁盘IO:数据库的随机写比较多,IO等待时间长
  3. 数据库:有几个慢查询,没有走索引
  4. JVM:GC频繁,尤其是Full GC
  5. 网络:连接数多,TIME_WAIT状态的连接多

找到了瓶颈,就可以针对性优化了。

二、BIOS设置优化

很多人做性能调优,只关注软件,忽略了BIOS。其实,BIOS设置对性能影响很大。

1. 关闭节能模式

华硕服务器的BIOS里,默认开启了节能模式(Power Saving Mode)。节能模式会降低CPU频率,减少功耗,但会影响性能。

我把节能模式改成了"性能模式"(Performance Mode),让CPU一直运行在最高频率。

操作路径: BIOS → Advanced → Power Management → Power Saving Mode → Disabled BIOS → Advanced → CPU Configuration → Intel SpeedStep → Disabled(如果不需要节能)

2. 开启超线程

确认超线程(Hyper-Threading)是开启的。超线程能让一个物理核心模拟两个逻辑核心,提高并发能力。

华硕服务器默认是开启的,但有时候会被关掉。检查一下: BIOS → Advanced → CPU Configuration → Hyper-Threading → Enabled

3. 内存设置

  • 确认内存运行在最高频率(DDR4-2933或更高)
  • 关闭内存节能模式(Memory Power Saving)
  • 开启NUMA(如果是多CPU的服务器)

4. PCIe设置

  • 确认PCIe插槽运行在最高速率(Gen3 x16或Gen4 x16)
  • 如果用了NVMe SSD,确认PCIe通道分配正确

5. 风扇设置

把风扇策略改成"性能模式",让风扇转速更高,散热更好。温度高了,CPU会降频,影响性能。

BIOS → Advanced → Fan Configuration → Fan Policy → Performance

三、操作系统优化

BIOS设置好之后,优化操作系统。我们用的是CentOS 7。

1. 关闭不必要的服务

关闭不需要的服务,释放CPU和内存。

systemctl disable postfix
systemctl disable firewalld  # 如果有其他防火墙
systemctl disable cups
systemctl disable avahi-daemon

只保留必要的服务:sshd、network、crond等。

2. 文件描述符限制

默认的文件描述符限制是1024,高并发场景下不够用。

修改 /etc/security/limits.conf

* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

修改 /etc/sysctl.conf

fs.file-max = 1000000

3. 网络优化

高并发场景下,网络优化很重要。

修改 /etc/sysctl.conf

# 开启TCP连接复用
net.ipv4.tcp_tw_reuse = 1
# 开启TCP快速回收
net.ipv4.tcp_tw_recycle = 1
# 减少TIME_WAIT时间
net.ipv4.tcp_fin_timeout = 30
# 增加本地端口范围
net.ipv4.ip_local_port_range = 1024 65535
# 增加TCP最大连接数
net.core.somaxconn = 65535
# 增加TCP接收/发送缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

执行 sysctl -p 生效。

4. 磁盘调度算法

如果用的是机械硬盘,把磁盘调度算法改成deadline或noop,提高IO性能。

echo deadline > /sys/block/sda/queue/scheduler

如果用的是SSD,用noop调度算法。

永久生效,在 /etc/rc.local 里加上上面的命令。

5. 文件系统优化

如果用的是ext4,挂载时加上noatime选项,减少磁盘写入。

修改 /etc/fstab

/dev/sda1 / ext4 defaults,noatime 0 1

noatime表示不更新文件的访问时间,能减少磁盘IO。

6. 关闭透明大页

数据库场景下,透明大页(Transparent Huge Pages)会导致性能问题。

echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

永久生效,在 /etc/rc.local 里加上。

四、JVM优化

我们的应用是Java写的,JVM优化很重要。

1. 堆内存设置

根据服务器内存,合理设置堆内存。我们的服务器是64G内存,给JVM分配了16G堆。

-Xms16g -Xmx16g

Xms和Xmx设成一样大,避免动态扩容的开销。

2. GC算法选择

JDK 8用G1 GC,JDK 11+也推荐G1 GC。

-XX:+UseG1GC
-XX:MaxGCPauseMillis=200

G1 GC适合大堆内存,能控制GC停顿时间。

3. GC日志

开启GC日志,方便排查GC问题。

-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-Xloggc:/var/log/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=100M

4. 其他优化

# 禁用显式GC(System.gc())
-XX:+DisableExplicitGC
# 优化字符串
-XX:+UseStringDeduplication
# 类元数据空间
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m

优化后,Full GC从每天几次降到了几乎没有,Young GC的停顿时间也从200ms降到了50ms。

五、应用优化

JVM优化之后,优化应用层。

1. 连接池优化

数据库连接池用的是HikariCP,调整了参数:

spring:
  datasource:
    hikari:
      maximum-pool-size: 50
      minimum-idle: 10
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

连接池大小不是越大越好,根据数据库的处理能力设置。一般来说,连接数 = (核心数 * 2) + 有效磁盘数。

2. 线程池优化

应用里的异步线程池,调整了核心线程数和最大线程数。

@Bean
public ExecutorService taskExecutor() {
    return new ThreadPoolExecutor(
        10, 50, 60L, TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(1000),
        new ThreadFactoryBuilder().setNameFormat("task-%d").build(),
        new ThreadPoolExecutor.CallerRunsPolicy()
    );
}

线程池参数要根据任务类型设置:

  • CPU密集型:核心线程数 = CPU核心数 + 1
  • IO密集型:核心线程数 = CPU核心数 * 2

3. 缓存优化

增加了本地缓存(Caffeine)和分布式缓存(Redis)。

  • 热点数据放本地缓存,减少Redis访问
  • 数据库查询结果放Redis,减少数据库压力
  • 设置合理的过期时间,避免缓存雪崩

加了缓存之后,很多接口直接从缓存返回,响应时间从几百ms降到了几ms。

4. 异步处理

把一些非核心流程改成异步处理:

  • 发送邮件、短信
  • 记录操作日志
  • 统计数据更新

异步处理不阻塞主流程,接口响应更快。

六、数据库优化

数据库是性能瓶颈的重灾区,重点优化。

1. 慢查询优化

通过慢查询日志,找到了几个慢查询,逐个优化。

  • 加索引:给where条件和join字段加索引
  • 避免select *:只查需要的字段
  • 避免在索引列上用函数:比如 WHERE DATE(create_time) = '2022-06-01' 改成范围查询
  • 分页优化:深分页用延迟关联

有一个查询,原来要2秒,加了索引之后,降到了50ms。

2. 索引优化

检查了所有表的索引,删除了没用的索引,增加了缺失的索引。

  • EXPLAIN 看查询计划
  • 确认索引是否被用到
  • 避免索引失效(隐式类型转换、前导模糊查询等)

3. MySQL配置优化

修改了MySQL的配置文件 /etc/my.cnf

[mysqld]
# 缓冲池大小,设为物理内存的50-70%
innodb_buffer_pool_size = 32G
# 日志文件大小
innodb_log_file_size = 1G
# 刷新日志策略,0=每秒刷新,1=每次提交刷新,2=每次提交写文件但不刷新
innodb_flush_log_at_trx_commit = 2
# 刷写方式,O_DIRECT绕过系统缓存
innodb_flush_method = O_DIRECT
# 连接数
max_connections = 500
# 临时表大小
tmp_table_size = 256M
max_heap_table_size = 256M
# 查询缓存(MySQL 8.0已移除)
# query_cache_type = 1
# query_cache_size = 128M

innodbflushlogattrx_commit = 2 是一个权衡,性能更好,但极端情况下可能丢1秒数据。如果对数据一致性要求高,设为1。

4. 读写分离

如果读多写少,可以考虑读写分离。

  • 主库负责写
  • 从库负责读
  • 用MyCat或ShardingSphere做中间件

我们的应用读多写少,做了读写分离之后,数据库的压力小了很多。

七、监控和验证

优化之后,要验证效果。

1. 性能指标监控

用Prometheus + Grafana监控:

  • 接口响应时间(平均、P95、P99)
  • CPU、内存、磁盘IO、网络
  • JVM:堆内存、GC次数、GC停顿时间
  • 数据库:连接数、慢查询数、QPS

2. 压测验证

用JMeter做压测,模拟高峰期的流量:

  • 100并发,持续10分钟
  • 对比优化前后的响应时间和吞吐量

优化前:平均500ms,吞吐量200 TPS 优化后:平均100ms,吞吐量800 TPS

3. 持续观察

优化不是一劳永逸的,要持续观察。

  • 每天看监控报表
  • 每周做一次性能复盘
  • 发现新的瓶颈,继续优化

八、调优的注意事项

说说调优中需要注意的事项。

1. 不要过早优化

先让系统跑起来,找到真正的瓶颈,再优化。不要凭感觉优化,很多时候你以为的瓶颈,并不是真正的瓶颈。

2. 每次只改一个地方

调优的时候,每次只改一个参数,然后测试效果。如果一次改多个,出了问题不知道是哪个改坏的。

3. 有回滚方案

每个优化,都要有回滚方案。万一改了之后性能更差,或者出了问题,能快速回滚。

4. 不要过度优化

优化到一定程度,收益会递减。不要为了追求极致性能,把系统搞得很复杂。够用就好。

5. 文档记录

把所有的优化都记录下来:改了什么、为什么改、效果如何。这样以后出了问题,能快速定位,新人也能快速上手。

九、写在最后

这次华硕服务器的性能调优,把响应时间降了80%,效果很明显。

但我想说的是,性能调优不是什么高深的技术,而是一个系统工程。从硬件到软件,从系统到应用,从数据库到网络,每个环节都可能是瓶颈。

调优的核心思路是:先定位瓶颈,再针对性优化,最后验证效果。不要凭感觉,要用数据说话。

这些调优思路,不只是适用于华硕服务器,任何服务器、任何应用都适用。

2022年了,应用的性能越来越重要。用户的耐心越来越少,响应慢一秒,可能就流失一个用户。做好性能调优,不仅是技术问题,也是业务问题。

最后,用一句话总结:"性能调优的本质,是找到瓶颈,然后用最小的代价,获得最大的提升。"

愿大家的系统,都能又快又稳。