使用 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 應用程式且已經啟用計費功能,系統就會開啟資訊主頁。若否,則按照提示選取地區並啟用計費功能。

  2. 啟用 Cloud SQL API。

    啟用 API

  3. 如要使用 gcloud 工具部署應用程式,您必須下載、安裝並初始化 Cloud SDK:
    下載 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 主控台的「執行個體詳細資料」頁面中找到此值。

  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 上按一下滑鼠右鍵,然後選取 [另存連結為...] 來下載 Proxy,並將這個程式重新命名為 cloud_sql_proxy.exe

    Windows 32 位元

    https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe 上按一下滑鼠右鍵,然後選取 [另存連結為...] 來下載 Proxy,並將這個程式重新命名為 cloud_sql_proxy.exe
    如果您的作業系統不包含在內,您也可以從來源編譯 Proxy

  3. 執行 Proxy:

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

    TCP 通訊端

    1. 從「執行個體詳細資料」頁面複製您的執行個體連線名稱。
    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. 如果您要明確指定執行個體,請從「執行個體詳細資料」頁面複製執行個體連線名稱。
    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 SQL_USER=[YOUR_SQL_USER]
    export SQL_PASSWORD=[YOUR_SQL_PASSWORD]
    export SQL_DATABASE=[YOUR_SQL_DATABASE]
    npm install
    

    依照預設,當您在本機上執行應用程式時,系統會嘗試使用 TCP 通訊端進行連線。如果您將 Proxy 設定為使用 Unix 通訊端,請額外設定下方這個環境變數:

    export INSTANCE_CONNECTION_NAME=[YOUR_INSTANCE_CONNECTION_NAME]
    

    這些環境變數用於建立連線:

    const config = {
      user: process.env.SQL_USER,
      password: process.env.SQL_PASSWORD,
      database: process.env.SQL_DATABASE
    };
    
    if (process.env.INSTANCE_CONNECTION_NAME && process.env.NODE_ENV === 'production') {
      config.host = `/cloudsql/${process.env.INSTANCE_CONNECTION_NAME}`;
    }
    
    // Connect to the database
    const knex = Knex({
      client: 'pg',
      connection: config
    });

  2. 如要允許應用程式在部署完成後可連線至 Cloud SQL 執行個體,請將使用者、密碼、資料庫、執行個體連線名稱變數從 Cloud SQL 新增到 app.flexible.yaml 檔案中的相關環境變數: 已部署的應用程式將會透過 Unix 通訊端連線。

    # The following env variables may contain sensitive information that grants
    # anyone access to your database. Do not add this file to your source control.
    env_variables:
      SQL_USER: YOUR_SQL_USER
      SQL_PASSWORD: YOUR_SQL_PASSWORD
      SQL_DATABASE: YOUR_SQL_DATABASE
      # e.g. my-awesome-project:us-central1:my-cloud-sql-instance
      INSTANCE_CONNECTION_NAME: YOUR_INSTANCE_CONNECTION_NAME
  3. app.flexible.yaml 中新增 beta_settings 區段,並在區段中使用您的 Cloud SQL 執行個體連線名稱。

    beta_settings:
      # The connection name of your instance, available by using
      # 'gcloud beta sql instances describe [INSTANCE_NAME]' or from
      # the Instance details page in the Google Cloud Platform Console.
      cloud_sql_instances: YOUR_INSTANCE_CONNECTION_NAME

  4. 在應用程式的 package.json 中新增 Node.js PostgreSQL 用戶端程式庫。例如,範例中的程式碼會將 Knex.js 做為驅動程式搭配 pg 套件使用:

    "dependencies": {
      "async": "2.6.0",
      "express": "4.16.2",
      "knex": "0.14.4",
      "pg": "7.4.1",
      "prompt": "1.0.0"
    },

執行程式碼範例

下列的 server.js 範例會在 Cloud SQL 執行個體中建立訪客記錄檔。

在執行範例之前,請先執行 createTables.js 來建立所需的資料表,以及確保資料庫的設定正確:

const Knex = require('knex');
const prompt = require('prompt');

const FIELDS = ['user', 'password', 'database'];

prompt.start();

// Prompt the user for connection details
prompt.get(FIELDS, (err, config) => {
  if (err) {
    console.error(err);
    return;
  }

  // Connect to the database
  const knex = Knex({ client: 'pg', connection: config });

  // Create the "visits" table
  knex.schema.createTable('visits', (table) => {
    table.increments();
    table.timestamp('timestamp');
    table.string('userIp');
  })
    .then(() => {
      console.log(`Successfully created 'visits' table.`);
      return knex.destroy();
    })
    .catch((err) => {
      console.error(`Failed to create 'visits' table:`, err);
      if (knex) {
        knex.destroy();
      }
    });
});
下列範例會在 Cloud SQL 中寫入造訪資料,並於讀取後傳回最後十次造訪的資訊:
const express = require('express');
const Knex = require('knex');
const crypto = require('crypto');

const app = express();
app.enable('trust proxy');

const knex = connect();

function connect () {
  const config = {
    user: process.env.SQL_USER,
    password: process.env.SQL_PASSWORD,
    database: process.env.SQL_DATABASE
  };

  if (process.env.INSTANCE_CONNECTION_NAME && process.env.NODE_ENV === 'production') {
    config.host = `/cloudsql/${process.env.INSTANCE_CONNECTION_NAME}`;
  }

  // Connect to the database
  const knex = Knex({
    client: 'pg',
    connection: config
  });

  return knex;
}

/**
 * Insert a visit record into the database.
 *
 * @param {object} knex The Knex connection object.
 * @param {object} visit The visit record to insert.
 * @returns {Promise}
 */
function insertVisit (knex, visit) {
  return knex('visits').insert(visit);
}

/**
 * Retrieve the latest 10 visit records from the database.
 *
 * @param {object} knex The Knex connection object.
 * @returns {Promise}
 */
function getVisits (knex) {
  return knex.select('timestamp', 'userIp')
    .from('visits')
    .orderBy('timestamp', 'desc')
    .limit(10)
    .then((results) => {
      return results.map((visit) => `Time: ${visit.timestamp}, AddrHash: ${visit.userIp}`);
    });
}

app.get('/', (req, res, next) => {
  // Create a visit record to be stored in the database
  const visit = {
    timestamp: new Date(),
    // Store a hash of the visitor's ip address
    userIp: crypto.createHash('sha256').update(req.ip).digest('hex').substr(0, 7)
  };

  insertVisit(knex, visit)
    // Query the last 10 visits from the database.
    .then(() => getVisits(knex))
    .then((visits) => {
      res
        .status(200)
        .set('Content-Type', 'text/plain')
        .send(`Last 10 visits:\n${visits.join('\n')}`)
        .end();
    })
    .catch((err) => {
      next(err);
    });
});

const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});

測試及部署

  1. 如要在本機測試您的應用程式,請輸入:

    npm start
    

  2. 進行本機測試後,請將應用程式部署至 App Engine

    gcloud app deploy app.flexible.yaml
    

  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 權限」頁面中驗證該 App Engine 服務帳戶。請確認您選取的是 App Engine 應用程式的專案,而非 Cloud SQL 執行個體的專案。

    前往「IAM 權限」頁面

  3. 前往 Google Cloud Platform 主控台的「IAM 與管理員」的專案頁面。

    前往「IAM 與管理員」的專案頁面

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

    如同舊版的 EditorOwner 專案角色,Cloud SQL ClientCloud SQL EditorCloud SQL Admin 角色均會提供必要權限。

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

    或者,您可以選取 [專案] > [編輯者] 來使用原始編輯者角色,但編輯者角色含有適用於整個 Google Cloud Platform 的權限。

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

  9. 按一下 [新增]

    您現在應該可以在畫面上看見服務帳戶且列出指定角色。

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

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

這個網頁
Node.js 適用的 App Engine 彈性環境文件