Cloud Spanner を Cloud Functions と一緒に使用する

Cloud Spanner

目標

Cloud Spanner にアクセスする HTTP Cloud Function を作成、デプロイ、トリガーします。

料金

このトピックでは、Google Cloud Platform の有料コンポーネントである Cloud Spanner と Cloud Functions を使用しています。

始める前に

  1. このトピックでは、test-instance という名前の Cloud Spanner インスタンスと、音楽アプリケーション スキーマを使用する example-db という名前のデータベースがあると想定します。音楽アプリケーション スキーマを使用するインスタンスとデータベースの作成方法については、Console を使用したクイックスタートか、GoJavaNode.jsPython のスタートガイドのチュートリアルをご覧ください。
  1. Cloud Functions API を有効にします。
    Cloud Functions API を有効にする

  2. Cloud SDK をインストールし、初期化します

  3. gcloud コンポーネントを更新し、インストールします。

    Node.js 8/10

    gcloud components update

    Node.js 6(非推奨)

    gcloud components update

    Python

    gcloud components update

    Go

    gcloud components update

  4. 開発環境を準備します。

アプリケーションを準備する

  1. ローカルマシンにサンプルアプリのリポジトリのクローンを作成します。

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    または、zip 形式のサンプルをダウンロードし、ファイルを抽出してもかまいません。

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    または、zip 形式のサンプルをダウンロードし、ファイルを抽出してもかまいません。

    Go

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git

    または、zip 形式のサンプルをダウンロードし、ファイルを抽出してもかまいません。

  2. Cloud Spanner にアクセスするための Cloud Functions サンプルコードが含まれているディレクトリに移動します。

    Node.js

    cd nodejs-docs-samples/functions/spanner/

    Python

    cd python-docs-samples/functions/spanner/

    Go

    cd golang-samples/functions/spanner/
  3. 次のサンプルコードを見てみましょう。

    Node.js

    // Imports the Google Cloud client library
    const {Spanner} = require('@google-cloud/spanner');
    
    // Instantiates a client
    const spanner = new Spanner();
    
    // Your Cloud Spanner instance ID
    const instanceId = 'test-instance';
    
    // Your Cloud Spanner database ID
    const databaseId = 'example-db';
    
    /**
     * HTTP Cloud Function.
     *
     * @param {Object} req Cloud Function request context.
     * @param {Object} res Cloud Function response context.
     */
    exports.get = (req, res) => {
      // Gets a reference to a Cloud Spanner instance and database
      const instance = spanner.instance(instanceId);
      const database = instance.database(databaseId);
    
      // The query to execute
      const query = {
        sql: 'SELECT * FROM Albums',
      };
    
      // Execute the query
      return database
        .run(query)
        .then(results => {
          const rows = results[0].map(row => row.toJSON());
          rows.forEach(row => {
            res.write(
              `SingerId: ${row.SingerId}, AlbumId: ${row.AlbumId}, AlbumTitle: ${
                row.AlbumTitle
              }\n`
            );
          });
          res.status(200).end();
        })
        .catch(err => {
          res
            .status(500)
            .send(`Error querying Spanner: ${err}`)
            .end();
        });
    };

    Python

    from google.cloud import spanner
    
    instance_id = 'test-instance'
    database_id = 'example-db'
    
    client = spanner.Client()
    
    def spanner_read_data(request):
        instance = client.instance(instance_id)
        database = instance.database(database_id)
    
        query = 'SELECT * FROM Albums'
    
        outputs = []
        with database.snapshot() as snapshot:
            results = snapshot.execute_sql(query)
    
            for row in results:
                output = 'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row)
                outputs.append(output)
    
        return '\n'.join(outputs)

    Go

    // Package spanner contains an example of using Spanner from a Cloud Function.
    package spanner
    
    import (
    	"context"
    	"fmt"
    	"log"
    	"net/http"
    
    	"cloud.google.com/go/spanner"
    	"google.golang.org/api/iterator"
    )
    
    // client is a global Spanner client, to avoid initializing a new client for
    // every request.
    var client *spanner.Client
    
    // db is the name of the database to query.
    var db = "projects/my-project/instances/my-instance/databases/example-db"
    
    // HelloSpanner is an example of querying Spanner from a Cloud Function.
    func HelloSpanner(w http.ResponseWriter, r *http.Request) {
    	if client == nil {
    		// Declare a separate err variable to avoid shadowing client.
    		var err error
    		client, err = spanner.NewClient(context.Background(), db)
    		if err != nil {
    			http.Error(w, "Error initializing database", http.StatusInternalServerError)
    			log.Printf("spanner.NewClient: %v", err)
    			return
    		}
    	}
    
    	fmt.Fprintln(w, "Albums:")
    	stmt := spanner.Statement{SQL: `SELECT SingerId, AlbumId, AlbumTitle FROM Albums`}
    	iter := client.Single().Query(r.Context(), stmt)
    	defer iter.Stop()
    	for {
    		row, err := iter.Next()
    		if err == iterator.Done {
    			return
    		}
    		if err != nil {
    			http.Error(w, "Error querying database", http.StatusInternalServerError)
    			log.Printf("iter.Next: %v", err)
    			return
    		}
    		var singerID, albumID int64
    		var albumTitle string
    		if err := row.Columns(&singerID, &albumID, &albumTitle); err != nil {
    			http.Error(w, "Error parsing database response", http.StatusInternalServerError)
    			log.Printf("row.Columns: %v", err)
    			return
    		}
    		fmt.Fprintf(w, "%d %d %s\n", singerID, albumID, albumTitle)
    	}
    }
    

    この関数は、SQL クエリを送信してデータベースから Albums のすべてのデータをフェッチします。この関数は、関数のエンドポイントに HTTP リクエストを行うと実行されます。

関数をデプロイする

HTTP トリガーを使用して関数をデプロイするには、spanner ディレクトリで次のコマンドを実行します。

Node.js 8

gcloud functions deploy get --runtime nodejs8 --trigger-http

Node.js 10(ベータ版)

gcloud functions deploy get --runtime nodejs10 --trigger-http

Node.js 6(非推奨)

gcloud functions deploy get --runtime nodejs6 --trigger-http

Python

gcloud functions deploy spanner_read_data --runtime python37 --trigger-http

Go

gcloud functions deploy HelloSpanner --runtime go111 --trigger-http

関数のデプロイには最大で 2 分かかります。

関数のデプロイが完了すると、url 値が返されることに注意してください。関数をトリガーするときにこの値を使用します。

Google Cloud Platform Console の Cloud Functions ページで、デプロイされた関数を参照できます。このページでは関数の作成と編集、関数の詳細と診断を得ることもできます。

関数をトリガーする

関数に HTTP リクエストを出します。

Node.js

curl "https://REGION-PROJECT_ID.cloudfunctions.net/get" 

Python

curl "https://REGION-PROJECT_ID.cloudfunctions.net/spanner_read_data" 

Go

curl "https://REGION-PROJECT_ID.cloudfunctions.net/HelloSpanner" 

ここで、REGIONPROJECT_ID は、関数のデプロイが完了したときにターミナルに表示される値と一致します。スタートガイドのチュートリアルを実施済みで、データベースにデータがある場合は、SQL クエリの結果を示す出力が表示されます。

SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold Your Peace
SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go
SingerId: 2, AlbumId: 1, AlbumTitle: Green
SingerId: 2, AlbumId: 3, AlbumTitle: Terrified
SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk

ブラウザで関数の URL にアクセスして、SQL クエリの結果を確認することもできます。

クリーンアップ

このトピックで使用した Cloud Spanner と Cloud Functions のリソースについて、GCP アカウントに課金されないようにする手順は次のとおりです。

  1. インスタンスを削除します。

    gcloud spanner instances delete test-instance
    
  2. デプロイした関数を削除します。

    Node.js

    gcloud functions delete get 

    Python

    gcloud functions delete spanner_read_data 

    Go

    gcloud functions delete HelloSpanner 

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Cloud Spanner のドキュメント