Usa Cloud Spanner con Cloud Functions

Cloud Spanner English Context Link

Objetivos

Escribe, implementa y activa una función de HTTP de Cloud Functions que acceda a Cloud Spanner.

Costos

En este tema, se usan Cloud Spanner y Cloud Functions, que son componentes facturables de Google Cloud Platform.

Antes de comenzar

  1. En este tema, se supone que tienes una instancia de Cloud Spanner llamada test-instance y una base de datos llamada example-db que usa el esquema de aplicación de música. A fin de obtener instrucciones para crear una instancia y una base de datos con el esquema de aplicación de música, consulta la Guía de inicio rápido sobre el uso de Console o los instructivos Introducción a Go, Java, Node.js o Python.

  2. Habilita la API de Cloud Functions.
    Habilita la API de Cloud Functions

  3. Instala y, luego, inicializa el SDK de Cloud.

  4. Actualiza los componentes de gcloud:

    gcloud components update
    
  5. Prepara tu entorno de desarrollo:

Prepara la aplicación

  1. Clona el repositorio de la app de muestra en tu máquina local:

    Node.js

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

    De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.

    Python

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

    De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.

    Go

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

    De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.

  2. Ve al directorio que contiene el código de muestra de Cloud Functions para acceder a Cloud Spanner:

    Node.js

    cd nodejs-docs-samples/functions/spanner/

    Python

    cd python-docs-samples/functions/spanner/

    Go

    cd golang-samples/functions/spanner/
  3. Observa el código de muestra:

    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)
    	}
    }
    

    La función envía una consulta de SQL para recuperar todos los datos de Albums de tu base de datos. La función se ejecuta cuando haces una solicitud HTTP al extremo de la función.

Implementa la función

Ejecuta el siguiente comando en el directorio spanner para implementar la función con un activador HTTP:

Node.js 8

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

Node.js 10 (Beta)

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

Node.js 6 (obsoleto)

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

La implementación de la función puede tardar hasta 2 minutos.

Ten en cuenta el valor de url que se muestra cuando tu función termina de implementarse. Lo usarás cuando actives la función.

Puedes ver las funciones que implementaste en la página de Cloud Functions en Google Cloud Platform Console. También puedes crear y editar funciones en esa página, en la que además puedes obtener detalles y diagnósticos de tus funciones.

Activa la función

Haz una solicitud HTTP a tu función:

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" 

donde REGION y PROJECT_ID coinciden con los valores que son visibles en la terminal cuando la función se termina de implementar. Deberías ver una respuesta que muestre los resultados de la consulta de SQL, suponiendo que trabajaste con un instructivo de introducción y propagaste la base de datos:

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

También puedes visitar la URL de la función en tu navegador para ver los resultados de tu consulta de SQL.

Limpieza

Para evitar incurrir en cargos adicionales en tu cuenta de GCP por los recursos de Cloud Spanner y Cloud Functions que se usaron en este tema, sigue estos pasos:

  1. Borra la instancia:

    gcloud spanner instances delete test-instance
    
  2. Borra la función que implementaste:

    Node.js

    gcloud functions delete get 

    Python

    gcloud functions delete spanner_read_data 

    Go

    gcloud functions delete HelloSpanner 

Qué sigue

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Documentación de Cloud Functions