垃圾回收日志分析 API

我们的垃圾回收日志分析 REST API 提供了作用强大的微指标。借助这些微指标,您可对程序的可用性和性能特征进行预测。

观看下方的短视频以了解如何使用我们的 API。

如何调用垃圾回收日志分析 API

垃圾回收日志分析功能的调用非常简单:

  1. 注册即可。我们会通过邮件向您发送 API Key。这是一次性的设置过程。注意:如果您购买了带有 API 的企业版本,则不需要进行注册。API Key 将随安装说明一并提供。
  2. Post HTTP 请求至 https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}
  3. HTTP 请求的主体中应包含需要分析的垃圾回收日志。
  4. HTTP 响应将以 JSON 格式回传。JSON 文件中将包含有关 GC 日志的多种重要数据。可在 JSON 响应中查找的主要元素是:“isProblem”。如果发现任何内存/性能问题,则该元素的值将为“true”。“problem”元素中将包含内存问题的详细描述。

CURL 命令

假设您的 Java GC 日志文件位于“./my-app-gc.log”,那么调用 API 的 CURL 命令为:

curl -X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY} --header "Content-Type:text"

好像不能再简单了,对吧?

压缩

GC 日志文件通常会很大。为了快速高效地进行处理,我们建议您对 GC 日志文件进行压缩后再发送。压缩 GC 日志时,您需要在 HTTP Header 元素或 URL 参数中传递“Content-Encoding”元素。

如果您想将 GC 日志文件压缩为“zip”格式,则可使用 HTTP Header 元素来调用 API

curl -X POST --data-binary @./my-app-gc.zip "https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}" --header "Content-Type:text" --header "Content-Encoding:zip"

也可在 URL 参数中使用“Content-Encoding”来调用 API

curl -X POST --data-binary @./my-app-gc.zip "https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&Content-Encoding=zip" --header "Content-Type:text"

我们支持以下压缩格式:

zipgzxzzlzmadeflateszlz4zstdbz2tar

您可根据自身需求进行选择。无论选择何种 GC 日志文件压缩格式,只需传递相应的“Content-Encoding”元素即可。

备注:可在 CURL 中使用“–data-binary”来取代“–data”选项。“–data”请求中不会保留新的换行符。新换行符应当保留以确保解析正常进行。

从远程位置下载 GC 日志

如果您的 Java GC 日志文件存储在了远程位置——如 AWS S3 存储桶中,那么在需要对 GC 日志进行分析时,您就必须将文件下载到本地计算机,然后再调用 API。为了简化这一过程并实现自动化,我们在 API 中引入了“location”参数。您可向“location”位置传递 http(s) URL 位置以调用 API。此时,API 将从远程位置下载文件,然后对其中的数据进行分析并返回响应。如需了解详情请参阅本文

curl -X POST "https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&location={GC-LOG-HTTP-URL}" --header "Content-Type:text"

其他工具

您也可以使用任意网络服务客户端工具(如:SOAP UI、PostMan Browser Plugin 等)来调用 API

图:通过 PostMan 插件发布 GC 日志

示例响应

{
{
"isProblem": true,
"problem": [
"分析表明您的程序中出现连续 Full GC。这可能会导致间歇性的 OutOfMemoryErrors 错误、响应速度下降或高 CPU 消耗,甚至使应用程序无响应。"
"我们的分析显示,您的应用程序正在遭受长时间 GC 活动的折磨。4 个 GC 事件耗时超过 10 秒。长时间运行的 GC 对于程序性能有负面影响。"
"应用程序线程已停止超过 10 秒 342 次。"
],
"jvmHeapSize": {
"youngGen": {
"allocatedSize": "7.5 gb",
"peakSize": "6 gb"
},
"oldGen": {
"allocatedSize": "22.5 gb",
"peakSize": "22.5 gb"
},
"metaSpace": {
"allocatedSize": "1.04 gb",
"peakSize": "48.52 mb"
},
"total": {
"allocatedSize": "30 gb",
"peakSize": "28.5 gb"
}
},
"gcStatistics": {
"totalCreatedBytes": "249.49 gb",
"measurementDuration": "7 hrs 32 min 52 sec",
"startTimestamp": "2018-12-15T15:58:37.622+0100",
"endTimestamp": "2018-12-15T15:58:44.622+0100",
"avgAllocationRate": "9.4 mb/sec",
"avgPromotionRate": "1.35 mb/sec",
"minorGCCount": "62",
"minorGCTotalTime": "1 min 19 sec",
"minorGCAvgTime": "1 sec 274 ms",
"minorGCAvgTimeStdDeviation": "2 sec 374 ms",
"minorGCMinTIme": "0",
"minorGCMaxTime": "13 sec 780 ms",
"minorGCIntervalAvgTime": "7 min 25 sec 442 ms",
"fullGCCount": "166",
"fullGCTotalTime": "14 min 11 sec 620 ms",
"fullGCAvgTime": "5 sec 130 ms",
"fullGCAvgTimeStdDeviation": "5 sec 207 ms",
"fullGCMinTIme": "120 ms",
"fullGCMaxTime": "57 sec 880 ms",
"fullGCIntervalAvgTime": "2 min 19 sec 104 ms"
},
"gcKPI": {
"throughputPercentage": 99.952,
"averagePauseTime": 750.232,
"maxPauseTime": 57880
},
"gcDurationSummary": {
"groups": [
{
"start": "0",
"end": "6",
"numberOfGCs": 212
},
{
"start": "6",
"end": "12",
"numberOfGCs": 4
},
{
"start": "12",
"end": "18",
"numberOfGCs": 2
},
{
"start": "42",
"end": "48",
"numberOfGCs": 1
},
{
"start": "54",
"end": "60",
"numberOfGCs": 1
}
]
},
"gcCauses": [
{
"cause": "分配失败",
"count": 57
},
{
"cause": "并发模式失败",
"count": 162
},
{
"cause": "Full GC - 分配失败",
"count": 369
}
],
"commandLineFlags": " -XX:CMSInitiatingOccupancyFraction=65 -XX:+CMSScavengeBeforeRemark -XX:CMSWaitDuration=2000 -XX:ConcGCThreads=8 -XX:+DisableExplicitGC -XX:GCLogFileSize=104857600 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=32212254720 -XX:InitialTenuringThreshold=4 -XX:+ManagementServer -XX:MaxHeapSize=32212254720 -XX:MaxTenuringThreshold=4 -XX:NewRatio=3 -XX:NumberOfGCLogFiles=10 -XX:OldPLABSize=16 -XX:ParGCCardsPerStrideChunk=32768 -XX:+PrintClassHistogram -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintPromotionFailure -XX:+PrintTenuringDistribution -XX:SurvivorRatio=3 -XX:ThreadStackSize=334 -XX:+UnlockDiagnosticVMOptions -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseGCLogFileRotation -XX:+UseParNewGC ",
"heapTuningTips": [
"似乎您过度分配了 Metaspace 的大小。在整个运行过程中,Metaspace 的峰值利用率仅为已分配大小的 4.53%。您可考虑降低 Metaspace 的大小。"
],
"tipsToReduceGCTime": [
{
"issue":"15.34% 的 GC 时间(即 54 分钟 13 秒 710 毫秒)是由 “并发模式失败”引起的。CMS 收集器会使用一个或多个垃圾回收线程,这些线程会与应用程序线程同时运行,目标是在 Tenured 代充满之前完成针对其的垃圾回收工作。在正常过程中,CMS 收集器会在程序线程运行的同时执行大部分追踪和扫描工作,因此程序线程只会出现短暂的暂停情况。但是,如果 CMS 收集器无法在 Tenured 代填满之前完成对象的回收工作,或者 Tenured 代中没有足够的空闲空间块能够用于分配的,则应用程序将被暂停且完成回收工作,同时所有程序线程都会被停止。无法同时完成回收的情形,就被称是为“并发模式失败”,表明需要调整 CMS 收集器参数。并发模式失败通常会触发 Full GC。",
"solution": "并发模式问题可以通过增加 Tenured 代大小来避免,或者通过将‘CMSInitiatingOccupancyFraction’设置为较低的值并将‘UseCMSInitiatingOccupancyOnly’设置为 true,以在较小的堆内存占用率下启动 CMS 回收。CMSInitiatingOccupancyFraction 的选择应当谨慎,将其值设置得过低会导致 CMS 回收过于频繁。"
}
],
"throughputPercentage": 99.996,
"responseId": "8296b5c3-25c7-4157-92df-a54d9083bab7",
"graphs": {
"heapAfterGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_after_gc-aad50e08-951f-4eca-9cc2-e2b296ba3f8b.png",
"heapBeforeGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_before_gc-868d5a56-c8b6-4125-bf8d-dc557937033a.png",
"gcDurationGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_duration-1048abf9-8833-44f1-a990-9a6dd24e9a94.png",
"gcPauseDurationGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_pause_duration-ef8b210e-1d08-4b5f-be28-e2d54a43732d.png"
}
"webReport": "http://gceasy.io/my-gc-report.jsp?p=YXJjaGl2ZWQvMjAxOS8wNC8xNC8tLWFwaS1lMDk0YTM0ZS1jM2ViLTRjOWEtODI1NC1mMGRkMTA3MjQ1Y2M1YjBjMTMzNy0yMDQyLTQ4NzAtYmI5My01NmEwZjUzOTg3M2YudHh0LS0=&channel=API",
"pdfReport": "http://gceasy.io/my-gc-report.jsp?p=YXJjaGl2ZWQvMjAxOS8wNC8xNC8tLWFwaS1lMDk0YTM0ZS1jM2ViLTRjOWEtODI1NC1mMGRkMTA3MjQ1Y2M1YjBjMTMzNy0yMDQyLTQ4NzAtYmI5My01NmEwZjUzOTg3M2YudHh0LS0=&channel=API&isPrinterFriendly=true"
}

JSON 响应元素

元素描述
responseId为各个响应生成的唯一事务 ID。可用于调试和诊断
webReport在网页浏览器中查看此 GC 分析可视化网页报告的超链接。
pdfReport通过网络浏览器下载此 GC 分析 PDF 报告的超链接。
isProblem如找到任何内存问题则会返回“true”。如未找到内存问题则会返回“false”。此元素可用于主动 GC 监测。
problem内存问题的描述将通过此元素给出。比如内存问题的类型、内存问题的副作用及其可能导致的表现等等
jvmHeapSize该部分的数据点是从 GC 日志中收集而来的,因此可能会与 JVM 系统属性(即:–Xmx、-Xms…)指定的大小相匹配,也可能会不匹配。假设您已将总的堆内存大小(即:–Xmx)配置为 2 GB,但在运行时,如果 JVM 只分配了 1 GB,那么在本报告中您将看到已分配的大小仅为 1 GB。
youngGen
> allocatedSizeYoung 代已分配大小(即:在 JVM 水平指定的大小)
> peakSizeYoung 代运行时的峰值利用率大小
oldGen
> allocatedSizeOld 代已分配大小(即:在 JVM 水平指定的大小)
> peakSizeOld 代运行时的峰值利用率大小
Metaspace
> allocatedSizeMetaspace 的已分配大小(即:在 JVM 水平指定的大小)
> peakSizeMetaspace 的运行时峰值利用率大小
permGen
> allocatedSizePerm 代已分配大小(即:在 JVM 水平指定的大小)
> peakSizePerm 代运行时的峰值利用率大小
total
> allocatedSize总的已分配堆内存大小(即:在 JVM 水平指定的大小),包含 Young + Old + Perm(或 Metaspace)
> peakSize堆内存运行时的峰值利用率大小
gcStatisticsGC 统计数据摘要基于 GC 日志中报告的“real”时间。有关 user、sys、real 时间差别的更多信息,请参考 http://blog.gceasy.io/2016/04/06/gc-logging-user-sys-real-which-time-to-use/
> totalCreatedBytes应用程序创建的总对象数。
> measurementDuration应用程序运行的总时间
> startTimestamp报告首个 GC 事件的时间戳
> endTimestamp报告最后一个 GC 事件的时间戳
> avgAllocationRate程序对象创建率。在分配更多对象时,Young 代将会很快填满,Minor GC 的出现频率会提高。
> avgPromotionRate从 Young 代到 Old 代的对象晋升率。当有更多对象被提升到 Old 代时,Full GC 将更频繁地运行。
> minorGCCount程序中发生 Minor GC 的次数
> minorGCTotalTimeMinor GC 花费的总时间
> minorGCAvgTimeMinor GC 所花费的平均时间(即:所有 Minor GC 所花费的总时间/Minor GC 次数)
> minorGCAvgTimeStdDeviationMinor GC 平均时间标准差
> minorGCMinTIme所有 Minor GC 的最小时间
> minorGCMaxTime所有 Minor GC 的最大时间
> minorGCIntervalAvgTimeMinor GC 间的平均时间间隔
> fullGCCount程序中发生 Full GC 的次数
> fullGCTotalTimeFull GC 花费的总时间
> fullGCAvgTimeFull GC 所花费的平均时间(即:所有 Full GC 所花费的总时间/Full GC 次数)
> fullGCAvgTimeStdDeviationFull GC 平均时间标准差
> fullGCMinTime所有 Full GC 的最小时间
> fullGCMaxTime所有 Full GC 的最大时间
> fullGCIntervalAvgTimeFull GC 间的平均时间间隔
gcKPI此 GC 分析的关键性能指标
>throughputPercentage处理真实事务所花费的时间 vs GC活动所花费的时间(百分比)。百分比数值较高意味着 GC 开销较低。应该以高吞吐量为目标。
>averagePauseTime平均 GC 停顿时间(毫秒)
>maxPauseTime最大 GC 停顿时间(毫秒)
gcDurationSummary
> groupsGC 持续时间摘要数组。示例组:
{
“start”: “0.2”,
“end”: “0.3”,
“numberOfGCs”: 5
}, 表示 5 次 GC 在 0.2 秒至 0.3 秒之间完成
>> start报告的组开始时间(秒)
>> end报告的组结束时间(秒)
>> numberOfGCs“start”时间和“end”时间之间完成的 GC 次数
graphs此 GC 日志分析的图形图像可以在该子元素中找到
> heapAfterGCGraph包含指向堆内存使用情况(GC 后)图形图像的 URL
> heapBeforeGCGraph包含指向堆内存使用情况(GC 前)图形图像的 URL
> gcDurationGraph包含指向 GC 持续时间图形图像的 URL
> gcPauseDurationGCGraph包含指向 GC 停顿持续时间图形图像的 URL
gcCauses报告 GC 原因的数组
> cause触发 GC 的原因。其中的值可能是:并发模式失败、分配失败、System.gc()调用
> count因此原因而导致的 GC 次数
commandLineFlags传递给应用程序的 JVM 参数
heapTuningTips数组。可选元素。提供 JVM 堆内存大小调优的建议
tipsToReduceGCTime数组。可选元素。提供缩短 GC 时间的建议
>issue说明引发 GC 的原因
>solution减少由此原因导致 GC 的解决方案

标记报告

假设您需要分析数百 JVM 的 GC 日志。此时可能需要使用主机名、日期等信息来对报告进行标记,这样就能清楚地知道其中的对应关系了。可通过在 GC API 端点中传递请求参数“fileName”来实现这一功能,如:

https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&fileName={YOUR_TAG}

响应 JSON 中包含“webReport”元素。该元素中包含一个 URL。在浏览器中访问该 URL 可看到通过 API 解析的 GC 日志可视化报告。现在,您将可在浏览器报告中的右上角看到通过 API 传递的标签。
比如您在 API 端点中传递了 fileName=hostABC8080,那么报告中就会如实展示。

图:通过 API 传递了标签的 GCeasy 报告

XML 响应

默认情况下 API 响应会以 JSON 格式发送。但是如果您想获取 XML 格式的相应,则可在 HTTP Header 元素中传递“accept”参数,值为“xml”即可。

Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY} –-header "accept:xml"

也可在 URL 参数中使用“accept”元素来调用 API

Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&accept=xml

图形图像

部分客户希望能够在 GCeasy API 响应中包含指向图形图像的 URL。客户会在以下情形中使用这些图形图像:

a.构建 GC 日志分析仪表板。
b.将 GC 分析集成至 CI/CD 管线。
c.横跨数百节点自动生成性能报告。

如需在 API 响应中启用图形,您需要在 API 请求 Header 中传递“graphs=true”,如下所示:

Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&graphs=true

然后您将能看到 API 响应中包含指向图形的 URL:

"graphs": {
"heapAfterGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_after_gc-aad50e08-951f-4eca-9cc2-e2b296ba3f8b.png",
"heapBeforeGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--heap_usage_before_gc-868d5a56-c8b6-4125-bf8d-dc557937033a.png",
"gcDurationGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_duration-1048abf9-8833-44f1-a990-9a6dd24e9a94.png",
"gcPauseDurationGCGraph": "https://graphs.gceasy.io/archived/2019/04/14/--gc_pause_duration-ef8b210e-1d08-4b5f-be28-e2d54a43732d.png"
}

统一单位

包含内存大小的响应元素将以 kb、mb、gb、tb 为单位回传。示例:

“allocatedSize”: “2.9 gb”,
“peakSize”: “1.36 gb”

同样的,带有时间的元素将以小时、分钟、秒、毫秒为单位回传。示例:

“minorGCTotalTime”: “1 min 9 sec 408 ms”,
“minorGCMaxTime”: “1 sec 65 ms”, 如果您想以内存单位“bytes”和时间单位“毫秒”来对单位进行统一,则可传递值为“true”的“normalizeUnits”URL 参数

Curl –X POST --data-binary @./my-app-gc.log https://api.gceasy.io/analyzeGC?apiKey={YOUR_API_KEY}&normalizeUnits=true

此时调用包含选项的 API 会返回如下所示的统一单位响应元素:

“allocatedSize”: “3.113877504E9”,
“peakSize”: “2.95285248E9”

“minorGCTotalTime”: “69408.36”,
“minorGCMaxTime”: “1065.17”,

基于时间的过滤

有时您可能会想要对某个时间段内的 GC 日志进行分析,而不是分析整个 Java GC 日志。下面是一些相关情形:

1. 如果 GC 日志未被配置为覆盖的话(这也是大部分组织的通常情况),则单个 GC 日志文件中最终将包含所有 GC 事件的信息。部分程序可能已经启动了好几天甚至好几周。因此,单一个 GC 日志文件中最终将包含这些时间内的所有 GC 事件。但是,用户可能只想对最近 24 小时的 GC 活动进行分析

2. 各个应用程序将在同一天中出现高流量和低流量的时段。用户可能只想分析峰值流量时段的 GC 情况。比如一名来自金融行业用户,他只想在 COW(关键在线窗口期)期间(即:9:00AM – 6:00PM)对 GC 活动进行监测。

如需进行此类基于时间的处理,请参考本文

相对时间戳转绝对时间戳

在您的 GC 日志文件中,时间戳可能会以相对格式输出,如:

[0.209s]   .....

但是如果您想以绝对时间戳在 GCeasy 图表中进行绘制,则可在 API 请求中传递“initialTimestamp”参数。有关此功能的更多详情可在这里查看。

API 响应关键元素

GCeasy 的 JSON API 可用于应用程序监测、CI/CD 管线代码质量分析以及多种其他目的。API 响应中包含丰富的信息集(即:元素)。在本文中,我们着重介绍了 API 响应中的一些关键元素。如果这些元素的值超过或低于特定阈值,你可能就需要考虑给出警报或中断程序。

最佳实践:构建警报

出于生产监测或性能测试目的,您可以围绕 JSON 响应构建警报。

a.如果“isProblem”元素的值为“true”,那么可以使用“problem”元素中的内容来生成警报

b.您还可在

“fullGCCount”、“fullGCTotalTime”、“fullGCAvgTime”、“fullGCAvgTimeStdDeviation”、“fullGCMinTIme”、“fullGCMaxTime”、“fullGCIntervalAvgTime”等元素上设置阈值。如果任意上述元素值超出您所设置的阈值,则也可以触发警报。

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: