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

Spring Boot无法连接Redis求助:连接提前关闭

无法从Spring Boot应用连接到Upstash Redis服务

我在upstash.io上拥有一个Redis服务,但Spring Boot应用无法连接到它,连接本地Redis也报相同错误:io.lettuce.core.RedisConnectionException: Connection closed prematurely,尝试增加超时时间无效。

原始Redis配置

@Configuration
public class RedisConfig {

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName("myhost");
        redisStandaloneConfiguration.setPort(6379);
        redisStandaloneConfiguration.setPassword(RedisPassword.of("password")); // Uncomment if password is needed
        return new LettuceConnectionFactory(redisStandaloneConfiguration);
    }

     @Bean
    public RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        return template;
    }

} 

Redis服务代码

@Component 
@RequiredArgsConstructor 
public class RedisService { 
    
    @Autowired
    private final RedisTemplate<Object, Object> redisTemplate; 
    
    @PostConstruct
    public void testConnection() {
        try {
            redisTemplate.getConnectionFactory().getConnection().ping();
            System.out.println("Connected to Redis successfully");
        } catch (Exception e) {
            System.err.println("Unable to connect to Redis: " + e.getMessage());
        }
    }
 
    public <V> void set(String key, V value, long timeout, TimeUnit timeUnit) { 
        System.out.println("Storing message to redis cache: Key[" + key + "]");
        redisTemplate.opsForValue().set(key, value); 
        redisTemplate.expire(key, timeout, timeUnit); 
    } 

    public <V> V get(String key) { 
        return (V) redisTemplate.opsForValue().get(key); 
    } 
 
    public Boolean hasKey(String key) { 
        return redisTemplate.hasKey(key); 
    } 
} 

pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springprojects</groupId>
    <artifactId>realtimechatapp</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>realtimechatapp</name>
    <description>Chat Application using Spring Boot</description>
    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
        <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>10.1.18</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity6</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </dependency>
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-data-redis</artifactId> 
        </dependency> 

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <image>
                        <builder>paketobuildpacks/builder-jammy-base:latest</builder>
                    </image>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

</project>

更新后的Redis配置

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        System.out.println("Creating RedisConnectionFactory");
        return new LettuceConnectionFactory();
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        System.out.println("Creating RedisTemplate");
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }
}

错误日志

Caused by: io.lettuce.core.RedisConnectionException: Connection closed prematurely

解决建议

1. 检查Redis服务状态

  • 本地Redis:执行redis-cli ping命令,确认本地Redis服务是否正常启动并能响应。
  • Upstash Redis:登录Upstash控制台,确认实例处于运行状态,同时检查IP访问白名单是否包含你的应用服务器IP(若开启了IP限制)。

2. 启用SSL连接(针对Upstash)

Upstash Redis默认强制要求SSL连接,当前配置未启用SSL是常见的连接失败原因,修改连接工厂配置:

@Bean
public RedisConnectionFactory redisConnectionFactory() {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
    config.setHostName("你的Upstash主机地址");
    config.setPort(6379);
    config.setPassword(RedisPassword.of("你的Upstash密码"));
    
    LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
            .useSsl().build(); // 启用SSL
    
    return new LettuceConnectionFactory(config, clientConfig);
}

3. 修正连接工厂实例管理

原始配置中redisTemplate()直接调用redisConnectionFactory()方法,会导致创建多个连接工厂实例,改为依赖注入方式获取:

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    return template;
}

4. 配置文件化管理参数

推荐将Redis配置移至application.properties,避免硬编码,Spring Boot会自动完成连接工厂配置:

spring.data.redis.host=你的Upstash主机地址
spring.data.redis.port=6379
spring.data.redis.password=你的Upstash密码
spring.data.redis.ssl=true

此时可移除自定义的RedisConfig类,简化配置。

5. 清理依赖冲突

pom.xml中同时引入了io.lettuce:lettuce-core和spring-boot-starter-data-redis,后者已包含Lettuce依赖,重复引入可能导致版本冲突,建议移除单独的lettuce-core依赖。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:39:50