性能分析
火焰图
开启火焰图,识别出了潜在的瓶颈,结合实际的代码进行分析,查看这些热点函数的实现,寻找可以优化的地方,比如减少循环次数、优化数据结构、减少同步操作
jvm
jstack 分析线程状态
gc占用时间过多jstat 查看 gc信息
jmap 内存分析
jmap -histo 113478 > map
对象实例过多,异常增长,怀疑内存泄漏
优化记录
算法优化
基于火焰图,减少系统调用函数
序列化优化
基于实现,选择性能更佳的序列化框架
算子优化
算子合并,减少序列化开销
数据结构优化
减少吞吐量、序列化开销
内存优化
基于jmap监控结果,解决存在的内存泄露问题
IO优化
- 减少IO次数
- kafka 攒批写配置优化
- redis pipeline的方式来提高性能
配置优化
选择合适的 GC 算法
Flink 主要在 JVM 上运行,因此选择合适的垃圾回收器是非常关键的。以下是一些常见的 GC 算法:
- G1 GC(Garbage-First Garbage Collector):推荐用于大多数生产环境。它可以在低延迟和高吞吐量之间取得平衡。
- CMS GC(Concurrent Mark-Sweep):适用于低延迟需求高的场景,但在堆内存较大的情况下可能表现不佳。
- ZGC(Z Garbage Collector):适用于低延迟、高吞吐量需求的场景,但需要使用较新的 JDK 版本(JDK 11 及以上)。
- Shenandoah GC:另一个低延迟的 GC 选项,适用于 JDK 8 和 JDK 11。
设置 JVM 参数
根据选择的 GC 算法设置合适的 JVM 参数。例如,使用 G1 GC 时,可以使用以下参数:1
2
3
4
5
6-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
-XX:G1ReservePercent=10
-XX:ConcGCThreads=4
-XX:ParallelGCThreads=4
这些参数可以根据实际情况进行调整。
调整堆内存大小
为 Flink 配置足够的堆内存,但不要过大,以免导致长时间的 Full GC。一般来说,可以使用以下参数来设置堆内存大小:
1 | -Xms4G |
确保 -Xms 和 -Xmx 设置为相同的值,以避免堆大小的动态调整带来的额外开销。
调整堆外内存
Flink 也使用堆外内存进行一些操作,特别是网络通信和 RocksDB 状态后端。如果使用 RocksDB,可以通过以下参数来限制堆外内存的使用:
1 | -XX:MaxDirectMemorySize=8G |
优化 Flink 的配置
Flink 提供了一些配置选项,可以帮助优化 GC 性能:
- taskmanager.memory.framework.off-heap.size:设置框架使用的堆外内存大小。
- taskmanager.memory.managed.size:设置托管内存的大小,这部分内存将用于内部的内存管理和缓存。
监控和分析 GC 日志
启用 GC 日志可以帮助分析和优化垃圾回收性能。使用以下 JVM 参数启用 GC 日志:1
2
3
4
5
6
7-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+PrintAdaptiveSizePolicy
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintPromotionFailure
-Xloggc:/path/to/gc.log
使用工具如 GCViewer、GCEasy 或 GC Log Analyzer 来分析 GC 日志,找出潜在的性能问题。
避免 Full GC
尽量避免 Full GC,因为 Full GC 会导致长时间的暂停。以下是一些避免 Full GC 的策略:
- 减少对象分配:优化代码,减少短生命周期对象的分配。
- 使用 Flink 的对象复用机制:Flink 提供了对象复用选项,可以减少垃圾回收的压力。
- 增大新生代内存:适当增加新生代内存,减少对象进入老年代的频率。
调整并发 GC 线程数
根据机器的 CPU 核心数调整并发 GC 线程数,可以通过以下参数设置:1
2-XX:ConcGCThreads=4
-XX:ParallelGCThreads=4
定期重启任务
对于长时间运行的流处理任务,可能会积累一些内存碎片,导致 GC 性能下降。定期重启任务可以帮助清理这些碎片。
使用分层存储
如果数据状态较大,可以考虑使用分层存储(如 RocksDB)来减少堆内存压力。RocksDB 可以将大部分数据存储在磁盘上,减少对堆内存的需求。