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

如何让多个WireMock实例共享同一请求日志(Journal)

解决WireMock多实例共享请求日志的方案

针对你在带负载均衡的可扩展环境中使用spring-cloud-contract-wiremock时遇到的请求日志验证问题,以下是几种可行的解决方案:

1. 自定义请求日志存储实现

WireMock的请求日志(Request Journal)默认使用内存存储InMemoryRequestJournal,但它提供了可扩展的接口RequestJournal,你可以自行实现该接口,将请求数据持久化到共享存储(数据库或共享文件系统)。

实现步骤:

  • 实现RequestJournal接口,核心是重写record(记录请求)、getRequests(查询请求)和reset(清空日志)方法,将请求序列化为JSON后写入共享存储,查询时再反序列化返回。
  • 在Spring配置中替换默认的日志实现,指定自定义的RequestJournal实例。

示例代码(基于数据库存储):

public class DbBackedRequestJournal implements RequestJournal {
    private final JdbcTemplate jdbcTemplate;

    public DbBackedRequestJournal(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
        // 初始化请求日志表(首次运行时执行)
        jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS wiremock_requests (" +
                "id BIGINT AUTO_INCREMENT PRIMARY KEY," +
                "request_json TEXT NOT NULL," +
                "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
    }

    @Override
    public void record(Request request) {
        String requestJson = Json.write(request);
        jdbcTemplate.update("INSERT INTO wiremock_requests (request_json) VALUES (?)", requestJson);
    }

    @Override
    public List<LoggedRequest> getRequests() {
        return jdbcTemplate.query("SELECT request_json FROM wiremock_requests ORDER BY created_at DESC",
                (rs, rowNum) -> Json.read(rs.getString("request_json"), LoggedRequest.class));
    }

    @Override
    public void reset() {
        jdbcTemplate.update("TRUNCATE TABLE wiremock_requests");
    }

    // 实现接口其他默认方法
    @Override
    public List<LoggedRequest> find(RequestPattern requestPattern) {
        return getRequests().stream()
                .filter(request -> requestPattern.match(request).isExactMatch())
                .collect(Collectors.toList());
    }
}

Spring配置整合:

@Bean
public WireMockServer wireMockServer(DataSource dataSource) {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    return new WireMockServer(wireMockConfig()
            .port(8080)
            .requestJournal(new DbBackedRequestJournal(jdbcTemplate)));
}

2. 统一请求收集代理

在负载均衡器与WireMock实例之间添加一层轻量代理,所有请求先经过代理,由代理负责将请求日志写入共享存储,再转发请求到WireMock实例。验证时直接从代理的共享存储中查询日志即可。

这种方式无需修改WireMock代码,适合快速落地:

  • 可以用Nginx配置日志模块,将请求日志写入共享文件系统;
  • 也可以自定义一个Spring Boot代理服务,在转发请求的同时记录请求到数据库或Redis。

3. 分布式查询验证逻辑

如果不想修改存储实现,可以调整测试验证逻辑,通过服务发现获取所有WireMock实例的地址,逐个查询实例的请求日志接口/__admin/requests,汇总结果后验证请求是否存在。

示例代码:

// 从服务发现获取所有WireMock实例地址
List<String> wireMockInstances = serviceDiscovery.getInstances("wiremock-service")
        .stream()
        .map(instance -> instance.getUri().toString())
        .collect(Collectors.toList());

String testRequestId = "unique-test-123"; // 测试请求中携带的唯一标识(比如X-Test-Id头)
boolean requestProcessed = false;

RestTemplate restTemplate = new RestTemplate();
for (String instanceUrl : wireMockInstances) {
    String requestUrl = instanceUrl + "/__admin/requests?headers.X-Test-Id=" + testRequestId;
    ResponseEntity<List<Map>> response = restTemplate.getForEntity(requestUrl, List.class);
    if (!response.getBody().isEmpty()) {
        requestProcessed = true;
        break;
    }
}

// 断言请求已被处理
assertTrue(requestProcessed);

4. 使用WireMock扩展插件

部分第三方扩展插件支持将请求日志存储到Redis等分布式存储中,你可以根据spring-cloud-contract-wiremock的版本选择兼容的插件,直接集成使用,无需自行实现存储逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 03:22:56