18、深入探索 MicroProfile Metrics:从入门到应用

深入探索 MicroProfile Metrics:从入门到应用

1. 开启 MicroProfile Metrics 之旅

在开始使用 MicroProfile Metrics 之前,我们需要完成服务的部署。通过以下命令将服务部署到 Kubernetes:

mvn clean package -DskipTests -Dquarkus.kubernetes.deploy=true    
cd ../transaction-service
mvn clean package -DskipTests -Dquarkus.kubernetes.deploy=true    

部署完成后,查看仪表盘,大约 15 到 30 秒内,“Used Heap” 面板会更新每个服务使用的 JVM 堆信息。需要注意的是,此时只有 JVM Used Heap 面板会更新,其他面板将随着后续对服务进行指标检测而更新。

2. 理解 MicroProfile Metrics

Java 平台自 JDK 5 起就引入了 Java Management Extensions(JMX),但它无法满足现代企业级 Java 应用的指标需求。例如,JMX API 较为复杂,且在 Java 平台引入注解之前就已创建。此外,JMX 既不暴露指标元数据,也不以现代云友好的格式展示指标。为了解决这些问题,MicroProfile 社区创建了 MicroProfile Metrics。

2.1 输出格式

MicroProfile Metrics 要求实现支持两种输出格式:
- OpenMetrics 格式 :这是由云原生计算基金会(CNCF)定义的标准文本格式,当 HTTP 接受头为 text/plain 时,它是 MicroProfile Metrics 的默认输出格式。示例如下:

# HELP base_classloader_loadedClasses_count Displays the number of classes  
that are currently loaded in the Java virtual machine.
# TYPE base_classloader_loadedClasses_count gauge     
base_classloader_loadedClasses_count 13010.0       

可以使用以下 curl 命令查看特定指标:

curl -i localhost:8080/q/metrics/base/classloader.loadedClasses.count   
  • JSON 格式 :通过设置 application/json 的 HTTP 请求头,可以获取 JSON 格式的指标输出。示例代码如下:
curl -i \
     -H "Accept:application/json" \
     localhost:8080/q/metrics

JSON 格式的示例输出:

{      
    "base": {                             
        "cpu.systemLoadAverage": 2.1865234375,
        "thread.count": 60,                       
        "classloader.loadedClasses.count": 9667,
        ...
    },
    "vendor": {          
    ...
    },
    "application": {     
    ...
    }
}

需要注意的是,JSON 格式不包含 OpenMetrics 格式中的 TYPE 和 HELP 元数据,它更侧重于高效的机器可读格式。由于 OpenMetrics 是一种标准格式,便于后续被 Prometheus 等工具使用,因此本文重点关注 OpenMetrics 输出。

2.2 命名约定

MicroProfile Metrics 遵循特定的命名约定: <scope>.<class>.<method>.<name> 。具体说明如下表:
| 约定 | 描述 |
| ---- | ---- |
| Scope | 必须是 base vendor application ,后续会详细解释 |
| Class | 注解应用的包和类名 |
| Method | 注解应用的方法 |
| Name | 指标的名称,如 classloader.loadedClasses.count |

2.3 指标范围

MicroProfile 将指标分为以下三个范围:
| 范围 | 描述 |
| ---- | ---- |
| Base | 所有 MicroProfile Metrics 实现都需要的指标,例如 base_thread_count 指标可显示运行应用程序进程中的活动线程数,这些指标在不同实现之间具有可移植性 |
| Vendor | 特定于运行时的指标,不具有跨实现的可移植性。例如,Quarkus 特定的 vendor_cpu_processCpuTime_seconds 指标可显示应用程序进程使用的 CPU 时间。随着应用程序使用的扩展数量增加,可用指标的数量也会增加 |
| Application | 由应用程序定义或代表应用程序定义的指标 |

可以通过在指标 URL 后附加范围来直接查询特定范围的指标。例如,请求 base 指标的命令如下:

curl -i localhost:8080/q/metrics/base
2.4 支持的指标类型

MicroProfile Metrics 支持多种常用的指标类型,如下表所示:
| 指标 | 注解 | 描述 |
| ---- | ---- | ---- |
| Counter | @Counter | 单调递增的数值 |
| Concurrent gauge | @ConcurrentGauge | 递增或递减的值 |
| Gauge | @Gauge | 采样以获取当前值的指标 |
| Meter | @Metered | 跟踪平均吞吐量以及 1、5 和 15 分钟的指数加权移动平均吞吐量 |
| Metric | @Metric | 不是一种指标类型,而是一个注解,用于在请求注入或生成指标时包含元数据信息 |
| Histogram | N/A | 计算值的分布 |
| Timer | @Timed | 聚合计时持续时间,提供持续时间统计和吞吐量统计 |

指标注解接受多个参数,具体说明如下表:
| 指标字段 | 描述 |
| ---- | ---- |
| name | 可选,设置指标的名称。如果未明确指定,则使用注解对象的名称 |
| absolute | 如果为 true ,则使用给定的名称作为指标的绝对名称;如果为 false ,则在给定名称前添加包名和类名。默认值为 false |
| displayName | 可选,用于元数据的人类可读显示名称,方便第三方工具使用 |
| description | 可选,指标的描述,对第三方工具很有用 |
| unit | 指标的单位,如千兆字节、纳秒和百分比等。可以查看 MetricUnits 类获取预定义的单位 |
| tags | 键值对列表,后续会详细介绍 |

3. 为账户服务添加指标

一个有用的起点是统计 ExceptionMapper 被调用的次数。基于这个统计结果,或许可以改进前端 Web UI 或增强 API。可以使用 Counter 指标来统计 ExceptionMapper 的调用次数,示例代码如下:

@Provider
public static class ErrorMapper implements ExceptionMapper<Exception> {
  @Metric(       
    name = "ErrorMapperCounter",   
    description = "Number of times the AccountResource ErrorMapper is invoked"
  )
  Counter errorMapperCounter;    
    @Override
    public Response toResponse(Exception exception) {
      errorMapperCounter.inc();          
      ...
  }
}

通过调用带有无效值的端点可以增加计数器的值。例如,使用以下命令传递无效的账户号码来调用 ErrorMapper

curl -i localhost:8080/accounts/234/balance

为了验证计数器是否增加以及计数器元数据是否可用,可以运行以下命令:

curl localhost:8080/q/metrics | grep ErrorMapper     
4. 为交易服务添加指标

MicroProfile Metrics 将指标及其元数据存储在 MetricRegistry 中,每个范围( base vendor application )都有一个指标注册表。开发者创建的自定义指标存储在 application 范围中。通过唯一的 MetricID (由指标名称和可选的标签列表组成)可以在 MetricRegistry 中标识一个指标。

4.1 使用标签跟踪回退情况

TransactionServiceFallbackHandler.java 为例,它将 Java 异常映射到 HTTP 响应代码。我们可以使用标签来跟踪回退情况,示例代码如下:

public class TransactionServiceFallbackHandler implements 
FallbackHandler<Response> {
    @Inject
    @RegistryType(type = MetricRegistry.Type.APPLICATION)      
    MetricRegistry metricRegistry;                         
    @Override
    public Response handle(ExecutionContext context) {
        Logger LOG = 
Logger.getLogger(TransactionServiceFallbackHandler.class);
        Response response;
        String name;
        if (context.getFailure().getCause() == null) {
            name = context.getFailure().getClass().getSimpleName();
        } else {
            name = context.getFailure().getCause().getClass().getSimpleName();
        }
        switch (name) {
        case "BulkheadException":
            response = Response.status(Response.Status.TOO_MANY_REQUESTS)
                    .build();
            break;
        case "TimeoutException":
            response = Response.status(Response.Status.GATEWAY_TIMEOUT)
                    .build();
            break;
        case "CircuitBreakerOpenException":
        case "ConnectTimeoutException":
        case "SocketException":
            response = Response.status(Response.Status.SERVICE_UNAVAILABLE)
                    .build();
            break;
        case "ResteasyWebApplicationException":
        case "WebApplicationException":
        case "HttpHostConnectException":
            response = Response.status(Response.Status.BAD_GATEWAY)
                    .build();
            break;
        default:
            response = 
Response.status(Response.Status.NOT_IMPLEMENTED).build();
        }
        metricRegistry.counter("fallback",    
              new Tag("http_status_code",           
                      "" + response.getStatus()))   
              .inc();    
        LOG.info("******** " + context.getMethod().getName() + ": " + name + " 
********");
        return response;
    }
}

为了测试回退计数器,可以运行以下命令:

metrics/scripts/overload_bulkhead.sh      

脚本执行完成后,运行以下命令查看指标输出:

export TRANSACTION_URL=http:/ /localhost:8088    
curl -i -s $TRANSACTION_URL/q/metrics/application | grep -i fallback_total  
4.2 使用 @Timed 注解跟踪性能

为了跟踪回退处理程序的性能,可以在 TransactionServiceFallbackHandler.handle() 方法上添加 @Timed 注解,示例代码如下:

public class TransactionServiceFallbackHandler
       implements FallbackHandler<Response> {
    @Inject
    @RegistryType(type = MetricRegistry.Type.APPLICATION)
    MetricRegistry metricRegistry;
    @Timed(                            
        name = "fallbackHandlerTimer",      
        displayName = "Fallback Handler Timer",   
        description = "Time spent handling fallbacks",    
        absolute = true,                     
        unit=MetricUnits.NANOSECONDS    
    )
    @Override
    public Response handle(ExecutionContext context) {
       ...
    }
    ...

重新部署应用程序后,再次运行 metrics/scripts/force_multiple_fallbacks.sh 脚本。仪表盘上的“Transaction Service Fallback Call Rate Rolling One Minute Average” 仪表将显示 application_fallbackHandlerTimer_one_min_rate_per_second 指标的值,即过去一分钟内方法调用的速率。

4.3 使用 @ConcurrentGauge 跟踪并发请求

另一种监控性能的方法是跟踪方法上的并发请求。可以通过添加 @ConcurrentGauge 注解来实现这一点,以满足服务级别协议(SLA)的要求。

通过以上步骤,我们可以全面地为微服务添加指标,从而更好地监控和优化服务的性能。

深入探索 MicroProfile Metrics:从入门到应用

5. 指标监控实战

在前面的部分,我们已经为账户服务和交易服务添加了指标。接下来,我们将通过一些实际操作,深入了解如何利用这些指标进行监控和分析。

5.1 生成故障并查看指标

为了测试回退计数器和相关指标,我们可以运行以下命令生成故障:

metrics/scripts/force_multiple_fallbacks.sh

该脚本会执行一系列操作,包括:
1. 发送一些请求,部分请求会成功执行,部分请求会超过并发请求限制(Bulkhead 限制)。
2. 将账户服务缩容以触发断路器。
3. 在断路器触发前向已关闭的服务发送请求。
4. 再将账户服务扩容到一个实例并等待其启动。
5. 服务启动后生成更多请求。

脚本执行的输出示例如下:

HTTP/1.1 200 OK        
Content-Length: 0
HTTP/1.1 429 Too Many Requests      
Content-Length: 0
HTTP/1.1 429 Too Many Requests
Content-Length: 0
HTTP/1.1 200 OK
Content-Length: 0
...
******* DISABLING ACCOUNT SERVICE ******
deployment.apps/account-service scaled     
HTTP/1.1 200 OK
Content-Length: 0
HTTP/1.1 502 Bad Gateway     
Content-Length: 0
HTTP/1.1 503 Service Unavailable     
Content-Length: 0
...
"******* RESTARTING ACCOUNT SERVICE ******"
deployment.apps/account-service scaled    
Waiting for container to start
Waiting for container to start
HTTP/1.1 200 OK          
Content-Length: 0

脚本执行完成后,我们可以通过以下命令查看指标输出:

export TRANSACTION_URL=http://localhost:8088    
curl -i -s $TRANSACTION_URL/q/metrics/application | grep -i fallback_total  

输出示例如下:

# TYPE application_fallback_total counter
application_fallback_total{http_status_code="429"} 290.0    

这表明在测试过程中,HTTP 状态码为 429(TOO_MANY_REQUESTS)的回退次数为 290 次。

5.2 重新部署服务

如果需要重新部署交易服务到 Minikube,可以使用以下命令:

mvn clean package -DskipTests -Dquarkus.kubernetes.deploy=true

需要注意的是,在 Quarkus 2.x 中,如果尝试使用 mvn package -Dquarkus.kubernetes.deploy=true 重新部署已经存在于 Kubernetes 中的应用程序,可能会导致错误。可以通过先使用 kubectl delete -f /target/kubernetes/minikube.yaml 删除应用程序来解决这个问题。

6. 指标可视化

指标可视化可以帮助我们更直观地了解服务的性能和健康状况。Grafana 是一个常用的指标可视化工具,我们可以在 Grafana 中查看和分析我们添加的指标。

6.1 查看 JVM 堆使用情况

部署完成后,打开 Grafana 仪表盘,大约 15 到 30 秒内,“Used Heap” 面板会更新每个服务使用的 JVM 堆信息。该面板的图形主体显示每个服务的使用堆大小,大约在 5 MB 到 45 MB 之间,具体取决于垃圾回收的时间。图形标题显示相关信息,图例显示交易服务和账户服务,每个服务的值是所有运行服务实例的平均值。

6.2 查看回退指标

通过运行 metrics/scripts/force_multiple_fallbacks.sh 脚本生成故障后,Grafana 仪表盘会相应更新。可以查看“Transaction Service Fallback Call Rate Rolling One Minute Average” 仪表,该仪表显示 application_fallbackHandlerTimer_one_min_rate_per_second 指标的值,即过去一分钟内方法调用的速率。

以下是一个简单的 mermaid 流程图,展示了指标监控和可视化的流程:

graph LR
    A[部署服务] --> B[添加指标]
    B --> C[生成故障]
    C --> D[查看指标输出]
    D --> E[重新部署服务]
    E --> F[指标可视化]
7. 总结与建议

通过本文的介绍,我们了解了 MicroProfile Metrics 的基本概念、输出格式、命名约定、指标范围、支持的指标类型等内容,并通过实际操作演示了如何为账户服务和交易服务添加指标,以及如何进行指标监控和可视化。

为了更好地使用 MicroProfile Metrics,以下是一些建议:
1. 合理选择指标类型 :根据实际需求选择合适的指标类型,如 Counter 用于统计次数, Timer 用于跟踪性能等。
2. 使用标签 :标签可以为指标添加额外的维度,方便进行更细致的分析和查询。
3. 定期监控和分析 :定期查看指标数据,及时发现潜在的问题并进行优化。
4. 结合可视化工具 :使用 Grafana 等可视化工具,将指标数据以直观的图表形式展示,便于理解和决策。

通过以上方法,可以有效地利用 MicroProfile Metrics 监控和优化微服务的性能,提高系统的稳定性和可靠性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值