Usa Cloud Functions

Objetivos

Escribe, implementa y activa una Cloud Function de HTTP que acceda a Bigtable.

Costos

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

  • Para obtener información sobre el costo del uso de Bigtable, consulta Precios de Bigtable.

  • Para obtener información sobre el costo del uso de Cloud Functions, incluidas las invocaciones gratuitas, consulta Precios de Cloud Functions.

Antes de comenzar

  1. En este tema, se supone que tienes una instancia de Bigtable llamada test-instance y una tabla llamada test-table. Puedes crear estos recursos si sigues los pasos en Crea una tabla de prueba. Asegúrate de borrar los recursos cuando termines para evitar incurrir en costos innecesarios.

  2. Habilita la API de Cloud Functions.

    Habilitar la API

  3. Instala e inicializa la CLI de gcloud.

    Si ya tienes instalada la CLI de gcloud, ejecuta el siguiente comando para actualizarla:

    gcloud components update
    
  4. 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. Cambia al directorio que contiene el código de muestra de Cloud Functions para acceder a Bigtable:

    Node.js

    cd nodejs-docs-samples/functions/bigtable/

    Python

    cd python-docs-samples/functions/bigtable/

    Go

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

    Node.js

    // Imports the Google Cloud client library
    const {Bigtable} = require('@google-cloud/bigtable');
    
    // Instantiates a client
    const bigtable = new Bigtable();
    
    exports.readRows = async (req, res) => {
      // Gets a reference to a Cloud Bigtable instance and database
      const instance = bigtable.instance(req.body.instanceId);
      const table = instance.table(req.body.tableId);
    
      // Execute the query
      try {
        const prefix = 'phone#';
        const rows = [];
        await table
          .createReadStream({
            prefix,
          })
          .on('error', err => {
            res.send(`Error querying Bigtable: ${err}`);
            res.status(500).end();
          })
          .on('data', row => {
            rows.push(
              `rowkey: ${row.id}, ` +
                `os_build: ${row.data['stats_summary']['os_build'][0].value}\n`
            );
          })
          .on('end', () => {
            rows.forEach(r => res.write(r));
            res.status(200).end();
          });
      } catch (err) {
        res.send(`Error querying Bigtable: ${err}`);
        res.status(500).end();
      }
    };
    

    Python

    from google.cloud import bigtable
    from google.cloud.bigtable.row_set import RowSet
    
    client = bigtable.Client()
    
    def bigtable_read_data(request):
        instance = client.instance(request.headers.get("instance_id"))
        table = instance.table(request.headers.get("table_id"))
    
        prefix = "phone#"
        end_key = prefix[:-1] + chr(ord(prefix[-1]) + 1)
    
        outputs = []
        row_set = RowSet()
        row_set.add_row_range_from_keys(prefix.encode("utf-8"), end_key.encode("utf-8"))
    
        rows = table.read_rows(row_set=row_set)
        for row in rows:
            output = "Rowkey: {}, os_build: {}".format(
                row.row_key.decode("utf-8"),
                row.cells["stats_summary"][b"os_build"][0].value.decode("utf-8"),
            )
            outputs.append(output)
    
        return "\n".join(outputs)
    
    

    Go

    
    // Package bigtable contains an example of using Bigtable from a Cloud Function.
    package bigtable
    
    import (
    	"context"
    	"fmt"
    	"log"
    	"net/http"
    	"sync"
    
    	"cloud.google.com/go/bigtable"
    )
    
    // client is a global Bigtable client, to avoid initializing a new client for
    // every request.
    var client *bigtable.Client
    var clientOnce sync.Once
    
    // BigtableRead is an example of reading Bigtable from a Cloud Function.
    func BigtableRead(w http.ResponseWriter, r *http.Request) {
    	clientOnce.Do(func() {
    		// Declare a separate err variable to avoid shadowing client.
    		var err error
    		client, err = bigtable.NewClient(context.Background(), r.Header.Get("projectID"), r.Header.Get("instanceId"))
    		if err != nil {
    			http.Error(w, "Error initializing client", http.StatusInternalServerError)
    			log.Printf("bigtable.NewClient: %v", err)
    			return
    		}
    	})
    
    	tbl := client.Open(r.Header.Get("tableID"))
    	err := tbl.ReadRows(r.Context(), bigtable.PrefixRange("phone#"),
    		func(row bigtable.Row) bool {
    			osBuild := ""
    			for _, col := range row["stats_summary"] {
    				if col.Column == "stats_summary:os_build" {
    					osBuild = string(col.Value)
    				}
    			}
    
    			fmt.Fprintf(w, "Rowkey: %s, os_build:  %s\n", row.Key(), osBuild)
    			return true
    		})
    
    	if err != nil {
    		http.Error(w, "Error reading rows", http.StatusInternalServerError)
    		log.Printf("tbl.ReadRows(): %v", err)
    	}
    }
    

    La función envía una solicitud de lectura a la tabla para recuperar todos los datos de stats_summary de las filas con un prefijo de clave de fila de phone. 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 bigtable para implementar la función con un activador HTTP:

Node.js

gcloud functions deploy get \
--runtime nodejs20 --trigger-http

Usa la marca --runtime para especificar el ID del entorno de ejecución de una versión compatible de Node.js para ejecutar la función.

Python

gcloud functions deploy bigtable_read_data \
--runtime python312 --trigger-http

Usa la marca --runtime para especificar el ID de entorno de ejecución de una versión de Python compatible para ejecutar la función.

Go

gcloud functions deploy BigtableRead \
--runtime go121 --trigger-http

Usa la marca --runtime para especificar el ID de entorno de ejecución de una versión de Go compatible con el fin de ejecutar tu función.

La implementación de la función puede tomar hasta dos minutos.

Cuando la función termina de implementarse, se muestra el valor url. Usarás ese valor cuando actives la función.

Puedes ver las funciones que implementaste en la página de Cloud Functions en la consola de Google Cloud. 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" -H "instance_id: test-instance" -H "table_id: test-table"

Python

curl "https://REGION-PROJECT_ID.cloudfunctions.net/bigtable_read_data" -H "instance_id: test-instance" -H "table_id: test-table"

Go

curl "https://REGION-PROJECT_ID.cloudfunctions.net/BigtableRead" -H "instance_id: test-instance" -H "table_id: test-table"

En el ejemplo anterior, 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 un resultado que muestre los resultados de la solicitud de lectura.

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

Limpia

Para evitar que se apliquen cargos adicionales a la cuenta de Google Cloud por los recursos de Bigtable y Cloud Functions usados en este tema, sigue estos pasos:

  1. Borra la instancia:

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

    Node.js

    gcloud functions delete get 

    Python

    gcloud functions delete bigtable_read_data 

    Go

    gcloud functions delete BigtableRead 

¿Qué sigue?