本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。
VPC高速直连是一种高性能的服务调用方式,允许客户端在专有网络(VPC)内部绕过公共网关,直接访问EAS服务实例。本文介绍其工作原理、配置方法,并提供使用官方SDK调用和自行实现调用逻辑的详细指引。
功能概述
适用场景
高性能要求:对于每秒查询数(QPS)极高的大流量服务(如图像、语音识别),直连可以大幅提升访问性能。
低延迟敏感:对于在线推荐、金融风控等对响应时间有严苛要求的业务,直连能有效降低延迟。
工作原理
核心机制包括:
网络连通:为服务配置专有网络后,EAS会在指定的VPC和交换机内,为每个服务实例创建并绑定一张免费的辅助弹性网卡,打通VPC和EAS服务实例之间的网络。这样VPC内客户端可直接访问EAS服务实例,而无需通过网关,避免了四层SLB和七层网络转发。
服务发现:EAS提供服务发现机制,允许客户端获取服务所有实例的实时
IP:PORT列表。客户端可基于该列表实现负载均衡和故障转移。
准备工作
在调用之前,请确认已为服务配置专有网络,详情请参见网络配置。
每个弹性网卡会占用交换机中的一个IP地址,请确保交换机的可用IP数不小于服务实例数,以满足服务实例的IP需求。
配置安全组规则,实现网络隔离和访问控制。
重要客户端(如ECS)与EAS服务实例之间的网络访问受安全组规则控制。
默认普通安全组内,实例之间是内网互通的。可以在为EAS服务配置VPC高速直连时,选择需要访问EAS服务的ECS实例所在安全组。
当需要配置使用不同的安全组时,请设置安全组的规则支持ECS实例之间能够互通。详情请参见不同安全组的经典网络实例内网互通。
通过官方SDK调用(推荐)
EAS官方SDK封装了服务发现、负载均衡和故障重试等复杂逻辑,是实现VPC高速直连调用的首选方式。
Python SDK调用
安装或升级SDK。
pip install -U eas-prediction --user更多详情请参见Python SDK使用说明。
编写调用代码。
以字符串作为输入输出的程序示例如下,其他格式(TensorFlow或PyTorch等)的输入输出的程序示例请参见Python SDK使用说明。
#!/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 # 替换为真实的地址。格式是{Uid}.vpc.{RegionId}.pai-eas.aliyuncs.com # Uid为阿里云账号UID, RegionId为EAS服务的地域 ENDPOINT = "123**********.vpc.cn-shanghai.pai-eas.aliyuncs.com" # 替换为真实的EAS服务名称 SERVICE_NAME = "mnist_saved_model_example" # 替换为服务Token。可以在目标服务的详情页查看调用信息来获取。建议通过环境变量或密钥管理服务(KMS)来管理和使用Token。 TOKEN = "M2FhNjJlZDBmMzBmMzE4NjFiNzZhMmUxY2IxZjkyMDczNzAzYjFi****" if __name__ == '__main__': client = PredictClient(ENDPOINT, SERVICE_NAME) client.set_token(TOKEN) client.set_endpoint_type(ENDPOINT_TYPE_DIRECT) # 表示通过直连通道访问服务。 client.init() # request = StringRequest('[{}]') req = TFRequest('predict_images') req.add_feed('images', [1, 784], TFRequest.DT_FLOAT, [1] * 784) resp = client.predict(req) print(resp)其中:
client = PredictClient()的函数入参分别为高速直连Endpoint地址和服务的名称。高速直连Endpoint地址:和地域绑定,格式为
{Uid}.vpc.{RegionId}.pai-eas.aliyuncs.com。其中,{Uid}为阿里云账号UID。例如华东2(上海)地域的高速直连Endpoint地址为123**********.vpc.cn-shanghai.pai-eas.aliyuncs.com。TOKEN:可以在目标服务的详情页查看调用信息来获取。
Java SDK调用
添加Maven依赖。
使用Java编写客户端代码时,在Maven工程中使用EAS Java SDK,必须在pom.xml文件<dependencies>中添加eas-sdk的依赖,示例如下,最新版本以Maven仓库中显示的为准。
<dependency> <groupId>com.aliyun.openservices.eas</groupId> <artifactId>eas-sdk</artifactId> <version>2.0.20</version> </dependency>更多详情请参见Java SDK使用说明。
编写调用代码。
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对象被正确共享,应当在启动时创建并初始化client对象,而不是在每个请求中都创建一个新的client对象。 PredictClient client = new PredictClient(new HttpConfig()); // 替换为服务Token。您可以单击目标服务的服务方式列下的调用信息来查看Token信息。 client.setToken("YWFlMDYyZDNmNTc3M2I3MzMwYmY0MmYwM2Y2MTYxMTY4NzBkNzdj****"); // 直连访问时请使用setDirectEndpoint方法,设置123**********.vpc.{region_id}.pai-eas.aliyuncs.com的域名进行访问,其中123**********需要替换为您自己的UID。例如华东2(上海)为cn-shanghai。 client.setDirectEndpoint("123**********.vpc.cn-shanghai.pai-eas.aliyuncs.com"); // 替换为服务名称。 client.setModelName("scorecard_pmml_example"); // 定义输入字符串。 String request = "[{\"money_credit\": 3000000}, {\"money_credit\": 10000}]"; System.out.println(request); // 通过EAS返回字符串。 try { String response = client.predict(request); System.out.println(response); } catch (Exception e) { e.printStackTrace(); } // 关闭客户端。 client.shutdown(); return; } }
Golang SDK调用
使用Golang SDK进行服务调用时,由于在编译代码时,Golang的包管理工具会自动从Github上将Golang SDK的代码下载到本地,因此您无需提前安装Golang SDK。该Golang SDK的调用详情请参见Golang SDK使用说明。
使用Golang官方SDK调用服务的方法如下:
package main
import (
"fmt"
"github.com/pai-eas/eas-golang-sdk/eas"
)
func main() {
// 设置123**********.vpc.{region_id}.pai-eas.aliyuncs.com的域名进行访问,其中123**********需要替换为您自己的UID。例如华东2(上海)为cn-shanghai。请替换为目标服务所在地域和服务名称。
client := eas.NewPredictClient("123**********.vpc.cn-shanghai.pai-eas.aliyuncs.com", "scorecard_pmml_example")
// 替换为服务Token。您可以单击目标服务的服务方式列下的调用信息来查看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)
}
}
}自行实现调用逻辑
如果需要使用其他语言或有定制化需求,可以参考如下内容自行实现HTTP调用逻辑。
自行实现调用逻辑需要客户端自行处理服务发现、负载均衡、故障重试等复杂的容错逻辑。客户端的实现将直接影响服务可用性。强烈建议使用官方SDK。平台SLA不覆盖因客户端实现不当导致的服务中断。
服务发现API
EAS在VPC环境中提供了一个HTTP接口用于服务发现。通过访问该接口,您可以获取服务所有后端实例的IP、端口和权重列表。
URL格式:
http://<您的阿里云账号ID>.vpc.<RegionID>.pai-eas.aliyuncs.com/exported/apis/eas.alibaba-inc.k8s.io/v1/upstreams/<服务名称>认证方式:该API无需Token认证,但仅限在为服务配置的VPC内部访问。
调用时机:此API为旁路接口,应由后台任务定期调用(例如,每5-10秒一次)。严禁在每次推理请求时调用此API,否则会严重影响性能。
调用示例:
对于部署在华东1(杭州)的mnist_saved_model_example服务(该服务有两个Instance),调用示例如下:
$curl http://123**********.vpc.cn-hangzhou.pai-eas.aliyuncs.com/exported/apis/eas.alibaba-inc.k8s.io/v1/upstreams/mnist_saved_model_example注意将上述地址中的123**********替换为您自己的UID。
获得的服务后端地址列表如下:
{
"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
}
]
}
}实现逻辑详解
一个健壮的自定义客户端调用应包含以下三个核心逻辑:
本地缓存实例列表并定时刷新
重要服务发现服务是一个旁路的服务,不可在每次发起推理请求时调用服务发现API。
客户端启动一个后台线程,定时(建议每5-10秒)调用服务发现API。
成功时:当HTTP状态码为200且返回的实例列表不为空时,用新列表覆盖本地缓存。
失败时:当API调用失败(如超时、返回非200状态码)或返回空列表时,必须沿用本地缓存,切勿清空,以保证服务的可用性。
请求时负载均衡
每次发起推理请求时,根据本地缓存的实例列表选择一个目标实例。建议采用加权轮询(Weighted Round Robin)等算法,也可根据自己的业务逻辑来进行选择。
失败重试
发起请求时,如遇连接失败等情况,则表示服务实例可能发生异常(如用户实例发生crash等),客户端需要进行重试。在本地缓存中实例数多于1的情况下,重新从缓存中获取一个不同的实例进行重试。
完整的实现流程,请参见Python SDK的实现。
相关文档
更多的服务调用方式,请参见调用方式概览。