משימה של Cloud Functions

משימת Cloud Function מאפשרת להגדיר ולהריץ פונקציות Cloud Run מהשילוב. פונקציות Cloud Run הן הדור הבא של Cloud Functions. הן מציעות מודל תכנות מבוסס-אירועים עם שליטה וגמישות משופרות, תוך שימוש בפלטפורמת Cloud Run ללא שרת. פונקציות Cloud Run מספקות פתרון יחיד ללא שרת לכל סוגי עומסי העבודה.

משימת Cloud Function תומכת בגרסאות הבאות של פונקציות Cloud Run:

מידע מפורט על ההבדלים בין גרסאות של פונקציות Cloud Run זמין במדריך השוואה בין Cloud Functions.

לפני שמתחילים

לפני שמגדירים את המשימה Cloud Function, צריך לוודא שמבצעים את המשימות הבאות בפרויקט בענן של Google.

  1. כדי להתחבר ל-Cloud Function, צריך לוודא שיצרתם פרופיל OAuth 2.0 או צירפתם חשבון שירות בניהול המשתמש לאינטגרציה:
    • אם לשילוב שלכם מצורף חשבון שירות, צריך להקצות לחשבון השירות הזה את תפקיד ה-IAM‏ Cloud Function Invoker.

      במאמר ניהול הגישה לחשבונות שירות מוסבר איך נותנים לחשבון שירות תפקיד.

    • המשימה Cloud Function תומכת רק בפרופילי אימות מהסוג Google OIDC ID Token. יוצרים פרופיל אימות מסוג אסימון מזהה של Google OIDC באמצעות חשבון השירות שהוקצה לו תפקיד IAM‏ Cloud Functions Invoker. אם המשימה של Cloud Function לא דורשת אימות, אפשר להשאיר את השדה Authentication profile בחלונית ההגדרות של המשימה ריק.

    אם בשילוב שלכם מוגדרים גם פרופיל מזהה OIDC וגם חשבון שירות בניהול המשתמשים, כברירת מחדל נעשה שימוש בפרופיל מזהה OIDC לאימות. אם לא מוגדר פרופיל OIDC ID ולא מוגדר חשבון שירות בניהול המשתמשים, נעשה שימוש בחשבון השירות שמוגדר כברירת מחדל (service-PROJECT_NUMBER@gcp-sa-integrations.iam.gserviceaccount.com) כדי לקרוא למשימה Cloud Function.

  2. חשוב לוודא ש-VPC Service Controls לא מוגדר עבור Application Integration ב Google Cloud פרויקט.

הגדרת המשימה של Cloud Functions

כדי להגדיר את המשימה Cloud Function בשילוב:

  1. בתפריט הניווט, לוחצים על Integrations (שילובים).

    רשימת השילובים הזמינים תיפתח בממשק המשתמש של Application Integration.

  2. בוחרים שילוב קיים או לוחצים על יצירת שילוב.

    אם יוצרים שילוב חדש, מזינים שם ותיאור בתיבת הדו-שיח ליצירה ולוחצים על יצירה.

  3. בתפריט הנפתח Tasks, לוחצים על Cloud Function כדי למקם אותה בכלי לעריכת שילובים.
  4. לוחצים על הרכיב Cloud Function (פונקציית Cloud) בכלי העיצוב כדי לפתוח את חלונית ההגדרה, ואז לוחצים על Configure Cloud Function (הגדרת פונקציית Cloud).
  5. אם מופיעה בקשה להעניק הרשאות לחשבון השירות, לוחצים על Grant (הענקה).

    ‫Application Integration מעניק באופן אוטומטי את ההרשאות הנדרשות לחשבון השירות.

  6. בחלונית Cloud Function configuration (הגדרת Cloud Function), בוחרים באחת מהאפשרויות הבאות:
    • קישור פונקציה קיימת: בוחרים באפשרות הזו כדי לשייך פונקציה קיימת לשילוב. אפשר לקשר בין Cloud Functions (דור ראשון) לבין Cloud Functions שנוצרו באמצעות Cloud Functions v2 API מהשילוב.
      • בשדה כתובת ה-URL של הטריגר של Cloud Functions, מזינים את כתובת ה-URL של הטריגר של הפונקציה הקיימת.

        כתובת ה-URL צריכה להיות באחד מהפורמטים הבאים:

        # For Cloud Functions (1st gen)
        https://REGION_NAME-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
        # For Cloud Run functions created using the Cloud Functions v2 API
        https://FUNCTION_NAME-PROJECT_ID.REGION_NAME.run.app

    • יצירת פונקציה חדשה: בוחרים באפשרות הזו כדי ליצור פונקציה חדשה לשילוב.
      1. בשדה שם הפונקציה, מזינים שם ייחודי לפונקציות החדשות של Cloud Run.
      2. בתפריט הנפתח אזור, בוחרים את האזור שבו פונקציות Cloud Run נפרסות.
      3. בתפריט הנפתח Function Version, בוחרים את הגרסה הרצויה של פונקציות Cloud Run:
        • Cloud Functions (דור ראשון): זוהי גרסת Legacy של פונקציות Cloud Run, שנקראה בעבר Cloud Functions (דור ראשון), והיא משתמשת בפורמט נקודת הקצה .cloudfunctions.net.
        • Cloud Functions (הדור האחרון): הגרסה האחרונה של פונקציות Cloud Run, שנוצרה באמצעות Cloud Functions v2 API. הוא מבוסס על Cloud Run ו-Eventarc, תומך בפסק זמן מורחב לבקשות (עד 60 דקות), מציע יותר פעולות בו-זמניות ומשתמש בפורמטים של נקודות קצה .cloudfunctions.net ו-.run.app.
        • מידע נוסף על ההבדלים בין שתי הגרסאות זמין במאמר השוואה בין Cloud Functions.
  7. לוחצים על Save.
  8. הגדרת משימת Cloud Function ב-Application Integration יוצרת פונקציות Cloud Run בסיסיות עם טריגר HTTP בפרויקט בענן שלכם ב-Google Cloud.

תבנית של פונקציית Cloud Functions

בדוגמאות הבאות אפשר לראות איך להשתמש במשימה Cloud Function בשילוב בשפות שונות.

Python

כשמגדירים את Cloud Function באמצעות פונקציות Cloud Run קיימות, צריך לוודא שקובצי המקור main.py, task.py ו-requirements.txt של הפונקציה הם בפורמט הבא:

task.py

      # Sample Code:
      # print(event.get('task_string_key'))
      # event.set('task_int_array_key', [456, 789]);
      # event.log('some logging')

      def run(event):
        """Actual cloud function custom logic.
        Args:
          event : event object in main.py that contains all parameters.
        """
        return
    

main.py

      """Un-editable platform wrapper which invokes user code."""
    import traceback

    from flask import json
    from flask import jsonify
    from task import run

    VALUE_NAME = [
        'stringValue', 'intValue', 'doubleValue', 'booleanValue', 'protoValue'
    ]
    ARRAY_VALUE_NAME = {
        'stringArray': 'stringValues',
        'intArray': 'intValues',
        'doubleArray': 'doubleValues',
        'booleanArray': 'booleanValues',
        'protoArray': 'protoValues'
    }
    VALUE_TYPE_URL = 'type.googleapis.com/google.protobuf.Value'
    CLOUD_FUNCTION_EXCEPTION_KEY = 'CloudFunctionException'
    CLOUD_FUNCTION_LOGGING_KEY = 'CloudFunctionLogging'


    class _Event(object):
      """Event object."""

      def __init__(self, json_payload):
        self._event_params = json_payload.get('eventParameters', dict())
        self._task_params = json_payload.get('taskParameters', dict())
        self._log = []
        print('Event param is ' + str(self._event_params))
        print('Task param is ' + str(self._task_params))

      def set(self, key, value):
        """Set the event parameters key-value.

        Args:
          key: parameter key.
          value: parameter value.
        """
        new_param = self._create_param(key, value)
        param = self._get_param_by_key(key)
        if param is None:
          if 'parameters' not in self._event_params:
            self._event_params['parameters'] = []
          self._event_params['parameters'].append(new_param)
        else:
          param['value'] = new_param['value']

      def _create_param(self, key, value):
        """Create a new parameter with given key value pair.

        Args:
          key: parameter key.
          value: parameter value.

        Returns:
          parameter.
        """
        new_param = {}
        new_param['key'] = key
        if isinstance(value, str):
          new_param['value'] = {'stringValue': value}
        elif isinstance(value, int):
          new_param['value'] = {'intValue': value}
        elif isinstance(value, float):
          new_param['value'] = {'doubleValue': value}
        elif isinstance(value, bool):
          new_param['value'] = {'booleanValue': value}
        elif isinstance(value, dict):
          if 'type@' in value:
            new_param['value'] = {'protoValue': value}
          else:
            new_param['value'] = {
                'protoValue': {
                    '@type': 'type.googleapis.com/google.protobuf.Value',
                    'value': value
                }
            }
        elif isinstance(value, list):
          if not value:
            raise RuntimeError('Cannot create a param with empty list')
          if any(not isinstance(val, type(value[0])) for val in value):
            print('Not all elements in the list have the same type')
            new_param['value'] = {
                'protoValue': {
                    '@type': 'type.googleapis.com/google.protobuf.Value',
                    'value': value
                }
            }
          elif isinstance(value[0], str):
            new_param['value'] = {'stringArray': {'stringValues': value}}
          elif isinstance(value[0], int):
            new_param['value'] = {'intArray': {'intValues': value}}
          elif isinstance(value[0], float):
            new_param['value'] = {'doubleArray': {'doubleValues': value}}
          elif isinstance(value[0], bool):
            new_param['value'] = {'booleanArray': {'booleanValues': value}}
          elif isinstance(value[0], dict):
            if all('@type' in val and val['@type'] == value[0]['@type']
                   for val in value):
              new_param['value'] = {'protoArray': {'protoValues': value}}
            else:
              new_param['value'] = {
                  'protoValue': {
                      '@type': 'type.googleapis.com/google.protobuf.Value',
                      'value': value
                  }
              }
          else:
            raise RuntimeError('The type ' + type(value[0]) +
                               ' in the list is not supported')
        else:
          raise RuntimeError('Value ' + str(value) + ' has the type ' +
                             type(value) + ' that is not supported')
        return new_param

      def get(self, key):
        """Get the event parameter value for specified key.

        Args:
          key: parameter key.

        Returns:
          Parameter value.
        """
        param = self._get_param_by_key(key)
        if param is None:
          raise RuntimeError('Can not find param with key ' + key)
        return self._get_param_value(param)

      def _get_param_by_key(self, key):
        """Get the parameter for specified key.

        Args:
          key: parameter key.

        Returns:
          Parameter.
        """
        param = self._get_param_by_key_from_params(key, self._task_params)
        if param is None:
          return self._get_param_by_key_from_params(key, self._event_params)
        value = self._get_param_value(param)
        if isinstance(value, str) and len(value) > 2 and value.startswith(
            '$') and value.endswith('$'):
          return self._get_param_by_key_from_params(value[1:-1], self._event_params)
        return param

      def _get_param_by_key_from_params(self, key, params):
        """Get the parameter for specified key from event parameters.

        Args:
          key: parameter key.
          params: event parameters.

        Returns:
          Parameter.
        """
        if not isinstance(params, dict) or 'parameters' not in params:
          return None
        for param in params['parameters']:
          if param['key'] == key:
            return param
        return None

      def _get_param_value(self, param):
        """Get the parameter value for specified parameter.

        Args:
          param: parameter.

        Returns:
          Parameter value.
        """
        value = param['value']
        if len(value) != 1:
          raise RuntimeError('param does not have size of 1')
        for value_name in VALUE_NAME:
          if value_name in value:
            if value_name == 'protoValue' and value[value_name][
                '@type'] == VALUE_TYPE_URL:
              return value[value_name]['value']
            return value[value_name]
        for array_value_name in ARRAY_VALUE_NAME:
          if array_value_name in value:
            return value[array_value_name][ARRAY_VALUE_NAME[array_value_name]]
        raise RuntimeError('Cannot get value from param ' + str(param))

      def set_error(self):
        """Set the cloud function error to event parameters in order for user to see on IP."""

        self.set(CLOUD_FUNCTION_EXCEPTION_KEY, traceback.format_exc())

      def log(self, message):
        self._log.append(str(message))

      def get_response(self):
        """Get the response that can be returned to IP.

        Returns:
          The response text or any set of values that can be turned into a
          Response object using
          `make_response
          <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
        """
        if self._log:
          self.set(CLOUD_FUNCTION_LOGGING_KEY, self._log)
        res = {
            'eventParameters': self._event_params,
        }
        return jsonify(res)


    def execute_function(request):
      """Entry point of the cloud function.

      Args:
        request (flask.Request): HTTP request object.

      Returns:
        The response text or any set of values that can be turned into a
        Response object using
        `make_response
        <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`.
      """
      try:
        request_json = request.get_json(silent=True)
        event = _Event(request_json)
        run(event)
      except:
        event.set_error()
      return event.get_response()

    

requirements.txt

    # Function dependencies, for example:
    # package>=version
    

מידע נוסף על פורמט התשובה זמין במאמר בנושא ValueType.

Java

בדוגמה הבאה אפשר לראות איך להשתמש במשימה Cloud Function בשילוב. מוודאים שהתגובה היא בפורמט JSON הנתמך, כפי שמתואר בדוגמה:

private static final Gson gson = new Gson();

@Override
public void service(HttpRequest request, HttpResponse response) throws Exception {
  JsonObject body = gson.fromJson(request.getReader(), JsonObject.class);

  JsonArray resParams = new JsonArray();
  for (JsonElement param: body.getAsJsonObject("eventParameters").getAsJsonArray("parameters")) {
    if (param.getAsJsonObject().get("key").getAsString().equals("input")) {
      JsonObject newParam= new JsonObject();
      newParam.addProperty("key", "input");
      JsonObject value = new JsonObject();
      value.addProperty("stringValue","2");
      newParam.add("value", value);
      resParams.add(newParam);
    } else {
      resParams.add(param);
    }
  }
  JsonObject parameters = new JsonObject();
  parameters.add("parameters", resParams);
  JsonObject res = new JsonObject();
  res.add("eventParameters", parameters);
  System.out.println(res);
  BufferedWriter writer = response.getWriter();
  writer.write(res.toString());
}

מידע נוסף על פורמט התשובה זמין במאמר בנושא ValueType.

JavaScript

בדוגמה הבאה אפשר לראות איך להשתמש במשימה Cloud Function בשילוב. מוודאים שהתגובה היא בפורמט JSON הנתמך, כפי שמתואר בדוגמה:

const functions = require('@google-cloud/functions-framework');

functions.http('execute_function', (req, res) => {
  console.log(JSON.stringify(req.body));
  let response = {"eventParameters":{"parameters":[{"key":"input","value":{"stringValue":"2"}}]}};
  res.send(JSON.stringify(response));
});

מידע נוסף על פורמט התשובה זמין במאמר בנושא ValueType.

PHP

בדוגמה הבאה אפשר לראות איך להשתמש במשימה Cloud Function בשילוב. מוודאים שהתגובה היא בפורמט JSON הנתמך, כפי שמתואר בדוגמה:

use Psr\Http\Message\ServerRequestInterface;
function execute_function(ServerRequestInterface $request)
{
  return '{"eventParameters":{"parameters":[{"key":"input","value":{"stringValue":"2"}}]}}';
}

מידע נוסף על פורמט התשובה זמין במאמר בנושא ValueType.

עריכת משימה של Cloud Functions

השירות Application Integration מפנה אתכם לדף המתאים במסוף Google Cloud כדי לערוך את הפונקציות של Cloud Run בהתאם לסוג הגרסה.

‫Cloud Functions (דור ראשון)

כדי לערוך משימה של Cloud Functions שהוגדרה באמצעות הגרסה של Cloud Functions (דור ראשון):

  1. בחלונית ההגדרות של המשימה, לוחצים על Open Cloud Function (פתיחת Cloud Function).

    מועברים לדף Cloud Functions (דור ראשון) > פרטי הפונקציה ב- Google Cloud console.

  2. לוחצים על Edit.
  3. בדף Edit function (עריכת הפונקציה), בשלב Configuration (הגדרה), אפשר לערוך את הגדרות ברירת המחדל של Cloud Function. מידע נוסף זמין במאמר הגדרת Cloud Functions.
  4. לוחצים על הבא כדי להמשיך לשלב קוד ולערוך את קוד המקור של Cloud Functions.

    כברירת מחדל, פונקציית Cloud מכילה את קובצי המקור הבאים:

    • main.py : הקובץ הזה מכיל את קוד האתחול להרצת פונקציית Cloud מהשילוב.
    • task.py : הקובץ הזה מכיל את הקוד הניתן להפעלה של Cloud Function. כותבים את הסקריפט בתוך הפונקציה run(event). הפונקציה הזו מופעלת כשמשימת Cloud Functions מתבצעת. אובייקט event מקובץ main.py מכיל את כל פרמטרי המשימה.

      במאמר גישה למשתני שילוב מוסבר איך להשתמש בסקריפט במשתנים שמוגדרים ברמת השילוב.

  5. לוחצים על פריסה.

פונקציות Cloud Run

כדי לערוך משימה של Cloud Functions שהוגדרה באמצעות הגרסה Cloud Functions (הדור האחרון):

  1. בחלונית ההגדרות של המשימה, לוחצים על Open Cloud Function (פתיחת Cloud Function).

    תופנו לדף Cloud Run functions > Service details ב- Google Cloud console.

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

    כברירת מחדל, פונקציות Cloud Run מכילות את קובצי המקור הבאים:

    • main.py : הקובץ הזה מכיל את קוד האתחול להרצת Cloud Functions מהשילוב.
    • task.py: הקובץ הזה מכיל את הקוד הניתן להפעלה של Cloud Functions. כותבים את הסקריפט בתוך הפונקציה run(event). הפונקציה הזו מופעלת כשמשימת הפונקציות של Cloud Run מופעלת. אובייקט event מקובץ main.py מכיל את כל פרמטרי המשימה.

      במאמר גישה למשתני שילוב מוסבר איך להשתמש בסקריפט במשתנים שמוגדרים ברמת השילוב.

  3. לוחצים על שמירה ופריסה מחדש.

גישה למשתני שילוב

כדי לגשת למשתנה שילוב בפונקציה של Cloud Functions, מעבירים את המשתנה כפרמטר של משימה למשימה Cloud Function. פרמטר המשימה הוא צמד מפתח/ערך שבו Key הוא השם של משתנה ההפניה שמשמש בקובץ המקור של Cloud Functions, ו-Value הוא השם של משתנה השילוב התואם שאליו משתנה ההפניה מצביע. אפשר להוסיף פרמטר משימה אחד או יותר בקטע פרמטרים של משימה בחלונית ההגדרה של המשימה.

כדי לגשת למשתני השילוב מ-Cloud Function, משתמשים בשיטות הבאות:

  • set: כתיבת הערך למשתנה.
  • get: קורא את הערך של משתנה.

לדוגמה, אם יש לכם משתנה שילוב בשם EmployeeName שבו אתם רוצים להשתמש בקובץ המקור של Cloud Functions, אתם צריכים להגדיר את פרמטרי המשימה הבאים:

  • מקרא: EmployeeKey
  • ערך: EmployeeName

בסקריפט לדוגמה הבא אפשר לראות איך משתמשים בפונקציות set ו-get כדי לגשת למשתני השילוב שהוגדרו.

def run(event):  
  # Read the integration variable EmployeeName using the reference variable EmployeeKey
  value = event.get('EmployeeKey');
  # Change the integration variable EmployeeName value using the reference variable EmployeeKey
  event.set('EmployeeKey' , 'XYZ');
  # The new value of the integration variable is retained throughout the Cloud Function task.
  return

אסטרטגיה לטיפול בשגיאות

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

החרגות בהסכם רמת השירות

למשימה של Cloud Functions יש תלות במוצר Google Cloud Functions. מכיוון שהתלות הזו היא חיצונית ל-Application Integration, כל ההפעלות של שילובי active שנכשלות בגלל הכשל במשימת Cloud Function לא נכללות בתנאים ובהגבלות של הסכם רמת השירות (SLA) של Application Integration.

מכסות ומגבלות

מידע על מכסות ומגבלות של פונקציות Cloud Run ו-Cloud Functions (דור ראשון) זמין במאמר השוואה בין הגדרות.

המאמרים הבאים