הכנת קוד הפלאגין

צריך לארוז את הקוד המותאם אישית שיוצרים עבור תוספים של Service Extensions ולהעלות אותו ל-Artifact Registry לפני ששירותים אחרים יוכלו לגשת אליו. בדף הזה מוסבר איך ליצור קוד של פלאגין, לארוז את הקוד ולהעלות אותו למאגר של Artifact Registry.

התכונה הזו נמצאת בגרסת טרום-השקה ב-Media CDN.

מידע על Service Extensions זמין במאמר סקירה כללית על Service Extensions.

לפני שמתחילים, מומלץ לעיין בשיטות המומלצות לכתיבת קוד של תוסף.

דוגמאות נוספות זמינות במאמר דוגמאות קוד לתוספים.

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

  1. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Network Services, Network Actions, Artifact Registry, Cloud Build, Cloud Logging, and Cloud Monitoring APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  5. התקינו את ה-CLI של Google Cloud.

  6. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  7. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init
  8. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  9. Verify that billing is enabled for your Google Cloud project.

  10. Enable the Network Services, Network Actions, Artifact Registry, Cloud Build, Cloud Logging, and Cloud Monitoring APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  11. התקינו את ה-CLI של Google Cloud.

  12. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  13. כדי לאתחל את ה-CLI של gcloud, הריצו את הפקודה הבאה:

    gcloud init

הגדרת שרשרת הכלים

C++‎

Proxy-Wasm C++ SDK מאפשר למפתחים להשתמש ב-C++‎ כדי להטמיע תוספים של WebAssembly ‏ (Wasm) עבור Service Extensions. ה-SDK משתמש בערכת הכלים של C++‎ WebAssembly‏ Emscripten, וגם בספריות אחרות, כמו protobuf, ובאופן אופציונלי, Abseil.

בגלל שבניית פלאגינים שנכתבו ב-C++ תלויה בגרסאות ספציפיות של הכלים והספריות האלה, אנחנו ממליצים להשתמש בקובץ אימג' של Docker שסופק על ידי Proxy-Wasm C++ SDK. ההוראות ל-C++‎ בדף הזה מתייחסות לשיטה של Docker. כדי ליצור תוספי C++ בלי להשתמש ב-Docker, אפשר לעיין במסמכי ה-SDK של Proxy-Wasm C++.

  1. מתקינים את Docker אם הוא עדיין לא מותקן. ‫Docker כלול ב-Cloud Shell, סביבת המעטפת האינטראקטיבית של Google Cloud .

  2. מורידים עותק של Proxy-Wasm C++ SDK. הדרך הכי פשוטה לעשות את זה היא לשכפל את מאגר Git:

    git clone https://github.com/proxy-wasm/proxy-wasm-cpp-sdk.git
    
  3. יוצרים את קובץ האימג' של Docker של Proxy-Wasm C++ SDK מקובץ Dockerfile שסופק על ידי ה-SDK:

    cd proxy-wasm-cpp-sdk
    docker build -t wasmsdk:v3 -f Dockerfile-sdk .
    

    כשהפקודה מסיימת ליצור ספריות ותלויות של SDK, קובץ האימג' של Docker שמתקבל משויך לתג שצוין, שהוא wasmsdk:v3 בדוגמה הזו.

המשך

Proxy-Wasm Go SDK מספק ערכת SDK מלאה של Go. ‫Go מספקת ביצועים טובים ותמיכה עשירה בספריות של צד שלישי שנכתבו ב-Go טהורה.

מתקינים את ערכת הכלים של Go בגרסה 1.24.0.

חלודה

היכולת להתאים אישית את Service Extensions ניתנת באמצעות WebAssembly ו-Proxy-Wasm. ‫WebAssembly תומך במספר שפות תכנות. ‫Google ממליצה על Rust כי היא מספקת תמיכה מצוינת ב-WebAssembly, ו-Proxy-Wasm מספקת ערכת SDK מלאה של Rust. בנוסף, Rust מספקת ביצועים טובים ובטיחות חזקה של טיפוסים.

  1. מתקינים את ערכת הכלים של Rust.

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

  2. הוספת תמיכה ב-Wasm לשרשרת הכלים של Rust:

    rustup target add wasm32-wasip1
    

יצירת חבילת הפלאגין

C++‎

  1. יצירת ספרייה חדשה, נפרדת מ-proxy-wasm-cpp-sdk:

    mkdir myproject
    
  2. בספרייה, יוצרים קובץ Makefile עם התוכן הבא:

    # Express any dependencies
    PROTOBUF=     # full / lite / none
    WASM_DEPS=    # absl_base re2 ...
    
    # Include the SDK Makefile
    PROXY_WASM_CPP_SDK=/sdk
    include ${PROXY_WASM_CPP_SDK}/Makefile
    
  3. מוסיפים קובץ מקור C++ לתוסף באותה ספרייה. השמות של קובצי המקור של C++ חייבים להיות זהים לקובצי ה-Wasm שהיעדים של קובץ ה-Makefile, עם הסיומת .wasm שהוחלפה ב-.cc. בדוגמה הזו, שם קובץ המקור צריך להיות myproject.cc.

  4. מוסיפים את קוד הפלאגין לקובץ המקור.

    דוגמת קוד המקור הבאה היא תוסף שכותב מחדש את מארח הבקשה, ופולט כותרת תגובה:

    #include "proxy_wasm_intrinsics.h"
    
    class MyHttpContext : public Context {
     public:
      explicit MyHttpContext(uint32_t id, RootContext* root) : Context(id, root) {}
    
      FilterHeadersStatus onRequestHeaders(uint32_t headers,
                                           bool end_of_stream) override {
        LOG_INFO("onRequestHeaders: hello from wasm");
    
        // Route Extension example: host rewrite
        if (replaceRequestHeader(":authority", "service-extensions.com") != WasmResult::Ok) {
          LOG_ERROR("Failed to replace :authority header");
        }
        if (replaceRequestHeader(":path", "/") != WasmResult::Ok) {
          LOG_ERROR("Failed to replace :path header");
        }
        return FilterHeadersStatus::Continue;
      }
    
      FilterHeadersStatus onResponseHeaders(uint32_t headers,
                                            bool end_of_stream) override {
        LOG_INFO("onResponseHeaders: hello from wasm");
    
        // Traffic Extension example: add response header
        if (addResponseHeader("hello", "service-extensions") != WasmResult::Ok) {
          LOG_ERROR("Failed to add response header");
        }
        return FilterHeadersStatus::Continue;
      }
    };
    
    static RegisterContextFactory register_StaticContext(
        CONTEXT_FACTORY(MyHttpContext), ROOT_FACTORY(RootContext));

    השיטה onRequestHeaders היא קריאה חוזרת (callback) שמופעלת על ידי Service Extensions.

המשך

  1. יוצרים ספרייה חדשה לתוסף:

    mkdir go-plugin
    
  2. בספרייה, יוצרים קובץ go.mod באמצעות הכלי Go:

    go mod init go-plugin
    
  3. באותה תיקייה, יוצרים קובץ מקור בשם main.go ומוסיפים לקובץ את קוד הפלאגין.

    דוגמת קוד המקור הבאה היא תוסף שכותב מחדש את מארח הבקשה, ופולט כותרת תגובה:

    package main
    
    import (
    	"fmt"
    
    	"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm"
    	"github.com/proxy-wasm/proxy-wasm-go-sdk/proxywasm/types"
    )
    
    func main() {}
    func init() {
    	proxywasm.SetVMContext(&vmContext{})
    }
    
    type vmContext struct {
    	types.DefaultVMContext
    }
    
    type pluginContext struct {
    	types.DefaultPluginContext
    }
    
    type httpContext struct {
    	types.DefaultHttpContext
    }
    
    func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
    	return &pluginContext{}
    }
    
    func (*pluginContext) NewHttpContext(uint32) types.HttpContext {
    	return &httpContext{}
    }
    
    func (ctx *httpContext) OnHttpRequestHeaders(numHeaders int, endOfStream