You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何拦截Java应用的指定REST API调用并开展性能分析?

Java应用REST API调用监控与性能统计实现思路

一、统一拦截目标REST请求的方案

由于应用混用Apache和Google两种REST客户端,需针对性实现拦截逻辑,或采用全局代理方式统一处理:

1. 针对各客户端的拦截器实现

Apache HttpClient拦截

自定义请求/响应拦截器,在请求发送前记录时间戳,响应返回后计算耗时并过滤目标URL:

public class TimingInterceptor implements HttpRequestInterceptor, HttpResponseInterceptor {
    private static final ThreadLocal<Long> START_TIME = new ThreadLocal<>();

    @Override
    public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
        String url = ((HttpRequestWrapper) request).getOriginal().getRequestLine().getUri();
        if (url.startsWith("https://test/api/v2/")) {
            START_TIME.set(System.currentTimeMillis());
        }
    }

    @Override
    public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
        Long startTime = START_TIME.get();
        if (startTime != null) {
            long elapsed = System.currentTimeMillis() - startTime;
            String url = ((HttpRequestWrapper) context.getAttribute(HttpCoreContext.HTTP_REQUEST)).getOriginal().getRequestLine().getUri();
            StatsCollector.record(url, elapsed);
            START_TIME.remove();
        }
    }
}

将拦截器注入HttpClient实例:

CloseableHttpClient httpClient = HttpClients.custom()
    .addInterceptorFirst(new TimingInterceptor())
    .build();

Google HTTP Client拦截

通过自定义HttpRequestInitializer添加执行拦截器,实现耗时统计:

public class GoogleClientTimingInterceptor implements HttpRequestInitializer {
    @Override
    public void initialize(HttpRequest request) throws IOException {
        request.setInterceptor(new HttpExecuteInterceptor() {
            private long startTime;

            @Override
            public void intercept(HttpRequest request) throws IOException {
                String url = request.getUrl().toString();
                if (url.startsWith("https://test/api/v2/")) {
                    startTime = System.currentTimeMillis();
                }
            }

            @Override
            public void intercept(HttpRequest request, HttpResponse response) throws IOException {
                String url = request.getUrl().toString();
                if (url.startsWith("https://test/api/v2/")) {
                    long elapsed = System.currentTimeMillis() - startTime;
                    StatsCollector.record(url, elapsed);
                }
            }
        });
    }
}

创建Google客户端时注入初始化器:

HttpRequestFactory requestFactory = new HttpRequestFactoryBuilder()
    .setHttpRequestInitializer(new GoogleClientTimingInterceptor())
    .build();

2. 全局代理拦截方案

若不想修改业务客户端代码,可搭建本地代理服务器,强制所有REST请求通过代理转发,在代理层统一拦截统计。例如用Java实现轻量代理,监听本地端口,转发请求至目标服务器的同时记录URL和耗时。此方式无需侵入业务代码,适配多客户端场景。

二、API请求统计与聚合

实现一个线程安全的统计组件,完成数据收集与聚合:

  • 路径归一化:用正则或Ant匹配规则将带参数的URL归一化为模板(如将https://test/api/v2/accounts/123映射为/accounts/{accountId}),确保同类型请求被归类统计。
  • 统计维度:针对每个API模板,收集总调用次数、总耗时、平均耗时、最大/最小耗时,可将数据存储在内存(ConcurrentHashMap)或时序数据库(如InfluxDB)中。

示例统计组件核心逻辑:

public class StatsCollector {
    private static final Map<String, ApiStats> STATS_MAP = new ConcurrentHashMap<>();

    public static void record(String url, long elapsed) {
        String template = normalizeUrl(url);
        STATS_MAP.compute(template, (key, stats) -> {
            if (stats == null) {
                stats = new ApiStats();
            }
            stats.incrementCount();
            stats.addTotalTime(elapsed);
            stats.updateMinMax(elapsed);
            return stats;
        });
    }

    private static String normalizeUrl(String url) {
        // 正则替换accountId为占位符
        return url.replaceAll("https://test/api/v2/accounts/\\d+", "https://test/api/v2/accounts/{accountId}");
    }

    // ApiStats实体类:包含count、totalTime、minTime、maxTime等字段
}

三、可视化数据生成

  • 实时仪表盘:基于Spring Boot + Thymeleaf或Java Swing开发简易面板,展示各API的统计数据(如总耗时占比、调用次数)。
  • 离线分析报表:将统计数据导出为CSV,用Excel或Python的Matplotlib生成柱状图、饼图,直观展示不同API的耗时分布(如批量获取账户ID耗时3分钟、明细查询耗时48分钟的对比)。
  • 时序可视化:若使用时序数据库,可集成Grafana搭建监控面板,展示API耗时随时间的变化趋势。

四、关键注意事项

  • 性能损耗控制:拦截器逻辑需精简,避免在拦截流程中执行重操作,降低对业务请求的影响。
  • 线程安全保障:统计组件需使用线程安全的数据结构(如ConcurrentHashMap)或原子类,避免并发统计错误。
  • 配置灵活性:将监控的API前缀配置化(如存入properties文件),无需修改代码即可调整监控范围。

内容的提问来源于stack exchange,提问作者Prasad Parab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:27:47