Spring Boot集成AWS RDS Aurora只读副本未生效问题排查
咱们来一步步排查你遇到的这个只读副本路由不生效的问题,结合你的环境和配置,核心问题大概率出在RDS集群的配置识别上,下面是具体的分析和解决方案:
1. 纠正RDS配置的节点标识符
你当前配置里用的是主实例ID rds-db-cluster-instance-1 作为配置key,但Spring Cloud AWS要识别Aurora集群并启用只读副本路由,必须用集群的名称作为配置key,而不是单个实例的ID。
这就是为什么你用集群名启动失败、用主实例ID启动后只读副本没流量的原因:当你用单个实例ID配置时,Spring只会创建连接该实例的普通数据源,不会去发现集群里的只读副本,自然不会触发ReadOnlyRoutingDataSource的路由逻辑。
修正后的配置应该把rds-db-cluster-instance-1替换成你的Aurora集群名称,比如:
cloud: aws: region: static: ap-southeast-2 credentials: accessKey: ${ACCESS_KEY} secretKey: ${SECRET_KEY} rds: # 替换成你的Aurora集群名称(不是单个实例ID) my-aurora-cluster: password: ${POSTGRES_PASSWORD} username: postgres readReplicaSupport: true databaseName: postgres stack: auto: false
2. 确保只读路由数据源被正确加载
你的ReadOnlyRoutingDataSource断点从未触发,说明这个数据源根本没被Spring作为主数据源使用。除了配置key的问题,还要检查:
- 有没有自定义的
@Bean DataSource覆盖了Spring Cloud AWS的自动配置?如果自己定义了数据源Bean,会导致自动配置的只读路由数据源失效。 - 确认
readReplicaSupport: true的取值是布尔值true,而不是字符串"true"(你当前配置里加了引号,虽然Spring会自动转换,但改成无引号的布尔值更稳妥)。
3. 验证@Transactional(readOnly = true)的生效逻辑
虽然你在GET方法上加了@Transactional(readOnly = true),但要确保:
- 控制器所在的包被
@SpringBootApplication的扫描范围覆盖(比如控制器在com.example.controller,启动类在com.example就没问题) - 没有其他事务注解(比如类级别的
@Transactional)覆盖了方法级别的只读配置 - 方法是public修饰的(你的方法满足这点,没问题)
另外,Spring Data JPA的findAll()本身是只读操作,但路由逻辑依赖事务的readOnly属性来切换到只读副本,所以这个注解是必须的。
4. 检查只读副本的基础可用性和权限
- 登录AWS控制台确认只读副本的状态是Available,没有故障或复制延迟过高的情况
- 确认数据库用户
postgres有访问只读副本的权限:Aurora集群默认会同步主库的用户权限,但可以临时用该用户直接连接只读副本测试是否能正常访问 - 查看只读副本的CloudWatch日志,有没有连接失败的错误记录
5. 手动配置只读路由数据源(备选方案)
如果自动配置还是不生效,可以手动创建ReadOnlyRoutingDataSource来强制启用路由逻辑,示例代码如下:
@Configuration public class CustomDataSourceConfig { @Autowired private AmazonRDS amazonRDS; @Value("${cloud.aws.rds.my-aurora-cluster.username}") private String dbUsername; @Value("${cloud.aws.rds.my-aurora-cluster.password}") private String dbPassword; @Value("${cloud.aws.rds.my-aurora-cluster.databaseName}") private String dbName; @Value("${cloud.aws.rds.my-aurora-cluster}") private String clusterName; @Bean public DataSource dataSource() { RdsDataSourceFactory dataSourceFactory = new RdsDataSourceFactory(amazonRDS); dataSourceFactory.setUsername(dbUsername); dataSourceFactory.setPassword(dbPassword); dataSourceFactory.setDatabaseName(dbName); dataSourceFactory.setClusterIdentifier(clusterName); dataSourceFactory.setReadReplicaSupport(true); return dataSourceFactory.createDataSource(); } }
验证方法
修改配置后重启应用,调用GET接口,然后查看AWS控制台的只读副本连接数,如果连接数从0变成非零,说明路由生效了。也可以在只读副本上临时修改一条测试数据(比如修改某个counter的名称),调用GET接口如果返回修改后的数据,就确认流量已经走到只读副本了(注意Aurora的复制有几秒延迟,需要稍等再测试)。
内容的提问来源于stack exchange,提问作者stringy05

