Golang SDK提供TensorFlow、PyTorch和字串等多種輸入輸出格式的封裝,以及佇列服務的非同步呼叫能力。本文介紹各介面詳情並提供完整程式樣本。
關於SDK的適用情境、調用原理,請參見服務調用SDK。
前置準備
Golang的包管理工具會在編譯時間自動下載SDK代碼,無需提前安裝。如需自訂調用邏輯,可先下載Golang SDK代碼再修改。
引入SDK的方式如下:
import (
"github.com/pai-eas/eas-golang-sdk/eas"
)快速上手
根據您的模型輸入資料格式,選擇對應的Request類,以下是最小的字串請求端到端調用樣本:
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
)
func main() {
client := eas.NewPredictClient("182848887922****.cn-shanghai.pai-eas.aliyuncs.com", "my_service")
client.SetToken("YOUR_SERVICE_TOKEN")
client.Init()
resp, err := client.StringPredict("[{}]")
if err != nil {
fmt.Printf("failed to predict: %v\n", err.Error())
} else {
fmt.Printf("%v\n", resp)
}
}介面列表
Golang SDK 提供以下介面類,按用途分為三組:
分組 | 類說明 |
用戶端主類 | PredictClient:佈建服務資訊(Endpoint / ServiceName / Token)、發送請求、接收響應。 |
輸入輸出 |
|
佇列服務 |
|
類PredictClient
用戶端主類,用於佈建服務資訊、發送請求和接收預測結果。
介面 | 描述 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 初始化PredictClient對象。設定完所有參數後,需調用 |
|
|
|
|
|
|
|
|
類TFRequest
用於構建TensorFlow模型的輸入資料。
介面 | 描述 |
|
|
|
|
|
|
類TFResponse
用於解析TensorFlow模型的輸出資料。
介面 | 描述 |
|
|
|
|
類TorchRequest
用於構建PyTorch模型的輸入資料。
介面 | 描述 |
| TorchRequest類的構建函數。 |
|
|
|
|
類TorchResponse
用於解析PyTorch模型的輸出資料。
介面 | 描述 |
|
|
|
|
類QueueClient
用於與EAS佇列服務進行互動,實現資料的生產、消費和管理。
介面 | 描述 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
類types.Watcher
用於從佇列服務訂閱的資料管道中讀取推送資料。
介面 | 描述 |
|
|
| 功能:關閉一個Watcher對象,用於關閉後端的資料連線。 說明 一個用戶端只能啟動一個Watcher對象,使用完成後需要將該對象關閉才能啟動新的Watcher對象。 |
程式樣本
同步推理樣本(按輸入輸出格式)
根據服務的輸入輸出類型,選擇對應的範例程式碼。
字串
對於使用自訂Processor部署服務的使用者而言,通常採用字串進行服務調用(例如,PMML模型服務的調用),具體的Demo程式如下。
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
)
func main() {
client := eas.NewPredictClient("182848887922****.cn-shanghai.pai-eas.aliyuncs.com", "scorecard_pmml_example")
client.SetToken("YWFlMDYyZDNmNTc3M2I3MzMwYmY0MmYwM2Y2MTYxMTY4NzBkNzdj****")
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)
}
}
}TensorFlow
使用TensorFlow的使用者,需要將TFRequest和TFResponse分別作為輸入和輸出資料格式,具體Demo樣本如下。
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
)
func main() {
client := eas.NewPredictClient("182848887922****.cn-shanghai.pai-eas.aliyuncs.com", "mnist_saved_model_example")
client.SetToken("YTg2ZjE0ZjM4ZmE3OTc0NzYxZDMyNmYzMTJjZTQ1YmU0N2FjMTAy****")
client.Init()
tfreq := eas.TFRequest{}
tfreq.SetSignatureName("predict_images")
tfreq.AddFeedFloat32("images", []int64{1, 784}, make([]float32, 784))
for i := 0; i < 100; i++ {
resp, err := client.TFPredict(tfreq)
if err != nil {
fmt.Printf("failed to predict: %v", err)
} else {
fmt.Printf("%v\n", resp)
}
}
}PyTorch
使用PyTorch的使用者,需要將TorchRequest和TorchResponse分別作為輸入和輸出資料格式,具體Demo樣本如下。
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
)
func main() {
client := eas.NewPredictClient("182848887922****.cn-shanghai.pai-eas.aliyuncs.com", "pytorch_resnet_example")
client.SetTimeout(500)
client.SetToken("ZjdjZDg1NWVlMWI2NTU5YzJiMmY5ZmE5OTBmYzZkMjI0YjlmYWVl****")
client.Init()
req := eas.TorchRequest{}
req.AddFeedFloat32(0, []int64{1, 3, 224, 224}, make([]float32, 150528))
req.AddFetch(0)
for i := 0; i < 10; i++ {
resp, err := client.TorchPredict(req)
if err != nil {
fmt.Printf("failed to predict: %v", err)
} else {
fmt.Println(resp.GetTensorShape(0), resp.GetFloatVal(0))
}
}
}通過VPC網路直連方式調用服務的樣本
通過網路直連方式,您只能訪問部署在EAS專屬資源群組的服務,且需要為該資源群組與使用者指定的vSwitch連通網路後才能使用。關於如何購買EAS專屬資源群組和連通網路,請參見使用EAS資源群組和EAS訪問公網或內網資源。該調用方式與普通調用方式相比,僅需增加一行代碼client.SetEndpointType(eas.EndpointTypeDirect)即可,特別適合大流量高並發的服務,具體樣本如下。
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
)
func main() {
// VPC高速直連Endpoint格式:{uid}.vpc.{region-id}.pai-eas.aliyuncs.com,可在EAS控制台服務詳情頁的"調用資訊"中查看
client := eas.NewPredictClient("182848887922****.vpc.cn-shanghai.pai-eas.aliyuncs.com", "scorecard_pmml_example")
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)
}
}
}用戶端串連參數設定樣本
您可以通過http.Transport屬性佈建要求用戶端的串連參數,範例程式碼如下。
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
"net/http"
"time"
)
func main() {
// VPC高速直連Endpoint格式:{uid}.vpc.{region-id}.pai-eas.aliyuncs.com,可在EAS控制台服務詳情頁的"調用資訊"中查看
client := eas.NewPredictClient("182848887922****.vpc.cn-shanghai.pai-eas.aliyuncs.com", "network_test")
client.SetToken("MDAwZDQ3NjE3OThhOTI4ODFmMjJiYzE0MDk1NWRkOGI1MmVhMGI0****")
client.SetEndpointType(eas.EndpointTypeDirect)
client.SetHttpTransport(&http.Transport{
MaxConnsPerHost: 300,
TLSHandshakeTimeout: 100 * time.Millisecond,
ResponseHeaderTimeout: 200 * time.Millisecond,
ExpectContinueTimeout: 200 * time.Millisecond,
})
}佇列服務發送、訂閱資料樣本
通過QueueClient可向佇列服務中發送資料、查詢資料、查詢佇列服務的狀態以及訂閱佇列服務中的資料推送。以下Demo為例,介紹一個線程向佇列服務中推送資料,另一個線程通過Watcher訂閱佇列服務中推送過來的資料。
在EAS部署非同步推理服務,會自動產生輸入隊列和輸出隊列,通常地址格式如下:
輸入隊列:<domain>/api/predict/<service_name>
輸出隊列:<domain>/api/predict/<service_name>/sink
請根據您實際需要採用<service_name>或者<service_name>/sink構建QueueClient。
const (
QueueEndpoint = "182848887922****.cn-shanghai.pai-eas.aliyuncs.com"
// eg:EAS服務名為test_qservice,則輸入隊列名為test_qservice,輸出隊列名為test_qservice/sink
QueueName = "test_qservice"
QueueToken = "YmE3NDkyMzdiMzNmMGM3ZmE4ZmNjZDk0M2NiMDA3OTZmNzc1MTUx****"
)
queue, err := NewQueueClient(QueueEndpoint, QueueName, QueueToken)
// truncate all messages in the queue
attrs, err := queue.Attributes()
if index, ok := attrs["stream.lastEntry"]; ok {
idx, _ := strconv.ParseUint(index, 10, 64)
queue.Truncate(context.Background(), idx+1)
}
ctx, cancel := context.WithCancel(context.Background())
// create a goroutine to send messages to the queue
go func() {
i := 0
for {
select {
case <-time.NewTicker(time.Microsecond * 1).C:
_, _, err := queue.Put(context.Background(), []byte(strconv.Itoa(i)), types.Tags{})
if err != nil {
fmt.Printf("Error occured, retry to handle it: %v\n", err)
}
i += 1
case <-ctx.Done():
break
}
}
}()
// create a watcher to watch the messages from the queue
watcher, err := queue.Watch(context.Background(), 0, 5, false, false)
if err != nil {
fmt.Printf("Failed to create a watcher to watch the queue: %v\n", err)
return
}
// read messages from the queue and commit manually
for i := 0; i < 100; i++ {
df := <-watcher.FrameChan()
err := queue.Commit(context.Background(), df.Index.Uint64())
if err != nil {
fmt.Printf("Failed to commit index: %v(%v)\n", df.Index, err)
}
}
// everything is done, close the watcher
watcher.Close()
cancel()常見問題排查
Golang SDK調用異常的現象、原因與排查方向(鑒權、路由、串連、服務端類等共性問題)請參見服務調用SDK的"調用異常排查"章節。
完整的服務狀態代碼、錯誤資訊含義與處理建議請參見附錄:服務狀態代碼與常見報錯。