百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

监控Spring Boot中的Tomcat性能数据

toyiye 2024-06-21 12:33 18 浏览 0 评论

现在,我们经常会使用Spring Boot以开发Web服务,其内嵌容器的方法的确使得开发效率大大提升。

由于网关层通常是直接面对用户请求的一层,也是微服务里面最上游的一个服务,其请求量通常是所有服务中最大的,如果服务出现了性能上的问题,网关层通常都会出现阻塞、超时等现象,这时候就很可能需要性能的调优,其中最常见的则是参数调优。但如何知道哪些性能参数成为了瓶颈(如容器线程数是否不足等),则是调优的前提条件。

本文总结介绍如何在使用了Spring Boot的前提下,获取运行时的Tomcat性能运行情况。

Spring Boot中有一个Spring Boot actuator的模块,用来监控和管理应用的运行状态,例如健康状况,线程运行情况等。

Maven 依赖:

<dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

然后当Spring Boot运行之后,Spring Boot会有很多服务暴露在http服务中,这些服务叫EndPoints, 通过 http://{应用路径}/actuator 这个 url 即可访问,例如 http://{应用路径}/actuator/info, http://{应用路径}/actuator/health 这两个endpoints是默认开启的。

其中actuator这个路径可以通过配置修改:

management.endpoints.web.base-path=/mypath

以下是获取健康状态的一个例子:

$ curl 'http://localhost:8080/actuator/health' -i -X GET

可能会得到类似这样的结果:

{
    "status" : "UP"
}

比较简陋,如果希望这个接口有更多数据,可以尝试这样的配置:

management.endpoint.health.show-details=always

结果就会丰富了(我的应用用了Redis):类似

{
  "status": "UP",
  "details": {
      "diskSpace": {
          "status": "UP",
          "details": {
              "total": 214745214976,
              "free": 174805827584,
              "threshold": 10485760
          }
      },
      "redis": {
          "status": "UP",
          "details": {
              "cluster_size": 3,
              "slots_up": 16384,
              "slots_fail": 0
          }
      }
  }
}

但是这还不够,我们需要详细的容器数据。监控状况只是一部分。而这些我们想要的数据,是在一个叫metric的EndPoint下面。 但是此endpoint 默认没有暴露到http接口的的,需要添加配置:

#默认只开启info, health 的http暴露,在此增加metric endpoint
management.endpoints.web.exposure.include=info, health,metric

之后我们就能访问这个metric有哪些数据了

$ curl ‘http://localhost:8080/actuator/metric’ -i -X GET

{
    "names": [
        "jvm.memory.max",
        "jvm.threads.states",
        "process.files.max",
        "jvm.gc.memory.promoted",
        "tomcat.cache.hit",
        "tomcat.servlet.error",
        "system.load.average.1m",
        "tomcat.cache.access",
        "jvm.memory.used",
        "jvm.gc.max.data.size",
        "jvm.gc.pause",
        "jvm.memory.committed",
        "system.cpu.count",
        "logback.events",
        "tomcat.global.sent",
        "jvm.buffer.memory.used",
        "tomcat.sessions.created",
        "jvm.threads.daemon",
        "system.cpu.usage",
        "jvm.gc.memory.allocated",
        "tomcat.global.request.max",
        "tomcat.global.request",
        "tomcat.sessions.expired",
        "jvm.threads.live",
        "jvm.threads.peak",
        "tomcat.global.received",
        "process.uptime",
        "http.client.requests",
        "tomcat.sessions.rejected",
        "process.cpu.usage",
        "tomcat.threads.config.max",
        "jvm.classes.loaded",
        "http.server.requests",
        "jvm.classes.unloaded",
        "tomcat.global.error",
        "tomcat.sessions.active.current",
        "tomcat.sessions.alive.max",
        "jvm.gc.live.data.size",
        "tomcat.servlet.request.max",
        "tomcat.threads.current",
        "tomcat.servlet.request",
        "process.files.open",
        "jvm.buffer.count",
        "jvm.buffer.total.capacity",
        "tomcat.sessions.active.max",
        "tomcat.threads.busy",
        "process.start.time"
    ]
}

其中列出的是所有可以获取的监控数据,在其中我们发现了我们想要的

"tomcat.threads.config.max"
"tomcat.threads.current"
"tomcat.threads.busy"

那么如何获取其中的值呢?只需要在metric路径下加上希望获取的指标即可: curl ‘http://localhost:8080/actuator/metric/tomcat.threads.busy’

{
  "name": "tomcat.threads.busy",
  "description": null,
  "baseUnit": "threads",
  "measurements": [{
      "statistic": "VALUE",
      "value": 1.0
  }],
  "availableTags": [{
      "tag": "name",
      "values": ["http-nio-10610"]
  }]
}

在此,基本我们想要的数据都能实时的通过http服务接口的方式获取了,那么在流量峰值的时候,一些实时的状态便可获取到了。

监控数据

但是我们面对的情况是这样的,半个小时前,一个push活动带来了很大的量,但现在流量已经过去了,需要定位当时的性能问题意味着需要采集到过去的数据。所以我们可能需要一个服务定期去监控这些数据。Spring Boot已经考虑到了这种情况,所以其中有一个prometheus的模块,他是一个独立的服务去采集其中的监控数据并可视化,具体的介绍可以参考:https://www.callicoder.com/spring-boot-actuator-metrics-monitoring-dashboard-prometheus-grafana/

以日志形式定期输出监控数据

很多时候,如果有日志的方法去定期输出监控的数据这样已经足够我们分析了。在Spring Boot 2.x里,只需要配置一个Bean

@Configuration
class MetricsConfig {
    @Bean
    LoggingMeterRegistry loggingMeterRegistry() {
        return new LoggingMeterRegistry();
    }
}

之所以需要Spring Boot版本2.x,LoggingMeterRegistry是因为是micrometer-core里面的1.10以上才引入的,而Spring Boot 1.x都低于这个版本,如果不想升级Spring Boot版本,可以尝试显示变更此版本:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-core</artifactId>
    <version>1.1.3</version>
</dependency>

最后日志的内容就会每一分钟的打印出来:

jvm.buffer.count{id=direct} value=26 buffers
jvm.buffer.count{id=mapped} value=0 buffers
jvm.buffer.memory.used{id=direct} value=632.600586 KiB
jvm.buffer.memory.used{id=mapped} value=0 B
jvm.buffer.total.capacity{id=direct} value=632.599609 KiB
jvm.buffer.total.capacity{id=mapped} value=0 B
jvm.classes.loaded{} value=12306 classes
jvm.gc.live.data.size{} value=39.339607 MiB
jvm.gc.max.data.size{} value=2.666992 GiB
jvm.memory.committed{area=nonheap,id=Compressed Class Space} value=8.539062 MiB
jvm.memory.committed{area=nonheap,id=Code Cache} value=26.8125 MiB
jvm.memory.committed{area=heap,id=PS Survivor Space} value=30 MiB
jvm.memory.committed{area=heap,id=PS Eden Space} value=416.5 MiB
jvm.memory.committed{area=heap,id=PS Old Gen} value=242 MiB
jvm.memory.committed{area=nonheap,id=Metaspace} value=66.773438 MiB
jvm.memory.max{area=heap,id=PS Survivor Space} value=30 MiB
jvm.memory.max{area=heap,id=PS Eden Space} value=1.272949 GiB
jvm.memory.max{area=heap,id=PS Old Gen} value=2.666992 GiB
jvm.memory.max{area=nonheap,id=Metaspace} value=-1 B
jvm.memory.max{area=nonheap,id=Compressed Class Space} value=1 GiB
jvm.memory.max{area=nonheap,id=Code Cache} value=240 MiB
jvm.memory.used{area=nonheap,id=Code Cache} value=26.635071 MiB
jvm.memory.used{area=heap,id=PS Survivor Space} value=25.214882 MiB
jvm.memory.used{area=heap,id=PS Eden Space} value=46.910545 MiB
jvm.memory.used{area=heap,id=PS Old Gen} value=39.34742 MiB
jvm.memory.used{area=nonheap,id=Metaspace} value=63.333778 MiB
jvm.memory.used{area=nonheap,id=Compressed Class Space} value=7.947166 MiB
jvm.threads.daemon{} value=52 threads
jvm.threads.live{} value=54 threads
jvm.threads.peak{} value=67 threads
jvm.threads.states{state=terminated} value=0 threads
jvm.threads.states{state=blocked} value=0 threads
jvm.threads.states{state=new} value=0 threads
jvm.threads.states{state=runnable} value=20 threads
jvm.threads.states{state=waiting} value=19 threads
jvm.threads.states{state=timed-waiting} value=15 threads
process.cpu.usage{} value=-1
process.start.time{} value=435900h 48m 53.344s
process.uptime{} value=56m 6.709s
system.cpu.count{} value=8
system.cpu.usage{} value=-1
tomcat.global.request.max{name=http-nio-10610} value=0.597s
tomcat.servlet.request.max{name=dispatcherServlet} value=0.567s
tomcat.sessions.active.current{} value=0 sessions
tomcat.sessions.active.max{} value=0 sessions
tomcat.threads.busy{name=http-nio-10610} value=0 threads
tomcat.threads.config.max{name=http-nio-10610} value=200 threads
tomcat.threads.current{name=http-nio-10610} value=10 threads

如果需要修改打印的频率,可修改LoggingRegistryConfig以更改其打印频率

//下面是单独的配置实现的参考,当需要修改配置时候可以使用
  return new LoggingMeterRegistry(new LoggingRegistryConfig() {
       @Override
     public Duration step() {
         return Duration.ofSeconds(10);//10秒输出一次
       }

       @Override
       public String get(String key) {
            return null;
       }
   }, Clock.SYSTEM);
}

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码