VPC高速直連調(diào)用
EAS支持通過(guò)Python官方SDK或自行實(shí)現(xiàn)調(diào)用邏輯的方式對(duì)服務(wù)進(jìn)行VPC高速直連調(diào)用。本文詳細(xì)介紹這兩種調(diào)用方式的實(shí)現(xiàn)方法。
調(diào)用原理
VPC高速直連調(diào)用、公網(wǎng)調(diào)用及VPC地址調(diào)用的鏈路如下圖所示。
開啟服務(wù)運(yùn)行所在資源組的VPC高速直連功能后,EAS會(huì)在您指定的安全組內(nèi)綁定輔助網(wǎng)卡,打通您的VPC和EAS服務(wù)實(shí)例之間的網(wǎng)絡(luò)。之后您可以在自己的VPC中直接訪問(wèn)EAS實(shí)例,無(wú)需通過(guò)網(wǎng)關(guān)訪問(wèn)服務(wù),避免了四層SLB和七層網(wǎng)絡(luò)轉(zhuǎn)發(fā)。同時(shí),EAS預(yù)置的RPC實(shí)現(xiàn)了HTTP相關(guān)協(xié)議棧,對(duì)于高QPS(Queries Per Second)的大流量服務(wù)(例如圖像服務(wù)),可以大幅度提高訪問(wèn)性能、降低訪問(wèn)延時(shí)。
前提條件
如果您使用專屬資源組部署服務(wù),則部署服務(wù)前,需要為專屬資源組開通VPC高速直連功能,詳情請(qǐng)參見配置網(wǎng)絡(luò)連通。
安全組控制ECS實(shí)例機(jī)器的出入流量,用戶的ECS實(shí)例和EAS服務(wù)實(shí)例之間的網(wǎng)絡(luò)互通也受安全組的配置控制。默認(rèn)普通安全組內(nèi),實(shí)例之間是內(nèi)網(wǎng)互通的,您可以在配置VPC高速直連時(shí),選擇需要訪問(wèn)在線服務(wù)的ECS實(shí)例所在安全組,從而支持實(shí)例之間網(wǎng)絡(luò)互通。當(dāng)需要配置使用不同的安全組時(shí),請(qǐng)?jiān)O(shè)置安全組的規(guī)則支持ECS實(shí)例之間能夠互通。
調(diào)用方式
為方便用戶調(diào)用服務(wù),EAS提供了以下兩種方式實(shí)現(xiàn)VPC高速直連調(diào)用:
EAS封裝了調(diào)用邏輯并提供了Python SDK、Java SDK和Golang SDK的調(diào)用方法,您可以直接使用SDK實(shí)現(xiàn)VPC高速直連調(diào)用。
推薦使用官方SDK調(diào)用服務(wù),從而有效減少編寫調(diào)用邏輯的時(shí)間并提高服務(wù)調(diào)用穩(wěn)定性。如果您需要使用其他語(yǔ)言或希望自己編寫實(shí)現(xiàn)調(diào)用邏輯,下文也提供了方法指導(dǎo)供您參考。此外,自行實(shí)現(xiàn)調(diào)用邏輯需要根據(jù)不同框架構(gòu)建服務(wù)請(qǐng)求,詳情請(qǐng)參見構(gòu)建通用Processor服務(wù)請(qǐng)求。
使用官方SDK調(diào)用
Python SDK調(diào)用
使用Python官方SDK調(diào)用服務(wù)的方法如下:
安裝。
pip install -U eas-prediction --user
該Python SDK的調(diào)用詳情請(qǐng)參見Python SDK使用說(shuō)明。
編寫調(diào)用程序。
以字符串作為輸入輸出的程序示例如下,其他格式(TensorFlow或PyTorch等)的輸入輸出的程序示例請(qǐng)參見Python SDK使用說(shuō)明。
#!/usr/bin/env python from eas_prediction import PredictClient from eas_prediction import StringRequest from eas_prediction import TFRequest from eas_prediction import ENDPOINT_TYPE_DIRECT if __name__ == '__main__': client = PredictClient('http://pai-eas-vpc.cn-shanghai.aliyuncs.com', 'mnist_saved_model_example') # 替換為服務(wù)Token。您可以單擊目標(biāo)服務(wù)的服務(wù)方式列下的調(diào)用信息來(lái)查看Token信息。 client.set_token('M2FhNjJlZDBmMzBmMzE4NjFiNzZhMmUxY2IxZjkyMDczNzAzYjFi****') client.set_endpoint_type(ENDPOINT_TYPE_DIRECT) # 表示通過(guò)直連通道訪問(wèn)服務(wù)。 client.init() # request = StringRequest('[{}]') req = TFRequest('predict_images') req.add_feed('images', [1, 784], TFRequest.DT_FLOAT, [1] * 784) for x in range(0, 1000000): resp = client.predict(req) print(resp)
其中
client = PredictClient()
的函數(shù)入?yún)⒎謩e為高速直連Endpoint地址(endpoint參數(shù)),服務(wù)的名稱(service_name參數(shù))。高速直連Endpoint地址和地域綁定的,他的格式是pai-eas-vpc.{RegionId}.aliyuncs.com
,例如華東2(上海)地域的高速直連Endpoint地址為pai-eas-vpc.cn-shanghai.aliyuncs.com
。
Java SDK調(diào)用
使用Java官方SDK調(diào)用服務(wù)的方法如下:
添加依賴項(xiàng),EAS SDK的最新版本以Maven倉(cāng)庫(kù)中顯示的為準(zhǔn)。
<dependency> <groupId>com.aliyun.openservices.eas</groupId> <artifactId>eas-sdk</artifactId> <version>2.0.13</version> </dependency>
該Java SDK的調(diào)用詳情請(qǐng)參見Java SDK使用說(shuō)明。
編寫調(diào)用程序。
import com.aliyun.openservices.eas.predict.http.PredictClient; import com.aliyun.openservices.eas.predict.http.HttpConfig; public class TestString { public static void main(String[] args) throws Exception { // 為了確保client對(duì)象被正確共享,應(yīng)當(dāng)在啟動(dòng)時(shí)創(chuàng)建并初始化client對(duì)象,而不是在每個(gè)請(qǐng)求中都創(chuàng)建一個(gè)新的client對(duì)象。 PredictClient client = new PredictClient(new HttpConfig()); // 替換為服務(wù)Token。您可以單擊目標(biāo)服務(wù)的服務(wù)方式列下的調(diào)用信息來(lái)查看Token信息。 client.setToken("YWFlMDYyZDNmNTc3M2I3MzMwYmY0MmYwM2Y2MTYxMTY4NzBkNzdj****"); // 直連訪問(wèn)時(shí)請(qǐng)使用setDirectEndpoint方法,設(shè)置pai-eas-vpc.{region_id}.aliyuncs.com的域名進(jìn)行訪問(wèn),例如華東2(上海)為cn-shanghai。 client.setDirectEndpoint("pai-eas-vpc.cn-shanghai.aliyuncs.com"); // 替換為服務(wù)名稱。 client.setModelName("scorecard_pmml_example"); // 定義輸入字符串。 String request = "[{\"money_credit\": 3000000}, {\"money_credit\": 10000}]"; System.out.println(request); // 通過(guò)EAS返回字符串。 try { String response = client.predict(request); System.out.println(response); } catch (Exception e) { e.printStackTrace(); } // 關(guān)閉客戶端。 client.shutdown(); return; } }
Golang SDK調(diào)用
使用Golang SDK進(jìn)行服務(wù)調(diào)用時(shí),由于在編譯代碼時(shí),Golang的包管理工具會(huì)自動(dòng)從Github上將Golang SDK的代碼下載到本地,因此您無(wú)需提前安裝Golang SDK。該Golang SDK的調(diào)用詳情請(qǐng)參見Golang SDK使用說(shuō)明。
使用Golang官方SDK調(diào)用服務(wù)的方法如下:
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
)
func main() {
// 設(shè)置pai-eas-vpc.{region_id}.aliyuncs.com的域名進(jìn)行訪問(wèn),例如華東2(上海)為cn-shanghai。請(qǐng)?zhí)鎿Q為目標(biāo)服務(wù)所在地域和服務(wù)名稱。
client := eas.NewPredictClient("pai-eas-vpc.cn-shanghai.aliyuncs.com", "scorecard_pmml_example")
// 替換為服務(wù)Token。您可以單擊目標(biāo)服務(wù)的服務(wù)方式列下的調(diào)用信息來(lái)查看Token信息。
client.SetToken("YWFlMDYyZDNmNTc3M2I3MzMwYmY0MmYwM2Y2MTYxMTY4NzBkNzdj****")
client.SetEndpointType(eas.EndpointTypeDirect)
client.Init()
req := "[{\"fea1\": 1, \"fea2\": 2}]"
for i := 0; i < 100; i++ {
resp, err := client.StringPredict(req)
if err != nil {
fmt.Printf("failed to predict: %v\n", err.Error())
} else {
fmt.Printf("%v\n", resp)
}
}
}
自行實(shí)現(xiàn)調(diào)用邏輯
推薦您使用PAI提供的官方SDK來(lái)進(jìn)行直連訪問(wèn),如果您有特殊業(yè)務(wù)場(chǎng)景的需求,需要使用其他語(yǔ)言或希望自己編寫調(diào)用邏輯,則可以參見如下方法,自行實(shí)現(xiàn)直連訪問(wèn)功能,采用HTTP接口調(diào)用。EAS提供服務(wù)發(fā)現(xiàn)機(jī)制,在VPC環(huán)境中,通過(guò)如下地址即可獲得服務(wù)的后端地址列表。
地域 | 地址 |
華東2(上海) | http://pai-eas-vpc.cn-shanghai.aliyuncs.com/exported/apis/eas.alibaba-inc.k8s.io/v1/upstreams/ |
華北2(北京) | http://pai-eas-vpc.cn-beijing.aliyuncs.com/exported/apis/eas.alibaba-inc.k8s.io/v1/upstreams/ |
華東1(杭州) | http://pai-eas-vpc.cn-hangzhou.aliyuncs.com/exported/apis/eas.alibaba-inc.k8s.io/v1/upstreams/ |
例如訪問(wèn)華東1(杭州)的mnist_saved_model_example服務(wù)(該服務(wù)有兩個(gè)Instance),示例如下。
$curl http://pai-eas-vpc.cn-hangzhou.aliyuncs.com/exported/apis/eas.alibaba-inc.k8s.io/v1/upstreams/mnist_saved_model_example
獲得的服務(wù)后端地址列表如下。
{
"correlative": [
"mnist_saved_model_example"
],
"endpoints": {
"items": [
{
"app": "mnist-saved-model-example",
"ip": "172.16.XX.XX",
"port": 50000,
"weight": 100
},
{
"app": "mnist-saved-model-example",
"ip": "172.16.XX.XX",
"port": 50000,
"weight": 100
}
]
}
}
如上所示,通過(guò)服務(wù)發(fā)現(xiàn)可以獲得客戶模型服務(wù)mnist_saved_model_example的兩個(gè)實(shí)例的ip、port及weight信息。相關(guān)的IP在用戶部署服務(wù)時(shí)選擇的VPC中即可直接連通。
對(duì)于通過(guò)服務(wù)發(fā)現(xiàn)來(lái)進(jìn)行直連訪問(wèn)的方法請(qǐng)參考如下步驟:
客戶端代碼中建立后臺(tái)線程,定時(shí)訪問(wèn)上述的服務(wù)發(fā)現(xiàn)服務(wù),建議每5秒訪問(wèn)一次,獲取當(dāng)前服務(wù)最新的實(shí)例列表,并將其保存在本地緩存中。
在發(fā)起推理請(qǐng)求時(shí),從本地緩存中獲取一個(gè)實(shí)例IP+端口發(fā)起訪問(wèn),可使用Weighted Round Robin算法進(jìn)行獲取,也可根據(jù)自己的業(yè)務(wù)邏輯來(lái)進(jìn)行選擇。
發(fā)起請(qǐng)求時(shí),如遇連接失敗等情況,則表示服務(wù)實(shí)例可能發(fā)生異常(如用戶實(shí)例發(fā)生crash等),客戶端需要進(jìn)行重試,重新從緩存中獲取一個(gè)新的實(shí)例,在本地緩存中實(shí)例數(shù)多于1的情況下,新IP+Port組合應(yīng)該避免與已經(jīng)失敗的IP+Port相同,即確保更換一個(gè)實(shí)例進(jìn)行重試。
在使用服務(wù)發(fā)現(xiàn)進(jìn)行直連訪問(wèn)時(shí),請(qǐng)遵循下面幾條原則,否則可能導(dǎo)致服務(wù)訪問(wèn)異常:
服務(wù)發(fā)現(xiàn)服務(wù)是一個(gè)旁路的服務(wù),不可在每次發(fā)起請(qǐng)求時(shí)對(duì)服務(wù)發(fā)現(xiàn)服務(wù)進(jìn)行請(qǐng)求。
訪問(wèn)服務(wù)發(fā)現(xiàn)服務(wù)時(shí),在返回狀態(tài)碼為200且返回實(shí)例數(shù)不為空時(shí),再更新緩存,返回非200時(shí),千萬(wàn)不能清空緩存。
直連的方式負(fù)載均衡和重試邏輯都需要在客戶端側(cè)完成,穩(wěn)定性依賴客戶端實(shí)現(xiàn),平臺(tái)側(cè)不負(fù)責(zé)直連場(chǎng)景的客戶端請(qǐng)求容錯(cuò),在實(shí)現(xiàn)時(shí)請(qǐng)嚴(yán)格遵循上述的步驟來(lái)實(shí)現(xiàn)容錯(cuò)邏輯,否則平臺(tái)側(cè)無(wú)法保障SLA。
完整的實(shí)現(xiàn)流程,請(qǐng)參見Python SDK的實(shí)現(xiàn)。
相關(guān)文檔
更多的服務(wù)調(diào)用方式,請(qǐng)參見調(diào)用方式概覽。