Mit einer Spanner-Remote-Funktion können Sie Ihre Funktion in anderen Sprachen als SQL implementieren. Funktionen müssen in Cloud Run Functions oder Cloud Run gehostet werden. Wenn Sie Funktionen auf diese Weise hosten, kann komplexe Geschäftslogik in separate Remote-Funktionen aufgeteilt werden.
Eine typische Bereitstellung von Remote-Funktionen umfasst die folgenden Schritte:
Erstellen Sie einen HTTPS-Endpunkt in Cloud Run-Funktionen oder Cloud Run.
- Wenn Sie noch keine Erfahrung mit Remote-Funktionen haben, empfehlen wir die Verwendung von Cloud Run Functions.
Erstellen Sie eine Remote-Funktion in Spanner, die auf diesen HTTPS-Endpunkt verweist.
Erforderliche Rollen
Damit Ihr Spanner-Agent-Dienstkonto (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) die erforderlichen Berechtigungen zum Verwenden von Spanner-Remote-Funktionen hat, bitten Sie Ihren Administrator, Ihrem Spanner-Agent-Dienstkonto (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) die
Spanner API Service Agent (roles/spanner.serviceAgent) IAM-Rolle für das Projekt zu gewähren.
Ihr Administrator kann Ihrem Spanner-Agent-Dienstkonto (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) auch Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.
Unterstützte Typen
Remote-Funktionen unterstützen die folgenden Datentypen als Argument- oder Rückgabetypen:
ARRAY(eines der folgenden unterstützten Typen)BOOLEANBYTESDATEJSONINTEGERNUMERICSTRINGTIMESTAMP
Beschränkungen
Tabellenwert-Remote-Funktionen mit können nicht erstellt werden.
Remote-Funktionen werden in Ausdrücken für generierte Spalten nicht unterstützt.
Vorübergehende Anfragen mit denselben Daten an Ihrem Endpunkt können aufgrund vorübergehender Netzwerkfehler oder interner Spanner-Neustarts auch nach erfolgreichen Antworten wiederholt werden.
Das Ausführen von Remote-Funktionen in fraktionierten Spanner-Instanzen wird nicht unterstützt.
Remote-Funktionen werden für Cloud Run-Funktionen hinter benutzerdefinierten Domains nicht unterstützt.
Remote-Funktionen werden im PostgreSQL-Dialekt nicht unterstützt.
Endpunkt erstellen
Die Geschäftslogik muss als Cloud Functions-Funktion oder Cloud Run implementiert werden. Der Endpunkt muss einen Zeilen-Batch in einer einzelnen HTTPS-POST-Anfrage verarbeiten und das Ergebnis für den Batch als HTTPS-Antwort zurückgeben können.
Wenn Sie Remote-Funktionen für BigQuery erstellt haben, können Sie sie für Spanner wiederverwenden.
Informationen zum Schreiben, Bereitstellen, Testen und Verwalten einer Cloud Run-Funktion finden Sie in der Cloud Run Functions-Anleitung und in der weiteren Dokumentation zu Cloud Run Functions.
In der Cloud Run-Kurzanleitung und anderen Cloud Run-Dokumentationen erfahren Sie, wie Sie einen Cloud Run-Dienst schreiben, bereitstellen, testen und warten.
Wir empfehlen, die Standardauthentifizierung für Ihre Cloud Run-Funktion oder Ihren Cloud Run-Dienst beizubehalten. Konfigurieren Sie den Dienst nicht so, dass nicht authentifizierte Aufrufe zugelassen werden.
Eingabeformat
Spanner sendet HTTPS-POST-Anfragen mit JSON-Texten im folgenden Format:
| Feldname | Beschreibung | Feldtyp |
|---|---|---|
requestId
|
Anfragekennung. Eindeutiger Wert für mehrere Anfragen, die in einer GoogleSQL-Abfrage an den Endpunkt gesendet werden. | Immer bereitgestellt. String. |
calls
|
Ein Eingabedaten-Batch. | Immer bereitgestellt. Ein JSON-Array.
Jedes Element ist ein JSON-Array, das eine JSON-codierte Argumentenliste für einen einzelnen Remote-Funktionsaufruf darstellt. |
Beispiel für eine Anfrage:
// Sample request to a Cloud Run functions to calculate sum of two numbers. This request
// has two calls batched together into a single request.
{
"requestId": "124ab1c",
"calls": [
[1, 2],
[3, 4]
]
}
Ausgabeformat
Spanner erwartet, dass der Endpunkt eine HTTPS-Antwort im folgenden Format zurückgibt. Andernfalls kann Spanner die Antwort nicht verarbeiten und die Abfrage, die die Remote-Funktion aufruft, schlägt fehl.
| Feldname | Beschreibung | Wertebereich |
replies
|
Ein Rückgabewerte-Batch. | JSON-Array.
Jedes Element entspricht einem JSON-codierten Rückgabewert der externen Funktion. Die Größe des Arrays muss mit der Größe des JSON-Arrays voncalls in der HTTPS-Anfrage übereinstimmen. Wenn das JSON-Array in calls beispielsweise vier Elemente hat, muss dieses JSON-Array auch vier Elemente haben. Erforderlich für eine erfolgreiche Antwort.
|
errorMessage
|
Fehlermeldung, wenn ein anderer HTTPS-Antwortcode als 200 zurückgegeben wird. Bei nicht wiederholbaren Fehlern gibt Spanner diese Fehlermeldung an den Nutzer zurück. Erforderlich bei fehlgeschlagenen Antworten. In der Regel weniger als 1 KB. | String. |
Beispiel für eine erfolgreiche Antwort:
// Sample response from the Cloud Run functions which has the sum of the two numbers. Note
// that the order of the values within `replies` field matches the `calls` field from
// the request.
{
"replies": [
3, // 1 + 2 = 3
7 // 3 + 4 = 7
]
}
Beispiel für eine fehlgeschlagene Antwort:
{
// The error message returned by your Cloud Run functions to indicate an error.
// In this sample, the error message states that an overflow occurred when summing two numbers.
"errorMessage": "Overflow detected when calculating sum of two numbers."
}
HTTPS-Antwortcode
Ihr Endpunkt gibt für eine erfolgreiche Antwort den HTTPS-Code 200 zurück. Wenn Spanner einen beliebigen anderen Wert empfängt, betrachtet Spanner die Antwort als Fehler und wiederholt den Vorgang, wenn der HTTPS-Antwortcode 408, 429, 500, 503 oder 504 bis zu einem internen Limit ist.
Beispielcode
Cloud Run-Funktion
Im folgenden Python-Beispielcode wird das Hinzufügen aller Ganzzahlargumente der Remote-Funktion implementiert. Er verarbeitet eine Anfrage mit den Argumenten für Batchaufrufe und gibt das gesamte Ergebnis in einer Antwort zurück.
"""
Python script which uses Flask framework to spin up a HTTP server to take
integers and return their sum. In case of overflow, it returns the error
as part of the response.
"""
import functions_framework
from flask import jsonify
# Max INT64 value encoded as a number in JSON by TO_JSON_STRING. Larger values are encoded as
# strings.
_MAX_LOSSLESS=9007199254740992
@functions_framework.http
def batch_add(request):
try:
return_value = []
request_json = request.get_json()
calls = request_json['calls']
for call in calls:
return_value.append(sum([int(x) if isinstance(x, str) else x for x in call if x is not None]))
replies = [str(x) if x > _MAX_LOSSLESS or x < -_MAX_LOSSLESS else x for x in return_value]
return_json = jsonify( { "replies": replies } )
return return_json
except Exception as e:
return jsonify( { "errorMessage": str(e) } ), 400
Angenommen, die Funktion wird im Projekt PROJECT_ID
in der Region us-east1 als Funktionsname remote_add bereitgestellt und kann über den Endpunkt https://us-east1-PROJECT_ID.cloudfunctions.net/remote_add aufgerufen werden.
Cloud Run
Im folgenden Python-Beispielcode wird ein Webdienst implementiert, der für dieselbe Funktionalität in Cloud Run erstellt und bereitgestellt werden kann.
"""
Python script which uses Flask framework to spin up a HTTP server to take
integers and return their sum. In case of overflow, it returns the error
as part of the response.
"""
import os
from flask import Flask, request, jsonify
# Max INT64 value encoded as a number in JSON by TO_JSON_STRING. Larger values are encoded as
# strings.
_MAX_LOSSLESS=9007199254740992
app = Flask(__name__)
@app.route("/", methods=['POST'])
def batch_add():
try:
return_value = []
request_json = request.get_json()
calls = request_json['calls']
for call in calls:
return_value.append(sum([int(x) if isinstance(x, str) else x for x in call if x is not None]))
replies = [str(x) if x > _MAX_LOSSLESS or x < -_MAX_LOSSLESS else x for x in return_value]
return jsonify( { "replies" : replies } )
except Exception as e:
return jsonify( { "errorMessage": str(e) } ), 400
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Informationen zum Erstellen und Bereitstellen des Codes finden Sie unter Kurzanleitung: Python-Web-App (Flask) in Cloud Run erstellen und bereitstellen.
Angenommen, der Cloud Run-Dienst wird im Projekt PROJECT_ID in der Region us-east1 als Dienstname remote_add bereitgestellt, auf den über den Endpunkt https://remote_add-<project_id_hash>-ue.a.run.app zugegriffen werden kann.
Remote-Funktion erstellen
So erstellen Sie eine Remote-Funktion:
SQL
Führen Sie die folgende CREATE FUNCTION-Anweisung in Spanner aus:
CREATE FUNCTION REMOTE_FUNCTION_NAME(x INT64, y INT64) RETURNS INT64 NOT DETERMINISTIC LANGUAGE REMOTE OPTIONS (
endpoint = `ENDPOINT_URL`,
max_batching_rows = MAX_BATCHING_ROWS
);
Ersetzen Sie Folgendes:
REMOTE_FUNCTION_NAME: Der Name Ihrer Remote-Funktion. Beispiel:sum_funcENDPOINT_URL: die Cloud Run-Funktionen oder der Cloud Run-Endpunkt, die im vorherigen Schritt erstellt wurden.MAX_BATCHING_ROWS(optional): Die maximale Anzahl der Zeilen, die als Teil einer Anfrage gesendet werden sollen. Wenn nichts angegeben ist, bestimmt Spanner die Batchgröße automatisch.
Remote-Funktion in einer Abfrage verwenden
Wenn Sie die Remote-Funktion aus dem vorherigen Schritt in einer Abfrage aufrufen möchten, verwenden Sie das folgende Beispiel:
SELECT REMOTE_FUNCTION_NAME(1, 2); -- 1 + 2 = 3
Preise
Es gelten die standardmäßigen Spanner-Preise.
Spanner berechnet die an Cloud Run Functions oder Cloud Run gesendeten und von dort empfangenen Bytes.
Für diese Funktion können Kosten für Cloud Run Functions und Cloud Run anfallen. Weitere Informationen finden Sie auf den Preisseiten für Cloud Run-Funktionen und Cloud Run.