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

基于Quarkus+MongoDB场景收集存储HTTP请求数据的最佳实践咨询

Quarkus JAX-RS 请求日志采集存储到MongoDB 最佳实践

1. 全局拦截层选型

优先用JAX-RS标准的ContainerRequestFilter实现全局拦截,不要在业务接口代码里硬编码采集逻辑:

  • 给过滤器加@Provider、@PreMatching注解,保证所有请求(包括路由匹配失败的请求)都会被拦截到
  • 调整过滤器优先级为@Priority(Priorities.USER + 100),晚于鉴权等核心过滤器执行,避免采集逻辑影响核心流程
  • 所有采集、存储逻辑必须包裹独立的try-catch,异常仅打印本地日志,绝不向上抛出,避免日志采集故障导致业务请求失败

代码示例:

@Provider
@PreMatching
@Priority(Priorities.USER + 100)
public class RequestLogFilter implements ContainerRequestFilter {
    @Inject
    RequestLogService requestLogService;
    @Context
    HttpServletRequest httpServletRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        try {
            // 采集基础字段
            RequestLog log = new RequestLog();
            log.setMethod(requestContext.getMethod());
            log.setPath(requestContext.getUriInfo().getPath());
            // 采集IP,适配反向代理场景
            String xff = requestContext.getHeaderString("X-Forwarded-For");
            log.setAddress(xff != null ? xff.split(",")[0].trim() : httpServletRequest.getRemoteAddr());
            log.setHost(requestContext.getHeaderString("Host"));
            log.setUserAgent(requestContext.getHeaderString("User-Agent"));
            log.setRequestTime(LocalDateTime.now());
            
            // 采集请求体
            if (requestContext.hasEntity()) {
                // 包装请求流,避免读一次后业务层拿不到body
                byte[] bodyBytes = IOUtils.toByteArray(requestContext.getEntityStream());
                log.setBody(new String(bodyBytes, StandardCharsets.UTF_8));
                // 把流塞回请求上下文供业务层使用
                requestContext.setEntityStream(new ByteArrayInputStream(bodyBytes));
            }
            
            // 异步存库
            requestLogService.asyncSave(log);
        } catch (Exception e) {
            // 仅打本地日志,不影响业务请求处理
            log.error("请求日志采集失败", e);
        }
    }
}

2. 字段采集注意事项

  • 基础字段优先从请求上下文和请求头获取,IP采集要适配Nginx等反向代理场景,优先取X-Forwarded-For头的值
  • 请求体采集必须包装请求流,因为HTTP请求的输入流默认只能读取一次,直接读取会导致后续业务接口无法拿到请求参数
  • 可选补充字段:请求时间戳、链路追踪traceId、响应状态码、接口耗时,配套实现ContainerResponseFilter即可采集响应相关字段
  • 必须做敏感信息脱敏:请求体中的密码、手机号、身份证、支付信息等敏感字段,要替换为***后再存储,避免合规风险

3. MongoDB存储优化方案

  • 实体类直接继承Quarkus MongoDB Panache的PanacheMongoEntity,快速实现CRUD能力,请求体body字段根据业务需要选择存储为String或者Binary类型
  • 禁止同步写库:用Quarkus的@Async注解或者线程池异步提交存储任务,高并发场景下可以用本地队列缓冲,批量写入MongoDB,降低IO开销,避免拖慢接口响应速度
  • 索引优化:给requestTime、method、path、address等常用查询字段加索引,提升日志查询效率
  • 生命周期管理:给日志集合设置TTL索引,自动删除超过保留周期(比如30天)的日志,避免存储空间无限增长
  • 特殊场景过滤:文件上传接口跳过二进制内容采集,仅存文件名、大小等元数据;超过1M的超大请求体可做截断存储,避免占用过多存储资源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 23:09:03