跳到主要内容

GCP 如何在 Cloud Run 使用 Spring Boot 连线 Cloud SQL

· 5 分钟阅读
Eric Cheng

需求是我在 GCP 用 Spring Boot 部署了一台 Cloud Run,同时也 Cloud Run 申请了一台 PostgreSQL,我希望能从这台 Cloud Run 使用 JDBC 连线到 Cloud SQL,原本认为应该很容易,意外的却卡关有点久,整理了一下笔记,至少下次有同样的需求时不会忘掉

笔记开始前

  • 在 Cloud SQL 申请 PostgreSQL,这个部份不在这篇笔记讨论的范围,不过很简单,一直按下一步就差不多了,要稍微注意的是 GCP 预设申请的是「4 个 vCPU 和 26 GB」的机器,价格有点贵,有预算考量的人记得申请时选等级差一点的机器
  • 将 Spring Boot 包成 docker image 档上传到 GCP 的 Artifact Registry,这个部份也不在这篇笔记讨论的范围,晚点有空的时候再来整理一下这里的笔记

什么是 Cloud Run

Cloud Run 是 GCP 的一个 serverless 服务,和 AWS 的 Lambda 不同的是,Cloud Run 使用 docker container 来部署,也就是说只要能把程式包成 docker image 档上传到 GCP 的 Artifact Registry 或 Container Registry,程式就可以跑,不限制使用什么语言,测试过 Python Flask 和 Java Spring Boot 都能正常执行

然后 Cloud Run 提供了「只在要求处理期间分配 CPU」和「随时分配 CPU」两种选项,实测如果选择「只在要求处理期间分配 CPU」在很久没有执行后,再次执行大概要等个 10 秒,如果某个服务不需要 24 小时执行(ex:排程执行的服务),这个选择可以省下不少费用

Spring Boot 怎么连线 PostgreSQL

这篇文章其实也预设大家已经知道 Spring Boot 怎么连线 PostgreSQL,所以写的简洁一点

  • gradle 设定:增加以下两行设定
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'org.postgresql:postgresql'
}
  • application.properties 或 application.yml 设定,以下范例为 application.yml
spring:
datasource:
url: jdbc:postgresql://127.0.0.1:5432/database-name
driverClassName: org.postgresql.Driver
username: user-name
password: ******

Spring Boot 其实算是简化 db 连线的设定,基本上就是 gradle 设定好,application.properties 设定好就可以了

GCP 如何在 Cloud Run 使用 Spring Boot 连线 Cloud SQL

终于写到正文

Step 1:Cloud Run 建立服务时,新增 Cloud SQL 连线

如果已经申请好 Cloud SQL 的话,在建立 Cloud Run 时,应该会有选项可以选,如下图

2023-02-16_140858.png

Step 2:Spring Boot 增加 import library

以下范例为 gradle,使用 maven 请自行修改

dependencies {
implementation 'com.google.cloud.sql:postgres-socket-factory:1.10.0'
}

笔记撰写时版本为 1.10.0,该版本测试能用,有需要的请自行升版

Step 3:修改 application 设定

修改 application.yml

# DB
spring:
datasource:
url: jdbc:postgresql:///database-name
driverClassName: org.postgresql.Driver
username: user-name
password: ******

cloudSQL:
socketFactory: com.google.cloud.sql.postgres.SocketFactory
cloudSqlInstance: INSTANCE_CONNECTION_NAME
unixSocketPath: /cloudsql/INSTANCE_CONNECTION_NAME/.s.PGSQL.5432

这里几个注意的地方

  • url 不需要写 hostname 和 port,用以上的范例置换 database-name 就可以
  • cloudSQL.xxxx 名称是我自己随便取的,可自己更换,重点在对应下面的新增程式
  • INSTANCE_CONNECTION_NAME 格式为:PROJECT-ID:REGION:INSTANCE-ID,也就是下图中的「执行个体连线名称」,请自行置换

2023-02-16_142344.png

Step 4:置换 Spring Boot DataSource Configuration

新增一支程式

package tw.havocfuture;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
public class DataSourceConfig {

@Value("${spring.datasource.url}")
private String dataSourceUrl;

@Value("${spring.datasource.username}")
private String user;

@Value("${spring.datasource.password}")
private String password;

@Value("${cloudSQL.socketFactory}")
private String socketFactory;

@Value("${cloudSQL.cloudSqlInstance}")
private String cloudSqlInstance;

@Value("${cloudSQL.unixSocketPath}")
private String unixSocketPath;

@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dataSourceUrl);
config.setUsername(user);
config.setPassword(password);

config.addDataSourceProperty("socketFactory", socketFactory);
config.addDataSourceProperty("cloudSqlInstance", cloudSqlInstance);
config.addDataSourceProperty("unixSocketPath", unixSocketPath);

HikariDataSource ds = new HikariDataSource(config);
return ds;
}
}

Spring Boot 预设就是使用 hikari,这里主要就是要增加 socketFactory, cloudSqlInstance, unixSocketPath 的设定,用 @Value 取出 application.yml 的值,然后用 @Configuration 置换掉预设值

测试连线成功,问题解决

参考资料

版权声明


這是 google 廣告