Uber jvm profiler 使用

简介: Uber jvm profiler 使用

背景


uber jvm profiler是用于在分布式监控收集jvm 相关指标,如:cpu/memory/io/gc信息等


安装


确保安装了maven和JDK>=8前提下,直接mvn clean package


java application


说明


直接以java agent的部署就可以使用


使用


java -javaagent:jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.KafkaOutputReporter,brokerList='kafka1:9092',topicPrefix=demo_,tag=tag-demo,metricInterval=5000,sampleInterval=0 -cp target/jvm-profiler-1.0.0.jar


选项解释

image.png

  • 结果展示
  "nonHeapMemoryTotalUsed": 11890584.0,
  "bufferPools": [
      {
          "totalCapacity": 0,
          "name": "direct",
          "count": 0,
          "memoryUsed": 0
      },
      {
          "totalCapacity": 0,
          "name": "mapped",
          "count": 0,
          "memoryUsed": 0
      }
  ],
  "heapMemoryTotalUsed": 24330736.0,
  "epochMillis": 1515627003374,
  "nonHeapMemoryCommitted": 13565952.0,
  "heapMemoryCommitted": 257425408.0,
  "memoryPools": [
      {
          "peakUsageMax": 251658240,
          "usageMax": 251658240,
          "peakUsageUsed": 1194496,
          "name": "Code Cache",
          "peakUsageCommitted": 2555904,
          "usageUsed": 1173504,
          "type": "Non-heap memory",
          "usageCommitted": 2555904
      },
      {
          "peakUsageMax": -1,
          "usageMax": -1,
          "peakUsageUsed": 9622920,
          "name": "Metaspace",
          "peakUsageCommitted": 9830400,
          "usageUsed": 9622920,
          "type": "Non-heap memory",
          "usageCommitted": 9830400
      },
      {
          "peakUsageMax": 1073741824,
          "usageMax": 1073741824,
          "peakUsageUsed": 1094160,
          "name": "Compressed Class Space",
          "peakUsageCommitted": 1179648,
          "usageUsed": 1094160,
          "type": "Non-heap memory",
          "usageCommitted": 1179648
      },
      {
          "peakUsageMax": 1409286144,
          "usageMax": 1409286144,
          "peakUsageUsed": 24330736,
          "name": "PS Eden Space",
          "peakUsageCommitted": 67108864,
          "usageUsed": 24330736,
          "type": "Heap memory",
          "usageCommitted": 67108864
      },
      {
          "peakUsageMax": 11010048,
          "usageMax": 11010048,
          "peakUsageUsed": 0,
          "name": "PS Survivor Space",
          "peakUsageCommitted": 11010048,
          "usageUsed": 0,
          "type": "Heap memory",
          "usageCommitted": 11010048
      },
      {
          "peakUsageMax": 2863661056,
          "usageMax": 2863661056,
          "peakUsageUsed": 0,
          "name": "PS Old Gen",
          "peakUsageCommitted": 179306496,
          "usageUsed": 0,
          "type": "Heap memory",
          "usageCommitted": 179306496
      }
  ],
  "processCpuLoad": 0.0008024004394748531,
  "systemCpuLoad": 0.23138430784607697,
  "processCpuTime": 496918000,
  "appId": null,
  "name": "24103@machine01",
  "host": "machine01",
  "processUuid": "3c2ec835-749d-45ea-a7ec-e4b9fe17c23a",
  "tag": "mytag",
  "gc": [
      {
          "collectionTime": 0,
          "name": "PS Scavenge",
          "collectionCount": 0
      },
      {
          "collectionTime": 0,
          "name": "PS MarkSweep",
          "collectionCount": 0
      }
  ]
}

spark application


说明


和java应用不同,需要把jvm-profiler.jar分发到各个节点上


使用

   --jars hdfs:///public/libs/jvm-profiler-1.0.0.jar   
   --conf spark.driver.extraJavaOptions=-javaagent:jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.KafkaOutputReporter,brokerList='kafka1:9092',topicPrefix=demo_,tag=tag-demo,metricInterval=5000,sampleInterval=0 
   --conf spark.executor.extraJavaOptions=-javaagent:jvm-profiler-1.0.0.jar=reporter=com.uber.profiling.reporters.KafkaOutputReporter,brokerList='kafka1:9092',topicPrefix=demo_,tag=tag-demo,metricInterval=5000,sampleInterval=0

选项解释

image.png

结果展示

  "nonHeapMemoryTotalUsed": 11890584.0,
  "bufferPools": [
      {
          "totalCapacity": 0,
          "name": "direct",
          "count": 0,
          "memoryUsed": 0
      },
      {
          "totalCapacity": 0,
          "name": "mapped",
          "count": 0,
          "memoryUsed": 0
      }
  ],
  "heapMemoryTotalUsed": 24330736.0,
  "epochMillis": 1515627003374,
  "nonHeapMemoryCommitted": 13565952.0,
  "heapMemoryCommitted": 257425408.0,
  "memoryPools": [
      {
          "peakUsageMax": 251658240,
          "usageMax": 251658240,
          "peakUsageUsed": 1194496,
          "name": "Code Cache",
          "peakUsageCommitted": 2555904,
          "usageUsed": 1173504,
          "type": "Non-heap memory",
          "usageCommitted": 2555904
      },
      {
          "peakUsageMax": -1,
          "usageMax": -1,
          "peakUsageUsed": 9622920,
          "name": "Metaspace",
          "peakUsageCommitted": 9830400,
          "usageUsed": 9622920,
          "type": "Non-heap memory",
          "usageCommitted": 9830400
      },
      {
          "peakUsageMax": 1073741824,
          "usageMax": 1073741824,
          "peakUsageUsed": 1094160,
          "name": "Compressed Class Space",
          "peakUsageCommitted": 1179648,
          "usageUsed": 1094160,
          "type": "Non-heap memory",
          "usageCommitted": 1179648
      },
      {
          "peakUsageMax": 1409286144,
          "usageMax": 1409286144,
          "peakUsageUsed": 24330736,
          "name": "PS Eden Space",
          "peakUsageCommitted": 67108864,
          "usageUsed": 24330736,
          "type": "Heap memory",
          "usageCommitted": 67108864
      },
      {
          "peakUsageMax": 11010048,
          "usageMax": 11010048,
          "peakUsageUsed": 0,
          "name": "PS Survivor Space",
          "peakUsageCommitted": 11010048,
          "usageUsed": 0,
          "type": "Heap memory",
          "usageCommitted": 11010048
      },
      {
          "peakUsageMax": 2863661056,
          "usageMax": 2863661056,
          "peakUsageUsed": 0,
          "name": "PS Old Gen",
          "peakUsageCommitted": 179306496,
          "usageUsed": 0,
          "type": "Heap memory",
          "usageCommitted": 179306496
      }
  ],
  "processCpuLoad": 0.0008024004394748531,
  "systemCpuLoad": 0.23138430784607697,
  "processCpuTime": 496918000,
  "appId": null,
  "name": "24103@machine01",
  "host": "machine01",
  "processUuid": "3c2ec835-749d-45ea-a7ec-e4b9fe17c23a",
  "tag": "mytag",
  "gc": [
      {
          "collectionTime": 0,
          "name": "PS Scavenge",
          "collectionCount": 0
      },
      {
          "collectionTime": 0,
          "name": "PS MarkSweep",
          "collectionCount": 0
      }
  ]
}

分析

  • 已有的reporter

image.png

建议在生产环境下使用KafkaOutputReporter,操作灵活性高,可以结合clickhouse grafana进行指标展示

源码分析


该jvm-profiler整体是基于java agent实现,项目pom文件 指定了MANIFEST.MF中的Premain-Class项和Agent-Class为com.uber.profiling.Agent

具体的实现类为AgentImpl

就具体的AgentImpl类的run方法来进行分析

public void run(Arguments arguments, Instrumentation instrumentation, Collection<AutoCloseable> objectsToCloseOnShutdown) {
      if (arguments.isNoop()) {
          logger.info("Agent noop is true, do not run anything");
          return;
      }
      Reporter reporter = arguments.getReporter();
      String processUuid = UUID.randomUUID().toString();
      String appId = null;
      String appIdVariable = arguments.getAppIdVariable();
      if (appIdVariable != null && !appIdVariable.isEmpty()) {
          appId = System.getenv(appIdVariable);
      }
      if (appId == null || appId.isEmpty()) {
          appId = SparkUtils.probeAppId(arguments.getAppIdRegex());
      }
      if (!arguments.getDurationProfiling().isEmpty()
              || !arguments.getArgumentProfiling().isEmpty()) {
          instrumentation.addTransformer(new JavaAgentFileTransformer(arguments.getDurationProfiling(), arguments.getArgumentProfiling()));
      }
      List<Profiler> profilers = createProfilers(reporter, arguments, processUuid, appId);
      ProfilerGroup profilerGroup = startProfilers(profilers);
      Thread shutdownHook = new Thread(new ShutdownHookRunner(profilerGroup.getPeriodicProfilers(), Arrays.asList(reporter), objectsToCloseOnShutdown));
      Runtime.getRuntime().addShutdownHook(shutdownHook);
  }

arguments.getReporter() 获取reporter,如果没有设置则设置为reporterConstructor,否则设置为指定的reporter


String appId ,设置appId,首先从配置中查找,如果没有设置,再从env中查找,对于spark应用则取spark.app.id的值


List profilers = createProfilers(reporter, arguments, processUuid, appId),创建profilers,默认有CpuAndMemoryProfiler,ThreadInfoProfiler,ProcessInfoProfiler ;

1.其中CpuAndMemoryProfiler,ThreadInfoProfiler,ProcessInfoProfiler是从JMX中读取数据,ProcessInfoProfiler还会从 /pro读取数据;

2.如果设置了durationProfiling,argumentProfiling,sampleInterval,ioProfiling,则会增加对应的MethodDurationProfiler(输出方法调用花费的时间),MethodArgumentProfiler(输出方法参数的值),StacktraceReporterProfiler,IOProfiler;

3.MethodArgumentProfiler和MethodDurationProfiler利用javassist第三方字节码编译工具来改写对应的类,具体实现参照JavaAgentFileTransformer

4.StacktraceReporterProfiler从JMX中读取数据

5.IOProfiler则是读取本地机器上的/pro文件对应的目录的数据


ProfilerGroup profilerGroup = startProfilers(profilers) 开始进行profiler的定时report

其中还会区分oneTimeProfilers和periodicProfilers,ProcessInfoProfiler就属于oneTimeProfilers,因为process的信息,在运行期间是不会变的,不需要周期行的reporter

至此,整个流程结束


相关文章
|
存储 SQL 分布式计算
如何用 Uber JVM Profiler 等可视化工具监控 Spark 应用程序?
  关键要点   持续可靠地运行 Spark 应用程序是一项具有挑战性的任务,而且需要一个良好的性能监控系统。   - 在设计性能监控系统时有三个目标——收集服务器和应用程序指标、在时序数据库中存储指标,并提供用于数据可视化的仪表盘。   Uber JVM Profiler 被用于监控 Spark 应用程序,用到的其他技术还有 InfluxDB(用于存储时序数据)和 Grafana(数据可视化工具)。性能监控系统可帮助 DevOps 团队有效地监控系统,用以满足应用程序的合规性和 SLA。
263 0
|
监控 Java 调度
JVM Profiler 启动过程分析
开篇  先来调侃一句,原来独角兽Uber的程序员写的代码也是看得懂的,而且还是比较容易看得懂的,所以有时候在设计模式和代码结构清晰以及可读性方面我还是更倾向于后者,宁可重复或浪费一部分代码也要整个代码的可读性更强一些。
1149 0
|
数据采集 Linux 索引
JVM Profiler IOProfiler
开篇  IOProfiler因为采集方法的限制,目前支持linux系统指标采集,但是不支持mac,windows等操作系统。  IOProfiler通过读取linux系统的/proc/self/io的当前线程的IO指标数据,该文件的内容如下图所示,通过解析成kv键值对完成采集。
1027 0
|
Java
JVM Profiler CpuAndMemoryProfiler
开篇   CpuAndMemoryProfiler主要用来采集cpu和memory相关的信息,采集核心方法都是由ManagementFactory提供的接口: getClassLoadingMXBean() 返回 Java 虚拟机的类加载系统的管理 Bean。
889 0
|
Java
JVM Profiler StacktraceCollectorProfiler
开篇  StacktraceCollectorProfiler主要用来采集线程的调用栈,原理是通过ManagementFactory.getThreadMXBean()返回的ThreadMXBean对象来实现。
813 0
|
监控 Java 编解码
JVM Profiler 方法耗时采集
开篇  JVM Profile的方法采集通过修改字节码在原来方法体的前置和后置增加采集耗时的代码。核心是基于基于java自带的instrument包和javassist包来实现的。
1169 0
|
NoSQL Java Redis
JVM Profiler Reporter介绍
开篇  JVM Profiler采集完数据后可以通过多种途径上报数据,对接Console,File,redis,kafka等,这篇文章会把源码罗列一下毕竟都很简单。
1167 0
|
消息中间件 分布式计算 Java
JVM Profiler介绍
开篇  过去的几周把java多线程相关部分的源码粗粗的看了一遍基本上也算告一段落了,后面应该会聚焦看下dubbo、mycat、datax以及剩下部分的mybatis。
1706 0
|
监控 Java 消息中间件
JVM Profiler 整体架构
开篇 整个JVM Profiler的组件类似于上图,抽象出来主要分为:Class File Transformer:负责转换被监控方法的字节码,在前后增加耗时统计。
1054 0
|
2月前
|
Java Docker 索引
记录一次索引未建立、继而引发一系列的问题、包含索引创建失败、虚拟机中JVM虚拟机内存满的情况
这篇文章记录了作者在分布式微服务项目中遇到的一系列问题,起因是商品服务检索接口测试失败,原因是Elasticsearch索引未找到。文章详细描述了解决过程中遇到的几个关键问题:分词器的安装、Elasticsearch内存溢出的处理,以及最终成功创建`gulimall_product`索引的步骤。作者还分享了使用Postman测试接口的经历,并强调了问题解决过程中遇到的挑战和所花费的时间。