通過HTTP回調URL或MQ接收非同步任務完成通知
在非同步任務處理中,頻繁輪詢任務結果介面不僅會造成資源浪費,還可能因請求頻率過高觸發介面限流。阿里雲百鍊支援通過事件匯流排在任務完成處理後主動推送任務完成通知。您可以通過配置 HTTP 回調 URL 或 RocketMQ 訊息佇列來接收通知,在收到通知後,只需一次查詢即可擷取任務結果,從而避免頻繁輪詢。
背景介紹
阿里雲百鍊的非同步任務已接入事件匯流排EventBridge。事件匯流排作為事件代理服務,負責將事件路由至配置的事件目標(即事件接收端)。本文中提到的“通知”,在事件匯流排體系中即為一個具體的“事件”。
當阿里雲百鍊完成非同步任務處理後,無論任務成功還是失敗,都會產生一個“任務完成事件”(包含任務狀態、任務ID等資訊),並將其上報到事件匯流排。事件匯流排會將該事件推送到您配置的事件目標。更多的事件目標及配置方式請參見事件目標、目標服務類型。
主動輪詢 VS 接收非同步任務完成通知
|
對比維度 |
主動輪詢 |
接收非同步任務完成通知 |
|
是否限流 |
查詢結果介面限流(20QPS) |
不限流 |
|
接入難度 |
簡單,輪詢查詢結果介面即可 部分任務(如文生圖、文生視頻)提供了SDK,SDK已實現輪詢,可直接使用;若未提供SDK,需自行實現 |
稍複雜 需要在事件匯流排中配置HTTP回調URL或RocketMQ,還需解析事件匯流排推送的通知 |
|
伺服器資源消耗 |
輪詢會佔用您的業務系統資源,尤其是高頻查詢 |
不佔用您的業務系統資源,由事件匯流排主動推送 |
|
即時性 |
即時性較低,依賴輪詢頻率 |
即時性高,任務完成後立即推送 |
|
選型建議 |
適合低並發、小規模任務,或對即時性要求不高的情境 |
適合高並發、大規模任務,或對即時性要求較高的情境 |
為接收非同步任務完成通知,您可以通過事件匯流排配置事件目標,常見的配置方案包括:
-
配置HTTP回調URL:需要一個支援公網或阿里雲Virtual Private Cloud訪問的 HTTP URL,且支援 POST 請求,適合大多數通用情境。
-
配置RocketMQ:通過雲訊息佇列 RocketMQ 接收事件並進行消費,適用於對訊息可靠性要求較高的情境。
方案一:配置HTTP回調URL
方案介紹
阿里雲百鍊在任務完成後上報至事件匯流排,事件匯流排將任務完成事件推送到回調介面。回調介面接收到事件並進行解析,解析出已成功處理的任務 ID,隨後只需調用一次查詢結果介面即可擷取任務結果。
方案特點:與直接輪詢相比,該方案有效避免了無效輪詢請求,減少資源消耗並降低查詢結果介面的限流壓力。
計費說明:事件匯流排計費。
|
以文生圖為例,基於HTTP回調URL的非同步呼叫流程為:
|
|
操作步驟
步驟1:準備HTTP回調介面
通常情況下,HTTP 回調介面部署在您的業務系統中,用於接收非同步事件通知。其配置需滿足以下要求:
-
請求URL:支援公網或阿里雲Virtual Private Cloud 訪問的 HTTP URL。
-
請求方式:
POST。 -
請求Body:
JSON格式,內容為非同步任務完成事件數目據。具體事件結構可在事件匯流排控制台查詢,樣本如下:
點擊查看非同步任務完成事件的資料結構
{
"datacontenttype": "application/json;charset=utf-8",
"aliyunaccountid": "xxxxx",
"aliyunpublishtime": "2023-10-25T01:45:16.993Z",
"data": {
"start_time": "2023-10-25 09:45:09",
"user_api_unique_key": "apikey:v1:audio:asr:transcription:paraformer-8k-v1",
"task_status": "SUCCEEDED",
"contain_result": false,
"end_time": "2023-10-25 09:45:16",
"task_id": "a154c328-xxxx-xxxx-xxxx-e52a9a7e9a35",
"region": "ap-southeast-1",
"request_id": "108f38f5-xxxx-xxxx-xxxx-6504db9080b3",
"api_key_id": "1250"
},
"aliyunoriginalaccountid": "xxxxxxxx",
"specversion": "1.0",
"aliyuneventbusname": "default",
"id": "81765e5b-xxxx-xxxx-xxxx-bbad8dde2bd9",
"source": "acs.dashscope",
"time": "2023-1-25T01:45:16.969Z",
"aliyunregionid": "ap-southeast-1",
"type": "dashscope:System:AsyncTaskFinish"
}步驟2:在事件匯流排控制台查詢事件
事件匯流排控制台支援查詢阿里雲百鍊投遞的事件。
-
登入阿里雲主帳號,進入事件匯流排控制台,切換到新加坡地區,在左側導覽列選擇事件匯流排,點擊default進入雲端服務專用匯流排。
阿里雲百鍊所屬的事件匯流排預設為default。
-
點擊事件追蹤,輸入查詢條件,查詢阿里雲百鍊的非同步任務完成事件。
-
事件來源:搜尋選擇
acs.dashscope,表示事件來源於 DashScope(即靈積模型服務,屬於阿里雲百鍊的底層服務)。 -
事件類型:搜尋選擇
dashscope:System:AsyncTaskFinish,表示非同步任務完成事件。
-
-
點擊詳情,查看阿里雲百鍊上報的非同步任務完成事件的詳細資料。
{ "datacontenttype": "application/json;charset=utf-8", "aliyunaccountid": "xxxxx", "aliyunpublishtime": "2023-10-25T01:45:16.993Z", "data": { "start_time": "2023-10-25 09:45:09", "user_api_unique_key": "apikey:v1:audio:asr:transcription:paraformer-8k-v1", "task_status": "SUCCEEDED", "contain_result": false, "end_time": "2023-10-25 09:45:16", "task_id": "a154c328-xxxx-xxxx-xxxx-e52a9a7e9a35", "region": "ap-southeast-1", "request_id": "108f38f5-xxxx-xxxx-xxxx-6504db9080b3", "api_key_id": "1250" }, "aliyunoriginalaccountid": "xxxxxxxx", "specversion": "1.0", "aliyuneventbusname": "default", "id": "81765e5b-xxxx-xxxx-xxxx-bbad8dde2bd9", "source": "acs.dashscope", "time": "2023-1-25T01:45:16.969Z", "aliyunregionid": "ap-southeast-1", "type": "dashscope:System:AsyncTaskFinish" }
點擊查看事件的參數描述
|
參數 |
類型 |
描述 |
樣本值 |
|
datacontenttype |
String |
參數data的內容形式。datacontenttype只支援 |
|
|
aliyunaccountid |
String |
阿里雲帳號ID。 |
123456789098**** |
|
aliyunpublishtime |
String |
接收事件的時間。 |
2020-11-19T21:04:42.179PRC |
|
data |
Object |
事件內容。JSON對象,內容由發起事件的服務決定。CloudEvents可能包含事件發生時由事件生產者給定的上下文,data中封裝了這些資訊。 |
|
|
data[].start_time |
String |
非同步任務開始時間, 格式:yyyy-MM-dd HH:mm:ss |
2023-10-25 09:45:09 |
|
data[].end_time |
String |
非同步任務完成時間 格式:yyyy-MM-dd HH:mm:ss |
2023-10-25 09:45:16 |
|
data[].user_api_unique_key |
String |
API 的唯一key(提交任務時,模型API的五要素),組成格式為:
|
|
|
data[].task_status |
String |
任務狀態
|
SUCCEEDED |
|
data[].task_id |
String |
任務ID |
a154c328-xxxx-xxxx-xxxx-e52a9a7e9a35 |
|
data[].region |
String |
任務所在地區 |
ap-southeast-1 |
|
data[].request_id |
String |
請求ID |
108f38f5-xxxx-xxxx-xxxx-6504db9080b3 |
|
data[].api_key_id |
String |
API Key ID |
1234 |
|
aliyunoriginalaccountid |
String |
阿里雲原始帳號ID |
123456789098**** |
|
specversion |
String |
CloudEvents協議版本 |
1.0 |
|
aliyuneventbusname |
String |
接收事件的事件匯流排名稱 |
default |
|
id |
String |
事件ID,標識事件的唯一值。 |
45ef4dewdwe1-7c35-447a-bd93-fab**** |
|
source |
String |
事件來源。 提供事件的服務,標識事件發生的內容。通常包含事件來源的類型,發布事件的機制或生產事件的過程。發送端必須確保每個事件的 |
acs.dashscope |
|
time |
String |
事件產生的時間。 如果無法確定事件發生的時間,CloudEvents生產者可以把time設定為其他時間(例如目前時間),但是同一個source的所有生產者設定的值必須是一致的。 |
2020-11-19T21:04:41+08:00 |
|
aliyunregionid |
String |
接收事件的地區。 |
ap-southeast-1 |
|
type |
String |
事件類型。 描述事件來源相關的事件類型。該參數用於路由、事件查詢和策略執行等。格式由生產者定義且包含版本等資訊。 |
dashscope:System:AsyncTaskFinish |
步驟3:配置事件轉寄規則
-
在左側導覽列選擇事件規則,單擊建立規則。
-
配置基本資料,自訂規則名稱和描述。
-
配置事件模式:指定需要轉寄的事件。
-
事件來源:搜尋選擇
acs.dashscope,表示事件來源於阿里雲百鍊。 -
事件類型:搜尋選擇
dashscope:System:AsyncTaskFinish,表示非同步任務完成事件。 -
模式內容:用來配置過濾條件,可通過指定欄位過濾事件。指定欄位來源於步驟2中查詢到的事件詳情欄位。模式編寫規則請參見事件模式,樣本如下:
-
預設情況:在選擇事件來源和事件類型後,模式內容預設展示如下內容,表示轉寄所有的
dashscope:System:AsyncTaskFinish事件。
{ "source": ["acs.dashscope"], "type": ["dashscope:System:AsyncTaskFinish"] }-
通過指定欄位過濾事件:篩選出
user_api_unique_key欄位尾碼為:paraformer-8k-v1的事件,即僅轉寄模型名稱為paraformer-8k-v1的事件。事件類型為dashscope:System:AsyncTaskFinish。
{ "source": ["acs.dashscope"], "type": ["dashscope:System:AsyncTaskFinish"], "data": { "user_api_unique_key": [ {"suffix": ":paraformer-8k-v1"} ] } } -
-
-
配置事件目標:支援配置多種類型的事件目標,包括HTTP回調URL、RocketMQ訊息佇列等。具體操作見步驟4。
步驟4:配置事件目標為HTTP回調介面
-
配置事件目標:將事件轉寄到HTTP回調URL。
-
服務類型:選擇“HTTP”。
-
URL:填寫HTTP服務地址。
-
Body:選擇“完整事件”。
-
網路類型:根據服務地址選擇。
-
HTTP支援公網和專用網路兩種類型,當選擇專用網路時,需要配置VPC、vSwitch和SecurityGroup。
-
-
-
點擊确认即可完成規則的修改。查看事件目標,如果有HTTP樣式,則代表配置成功。
此時規則的事件目標列將顯示HTTP (1)。
方案二:配置RocketMQ
方案介紹
阿里雲百鍊在任務完成後上報至事件匯流排,事件匯流排將任務完成事件推送到雲訊息佇列RocketMQ。業務方監聽訊息佇列並消費訊息,解析出已成功處理的任務 ID,隨後只需調用一次查詢結果介面即可擷取任務結果。
方案特點:與HTTP回調介面方案不同的是,RocketMQ 能夠保證訊息無丟失並支援失敗重試,適合對訊息可靠性要求較高的情境。
計費說明:事件匯流排計費、RocketMQ計費。
|
以文生圖為例,基於RocketMQ的非同步呼叫流程為:
|
|
操作步驟
步驟1:準備RocketMQ執行個體(若已有RocketMQ隊列,可跳過此步)
通過RocketMQ訊息佇列接收事件,需要先準備好RocketMQ隊列,再接收訊息。
-
進入RocketMQ控制台,在左側導覽列選擇執行個體列表,單擊建立執行個體。
執行個體ID:樣本為
rmq-cn-nwy*******。 -
建立對應執行個體的
Topic,設定自訂的Topic名稱。 -
建立對應執行個體的
Group,設定自訂的Group名稱。
步驟2:在事件匯流排控制台查詢事件
事件匯流排控制台支援查詢阿里雲百鍊投遞的事件。
-
登入阿里雲主帳號,進入事件匯流排控制台,切換到新加坡地區,在左側導覽列選擇事件匯流排,點擊default進入雲端服務專用匯流排。
阿里雲百鍊所屬的事件匯流排預設為default。
-
點擊事件追蹤,輸入查詢條件,查詢阿里雲百鍊的非同步任務完成事件。
-
事件來源:搜尋選擇
acs.dashscope,表示事件來源於 DashScope(即靈積模型服務,屬於阿里雲百鍊的底層服務)。 -
事件類型:搜尋選擇
dashscope:System:AsyncTaskFinish,表示非同步任務完成事件。
-
-
點擊詳情,查看阿里雲百鍊上報的非同步任務完成事件的詳細資料。
{ "datacontenttype": "application/json;charset=utf-8", "aliyunaccountid": "xxxxx", "aliyunpublishtime": "2023-10-25T01:45:16.993Z", "data": { "start_time": "2023-10-25 09:45:09", "user_api_unique_key": "apikey:v1:audio:asr:transcription:paraformer-8k-v1", "task_status": "SUCCEEDED", "contain_result": false, "end_time": "2023-10-25 09:45:16", "task_id": "a154c328-xxxx-xxxx-xxxx-e52a9a7e9a35", "region": "ap-southeast-1", "request_id": "108f38f5-xxxx-xxxx-xxxx-6504db9080b3", "api_key_id": "1250" }, "aliyunoriginalaccountid": "xxxxxxxx", "specversion": "1.0", "aliyuneventbusname": "default", "id": "81765e5b-xxxx-xxxx-xxxx-bbad8dde2bd9", "source": "acs.dashscope", "time": "2023-1-25T01:45:16.969Z", "aliyunregionid": "ap-southeast-1", "type": "dashscope:System:AsyncTaskFinish" }
點擊查看事件的參數描述
|
參數 |
類型 |
描述 |
樣本值 |
|
datacontenttype |
String |
參數data的內容形式。datacontenttype只支援 |
|
|
aliyunaccountid |
String |
阿里雲帳號ID。 |
123456789098**** |
|
aliyunpublishtime |
String |
接收事件的時間。 |
2020-11-19T21:04:42.179PRC |
|
data |
Object |
事件內容。JSON對象,內容由發起事件的服務決定。CloudEvents可能包含事件發生時由事件生產者給定的上下文,data中封裝了這些資訊。 |
|
|
data[].start_time |
String |
非同步任務開始時間, 格式:yyyy-MM-dd HH:mm:ss |
2023-10-25 09:45:09 |
|
data[].end_time |
String |
非同步任務完成時間 格式:yyyy-MM-dd HH:mm:ss |
2023-10-25 09:45:16 |
|
data[].user_api_unique_key |
String |
API 的唯一key(提交任務時,模型API的五要素),組成格式為:
|
|
|
data[].task_status |
String |
任務狀態
|
SUCCEEDED |
|
data[].task_id |
String |
任務ID |
a154c328-xxxx-xxxx-xxxx-e52a9a7e9a35 |
|
data[].region |
String |
任務所在地區 |
ap-southeast-1 |
|
data[].request_id |
String |
請求ID |
108f38f5-xxxx-xxxx-xxxx-6504db9080b3 |
|
data[].api_key_id |
String |
API Key ID |
1234 |
|
aliyunoriginalaccountid |
String |
阿里雲原始帳號ID |
123456789098**** |
|
specversion |
String |
CloudEvents協議版本 |
1.0 |
|
aliyuneventbusname |
String |
接收事件的事件匯流排名稱 |
default |
|
id |
String |
事件ID,標識事件的唯一值。 |
45ef4dewdwe1-7c35-447a-bd93-fab**** |
|
source |
String |
事件來源。 提供事件的服務,標識事件發生的內容。通常包含事件來源的類型,發布事件的機制或生產事件的過程。發送端必須確保每個事件的 |
acs.dashscope |
|
time |
String |
事件產生的時間。 如果無法確定事件發生的時間,CloudEvents生產者可以把time設定為其他時間(例如目前時間),但是同一個source的所有生產者設定的值必須是一致的。 |
2020-11-19T21:04:41+08:00 |
|
aliyunregionid |
String |
接收事件的地區。 |
ap-southeast-1 |
|
type |
String |
事件類型。 描述事件來源相關的事件類型。該參數用於路由、事件查詢和策略執行等。格式由生產者定義且包含版本等資訊。 |
dashscope:System:AsyncTaskFinish |
步驟3:配置事件轉寄規則
-
在左側導覽列選擇事件規則,單擊建立規則。
-
配置基本資料,自訂規則名稱和描述。
-
配置事件模式:指定需要轉寄的事件。
-
事件來源:搜尋選擇
acs.dashscope,表示事件來源於阿里雲百鍊。 -
事件類型:搜尋選擇
dashscope:System:AsyncTaskFinish,表示非同步任務完成事件。 -
模式內容:用來配置過濾條件,可通過指定欄位過濾事件。指定欄位來源於步驟2中查詢到的事件詳情欄位。模式編寫規則請參見事件模式,樣本如下:
-
預設情況:在選擇事件來源和事件類型後,模式內容預設展示如下內容,表示轉寄所有的
dashscope:System:AsyncTaskFinish事件。
{ "source": ["acs.dashscope"], "type": ["dashscope:System:AsyncTaskFinish"] }-
通過指定欄位過濾事件:篩選出
user_api_unique_key欄位尾碼為:paraformer-8k-v1的事件,即僅轉寄模型名稱為paraformer-8k-v1的事件。事件類型為dashscope:System:AsyncTaskFinish。
{ "source": ["acs.dashscope"], "type": ["dashscope:System:AsyncTaskFinish"], "data": { "user_api_unique_key": [ {"suffix": ":paraformer-8k-v1"} ] } } -
-
-
配置事件目標:支援配置多種類型的事件目標,包括HTTP回調URL、RocketMQ訊息佇列等。具體操作見步驟4。
步驟5:在RocketMQ控制台查看訊息
配置完成後,提交非同步任務,待任務完成後,在配置的RocketMQ的Topic中查看訊息。
-
RocketMQ線上查看訊息需要開通訊息一鍵收發體驗功能。
-
訊息一鍵收發體驗功能是基於Function Compute實現的,如果超過了免費試用額度後將會產生少量費用,請查看Function Compute計費規則。
在Topic 管理頁面找到已建立的Topic,單擊其右側操作列中的詳情。
進入Topic詳情後,切換到訊息一鍵收發體驗頁簽,在基礎功能地區選取項目消費方式,如PushConsumer 方式消費。
配置好Topic 名稱和Group ID等參數後,單擊運行開始接收訊息。運行結果頁簽將顯示收到的訊息列表,包括訊息ID和接收時間等資訊。
步驟6:使用SDK接收並消費訊息
使用RocketMQ的Java SDK實現以下邏輯:先訂閱相關Topic,實現訊息監聽邏輯。在接收到訊息後,再進行消費處理。
下面展示RocketMQ 5.0版本的Java用戶端範例程式碼。
-
在Maven專案中,引入以下依賴
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client-java</artifactId>
<version>5.0.4</version>
</dependency>
-
消費MQ訊息的範例程式碼
import com.alibaba.fastjson2.JSON;
import org.apache.rocketmq.client.apis.*;
import org.apache.rocketmq.client.apis.consumer.ConsumeResult;
import org.apache.rocketmq.client.apis.consumer.FilterExpression;
import org.apache.rocketmq.client.apis.consumer.FilterExpressionType;
import org.apache.rocketmq.client.apis.consumer.PushConsumer;
import org.apache.rocketmq.shaded.org.slf4j.Logger;
import org.apache.rocketmq.shaded.org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collections;
public class ConsumerExample {
private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerExample.class);
private ConsumerExample() {
}
public static void main(String[] args) throws ClientException, IOException, InterruptedException {
/*
執行個體存取點,從控制台執行個體詳情頁的存取點頁簽中擷取。
如果是在阿里雲ECS內網訪問,建議填寫VPC存取點。
如果是在本地公網訪問,或者是線下IDC環境訪問,可以使用公網存取點。使用公網存取點訪問,必須開啟執行個體的公網訪問功能。
*/
String endpoints = "xxxx";
//指定需要訂閱哪個目標Topic,Topic需要提前在控制台建立,如果不建立直接使用會返回報錯。
String topic = "xxxx";
//為消費者指定所屬的消費者分組,Group需要提前在控制台建立,如果不建立直接使用會返回報錯。
String consumerGroup = "xxxx";
final ClientServiceProvider provider = ClientServiceProvider.loadService();
ClientConfigurationBuilder builder = ClientConfiguration.newBuilder().setEndpoints(endpoints);
/*
如果是使用公網存取點訪問,configuration還需要設定執行個體的使用者名稱和密碼。使用者名稱和密碼在控制台執行個體詳情頁擷取。
如果是在阿里雲ECS內網訪問,無需填寫該配置,服務端會根據內網VPC資訊智能擷取。
*/
builder.setCredentialProvider(new StaticSessionCredentialsProvider("xxxx", "xxxx"));
ClientConfiguration clientConfiguration = builder.build();
//訂閱訊息的過濾規則,表示訂閱所有Tag的訊息。
String tag = "*";
FilterExpression filterExpression = new FilterExpression(tag, FilterExpressionType.TAG);
//初始化SimpleConsumer,需要綁定消費者分組ConsumerGroup、通訊參數以及訂閱關係。
PushConsumer pushConsumer = provider.newPushConsumerBuilder()
.setClientConfiguration(clientConfiguration)
//設定消費者分組。
.setConsumerGroup(consumerGroup)
//設定預綁定的訂閱關係。
.setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression))
//設定消費監聽器。
.setMessageListener(messageView -> {
try {
//處理訊息並返回消費結果。
ByteBuffer buffer = messageView.getBody();
ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity());
for (int i = 0; i < buffer.capacity(); i++) {
newBuffer.put(buffer.get(i));
}
String result = new String(newBuffer.array());
LOGGER.info("Consume message={}", JSON.toJSONString(result));
System.out.println(result);
return ConsumeResult.SUCCESS;
} catch (Exception e) {
LOGGER.error("deal message has error", e);
return ConsumeResult.FAILURE;
}
})
.build();
Thread.sleep(Long.MAX_VALUE);
//如果不需要再使用PushConsumer,可關閉該進程。
pushConsumer.close();
}
}
常見問題
一個事件規則可以配置多個事件目標嗎?
可以,同一個事件規則可以配置多個事件目標。如果配置多個事件目標,則同一個事件會投遞到配置的每個事件目標中。
配置完事件規則,但是接收不到事件?
請確認事件轉寄規則的地區與事件所屬地區一致。例如,新加坡地區配置的規則僅能轉寄新加坡地區的事件,無法轉寄其他地區的事件。事件匯流排所在地區可在控制台頁面頂部導覽列的地區選取器中查看。
HTTP/HTTPS服務要求逾時或者請求錯誤?
請按以下步驟排查:
-
檢查HTTP/HTTPS服務狀態。
-
檢查事件目標中配置的 URL 是否正確。
-
檢查事件目標配置的Network類型:
-
PublicNetwork:公網,需確保 URL 可被公網訪問。
-
PrivateNetwork:VPC網路,若選擇此項,需正確配置VPC、vSwitch和SecurityGroup資訊。
-
檢查VPC網路和交換器配置是否正確。
-
檢查網路安全性群組配置是否正確。
-
-
-
其他參數配置:請參見事件目標參數。

