Share

  1. 最近看了一篇关于Netflix 调优JVM 的[文章](https://medium.com/@NetflixTechBlog/introducing-jvmquake-ec944c60ba70),里面提供了一些实用的思路来讲解 JVM 调优的过程。

首先要解决的是 JVM OOM 的问题, 当JVM 出现OOM 的时候,对应的进程不一定会被kill 掉,这个时候JVM 就会处于一个非常不稳定的状态,所运行的代码就无法保证其正确性。 要解决这种问题的思路也很直接,通过 jvm agent 参数挂载 jvmkill 工具。
这个工具可以监听OOM 事件,然后发送 SIGKILL 信号,配合 XX:HeapDumpOnOutOfMemoryError 参数就可以保存dump文件。

但其实我们遇到更多的是另外一种”灰色状态”, 那就是JVM 反复产生full gc, 但由于还未到达OOM 的临界点,这个时候JVM 的吞吐量就会不稳定, 处理请求的延时也会受到 fullgc 的影响。由于这种”灰色状态” 没有触发OOM, 所以也就无法通过 jvmkill 去自动化收集现场dump文件.

要解决这个问题的一个直接的思路是通过JVMTI 监听更多的内存错误事件(MemoryError*Event),但由于不同厂家的JVM 对这些事件的触发条件并不一致,所以Netflix 工程师通过他们自研的 jvmquake 工具来解决这个问题。

解决的思路大概是这样:

.清晰定义 “灰色状态” 的边界
.收集现场dump
.存储dump 到云服务器。

.清晰定义 “灰色状态” 的边界

  1. 如何定义"灰色状态" ? 其实原理也很简单, 通过时间序列建立一个“负债模型”, JVM 处于"灰色状态",那么它的Full GC 时间肯定会超过正常的 JVM 时间,当这种状态达到一定的比例(可以进行配置),那么就可以认定JVM 处于“灰色状态". 如何收集这个数据呢? 其实通过挂钩GarbageCollectionStart和GarbageCollectionFinish JVMTI回调就可以测量这些值。

.收集现场dump

  1. JVM 处于”灰色状态" 后, 该如何收集现场dump 呢?原来的做法是通过触发另外一个独立线程, 通过分配大量的对空间,导致 OOM, 然后通过发送SIGKILL, 来转存JVM dump,但这种方法有可能会让dump 文件反复收集从而占满磁盘空间。<br /> 更优雅的方式是发送 SIGABRT 事件, 让linux 内核去转存系统dump 文件而不是 JVM dump, 收集系统dump的时候可以指定文件大小, 这样可以保证dump文件不会占满磁盘。

.存储dump 到云服务器

  1. 最后就通过一个python 脚本来压缩dump 文件并上传到s3 服务器,经测试, 16G 的文件大约耗时两分钟。

总结

  1. 其实,解决问题最关键的就是思路和创造力,同时细节是魔鬼,这些细节的部分是最考验人的执行能力。最后,一定要坚持自动化的原则,这样才能保证整个方案往着正确的方向执行。

Review:

一篇关于弹性设计的文章, 里面提到了几个核心的要点 : designForFailure, 冗余,基础架构即代码, 基础设施的不变性等。
其实我觉得弹性设计的本质就是 : 高可用 + 高性能 + 成本控制 + 自动化。虽然网上有不少的文章,但我觉得结合自己的场景来设计才是最关键的。

Tips:

  1. 如果Meduim 的文章啃不动,就直接上google 翻译吧,先能看多少算多少,然后再还原英文来读,总比坚持不下去要好。

Algorithm:

  1. 1122. 数组的相对排序
  1. class Solution:
  2. def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
  3. arr_counter = [0] * 1000
  4. arr_result = []
  5. for i in arr1:
  6. arr_counter[i] += 1
  7. for i in arr2:
  8. counter = arr_counter[i]
  9. arr_result.extend([i] * counter)
  10. arr_counter[i] = 0
  11. for i in range(len(arr_counter)):
  12. counter = arr_counter[i]
  13. if counter:
  14. arr_result.extend([i] * counter)
  15. return arr_result
  16. s = Solution()
  17. arr1 = [2,3,1,3,2,4,6,7,9,2,19]
  18. arr2 =[2,1,4,3,9,6]
  19. s.relativeSortArray(arr1, arr2)