跳至主要内容

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 廣告