פונקציות מרוחקות של Spanner

פונקציה מרוחקת ב-Spanner מאפשרת לכם להטמיע את הפונקציה בשפות שאינן SQL. הפונקציות צריכות להתארח ב-פונקציות Cloud Run או ב- Cloud Run. אירוח פונקציות באופן הזה מאפשר לפצל לוגיקה עסקית מורכבת לפונקציות נפרדות מרחוק.

פריסה טיפוסית של פונקציה מרחוק כוללת את השלבים הבאים:

  1. יוצרים נקודת קצה מסוג HTTPS בפונקציות Cloud Run או ב-Cloud Run.

    • אם אתם חדשים בפונקציות מרחוק, מומלץ להשתמש בפונקציות של Cloud Run.
  2. יוצרים פונקציה מרוחקת ב-Spanner שמפנה לנקודת הקצה הזו מסוג HTTPS.

  3. שימוש בפונקציה remote בשאילתה.

התפקידים הנדרשים

כדי לוודא שלחשבון השירות של סוכן Spanner ‏ (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) יש את ההרשאות שנדרשות לשימוש בפונקציות מרוחקות של Spanner, צריך לבקש מהאדמין להקצות לחשבון השירות של סוכן Spanner ‏ (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) בפרויקט את תפקיד ה-IAM ‏Spanner API Service Agent (roles/spanner.serviceAgent).

מידע נוסף על הקצאת תפקידים מופיע במאמר ניהול הגישה לפרויקטים, לתיקיות ולארגונים.

יכול להיות שהאדמין יוכל גם לתת לחשבון השירות של סוכן Spanner (service-PROJECT_ID@gcp-sa-spanner.iam.gserviceaccount.com) ההרשאות הנדרשות באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש אחרים.

סוגים נתמכים

פונקציות מרוחקות תומכות בסוגי הנתונים הבאים כארגומנטים או כסוגי החזרה:

  • ARRAY (מכל אחד מהסוגים הנתמכים הבאים)
  • BOOLEAN
  • BYTES
  • DATE
  • JSON
  • INTEGER
  • NUMERIC
  • STRING
  • TIMESTAMP

מגבלות

  • אי אפשר ליצור פונקציות מרוחקות שמחזירות טבלה.

  • אין תמיכה בפונקציות מרוחקות בביטויי עמודות שנוצרו.

  • יכול להיות שתראו בקשות חוזרות עם אותם נתונים לנקודת הקצה, לפעמים גם אחרי תגובות מוצלחות, בגלל שגיאות זמניות ברשת או הפעלות מחדש פנימיות של Spanner.

  • אין תמיכה בהפעלת פונקציות מרוחקות במופעי Spanner חלקיים.

  • אין תמיכה בפונקציות מרוחקות בפונקציות Cloud Run מאחורי דומיינים בהתאמה אישית.

  • אין תמיכה בפונקציות מרחוק בניב PostgreSQL.

יצירת נקודת קצה

הלוגיקה העסקית צריכה להיות מוטמעת כפונקציית Cloud Run או כ-Cloud Run. נקודת הקצה צריכה להיות מסוגלת לעבד קבוצה של שורות בבקשת HTTPS POST אחת ולהחזיר את התוצאה של הקבוצה כתגובת HTTPS.

אם יצרתם פונקציות מרוחקות ל-BigQuery, תוכלו להשתמש בהן מחדש ב-Spanner.

במדריך לפונקציות Cloud Run ובמסמכים נוספים בנושא פונקציות Cloud Run מוסבר איך לכתוב, לפרוס, לבדוק ולתחזק פונקציית Cloud Run.

במאמר מדריך למתחילים בנושא Cloud Run וב מסמכי עזרה אחרים בנושא Cloud Run מוסבר איך לכתוב, לפרוס, לבדוק ולתחזק שירות Cloud Run.

מומלץ להשתמש באימות ברירת המחדל לפונקציית Cloud Run או לשירות Cloud Run. לא מומלץ להגדיר את השירות כך שיאפשר הפעלה לא מאומתת.

פורמט קלט

‫Spanner שולח בקשות HTTPS POST עם גופי JSON בפורמט הבא:

שם השדה תיאור סוג השדה
requestId מזהה הבקשה. ערך ייחודי בכמה בקשות שנשלחו לנקודת הקצה בשאילתת GoogleSQL. תמיד מסופק. מחרוזת.
calls אצווה של נתוני קלט. תמיד מסופק. מערך JSON.

כל רכיב הוא מערך JSON שמייצג רשימת ארגומנטים בקידוד JSON לבקשה יחידה להפעלת פונקציה מרוחקת.

דוגמה לבקשה:

// 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]
 ]
}

פורמט פלט

מערכת Spanner מצפה שנקודת הקצה תחזיר תגובת HTTPS בפורמט הבא. אחרת, מערכת Spanner לא יכולה לצרוך את התגובה והשאילתה נכשלת בקריאה לפונקציה המרוחקת.

שם השדה תיאור טווח ערכים
replies קבוצה של ערכים שמוחזרים. מערך JSON.

כל רכיב תואם לערך שמוחזר מהפונקציה החיצונית בקידוד JSON.

הגודל של המערך צריך להיות זהה לגודל של מערך ה-JSON של calls בבקשת ה-HTTPS. לדוגמה, אם מערך ה-JSON ב-calls מכיל 4 רכיבים, גם מערך ה-JSON הזה צריך להכיל 4 רכיבים. חובה למלא את השדות האלה כדי שהתגובה תהיה תקינה.
errorMessage הודעת שגיאה שמוחזרת כשקוד התגובה של HTTPS שונה מ-200. במקרה של שגיאות שלא ניתן לנסות שוב, Spanner מחזיר את הודעת השגיאה הזו למשתמש. חובה בתגובות שנכשלו. בדרך כלל פחות מ-1KB. מחרוזת.

דוגמה לתגובה מוצלחת:

// 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
  ]
}

דוגמה לתגובה שנכשלה:

{
  // 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

נקודת הקצה מחזירה קוד HTTPS 200 לתגובה מוצלחת. כש-Spanner מקבל ערך אחר, הוא מחשיב את התגובה ככישלון ומנסה שוב אם קוד התגובה של HTTPS הוא 408,‏ 429, ‏ 500, ‏ 503 או 504, עד שמגיעים למגבלה פנימית.

קוד לדוגמה

פונקציית Cloud Run

בדוגמת הקוד הבאה ב-Python מוצגת הטמעה של הוספת כל הארגומנטים של המספרים השלמים של הפונקציה המרוחקת. היא מטפלת בבקשה עם הארגומנטים להפעלות באצווה ומחזירה את כל התוצאות בתגובה.

"""
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

בהנחה שהפונקציה נפרסה בפרויקט PROJECT_ID באזור us-east1 עם שם הפונקציה remote_add, אפשר לגשת אליה באמצעות נקודת הקצה https://us-east1-PROJECT_ID.cloudfunctions.net/remote_add.

Cloud Run

קוד Python לדוגמה הבא מיישם שירות אינטרנט שאפשר ליצור ולפרוס ב-Cloud Run כדי לקבל את אותה הפונקציונליות.

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

כדי לבנות ולפרוס את הקוד, אפשר לעיין במאמר מדריך למתחילים: בנייה ופריסה של אפליקציית אינטרנט ב-Python ‏(Flask) ב-Cloud Run.

בהנחה ששירות Cloud Run נפרס בפרויקט PROJECT_ID באזור us-east1 עם שם השירות remote_add, אפשר לגשת אליו באמצעות נקודת הקצה https://remote_add-<project_id_hash>-ue.a.run.app.

יצירת פונקציה מרוחקת

כדי ליצור פונקציה מרחוק:

SQL

מריצים את ההצהרה CREATE FUNCTION הבאה ב-Spanner:

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

מחליפים את מה שכתוב בשדות הבאים:

  • REMOTE_FUNCTION_NAME: השם של הפונקציה המרוחקת. לדוגמה, sum_func.
  • ENDPOINT_URL: נקודת הקצה של פונקציות Cloud Run או Cloud Run שנוצרה בשלב הקודם.
  • MAX_BATCHING_ROWS (אופציונלי): מספר השורות המקסימלי שיישלח כחלק מהבקשה. אם לא מציינים את גודל האצווה, Spanner קובע אותו באופן אוטומטי.

שימוש בפונקציה מרוחקת באילתא

כדי להפעיל את הפונקציה המרוחקת מהשלב הקודם בתוך שאילתה, משתמשים בדוגמה הבאה:

SELECT REMOTE_FUNCTION_NAME(1, 2); -- 1 + 2 = 3

תמחור

  • יחול התמחור הרגיל של Spanner.

  • ב-Spanner, החיוב הוא לפי בייט שנשלח אל פונקציות Cloud Run או אל Cloud Run ומתקבל מהן.

  • יכול להיות שיהיו עלויות על השימוש בתכונה הזו מפונקציות Cloud Run ומ-Cloud Run. פרטים נוספים זמינים בדפי המחירון של פונקציות Cloud Run ושל Cloud Run.