使用 PostgreSQL 適用的 Cloud SQL

本頁說明如何從 App Engine 應用程式連線到 PostgreSQL 適用的 Cloud SQL 執行個體,以及如何讀取及寫入 Cloud SQL。Cloud SQL 是存放在 Google 雲端系統的 SQL 資料庫。

如要進一步瞭解 Cloud SQL,請參閱 Cloud SQL 說明文件。如要瞭解 Cloud SQL 定價和相關限制,請參閱 Cloud SQL 定價頁面。App Engine 應用程式也會受到 App Engine 配額的限制。

事前準備

  1. 在 GCP 主控台中建立或選取 GCP 專案,接著確認該專案含有 App Engine 應用程式並啟用了計費功能:
    前往 App Engine

    如果您的專案中已存在 App Engine 應用程式且已經啟用計費功能,系統就會開啟「Dashboard」(資訊主頁)。否則,請按照提示選取地區,然後啟用計費功能。

  2. 啟用Cloud SQL API。

    啟用 API

  3. 如要使用 gcloud 工具部署應用程式,您必須下載、安裝 Cloud SDK,然後將 Cloud SDK 初始化:
    下載 SDK

    如果您已安裝 gcloud 工具,並想將其設為使用某個 GCP 專案 ID,而非工具初始化時使用的 ID,請參閱管理 Cloud SDK 設定一文。

設定 Cloud SQL 執行個體

如要建立並設定 Cloud SQL 執行個體:

  1. 建立 PostgreSQL 執行個體適用的 Cloud SQL
  2. 如果您尚未在 Cloud SQL 執行個體上為預設使用者設定密碼,請先執行下列指令完成設定作業:
    gcloud sql users set-password postgres no-host --instance [INSTANCE_NAME] --password [PASSWORD]
    
  3. 如果您不想使用預設使用者進行連線,請建立使用者
  4. 記錄該執行個體的連線名稱:
    gcloud sql instances describe [INSTANCE_NAME]
    

    例如:

    connectionName: project1:us-central1:instance1
    

    您也可以在 Google Cloud Platform 主控台的「Instance details」(執行個體詳細資料) 頁面中找到此值。

  5. 在您的 Cloud SQL 執行個體上建立資料庫。
    gcloud sql databases create [DATABASE_NAME] --instance=[INSTANCE_NAME]
    
    如要進一步瞭解如何建立和管理資料庫,請參閱 Cloud SQL 說明文件

設定您的本機環境

在部署作業完成後,應用程式會使用 App Engine 執行階段環境內建的 Cloud SQL Proxy 與您的 Cloud SQL 執行個體進行通訊。不過,如要在本機上測試應用程式,您必須在開發環境中安裝並使用 Cloud SQL Proxy 的本機副本。

如要在 Cloud SQL 執行個體上執行基本的管理工作,您可以使用資料庫的管理用戶端或 GCP 主控台。

  1. 驗證 gcloud 工具,從您的本機電腦使用 Proxy 進行連線:

    gcloud auth application-default login
    
  2. 安裝 Cloud SQL Proxy:

    Linux 64 位元

    1. 下載 Proxy:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
      
    2. 授予 Proxy 執行權限:
      chmod +x cloud_sql_proxy
      

    Linux 32 位元

    1. 下載 Proxy:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.386 -O cloud_sql_proxy
      
    2. 授予 Proxy 執行權限:
      chmod +x cloud_sql_proxy
      

    macOS 64 位元

    1. 下載 Proxy:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
      
    2. 授予 Proxy 執行權限:
      chmod +x cloud_sql_proxy
      

    macOS 32 位元

    1. 下載 Proxy:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.386
      
    2. 授予 Proxy 執行權限:
      chmod +x cloud_sql_proxy
      

    Windows 64 位元

    https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe 上按一下滑鼠右鍵,然後選取 [Save Link As] (另存連結為) 來下載 Proxy。請將檔案重新命名為 cloud_sql_proxy.exe

    Windows 32 位元

    https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe 上按一下滑鼠右鍵,然後選取 [Save Link As] (另存連結為) 來下載 Proxy。請將檔案重新命名為 cloud_sql_proxy.exe
    如果此處未列出您的作業系統,您也可以利用原始碼編譯 Proxy
  3. 執行 Proxy:

    根據您的語言與環境,您可以使用 TCP 通訊端或 Unix 通訊端啟動 Proxy。

    TCP 通訊端

    1. 從「Instance details」(執行個體詳細資料) 頁面複製您的執行個體連線名稱。

      例如:myproject:us-central1:myinstance

    2. 如果您使用服務帳戶驗證 Proxy,請記下您在建立服務帳戶時建立的私密金鑰檔案的用戶端機器位置。
    3. 啟動 Proxy。

      以下是幾個可能的 Proxy 叫用字串:

      • 使用 Cloud SDK 驗證:
        ./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:5432
        
        請勿指定使用中的通訊埠,例如本機資料庫伺服器正在使用的通訊埠。
      • 使用服務帳戶並明確指定執行個體 (建議用於實際工作環境):
        ./cloud_sql_proxy -instances=<INSTANCE_CONNECTION_NAME>=tcp:5432 \
                          -credential_file=<PATH_TO_KEY_FILE> &
        

      如要進一步瞭解 Proxy 選項,請參閱驗證 Proxy 的選項指定執行個體的選項相關各節。

    Unix 通訊端

    1. 如果您要明確指定執行個體,請從「Instance details」(執行個體詳細資料) 頁面複製執行個體連線名稱。
    2. 建立 Proxy 通訊端運作的目錄:
      sudo mkdir /cloudsql; sudo chmod 777 /cloudsql
    3. 如果您使用服務帳戶來驗證 Proxy,請記下您之前建立服務帳戶時,私密金鑰檔案在用戶端機器上的建立位置。
    4. 開啟新的終端機視窗,然後啟動 Proxy。

      以下是幾個可能的 Proxy 叫用字串:

      • 使用服務帳戶並明確指定執行個體 (建議用於實際工作環境):
        ./cloud_sql_proxy -dir=/cloudsql -instances=<INSTANCE_CONNECTION_NAME> \
                          -credential_file=<PATH_TO_KEY_FILE> &
      • 使用 Cloud SDK 驗證和自動探索執行個體功能:
        ./cloud_sql_proxy -dir=/cloudsql &

      建議您在 Proxy 本身的終端機上啟動 Proxy,如此可避免將 Proxy 的輸出與其他程式的輸出混在一起,以便您監控 Proxy 的輸出。

      如要進一步瞭解 Proxy 選項,請參閱驗證 Proxy 的選項指定執行個體的選項相關各節。

  4. 如要使用管理用戶端,您可以安裝本機副本,然後使用 Proxy 或 IP 位址進行連線。

    詳情請參閱使用 Cloud SQL Proxy 連結 psql 用戶端一文和使用 IP 位址連結 psql 用戶端的說明。

設定連線字串及新增程式庫

  1. 設定本機環境以支援本機測試的連線。

    以下列提供的程式碼範例為例:

    export POSTGRES_CONNECTION="user=[USER_NAME] password=[PASSWORD] dbname=[DATABASE_NAME] sslmode=disable
    
  2. 如要讓應用程式在部署完成後可連線到 Cloud SQL 執行個體,請將 Cloud SQL 的使用者、密碼、資料庫和執行個體連線名稱等變數,新增到 app.yaml 檔案中的相關環境變數:

    env_variables:
      # See https://godoc.org/github.com/lib/pq
      #
      # Replace INSTANCE_CONNECTION_NAME with the same value as in the
      # beta_settings section below.
      POSTGRES_CONNECTION: "user=postgres password=pw dbname=db host=/cloudsql/INSTANCE_CONNECTION_NAME"
      #
      # If you're testing locally using the Cloud SQL proxy with TCP,
      # instead set this environment variable:
      # POSTGRES_CONNECTION="user=postgres password=pw dbname=db sslmode=disable"

  3. 使用您的 Cloud SQL 執行個體連線名稱,在 app.yaml 中新增 beta_settings 區段。

    # Replace INSTANCE_CONNECTION_NAME with the value obtained when configuring your
    # Cloud SQL instance, available from the Google Cloud Console or from the Cloud SDK.
    # For SQL v2 instances, this should be in the form of "project:region:instance".
    # Cloud SQL v1 instances are not supported.
    beta_settings:
      cloud_sql_instances: INSTANCE_CONNECTION_NAME
  4. 使用指令列將 PostgreSQL 套件下載至您的本機電腦。例如:

    go get -u github.com/lib/pq
    

執行程式碼範例

下列範例會將造訪資訊寫入 Cloud SQL,然後讀取並傳回最後十次造訪的資訊:

// Sample cloudsql demonstrates usage of Cloud SQL from App Engine flexible environment.
package main

import (
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"google.golang.org/appengine"

	_ "github.com/lib/pq"
)

var db *sql.DB

func main() {
	// Set this in app.yaml when running in production.
	datastoreName := os.Getenv("POSTGRES_CONNECTION")

	var err error
	db, err = sql.Open("postgres", datastoreName)
	if err != nil {
		log.Fatal(err)
	}

	// Ensure the table exists.
	// Running an SQL query also checks the connection to the PostgreSQL server
	// is authenticated and valid.
	if err := createTable(); err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", handle)
	appengine.Main()
}

func createTable() error {
	stmt := `CREATE TABLE IF NOT EXISTS visits (
			timestamp  BIGINT,
			userip     VARCHAR(255)
		)`
	_, err := db.Exec(stmt)
	return err
}

func handle(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}

	// Get a list of the most recent visits.
	visits, err := queryVisits(10)
	if err != nil {
		msg := fmt.Sprintf("Could not get recent visits: %v", err)
		http.Error(w, msg, http.StatusInternalServerError)
		return
	}

	// Record this visit.
	if err := recordVisit(time.Now().UnixNano(), r.RemoteAddr); err != nil {
		msg := fmt.Sprintf("Could not save visit: %v", err)
		http.Error(w, msg, http.StatusInternalServerError)
		return
	}

	fmt.Fprintln(w, "Previous visits:")
	for _, v := range visits {
		fmt.Fprintf(w, "[%s] %s\n", time.Unix(0, v.timestamp), v.userIP)
	}
	fmt.Fprintln(w, "\nSuccessfully stored an entry of the current request.")
}

type visit struct {
	timestamp int64
	userIP    string
}

func recordVisit(timestamp int64, userIP string) error {
	stmt := "INSERT INTO visits (timestamp, userip) VALUES ($1, $2)"
	_, err := db.Exec(stmt, timestamp, userIP)
	return err
}

func queryVisits(limit int64) ([]visit, error) {
	rows, err := db.Query("SELECT timestamp, userip FROM visits ORDER BY timestamp DESC LIMIT $1", limit)
	if err != nil {
		return nil, fmt.Errorf("Could not get recent visits: %v", err)
	}
	defer rows.Close()

	var visits []visit
	for rows.Next() {
		var v visit
		if err := rows.Scan(&v.timestamp, &v.userIP); err != nil {
			return nil, fmt.Errorf("Could not get timestamp/user IP out of row: %v", err)
		}
		visits = append(visits, v)
	}

	return visits, rows.Err()
}

Testing and deploying

  1. 如要在本機上測試您的應用程式,請執行下列指令:

    go run cloudsql.go
    
  2. 本機測試結束後,請將您的應用程式部署至 App Engine

    gcloud app deploy
    

  3. 如要啟動瀏覽器並在 http://[YOUR_PROJECT_ID].appspot.com 查看應用程式,請執行下列指令:

    gcloud app browse
    

在不同專案中執行 Cloud SQL 和 App Engine

如果您的 App Engine 應用程式和 Cloud SQL 執行個體位在不同的 Google Cloud Platform 專案中,您必須使用服務帳戶,允許 App Engine 應用程式存取 Cloud SQL。

這個服務帳戶代表您的 App Engine 應用程式,系統預設會在您建立 Google Cloud Platform 專案時一併建立此帳戶。

  1. 如果您的 App Engine 應用程式和 Cloud SQL 執行個體位於相同專案內,您可以略過此節,並請前往設定您的本機環境。否則,請繼續下一步。
  2. 找出與 App Engine 應用程式相關聯的服務帳戶。預設的 App Engine 服務帳戶名稱為 [PROJECT-ID]@appspot.gserviceaccount.com

    您可以在「IAM Permissions」(IAM 權限) 頁面中驗證該 App Engine 服務帳戶。請確認您選取的是 App Engine 應用程式的專案,而非 Cloud SQL 執行個體的專案。

    前往「IAM Permissions」(IAM 權限) 頁面

  3. 前往 Google Cloud Platform 主控台中的「IAM & Admin Projects」(IAM 與管理員) 的專案頁面。

    前往「IAM & Admin Projects」(IAM 與管理員) 的專案頁面

  4. 選取包含 Cloud SQL 執行個體的專案。
  5. 搜尋服務帳戶名稱。
  6. 如果服務帳戶已存在,並具備含有 cloudsql.instances.connect 權限的角色,您可以繼續設定本機環境

    與舊版的 EditorOwner 專案角色一樣,Cloud SQL ClientCloud SQL EditorCloud SQL Admin 角色均會提供所需的權限。

  7. 如果沒有服務帳戶,請按一下 [Add] (新增)來新增服務帳戶。
  8. 在「Add members」(新增成員) 對話方塊中輸入服務帳戶的名稱,然後選取包含 cloudsql.instances.connect 權限的角色 (除了「檢視者」之外,任何 Cloud SQL 預先定義角色皆可)。

    或者,您也可以選取 [Project] (專案) > [Editor] (編輯者) 來使用原始編輯者角色,不過編輯者角色包含 Google Cloud Platform 中的各種權限。

    如果您沒有看到這些角色,即表示您的 Google Cloud Platform 使用者可能沒有 resourcemanager.projects.setIamPolicy 權限。您可以前往 Google Cloud Platform 主控台的 IAM 頁面,然後搜尋您的使用者 ID,藉此檢查您的權限。

  9. 按一下 [Add] (新增)。

    畫面上應會列出具備指定角色的服務帳戶。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Go 適用的 App Engine 彈性環境