AWS自建Redis(非ElastiCache)本地SpringBoot连接超时求助
自建Redis集群(AWS Kubernetes)连接超时问题排查
一、部署架构与配置
在AWS环境中通过Kubernetes StatefulSet+LoadBalancer(MetalLB)部署自建Redis集群,核心配置如下:
apiVersion: apps/v1 kind: StatefulSet metadata: name: redis spec: serviceName: redis replicas: 3 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: initContainers: - name: config image: redis:7.0.5-alpine command: [ "sh", "-c" ] args: - | cp /tmp/redis/redis.conf /etc/redis/redis.conf echo "finding master..." MASTER_FDQN=`hostname -f | sed -e 's/redis-[0-9]\./redis-0./'` if [ "$(redis-cli -h sentinel -p 5000 ping)" != "PONG" ]; then echo "master not found, defaulting to redis-0" if [ "$(hostname)" = "redis-0" ]; then echo "this is redis-0, not updating config..." else echo "updating redis.conf..." echo "slaveof $MASTER_FDQN 6379" >> /etc/redis/redis.conf fi else echo "sentinel found, finding master" MASTER="$(redis-cli -h sentinel -p 5000 sentinel get-master-addr-by-name mymaster | grep -E '(^redis-\d{1,})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})')" echo "master found : $MASTER, updating redis.conf" echo "slaveof $MASTER 6379" >> /etc/redis/redis.conf fi volumeMounts: - name: redis-config mountPath: /etc/redis/ - name: config mountPath: /tmp/redis/ containers: - name: redis image: redis:7.0.5-alpine command: ["redis-server"] args: ["/etc/redis/redis.conf"] ports: - containerPort: 6379 name: redis volumeMounts: - name: data mountPath: /data - name: redis-config mountPath: /etc/redis/ volumes: - name: redis-config emptyDir: {} - name: config configMap: name: redis-config volumeClaimTemplates: - metadata: name: data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: nfs-1 resources: requests: storage: 50Mi --- apiVersion: v1 kind: Service metadata: name: redis spec: ports: - port: 6379 targetPort: 6379 name: redis selector: app: redis type: LoadBalancer
二、集群资源状态
所有Redis Pod运行正常,资源信息如下:
NAME READY STATUS RESTARTS AGE pod/redis-0 1/1 Running 0 22h pod/redis-1 1/1 Running 0 22h pod/redis-2 1/1 Running 0 22h NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/redis LoadBalancer 192.168.45.55 10.51.5.2 6379:30315/TCP 26h NAME READY AGE statefulset.apps/redis 3/3 22h
三、Redis Service详情
Name: redis Namespace: Namespace Labels: <none> Annotations: <none> Selector: app=redis Type: LoadBalancer IP Family Policy: SingleStack IP Families: IPv4 IP: 192.168.22.33 IPs: 192.168.22.33 LoadBalancer Ingress: 10.51.5.2 Port: redis 6379/TCP TargetPort: 6379/TCP NodePort: redis 30315/TCP Endpoints: 192.xxx:6379,192.xxx:6379,192.xxx:6379 Session Affinity: None External Traffic Policy: Cluster Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal IPAllocated 68s metallb-controller Assigned IP ["10.51.5.2"] Normal nodeAssigned 58s (x5 over 66s) metallb-speaker announcing from node "someaddress.com" with protocol "bgp" Normal nodeAssigned 58s (x5 over 66s) metallb-speaker announcing from node "someaddress.com" with protocol "bgp"
四、SpringBoot连接代码
本地SpringBoot应用通过Lettuce连接Redis的核心代码:
@Configuration public class RedisConfiguration { @Bean public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() { return new LettuceConnectionFactory("10.51.5.2", 30315); } } @Repository public class RedisRepository { private final ReactiveRedisOperations<String, String> reactiveRedisOperations; public RedisRepository(ReactiveRedisOperations<String, String> reactiveRedisOperations) { this.reactiveRedisOperations = reactiveRedisOperations; } public Mono<RedisPojo> save(RedisPojo redisPojo) { return reactiveRedisOperations.opsForValue().set(redisPojo.getInput(), redisPojo.getOutput()).map(__ -> redisPojo); } }
五、连接超时错误日志
每次请求均出现连接超时异常:
2022-12-02T20:20:08.015+08:00 ERROR 1184 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [8f16a752-1] 500 Server Error for HTTP POST "/save" org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1602) ~[spring-data-redis-3.0.0.jar:3.0.0] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ⇢ Handler com.redis.controller.RedisController#test(RedisRequest) [DispatcherHandler] *__checkpoint ⇢ HTTP POST "/save" [ExceptionHandlingWebHandler] Original Stack Trace: at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1602) ~[spring-data-redis-3.0.0.jar:3.0.0] Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to 10.51.5.2/<unresolved>:30315 at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:350) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] at io.lettuce.core.RedisClient.connect(RedisClient.java:216) ~[lettuce-core-6.2.1.RELEASE.jar:6.2.1.RELEASE] Caused by: io.netty.channel.ConnectTimeoutException: connection timed out: /10.51.5.2:30315 at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe$1.run(AbstractNioChannel.java:261) ~[netty-transport-4.1.85.Final.jar:4.1.85.Final] at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98) ~[netty-common-4.1.85.Final.jar:4.1.85.Final]
排查与解决步骤
1. 修正端口使用错误
代码中误用了NodePort(30315)连接LoadBalancer IP,LoadBalancer对外暴露的是Service端口6379,应修改连接配置:
@Bean public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() { return new LettuceConnectionFactory("10.51.5.2", 6379); }
2. 检查AWS网络安全规则
- 确认LoadBalancer安全组开放6379端口给本地SpringBoot应用的公网IP;
- 若坚持使用NodePort,需确保集群节点安全组开放30315端口给本地IP。
3. 验证Redis绑定配置
进入Redis Pod检查redis.conf的绑定规则:
kubectl exec -it redis-0 -- cat /etc/redis/redis.conf | grep bind
若结果为bind 127.0.0.1,需修改Redis ConfigMap,设置bind 0.0.0.0,然后重启StatefulSet:
kubectl rollout restart statefulset redis
4. 测试LoadBalancer连通性
在本地执行以下命令,验证IP和端口的可达性:
telnet 10.51.5.2 6379 # 或使用redis-cli测试 redis-cli -h 10.51.5.2 -p 6379 ping
若不通,检查MetalLB的BGP路由配置,以及AWS路由表是否包含该LoadBalancer IP的路由条目。
5. 调整外部流量策略
当前Service的ExternalTrafficPolicy为Cluster,流量会经过kube-proxy转发,可改为Local减少转发环节:
修改Service YAML:
spec: externalTrafficPolicy: Local
应用配置:
kubectl apply -f <service-yaml-path>
内容的提问来源于stack exchange,提问作者PatPanda
相关产品推荐
相关产品推荐

