SpringBoot部署于GCE无法连接CloudSQL的问题求助
SpringBoot连接CloudSQL遇权限拒绝错误排查
前提环境
- 部署环境:Google Cloud GCE实例
- 开发框架:SpringBoot 2.7.6
- 依赖版本:Java 11、MySQL 5.7
- 基础状态:Spring项目可正常启动,无数据库操作的接口可正常响应
需求目标
通过SpringBoot连接CloudSQL并读取数据库数据
问题现象
调用数据库接口时触发权限拒绝错误,无法建立连接:
SQLException: Access denied for user 'root'@'cloudsqlproxy~192.168.0.5' (using password: YES)
已验证操作
- 本地MySQL环境可正常连接并操作数据
- GCE上部署的SpringBoot服务,无数据库操作的接口可通过Postman正常接收响应
- SSH登录GCE后,使用
mysql命令可成功连接CloudSQL并查看表内容 - 仅涉及数据库操作的接口响应失败,无法建立连接
配置文件
build.gradle
plugins { id 'java' id 'org.springframework.boot' version '2.7.6' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { // implementation 'org.springframework.boot:spring-boot-starter-security' // implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' // implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' // testImplementation 'org.springframework.security:spring-security-test' implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.3.0' runtimeOnly 'mysql:mysql-connector-java' runtimeOnly 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.0.15' } tasks.named('test') { useJUnitPlatform() }
application.properties
database=mysql spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://google/<DB-Name>?cloudSqlInstance=<CONNECTION NAME>&socketFactory=com.google.cloud.sql.mysql.SocketFactory spring.datasource.username=root spring.datasource.password=<PASSWORD>
错误日志
2022-12-21 13:49:25.022 ERROR 1576 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Access denied for user 'root'@'cloudsqlproxy~192.168.0.5' (using password: YES)
排查与解决步骤
1. 修正MySQL用户权限
错误提示root@cloudsqlproxy~192.168.0.5被拒绝,说明该用户未被允许从cloudsqlproxy~开头的主机访问数据库。通过SSH连接CloudSQL后执行以下SQL:
-- 授权root用户从所有cloudsqlproxy来源访问目标数据库 GRANT ALL PRIVILEGES ON `<DB-Name>`.* TO 'root'@'cloudsqlproxy~%' IDENTIFIED BY '<PASSWORD>'; -- 刷新权限使配置生效 FLUSH PRIVILEGES;
2. 统一JDBC驱动与Socket Factory版本兼容性
当前依赖中使用了旧版mysql-connector-java(对应JDBC 5),但Socket Factory是适配JDBC 8的mysql-socket-factory-connector-j-8,两者版本不匹配会导致连接异常。可二选一调整:
- 方案一:升级JDBC驱动到8.x版本,修改build.gradle依赖:
同时修改application.properties中的驱动类:runtimeOnly 'mysql:mysql-connector-j:8.0.33' // 替换原mysql-connector-java runtimeOnly 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.0.15' // 保留此依赖spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver - 方案二:使用适配JDBC 5的Socket Factory,修改build.gradle依赖:
runtimeOnly 'mysql:mysql-connector-java' // 保留原驱动 runtimeOnly 'com.google.cloud.sql:mysql-socket-factory:1.0.15' // 替换原socket factory
3. 修正JDBC URL格式
Cloud SQL Socket Factory不需要指定主机地址,原URL中的google属于冗余配置,应修改为:
spring.datasource.url=jdbc:mysql:///<DB-Name>?cloudSqlInstance=<CONNECTION NAME>&socketFactory=com.google.cloud.sql.mysql.SocketFactory
4. 确认GCE服务账号权限
确保GCE实例关联的服务账号拥有Cloud SQL Client角色,这样Socket Factory才能通过IAM认证建立连接。可通过Google Cloud控制台检查实例的服务账号权限,若缺失则添加该角色。
内容的提问来源于stack exchange,提问作者katahik
相关产品推荐
相关产品推荐

