Spring Boot集成Couchbase集成测试超时问题求助
Couchbase集成测试超时问题排查与解决
问题背景
具备丰富Spring Boot开发经验,刚接触Couchbase,编写Repository、实体类、测试用例及配置后,执行测试时触发AmbiguousTimeoutException,错误详情包含COLLECTION_MAP_REFRESH_IN_PROGRESS提示。
代码与配置详情
Repository代码
import entity.Building; import org.springframework.data.couchbase.repository.Collection; import org.springframework.data.couchbase.repository.CouchbaseRepository; @Collection("buildings") public interface BuildingRepository extends CouchbaseRepository<Building, String> { }
Building实体类代码
@Document public class Building { @Id @GeneratedValue(strategy = GenerationStrategy.UNIQUE) private String id; @Field @NotNull private String erf; @Field @NotNull private String name; @Field @NotNull private Address address; @CreatedBy private String creator; @LastModifiedBy private String lastModifiedBy; @LastModifiedDate private LocalDateTime lastModification; @CreatedDate private LocalDateTime creationDate; @Version private long version; }
测试用例代码
@SpringBootTest @Testcontainers @ActiveProfiles({"test"}) @AutoConfigureMockMvc public class RetrieveBuildingTest { @Container private static final CouchbaseContainer COUCHBASE = new CouchbaseContainer( DockerImageName.parse("couchbase/server:7.1.2")).withBucket(new BucketDefinition("buildings").withPrimaryIndex(true)); @Autowired private MockMvc mvc; @Test public void testLifecycleForBuildings() throws Exception { final ClassPathResource resource = new ClassPathResource("payloads/successful-create-building.json"); final String payload = Files.readString(Path.of(resource.getURI())); // save mvc.perform(post("/building") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .content(payload)) .andExpect(status().isOk()) .andExpect(jsonPath("$.name", is("Knightsbridge Mansion"))); // retrieval all mvc.perform(get("/building")) .andExpect(status().isOk()) .andExpect(jsonPath("$.totalElements", is(1))); // retrieve specific building by id } @DynamicPropertySource public static void register(final DynamicPropertyRegistry register) { register.add("spring.couchbase.connection-string", COUCHBASE::getConnectionString); register.add("spring.couchbase.username", COUCHBASE::getUsername); register.add("spring.couchbase.password", COUCHBASE::getPassword); } }
application.properties配置
spring.data.couchbase.bucket-name=buildings spring.couchbase.env.timeouts.connect=30 spring.couchbase.env.timeouts.key-value-durable=30
核心错误信息
Caused by: com.couchbase.client.core.error.AmbiguousTimeoutException: InsertRequest, Reason: TIMEOUT {"cancelled":true,"completed":true,"coreId":"0xf0d3d25700000001","idempotent":false,"lastChannelId":"F0D3D25700000001/0000000058CD068A","lastDispatchedFrom":"127.0.0.1:38858","lastDispatchedTo":"localhost:49158","reason":"TIMEOUT","requestId":5,"requestType":"InsertRequest","retried":14,"retryReasons":["COLLECTION_MAP_REFRESH_IN_PROGRESS"],"service":{"bucket":"buildings","collection":"buildings","documentId":"54b991d2-fa8b-41eb-9b1e-d5519914e964","opaque":"0x15","scope":"_default","type":"kv","vbucket":233},"timeoutMs":2500,"timings":{"encodingMicros":5785,"totalMicros":2512314}}
解决方案
1. 确保目标Collection存在
报错中的COLLECTION_MAP_REFRESH_IN_PROGRESS说明客户端无法找到指定的buildings集合。Couchbase 7.x创建Bucket后,默认仅存在_default集合,不会自动生成自定义集合。
两种解决方式任选其一:
- 删除Repository上的
@Collection("buildings")注解,使用默认的_default集合。 - 在测试容器初始化时主动创建
buildings集合,修改容器配置:
注意:需保持命令中的用户名、密码与测试容器默认值(Administrator/password)一致,若有自定义配置需同步修改。@Container private static final CouchbaseContainer COUCHBASE = new CouchbaseContainer( DockerImageName.parse("couchbase/server:7.1.2")) .withBucket(new BucketDefinition("buildings").withPrimaryIndex(true)) .withCommand("/bin/sh", "-c", "/entrypoint.sh couchbase-server & " + "sleep 30 && " + "couchbase-cli collection-manage --cluster localhost:8091 --username Administrator --password password --bucket buildings --create-collection _default.buildings && " + "wait");
2. 修正超时配置的单位
Spring Boot中Couchbase的超时属性单位为毫秒,当前配置的30仅代表30毫秒,远不足以完成集合元数据刷新和数据插入操作。更新application.properties:
spring.data.couchbase.bucket-name=buildings # 连接超时设为30秒 spring.couchbase.env.timeouts.connect=30000 # KV操作超时设为10秒 spring.couchbase.env.timeouts.key-value=10000 spring.couchbase.env.timeouts.key-value-durable=10000
3. 等待Bucket与集合完全就绪
测试容器启动后,Bucket和集合需要时间完成初始化,添加等待逻辑确保服务就绪:
在测试类中新增@BeforeAll方法:
@BeforeAll static void setup() { COUCHBASE.start(); // 等待Bucket就绪 COUCHBASE.waitForBucket("buildings"); // 额外等待集合元数据同步 try { Thread.sleep(5000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }
4. 验证主索引状态
尽管测试容器配置了withPrimaryIndex(true),但索引可能未完全生效。可延长初始化等待时间,或在测试中添加索引可用性检查,确保主索引正常工作。
总结
核心问题是自定义集合未创建导致客户端反复刷新元数据,最终触发超时。结合调整超时配置、确保资源就绪,即可解决测试超时问题。属性配置完全满足需求,无需使用AbstractCouchbaseConfiguration。
内容的提问来源于stack exchange,提问作者user3465651
相关产品推荐
相关产品推荐

