diff --git a/src/main/java/com/yolo/keyborad/service/impl/QdrantVectorService.java b/src/main/java/com/yolo/keyborad/service/impl/QdrantVectorService.java index 2b846fa..60d4e44 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/QdrantVectorService.java +++ b/src/main/java/com/yolo/keyborad/service/impl/QdrantVectorService.java @@ -1,6 +1,7 @@ package com.yolo.keyborad.service.impl; import com.google.common.primitives.Floats; +import com.google.common.util.concurrent.ListenableFuture; import com.yolo.keyborad.common.ErrorCode; import com.yolo.keyborad.exception.BusinessException; import com.yolo.keyborad.model.vo.QdrantSearchItem; @@ -88,19 +89,32 @@ public class QdrantVectorService { // } // } + /** + * 搜索向量(高并发优化版本,避免阻塞线程池) + * + * @param userVector 用户输入的向量 + * @param limit 返回结果数量限制 + * @return 搜索结果列表 + */ public List searchPoint(float[] userVector, int limit) { try { Points.QueryPoints query = Points.QueryPoints.newBuilder() .setCollectionName(COLLECTION_NAME) // ★ 必须 .setQuery(nearest(userVector)) // ★ 语义向量 .setLimit(limit) // 限制返回数量 - .setWithPayload(enable(true)) // ★ 带上 payload + .setWithPayload(enable(true)) // ★ 带上 payload .build(); - List batchResults = qdrantClient.queryBatchAsync( + // 使用 ListenableFuture,添加超时保护 + ListenableFuture> future = qdrantClient.queryBatchAsync( COLLECTION_NAME, List.of(query) - ).get(); + ); + + // 设置超时时间(10秒),避免无限等待 + List batchResults = future.get( + 10, java.util.concurrent.TimeUnit.SECONDS + ); Points.BatchResult batchResult = batchResults.get(0); // 3. 把 Protobuf 的 ScoredPoint 转成你的 DTO @@ -129,10 +143,17 @@ public class QdrantVectorService { }) .toList(); - - } catch (InterruptedException | ExecutionException e) { - log.error("search point 失败", e); - throw new BusinessException(ErrorCode.OPERATION_ERROR); + } catch (InterruptedException e) { + // 恢复中断状态,避免吞掉中断信号 + Thread.currentThread().interrupt(); + log.error("search point 被中断", e); + throw new BusinessException(ErrorCode.OPERATION_ERROR, "向量搜索被中断"); + } catch (java.util.concurrent.TimeoutException e) { + log.error("search point 超时", e); + throw new BusinessException(ErrorCode.OPERATION_ERROR, "向量搜索超时,请稍后重试"); + } catch (ExecutionException e) { + log.error("search point 执行失败", e); + throw new BusinessException(ErrorCode.OPERATION_ERROR, "向量搜索执行失败"); } }