MilvusConfig.java 5.55 KB
package com.xly.milvus.config;

import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.support.RetryTemplate;

@Slf4j
@Configuration
@EnableRetry
public class MilvusConfig {

    @Value("${milvus.host:localhost}")
    private String host;

    @Value("${milvus.port:19530}")
    private Integer port;

    @Value("${milvus.database:default}")
    private String database;

    @Value("${milvus.username:}")
    private String username;

    @Value("${milvus.password:}")
    private String password;

    @Value("${milvus.connect-timeout:10000}")
    private Long connectTimeout;

    @Value("${milvus.rpc-deadline:10000}")
    private Long rpcDeadline;

    @Value("${milvus.keep-alive-time:300000}")
    private Long keepAliveTime;

    @Value("${milvus.keep-alive-timeout:5000}")
    private Long keepAliveTimeout;

    @Value("${milvus.secure:false}")
    private Boolean secure;

    @Value("${milvus.validate-on-startup:true}")
    private boolean validateOnStartup;

    @Value("${milvus.fail-on-connect-error:false}")
    private boolean failOnConnectError;

    @Value("${milvus.enable-precheck:true}")
    private boolean enablePrecheck;

    @Bean(destroyMethod = "close")
    public MilvusClientV2 milvusClient() {
        try {
            String uri = String.format("http://%s:%d", host, port);
            // 构建连接配置
            ConnectConfig.ConnectConfigBuilder configBuilder = ConnectConfig.builder()
                    .uri(uri)
                    .dbName("default")
                    .connectTimeoutMs(connectTimeout)
                    .rpcDeadlineMs(rpcDeadline)
                    .keepAliveTimeMs(keepAliveTime)
                    .keepAliveTimeoutMs(keepAliveTimeout)
                    .keepAliveWithoutCalls(true)
                    .secure(secure)
                    .enablePrecheck(enablePrecheck);

            // 添加认证信息(如果有)
            if (username != null && !username.isEmpty()) {
                configBuilder.username(username);
                if (password != null) {
                    configBuilder.password(password);
                }
            }

            ConnectConfig connectConfig = configBuilder.build();

            // 创建客户端
            MilvusClientV2 client = new MilvusClientV2(connectConfig);
            // 检查xlyerp数据库是否存在,如果不存在则创建
            var databases = client.listDatabases();
            if (!databases.getDatabaseNames().contains(database)) {
                log.info("数据库 xlyerp 不存在,正在创建...");
                client.createDatabase(
                        io.milvus.v2.service.database.request.CreateDatabaseReq.builder()
                                .databaseName(database)
                                .build()
                );
                log.info("数据库 xlyerp 创建成功");
            }

            // 切换到xlyerp数据库
            client.useDatabase (database);
            log.info("切换到数据库: {}",database);

            // 启动验证
            if (validateOnStartup) {
                validateConnection(client);
            }
            return client;
        } catch (Exception e) {
            log.error("创建Milvus客户端时发生异常: {}", e.getMessage(), e);
            throw new RuntimeException("无法创建Milvus客户端", e);
        }

    }

    /**
     * 验证Milvus连接 - 基于源码中可用的方法
     */
    private void validateConnection(MilvusClientV2 client) {
        try {
            // 方法1: 检查服务器版本(源码中存在getServerVersion())
            String serverVersion = client.getServerVersion();

            // 方法2: 列出数据库(源码中存在listDatabases())
            var databases = client.listDatabases();

            // 方法3: 检查健康状态(源码中存在checkHealth())
            var health = client.checkHealth();

            System.out.println("✅ Milvus连接成功");
            System.out.println("   - 服务器版本: " + serverVersion);
            System.out.println("   - 数据库: " + databases);
            System.out.println("   - 健康状态: " + health);

            // 验证指定数据库是否存在
            if (database != null && !database.isEmpty()) {
                boolean dbExists = databases.getDatabaseNames().contains(database);
                if (!dbExists && !"default".equals(database)) {
                    System.err.println("⚠️ 警告: 指定数据库 '" + database + "' 不存在");
                }
            }

        } catch (Exception e) {
            String errorMsg = String.format("❌ Milvus连接失败: %s:%d - %s",host, port, e.getMessage());

            if (failOnConnectError) {
                throw new IllegalStateException(errorMsg, e);
            } else {
                System.err.println(errorMsg);
                System.err.println("   ⚠️ 应用将继续启动,但Milvus功能可能不可用");
            }
        }
    }

    /**
     * 配置重试模板(可选)
     */
    @Bean
    public RetryTemplate milvusRetryTemplate() {
        return RetryTemplate.builder()
                .maxAttempts(3)
                .exponentialBackoff(1000, 2, 10000)
                .retryOn(Exception.class)
                .build();
    }
}