首页 > 编程语言 >Java服务通过动态开关 Profiling 实现关键问题定位-故障定位

Java服务通过动态开关 Profiling 实现关键问题定位-故障定位

时间:2024-01-27 15:32:37浏览次数:30  
标签:Profile 定位 Profiling Java name service ## datakit my

作者 观测云 高级技术专家 深圳办公室 黄小龙

简介

Profile 通过收集和分析应用程序运行过程中 CPU、内存和 I/O 相关的数据,可以识别应用程序的性能瓶颈和错误,帮助我们更好地了解程序的运行情况。Profile 是一种非常有价值的技术,通过 Profile 可以实现:

  • 识别性能瓶颈: Profiling 可以帮助发现程序的性能瓶颈,即程序中最耗费时间的部分。通过识别性能瓶颈,以便我们采取措施来优化这部分性能。
  • 优化程序性能: 通过 Profiling 收集的数据,我们可以知道程序的哪些部分需要进行优化。通过优化这些部分,可以提高程序的性能,减少资源的消耗。
  • 排查程序错误: 在应用程序中,有时会出现各种错误。通过 Profiling 分析程序的运行情况,我们可以找到错误的原因,并及时进行修复。

利用**观测云**可以快速收集应用程序 Profile 数据,利用 Profile 火焰图查看器分析 Java 、Python 、 Go 不同语言环境下应用程序运行过程中的动态性能数据,直观 查看每一个方法、类和线程的调用关系和执行效率。通过关联链路,获取链路相关 Span 的关联代码执行片段,实现方法级代码性能追踪,帮助开发人员发现代码优化方向。

收集应用程序 Profile 数据,会对应用程序本身性能造成一定的影响,所以一般情况下不建议在生产环境实时启动 Profile 数据收集,在 Kubernetes 部署的应用程序可以通过动态开关打开 Profile 数据采集,从而实现对应用程序的关键问题定位。


前置条件

安装 DataKit

登录观测云控制台,选择「集成」-「DataKit」-「Kubernetes」,按照所提示的安装步骤下载 datakit.yaml,并配置 DataWay 数据网关地址。

打开 Profile 采集器

修改 datakit.yaml 文件,ConfigMap 加入 Profile 采集配置:

apiVersion: v1
kind: ConfigMap
metadata:
  name: datakit-conf
  namespace: datakit
data:
  profile.conf: |-  
    [[inputs.profile]]
      ## profile Agent endpoints register by version respectively.
      ## Endpoints can be skipped listen by remove them from the list.
      ## Default value set as below. DO NOT MODIFY THESE ENDPOINTS if not necessary.
      endpoints = ["/profiling/v1/input"]
    
      ## set true to enable election, pull mode only
      election = true
    
    ## go pprof config
    ## collect profiling data in pull mode
    #[[inputs.profile.go]]
      ## pprof url
      #url = "http://localhost:6060"
    
      ## pull interval, should be greater or equal than 10s
      #interval = "10s"
    
      ## service name
      #service = "go-demo"
    
      ## app env
      #env = "dev"
    
      ## app version
      #version = "0.0.0"
    
      ## types to pull
      ## values: cpu, goroutine, heap, mutex, block
      #enabled_types = ["cpu","goroutine","heap","mutex","block"]
    
    #[inputs.profile.go.tags]
      # tag1 = "val1"
    
    ## pyroscope config
    #[[inputs.profile.pyroscope]]
      ## listen url
      #url = "0.0.0.0:4040"
    
      ## service name
      #service = "pyroscope-demo"
    
      ## app env
      #env = "dev"
    
      ## app version
      #version = "0.0.0"
    
    #[inputs.profile.pyroscope.tags]
      #tag1 = "val1"

DaemonSet 添加相应的挂载配置:

volumeMounts:
    - mountPath: /usr/local/datakit/conf.d/profile/profile.conf
      name: datakit-conf
      subPath: profile.conf

修改完成之后,安装 datakit.yaml 配置:

kubectl apply -f datakit.yaml

应用配置

本文以 Java 应用程序为例,介绍如何动态开关打开 Profile 数据采集。

安装 Datakit Operator

Datakit-Operator 通过 K8s 的 Admission Controller(准入控制器)功能,会向指定的 Pod 注入应用程序启动所需要的 dd-lib 探针文件,这样就不需要应用程序打包镜像时加入对应的探针文件,减少配置从而提高效率。

下载 datakit-operator.yaml文件并执行安装:

wget https://static.guance.com/datakit-operator/datakit-operator.yaml
kubectl apply -f datakit-operator.yaml

通过以下命令验证所有配置是否安装完成,正常会有 datakit 和 datakit-operator 两种类型的 Pod:

kubectl get pod -n datakit

修改 Dockerfile

修改应用 Dockerfile,暴露启动参数:

注意: java版本要求:java8版本需要高于8u262+,或者使用java11及以上版本。

FROM openjdk:8u292

RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone

ENV jar my-service.jar
ENV workdir /data/app/
RUN mkdir -p ${workdir}
COPY ${jar} ${workdir}
WORKDIR ${workdir}
ENTRYPOINT ["sh", "-ec", "exec java ${JAVA_OPTS} -jar ${jar} ${PARAMS} 2>&1 > /dev/null"]

应用部署 yaml

添加以下环境变量,通过 ENV_PROFILE 环境变量来动态控制 Profile 数据采集:

env:
- name: DD_AGENT_HOST
  valueFrom:
    fieldRef:
      apiVersion: v1
      fieldPath: status.hostIP
- name: ENABLE_PROFILE
  value: "true"
- name: JAVA_OPTS
  value: |-
    -javaagent:/datadog-lib/dd-java-agent.jar -Ddd.service=my-service  -Ddd.profiling.enabled=$(ENABLE_PROFILE) -Ddd.profiling.allocation.enabled=$(ENABLE_PROFILE) -Ddd.env=env -Ddd.agent.port=9529

添加 annotation,位置 spec.template.metadata 下:

annotations:
  admission.datakit/java-lib.version: ""

生产环境部署时,ENV_PROFILE 环境变量可以设置为 false,需要排查性能问题时,再打开 Profile 开关收集数据,从而实现动态采集 Profile 数据的功能。

完整 yaml 参考:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: profile
  labels:
    app: my-service
spec:
  selector:
    app: my-service
  ports:
    - protocol: TCP
      port: 9299
      nodePort: 30001
      targetPort: 9299
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service
  namespace: profile
  labels:
    app: my-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-service
  template:
    metadata:
      labels:
        app: my-service
      annotations:
        admission.datakit/java-lib.version: ""
    spec:
      containers:
        - name: my-container
          env:
          - name: DD_AGENT_HOST
            valueFrom:
              fieldRef:
                apiVersion: v1
                fieldPath: status.hostIP
          - name: ENABLE_PROFILE
            value: "true"
          - name: JAVA_OPTS
            value: |-
              -javaagent:/datadog-lib/dd-java-agent.jar -Ddd.service=my-service  -Ddd.profiling.enabled=$(ENABLE_PROFILE) -Ddd.profiling.allocation.enabled=$(ENABLE_PROFILE) -Ddd.env=env -Ddd.agent.port=9529
          image: my-service:v1.0
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 9299
            protocol: TCP
      restartPolicy: Always

实现效果

Java服务通过动态开关 Profiling 实现关键问题定位-故障定位_Java

Java服务通过动态开关 Profiling 实现关键问题定位-故障定位_性能优化_02

标签:Profile,定位,Profiling,Java,name,service,##,datakit,my
From: https://blog.51cto.com/u_12003135/9443787

相关文章

  • 浅克隆和深克隆 :Java中的对象克隆方式探究
    在Java编程中,我们经常需要对对象进行复制或克隆操作.对象克隆是创建一个新的对象,并将原始对象的值复制给新的对象,以便独立使用或修改.在对象克隆中,我们经常遇到两种主要的克隆方式:浅克隆(ShallowClone)和深克隆(DeepClone).本文将介绍这两种克隆方式的概念、区别以及在Java......
  • Java中的枚举
    Java的枚举是一个特殊的数据类型,用于定义一组命名的常量,用关键字enum来声明。这在项目开发中经常会用到,除了可以定义一些常量类来提高代码的复用性外,有些必要情况需要通过枚举,因为枚举这个数类型不是什么字符串七七八八的,比如项目开发中会有公告字段的填充,像aop切面类时通过自定义......
  • java enum枚举实现机制
    在上篇文章中,我们对Java中的枚举类进行了详细的介绍。对于Enum还不了解的小伙伴,可以先预习《Java中的枚举类型(Enum)详解》一文。通过反编译,我们知道Java枚举类会在编译之后转化为一个继承了java.lang.Enum的类,而我们定义的每个枚举值都会在类的初始化阶段被实例化为我们所定义的......
  • 初识JAVA的第4天,循环结构
    day4java新手随笔练习publicclassDoc{Stringname;//属性/***since指明需要最早使用的jak版本*@authorwushen作者名*@paramname参数名*@return返回值情况*@throwsException异常抛......
  • SpringBoot启动项目报错:java.lang.UnsatisfiedLinkError: D:\files\software\jdk-1
    目录问题描述解决方法:问题描述在运行向的时候出现报错:java.lang.UnsatisfiedLinkError:D:\files\software\jdk-15.0.1\jdk-17.0.3.1\bin\tcnative-1.dll:Can'tloadIA32-bit.dllonaAMD64-bitplatform atjava.base/jdk.internal.loader.NativeLibraries.load(Native......
  • windows下java启动失败
    windows下java启动失败一、问题现象微服务原来在linux下部署,现在有客户环境为windowsserver,把linux的包拷到windowsserver下,使用java-jar命令无法启动。同样的包在linux可以启动,就是在windows启动不了。问题提示:现象一:2023-10-2713:40:05.682ERROR11736---[main]o.......
  • 关于javascript的一些笔记(一)
    在script标签内使用import的时候,必须在script标签加上type=“module”当使用script标签加上type="module"的时候,是当所有模块都加载进来才进行工作的,也就是如果html在script标签下面也是可以正常运行的,他是后解析的当使用script标签加上type="module"的时候,script标签里面......
  • 每日一道Java面试题:Java是值传递还是引用传递?
    写在开头Java是值传递还是引用传递?这个问题几乎100%的出现在了各大主流Java面试题中,知识点很小,但很考验面试者对于Java运行的理解,今晚趁着生产投产的空子,过来小聊一下。实参与形参所谓的值传递or引用传递是指方法在调用的过程中实参传递的两种变现形式,那么好,想搞清楚这个问题的......
  • Java商城单体和微服务架构有什么区别
    微服务架构概述BizSpring移动全端国际化电商平台,是建立在SpringCloud基础上的微服务应用,服务化是系统达到一定规模以后的必然选择,主流的互联网公司基本都在迁移到服务化架构。我们的微服务化架构给客户带来更多便捷,每个开发团队及各人更加专注于自身业务的开发,每个服务独立......
  • Java学习日记 Day12 心累~
    SpringMVC:主要学了SpringMVC架构下请求与响应的各种方式,在响应中要知道请求转发和重定向的区别。算法:合并二叉树:判断当前节点两棵树的数值关系,然后递归判断左右子树的关系。二叉搜索树中的搜索:根据二叉搜索树的特点,递归查找左右子树,当值相等就返回。验证二叉搜索树:为自己的左......