全部產品
Search
文件中心

Function Compute:配置EventBridge類別的OSS觸發器

更新時間:Jul 06, 2024

如果您需要為OSS觸發器設定多個檔案首碼和檔案尾碼,或者希望在一個OSS Bucket中關聯10個以上的觸發器,您可以建立EventBridge類別的OSS觸發器,以便輕鬆辭彙索引檔上傳等事件。

注意事項

EventBridge類別的OSS觸發器與原生OSS觸發器不同,您需要關注以下注意事項。

  • 原生OSS觸發器,一個Bucket最多支援關聯10個觸發器。如您需要在一個Bucket內,關聯更多的OSS觸發器,可以選擇建立EventBridge類別的OSS觸發器。

    說明

    通常情況下,不推薦為一個Bucket關聯10個以上的觸發器。如需建立,建議您建立新的Bucket,並基於新的Bucket建立觸發器。

  • 事件匯流排EventBridge的資源限制數一致,目前最多支援建立50個EventBridge類別的OSS觸發器。更多資訊,請參見使用限制

  • EventBridge類別的OSS觸發器無需保證語義唯一性,即事件類型檔案首碼檔案尾碼組成的語義無需唯一。

  • EventBridge類別的OSS觸發器支援同時配置多個檔案首碼檔案尾碼,但是檔案首碼檔案尾碼不支援模糊比對和正則匹配。

  • EventBridge類別的OSS觸發器建立成功後,不會立即生效。需等待約30s後,Object Storage Service相關操作事件才能觸發函數。

樣本情境

您可以配置一個OSS觸發器,在觸發規則中設定首碼為sourcetest,尾碼為.rar.zip。當有壓縮檔存入指定的OSS Bucket中的source或者test目錄下,且檔案尾碼為.rar或者.zip時,會自動觸發函數執行。函數執行完成後,將解壓縮後的檔案存放到同一個Bucket的其他目錄下。

前提條件

步驟一:建立EventBridge類別的OSS觸發器

  1. 登入Function Compute控制台,在左側導覽列,單擊函數

  2. 在頂部功能表列,選擇地區,然後在函數頁面,單擊目標函數。

  3. 在函數詳情頁面,選擇配置頁簽,在左側導覽列,單擊觸發器,然後單擊建立觸發器

  4. 在建立觸發程序面板,觸發器類型選擇雲產品事件觸發程序類型中的Object Storage Service,設定其餘配置項,然後單擊確定

    配置項

    操作

    本文樣本

    名稱

    填寫自訂的觸發器名稱。

    oss-trigger

    版本或別名

    預設值為LATEST。如果您需要建立其他版本或別名的觸發器,需先在函數詳情頁的版本或別名下拉式清單選擇該版本。關於版本和別名的簡介,請參見版本管理別名管理

    LATEST

    Bucket 名稱

    選擇已建立的OSS Bucket。

    bucket-zh****

    檔案首碼

    輸入要匹配的檔案名稱的首碼。Function Compute建議您配置首碼和尾碼,避免觸發事件嵌套迴圈觸發引起額外費用。

    您可以在控制台單擊+添加檔案首碼同時添加多個檔案首碼

    重要

    檔案首碼不能以/開頭,否則會導致OSS觸發器無法被觸發。

    • source

    • test

    檔案尾碼

    輸入要匹配的檔案名稱的尾碼。Function Compute建議您配置首碼和尾碼,避免觸發事件嵌套迴圈觸發引起額外費用。

    您可以在控制台單擊+添加檔案尾碼同時添加多個檔案尾碼

    png

    事件類型

    選擇一個或多個觸發事件。關於Function Compute的事件類型,請參見OSS事件定義

    oss:ObjectCreated:PutObjectoss:ObjectCreated:PostObjectoss:ObjectCreated:CompleteMultipartUpload

    事件模式內容

    您建立檔案首碼檔案尾碼觸發事件後,該配置項自動填滿。

    重要

    請謹慎修改事件模式內容,否則可能導致觸發器觸發失敗。請瞭解事件模式的詳細規則後,再決定是否修改。更多資訊,請參見事件模式

    {
        "source":[
            "acs.oss"
        ]
    }

    調用方式

    選擇函數調用方式,預設為同步調用。

    • 同步調用:事件觸發函數執行,等待函數調用完成後,Function Compute返回執行結果。適用情境較廣泛,更多資訊,請參見同步調用

    • 非同步呼叫:事件觸發函數執行後,Function Compute立即返迴響應結果並且確保函數至少被成功執行一次,但不會返回具體執行結果。適用於調度延時較長的函數。更多資訊,請參見功能概覽

    同步調用

    觸發器啟用狀態

    建立觸發器後是否立即啟用。預設勾選啟用觸發器,即建立觸發器後立即啟用觸發器。

    不涉及

    推送格式

    指定函數入口參數的資料格式,該資料通過函數的Event參數進行傳遞。

    • CloudEvents:以通用格式描述事件數目據的規範,包含事件描述以及事件裝載資料,旨在簡化不同服務、平台間的事件聲明和傳輸。

    • RawData:只投遞事件裝載資料,不包含CloudEvents格式中的其它中繼資料資訊。

    說明

    兩種類型的OSS觸發器的推送格式不同。原生OSS觸發器與EventBridge類別的OSS觸發器不同,其Event參數支援OSSEvents模板,即阿里雲Object Storage Service產生的事件格式。

    CloudEvents

    建立完成後,在觸發器名稱列表中顯示已建立的觸發器。如需對建立的觸發器進行修改或刪除,具體操作,請參見觸發器管理

步驟二:配置函數入口參數

EventBridge類別的OSS觸發事件源會以CloudEvents模板作為輸入參數傳遞給函數,您可以手動將Event傳給函數類比觸發事件。

  1. 在函數詳情頁面的代碼頁簽,單擊測試函數右側的image.png表徵圖,從下拉式清單中,選擇配置測試參數

  2. 配置測試參數面板,選擇建立新測試事件編輯已有測試事件,填寫事件名稱和事件內容,然後單擊確定。

    Event是Function Compute的入口參數,當指定的OSS Bucket發生指定事件時,會將事件數目據以JSON格式發送給綁定的函數。具體格式如下所示。

    {
        "datacontenttype": "application/json;charset=utf-8",
        "aliyunaccountid": "143199913****",
        "data": {
            "eventVersion": "1.0",
            "responseElements": {
                "requestId": "6364D216511B143733C5A67B"
            },
            "eventSource": "acs:oss",
            "eventTime": "2023-11-04T08:49:26.000Z",
            "requestParameters": {
                "sourceIPAddress": "140.205.XX.XX"
            },
            "eventName": "ObjectCreated:PutObject",
            "userIdentity": {
                "principalId": "143199913****"
            },
            "region": "cn-hangzhou",
            "oss": {
                "bucket": {
                    "name": "bucket-zh***",
                    "arn": "acs:oss:cn-hangzhou:143199913****:bucket-zh***",
                    "virtualBucket": "",
                    "ownerIdentity": "143199913****"
                },
                "ossSchemaVersion": "1.0",
                "object": {
                    "size": 13,
                    "objectMeta": {
                        "mimeType": "text/plain"
                    },
                    "deltaSize": 13,
                    "eTag": "59CA0EFA9F5633CB0371BBC0355478D8",
                    "key": "source/a.png"
                }
            }
        },
        "subject": "acs:oss:cn-hangzhou:143199913****:bucket-zh***/source/a.png",
        "aliyunoriginalaccountid": "143199913****",
        "source": "acs.oss",
        "type": "oss:ObjectCreated:PutObject",
        "aliyunpublishtime": "203-11-04T08:49:26.745Z",
        "specversion": "1.0",
        "aliyuneventbusname": "default",
        "id": "6364D216511B143733C5A67B",
        "time": "2023-11-04T08:49:26Z",
        "aliyunregionid": "cn-hangzhou"
    }

    Event參數中不同屬性欄位的解釋如下表所示。

    參數

    類型

    樣本值

    描述

    datacontenttype

    String

    application/json;charset=utf-8

    參數data的內容形式。datacontenttype只支援application/json;charset=utf-8格式。

    aliyunaccountid

    String

    143199913****

    阿里雲帳號ID。您的阿里雲帳號ID,可在Function Compute控制台概覽頁面的常用資訊地區擷取。

    data

    Struct

    {}

    OSS事件內容,為JSON對象。CloudEvents包含事件發生時由OSS定義的上下文,data中封裝了這些資訊。

    subject

    String

    acs:oss:cn-hangzhou:143199913****:bucket-zh****/source/a.png

    事件主題。

    格式為acs:oss:<region>:<your_account_id>:<your_bucket>,需修改<region>為您建立函數時選擇的地區,修改<your_account_id>為您的阿里雲帳號ID,修改<your_bucket>為相同地區下您實際已經建立的Bucket名稱。

    aliyunoriginalaccountid

    String

    143199913****

    阿里雲帳號ID。

    source

    String

    acs.oss

    事件來源。OSS觸發器固定為acs.oss

    type

    String

    oss:ObjectCreated:PutObject

    事件類型。

    aliyunpublishtime

    Timestamp

    2023-11-04T08:49:26.745Z

    接收事件的時間。

    specversion

    String

    1.0

    CloudEvents協議版本。

    aliyuneventbusname

    String

    default

    接收事件的事件匯流排名稱。

    id

    String

    6364D216511B143733C5A67B

    事件ID。

    time

    Timestamp

    2023-11-04T08:49:26Z

    事件產生的時間。

    aliyunregionid

    String

    cn-hangzhou

    接收事件的地區。

    aliyunpublishaddr

    String

    140.205.XX.XX

    接收事件的伺服器位址。

    Event參數中data的以下內容需根據實際情況修改。

    • userIdentity.principalId:修改為您的阿里雲帳號ID。

    • region:修改為您建立函數時選擇的地區。

    • oss.bucket.name:修改為函數相同地區下您實際已經建立的Bucket名稱。

    • oss.bucket.arn:格式為acs:oss:<region>:<your_account_id>:<your_bucket>,需修改<region>為您建立函數時選擇的地區,修改<your_account_id>為您的阿里雲帳號ID,修改<your_bucket>為相同地區下您實際已經建立的Bucket名稱。

    • oss.bucket.ownerIdentity:修改為您的阿里雲帳號ID。

    • object.key:修改為您實際已經上傳到目標Bucket下的檔案。

      說明

      請確保您配置的Bucket中存在指定的檔案,本文樣本為source/a.png,否則無法觸發函數執行,或者函數執行會失敗。

步驟三:編寫函數代碼並測試

OSS觸發器建立完成後,您可以開始編寫函數代碼並測試,以驗證代碼的正確性。在實際操作過程中發生OSS事件時,會自動觸發函數執行。

警告

代碼中一定要避免迴圈觸發,否則會產生不必要的費用。一個典型的迴圈觸發情境是OSS的某個Bucket上傳檔案事件觸發函數執行,此函數執行完成後又產生了一個或多個檔案再寫回到OSS的Bucket裡,這個寫入動作又觸發了函數執行,形成了鏈狀迴圈。更多資訊,請參見OSS觸發器觸發規則

  1. 在函數詳情頁面的代碼頁簽,在代碼編輯器中編寫代碼,然後單擊部署代碼

    執行代碼前的準備工作和程式碼範例如下。

    說明

    如果您要在您的函數中讀寫OSS資源,建議使用OSS內網服務地址進行訪問,避免使用公網訪問,產生公網費用。關於OSS內網服務地址的格式,請參見訪問網域名稱和資料中心

    /*準備工作:
    1.請先在終端中執行以下代碼安裝package.json檔案和jimp圖片處理模組。
      a.在終端執行npm init安裝package.json檔案。
      b.在終端執行npm install jimp安裝jimp圖片處理模組。
    2.請確保函數的函數入口(handler)為index.handler。
    */
    
    'use strict';
     console.log('Loading function ...');
     var oss = require('ali-oss');
     var fs = require('fs');
     var jimp = require("jimp");
     module.exports.handler = function (eventBuf, ctx, callback) {
         console.log('Received event:', eventBuf.toString());
         var event = JSON.parse(eventBuf);
    
         var ossEvent = event.data;
    
         // OSS地區以“oss-”為首碼,例如“oss-cn-shanghai”。
         var ossRegion = "oss-" + ossEvent.region;
         // 建立OSS用戶端。
         var client = new oss({
             region: ossRegion,
             /*
             阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
             建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
             本樣本以從上下文中擷取AccessKeyId/AccessSecret為例。
             */
             accessKeyId: ctx.credentials.accessKeyId,
             accessKeySecret: ctx.credentials.accessKeySecret,
             stsToken: ctx.credentials.securityToken
         });
         // 從事件中擷取Bucket名稱。
         client.useBucket(ossEvent.oss.bucket.name);
         // 處理後的圖片被儲存至processed/目錄。
         var newKey = ossEvent.oss.object.key.replace("source/", "processed/");
         var tmpFile = "/tmp/processed.png";
         // 擷取OSS檔案對象。
         console.log('Getting object: ', ossEvent.oss.object.key)
         client.get(ossEvent.oss.object.key).then(function (val) {
             // 從緩衝中讀取OSS檔案對象內容。
             jimp.read(val.content, function (err, image) {
                 if (err) {
                     console.error("Failed to read image");
                     callback(err);
                     return;
                 }
                 // 調整圖片大小,並將其儲存至tmp檔案中。
                 image.resize(128, 128).write(tmpFile, function (err) {
                     if (err) {
                         console.error("Failed to write image locally");
                         callback(err);
                         return;
                     }
                     // 將讀取到的檔案對象上傳到OSS儲存空間中並重新命名。
                     console.log('Putting object: ', newKey);
                     client.put(newKey, tmpFile).then(function (val) {
                         console.log('Put object:', val);
                         callback(null, val);
                         return;
                     }).catch(function (err) {
                         console.error('Failed to put object: %j', err);
                         callback(err);
                         return
                     });
                 });
             });
         }).catch(function (err) {
             console.error('Failed to get object: %j', err);
             callback(err);
             return
         });
     };
    #準備工作:
    #1.請確保函數配置的角色具有訪問Object Storage Service的許可權。您可以登入RAM控制台,為該角色添加訪問Object Storage Service的許可權。
    #2.請確保函數的請求處理常式(handler)為index.handler。
    
    # -*- coding: utf-8 -*-
    import oss2, json
    from wand.image import Image
    def handler(event, context):
        evt = json.loads(event)
        creds = context.credentials
        # Required by OSS sdk
        # 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        # 建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        # 本樣本以從上下文中擷取AccessKeyId/AccessSecret為例。
        auth=oss2.StsAuth(
            creds.access_key_id,
            creds.access_key_secret,
            creds.security_token)
        evt = evt['data']
        bucket_name = evt['oss']['bucket']['name']
        endpoint = 'oss-' +  evt['region'] + '-internal.aliyuncs.com'
        bucket = oss2.Bucket(auth, endpoint, bucket_name)
        objectName = evt['oss']['object']['key']
        # Processed images will be saved to processed/
        newKey = objectName.replace("source/", "processed/")
        remote_stream = bucket.get_object(objectName)
        if not remote_stream:
            return
        remote_stream = remote_stream.read()
        with Image(blob=remote_stream)  as img:
            with img.clone() as i:
                i.resize(128, 128)
                new_blob = i.make_blob()
                bucket.put_object(newKey, new_blob)
    /*準備工作:
    1.請確保函數配置的角色具有訪問Object Storage Service的許可權。您可以登入RAM控制台,為該角色添加訪問Object Storage Service的許可權。
    2.請確保函數的請求處理常式(handler)為index.handler。
    */
    
    <?php
      use OSS\OssClient;
    function handler($event, $context) {
      $event           = json_decode($event, $assoc = true);
      /*
        阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        本樣本以從上下文中擷取AccessKey/AccessSecretKey為例。
      */
      $accessKeyId     = $context["credentials"]["accessKeyId"];
      $accessKeySecret = $context["credentials"]["accessKeySecret"];
      $securityToken   = $context["credentials"]["securityToken"];
      $evt        = $event['data'];
      $bucketName = $evt['oss']['bucket']['name'];
      $endpoint   = 'oss-' . $evt['region'] . '-internal.aliyuncs.com';
      $objectName = $evt['oss']['object']['key'];
      $newKey = str_replace("source/", "processed/", $objectName);
      try {
        $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken);
        $content = $ossClient->getObject($bucketName , $objectName);
        if ($content == null || $content == "") {
          return;
        }
        $imagick = new Imagick();
        $imagick->readImageBlob($content);
        $imagick->resizeImage(128, 128, Imagick::FILTER_LANCZOS, 1);
        $ossClient->putObject($bucketName, $newKey, $imagick->getImageBlob());
      } catch (OssException $e) {
        print($e->getMessage());
      }
    }
    /*準備工作:
    1.請先增加如下依賴到pom.xml。
    <dependencies>
        <dependency>
          <groupId>com.aliyun.fc.runtime</groupId>
          <artifactId>fc-java-core</artifactId>
          <version>1.4.1</version>
        </dependency>
        <dependency>
          <groupId>com.aliyun.fc.runtime</groupId>
          <artifactId>fc-java-event</artifactId>
          <version>1.2.0</version>
        </dependency>
    </dependencies>
    2.請確保函數的函數入口(handler)為example.App::handleRequest。
    */
    
    package example;
    
    import java.io.*;
    import java.util.Map;
    
    import com.aliyun.fc.runtime.Context;
    import com.aliyun.fc.runtime.StreamRequestHandler;
    import com.aliyun.fc.runtime.event.OSSEvent.Event;
    
    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    
    
    public class App implements StreamRequestHandler {
    
        private static final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        public static final class CloudEvent {
            public final String id;
    
            public final String source;
            public final String specversion;
    
            public final String type;
            public final String datacontenttype;
    
            public final String dataschema;
    
            public final String subject;
    
            public final String time;
    
            public final Map<String, ?> extensions;
    
            public final Event data;
    
            @JsonCreator
            public CloudEvent(@JsonProperty("id") String id, @JsonProperty("source") String source, @JsonProperty("specversion") String specversion, @JsonProperty("type") String type, @JsonProperty("datacontenttype") String datacontenttype, @JsonProperty("dataschema") String dataschema, @JsonProperty("subject") String subject, @JsonProperty("time") String time, @JsonProperty("extensions") Map<String, ?> extensions, @JsonProperty("data") Event data) {
                this.id = id;
                this.source = source;
                this.specversion = specversion;
                this.type = type;
                this.datacontenttype = datacontenttype;
                this.dataschema = dataschema;
                this.subject = subject;
                this.time = time;
                this.extensions = extensions;
                this.data = data;
            }
    
            public String getId() {
                return this.id;
            }
    
            public String getSource() {
                return this.source;
            }
    
            public String getSpecversion() {
                return this.specversion;
            }
    
            public String getType() {
                return this.type;
            }
    
            public String getDatacontenttype() {
                return this.datacontenttype;
            }
    
            public String getDataschema() {
                return this.dataschema;
            }
    
            public String getSubject() {
                return this.subject;
            }
    
            public String getTime() {
                return this.time;
            }
    
            public Map<String, ?> getExtensions() {
                return this.extensions;
            }
    
            public Event getData() {
                return this.data;
            }
        }
        @Override
        public void handleRequest(
                InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
            CloudEvent cloudEvents = mapper.readValue(inputStream, new TypeReference<CloudEvent>() {});
            Event ossEvent = cloudEvents.getData();
            context.getLogger().info(String.format("received %s from %s @ %s", ossEvent.eventName, ossEvent.eventSource, ossEvent.region));
            outputStream.write(String.format("received %s from %s @ %s", ossEvent.eventName, ossEvent.eventSource, ossEvent.region).getBytes());
            outputStream.write(String.format("received bucket %s", ossEvent.oss.bucket.arn).getBytes());
            outputStream.write(String.format("received object %s and it's size is %s", ossEvent.oss.object.key, ossEvent.oss.object.size).getBytes());
        }
    }
  2. 單擊測試函數

    執行完成後,您可以在代碼頁簽的上方查看執行結果。

常見問題

相關文檔

  • 如果您想瞭解可以配置的OSS事件類型,請參見OSS事件定義

  • 如果您需要對建立的觸發器進行修改或刪除,具體操作請參見更新觸發器配置

  • 觸發器相關問題

    • 如果您希望查看函數的執行觸發了哪個事件,可以手動在代碼邏輯中列印事件類型日誌,具體請參見日誌記錄

    • 如果您希望在函數中調用另一個函數,可以使用API調用指定函數或使用函數工作流程編排函數。如果調用的函數需要執行耗時操作且均為非同步呼叫,可以配置非同步呼叫目標服務。具體請參見函數可以相互調用嗎?配置非同步呼叫目標服務