打造Java可观测性的5个关键步骤

本文涉及的产品
应用实时监控服务-应用监控,每月50GB免费额度
应用实时监控服务-用户体验监控,每月100OCU免费额度
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 伴随云原生和微服务的普及,可观测性设计基本上是作为一个线上业务服务必备的基础能力。这篇文章我将介绍天罡项目围绕可观测性的三大支柱:日志,指标以及链路追踪所做的可观测性设计和实践,以及项目中实施可观测性的5个关键步骤。

作者:砧木 阿里云智能-基础产品事业部-块存储-平台服务研发

伴随云原生和微服务的普及,可观测性设计基本上是作为一个线上业务服务必备的基础能力。这篇文章我将介绍天罡项目围绕可观测性的三大支柱:日志,指标以及链路追踪所做的可观测性设计和实践,以及项目中实施可观测性的5个关键步骤。


本文中提供的例子,适用于Spring Boot 2.x版本


步骤一: 健康检查,还活着吗?

首先我们需要知道我们的应用实例是否还活着, 关于活着这件事情。 又可以细分为进程还在不在,如果进程在那应用实例是否能对外提供服务。 所以关于健康检查这件事情就可以分为:存活态(liveness)和就绪态(readiness)。就绪态又包含,应用自身服务的就绪以及必要依赖的外部组件的就绪状态。actuator内置了常见的如datasource, redis等常见外部依赖的依赖检查,对于未内置支持的外部依赖。可以通过自定义Healthlndicators的方式接入。

curl -Li http://localhost:8080/actuator/health
HTTP/1.1 200 
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Fri, 05 Nov 2021 03:37:54 GMT
{"status":"UP","components":{"db":{"status":"UP","details":{"database":"MySQL","validationQuery":"isValid()"}},"diskSpace":{"status":"UP","details":{"total":494384795648,"free":372947439616,"threshold":10485760,"exists":true}},"livenessState":{"status":"UP"},"ping":{"status":"UP"},"readinessState":{"status":"UP"}}}%

通过健康检查接口,无论是容器还是非容器环境,可以配合负载均衡或者kubernetes的探针,都可以实现对不可用实例流量的自动隔离。抛开spring boot框架来说,健康检查接口应该能够支持开发者或这外部系统快速判断存活与就绪状态。 没有涵盖到这两部分的健康检查都是耍流氓。此外这些数据还可以通过HTTP采集插件采集到SLS来设置告警。

步骤二: 监控指标,活得还好吗?

其次,当应用满足了活着这个基本条件以后,我们就需要知道我们的应用到底活着怎么样, 好不好,有没有潜在风险。对人来说如何评估你的活的好不好,就的看你所处的社会大环境好不好,家里还有没有余粮,以及你自己身体的机能状态。对应用也一样,以Java为例,首先是应用所在环境主机或者容器的物理资源情况。CPU,内存,磁盘,网络这几大基础件,其次是JVM相关的运行指标,最后再是应用自身的业务相关指标。


对于主机监控,天罡使用了Logtail内置的主机监控能力,并存储到SLS的时序存储中。除了主机监控以外,JVM以及应用业务指标监控则采用了prometheus规范。通过集成micrometer,默认即可输出JVM的相关监控指标。而对于spring-boot不支持的监控指标,如druid的数据库连接池状态,http client连接池的状态则通过自定义Metrics的方式进行统一采集。而为了让各个服务有统一的监控指标体系,这些常用组件的metrics则通过spring-starter二方库的形式进行管理,对于已有服务和新的服务可以无缝集成统一的监控指标体系。而对于业务类型的指标,自定义Metrics的方式同样适用。

curl -Li http://localhost:8080/actuator/prometheus
HTTP/1.1 200
Content-Type: text/plain; version=0.0.4;charset=utf-8
Content-Length: 13244
Date: Fri, 05 Nov 2021 06:32:31 GMT
# HELP jdbc_connections_active Current number of active connections that have been allocated from the data source.
# TYPE jdbc_connections_active gauge
jdbc_connections_active{app="aliyun-center",name="dataSource",source="30.1.1.1",} 0.0
# HELP jvm_gc_max_data_size_bytes Max size of long-lived heap memory pool
# TYPE jvm_gc_max_data_size_bytes gauge
jvm_gc_max_data_size_bytes{app="aliyun-center",source="30.1.1.1",} 2.863661056E9
# HELP jdbc_connections_max Maximum number of active connections that can be allocated at the same time.
# TYPE jdbc_connections_max gauge
jdbc_connections_max{app="aliyun-center",name="dataSource",source="30.1.1.1",} 8.0
# HELP process_cpu_usage The "recent cpu usage" for the Java Virtual Machine process
# TYPE process_cpu_usage gauge
process_cpu_usage{app="aliyun-center",source="30.1.1.1",} 0.0012296864771536287
# HELP system_load_average_1m The sum of the number of runnable entities queued to available processors and the number of runnable entities running on the available processors averaged over a period of time
# TYPE system_load_average_1m gauge
system_load_average_1m{app="aliyun-center",source="30.1.1.1",} 3.7958984375

而对于应用监控指标的采集和存储,新版的Logtail组件内置了prometheus监控指标的采集能力,操作参考通过Logtail插件接入Prometheus监控数据

步骤三: 链路追踪,有迹可循

不过即使注意了日常健康保养,小灾小病也不可避免,假如你有点不舒服,表现出来可能是脑袋疼,但是实际上可能是一连串连锁反应后的结果。 链路追踪就是为了让我们能够在不舒服的时候能够以最快的速度排出杂音,迅速缩小问题范围。


在天罡中,我们采用skywalking agent采集上报链路数据,具体安装和配置可以参考:通过SkyWalking上报Java应用数据

skywalking会为每一个请求生成一个唯一的trace id. 通过trace id可以查看整个完整的调用链路,并且可以快速确定问题实际的产生位置。


通常来说云产品的所有调用都是通过POP API进行接入,用户反馈问题时通常会提供报错时反馈的RequestId信息。而如何通过RequestId快速查找调用链路,或者通过调用链路找到RequestId. 这就是接下来日志相关性所要解决的问题。

步骤四: 日志相关性,有理可循

最后我们的应用是一个时刻运行的系统,这个系统每时每秒都在以日志的形式记录着它的运行状态和运行时信息,当发现问题时,我们能够根据这些运行记录定位到根因,为了能够找到真正有用的信息。 这时就需要我们的日志具有相关性,能够关联到某个特定的事件或者流程,因此搜集日志是其一(通常是外部运维环境决定),能够找到相关性日志则是更重要的点。


首先是RequestId, 借用logback的MDC机制,我们只需要在适当的位置,在MDC中注入request id.即可确保当前请求所产生的日志具有固定的标识:

@OverridepublicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler)
throwsException {
StringrequestId=request.getHeader(TBS_REQUEST_ID);
if (!Strings.isNullOrEmpty(requestId)) {
MDC.put("requestID", requestId);
    }
returntrue;
}


而skywalking本身内置了与logback的集成,可以自动往MDC中注入traceId信息。引入依赖即可:

<dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version>8.5.0</version></dependency>


并在logback配置中,打印即可:

<propertyname="FILE_LOG_PATTERN"value="[%X{tid}] %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%X{requestID}] %logger{36}:%line [%thread] - %msg%n"/><!--省略的其--><encoderclass="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layoutclass="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"><pattern>${LOG_PATTERN}</pattern></layout></encoder>


通过日志相关性配置后,我们既可以通过主动发现慢请求链路,通过trace id找到相关的日志记录,进行主动的问题分析。 也可以在线上问题排查是根据RequestId找到调用链路,定界问题,并找到相关的日志进行分析。

链路关联日志

日志关联链路


步骤五: 可视化,看见变化

到目前为止,关于可观测性,我们在应用中内置了健康检查接口,prometheus的metrics接口以及skywalking agent。 同时通过日志相关性策略,将业务,链路进行关联,帮助我们快速定位和分析问题。 那可观测性最后的一步当然是构建我们的可视化Dashboard了。而SLS时序存储提供标准的Prometheus接口,因此我们可以直接将SLS时序存储作为Prometheus数据源加入到Grafana中,并通过 Grafana进行可视化。

Dashboard本身也应该是持续迭代和演进的,因此本着万物皆可as code的原则,我们使用git来管理我们的可视化大盘。

.
├── README.md
├── docker-compose.yaml
└── grafana
    ├── config.monitoring
    ├── dashboards
    │   ├── app
    │   │   └── jvm-micrometer.json # jvm监控打包
    │   └── server
    │       └── hosts.json # 主机监控大盘
    └── provisioning # 初始化
        ├── dashboards
        │   └── dashboard.yaml # dashboard配置
        └── datasources
            └── datasource.yaml # 数据源配置


小结

可观测性,有如一把钥匙,让我们打开了应用的黑盒子,让我们可以时刻了解我们应用自身的运行情况。同时通过外在表现(监控指标)与内部状态(链路和日志)帮助我们更快的定位和分析问题。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
目录
相关文章
|
设计模式 算法 Java
JAVA设计模式13:模版方法模式,将一些步骤延迟到子类中实现
JAVA设计模式13:模版方法模式,将一些步骤延迟到子类中实现
|
3月前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
27天前
|
SQL 安全 前端开发
对于Java代码审计,主要的审计步骤如下:
### Java代码审计简介 Java代码审计是确保应用程序安全的重要步骤,主要包括以下几个关键环节: 1. **确定项目结构与技术框架**:了解项目的整体架构和技术栈。 2. **环境搭建**:配置开发环境,确保能够正常运行项目。 3. **配置文件分析**:重点分析`pom.xml`、`web.xml`等配置文件,特别是依赖组件的版本是否存在已知漏洞。
|
28天前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
52 2
|
28天前
|
前端开发 NoSQL Java
【Java若依框架】RuoYi-Vue的前端和后端配置步骤和启动步骤
本文介绍了如何配置和启动基于Java的若依(RuoYi)项目,涵盖后端和前端的详细步骤。首先,准备Redis、MySQL以及IDE(如Idea和VS)。接着,通过GitHub获取代码并导入到IDE中,执行必要的SQL文件和配置数据库密码。然后,启动Redis并进行相关配置。最后,按照前端配置步骤克隆前端代码库,打开终端执行命令完成前端配置。整个过程详细记录了每一步的操作,帮助开发者顺利部署若依项目。 如果你觉得有帮助,请点赞、关注和收藏,这将是我持续分享的动力!
283 1
|
3月前
|
数据采集 Java API
java怎么设置代理ip:简单步骤,实现高效网络请求
本文介绍了在Java中设置代理IP的方法,包括使用系统属性设置HTTP和HTTPS代理、在URL连接中设置代理、设置身份验证代理,以及使用第三方库如Apache HttpClient进行更复杂的代理配置。这些方法有助于提高网络请求的安全性和灵活性。
110 0
|
4月前
|
运维 监控 搜索推荐
阿里大鱼进行发短信业务---使用详细步骤-Java操作
这篇文章详细介绍了如何在Java中使用阿里大鱼服务来发送短信,包括开通短信服务、签名和模板管理,以及具体的Java开发步骤和代码示例。
205 0
阿里大鱼进行发短信业务---使用详细步骤-Java操作
|
6月前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
6月前
|
消息中间件 缓存 监控
JAVA服务可观测性最佳实践
在实现这些最佳实践时,需考虑到服务的规模、复杂度和所处环境。通过持续地优化和调整可观测性策略,可以大大提高服务的可靠性和性能,减少系统故障时间,提升用户满意度。
86 2
|
6月前
|
缓存 NoSQL Java
【Azure Redis 缓存】定位Java Spring Boot 使用 Jedis 或 Lettuce 无法连接到 Redis的网络连通性步骤
【Azure Redis 缓存】定位Java Spring Boot 使用 Jedis 或 Lettuce 无法连接到 Redis的网络连通性步骤
103 0