VPC高速直连调用

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

VPC高速直连是一种高性能的服务调用方式,允许客户端在专有网络(VPC)内部绕过公共网关,直接访问EAS服务实例。本文介绍其工作原理、配置方法,并提供使用官方SDK调用和自行实现调用逻辑的详细指引。

功能概述

适用场景

  • 高性能要求:对于每秒查询数(QPS)极高的大流量服务(如图像、语音识别),直连可以大幅提升访问性能。

  • 低延迟敏感:对于在线推荐、金融风控等对响应时间有严苛要求的业务,直连能有效降低延迟。

工作原理

核心机制包括:

  • 网络连通:为服务配置专有网络后,EAS会在指定的VPC和交换机内,为每个服务实例创建并绑定一张免费的辅助弹性网卡,打通VPCEAS服务实例之间的网络。这样VPC内客户端可直接访问EAS服务实例,而无需通过网关,避免了四层SLB和七层网络转发。

  • 服务发现:EAS提供服务发现机制,允许客户端获取服务所有实例的实时IP:PORT列表。客户端可基于该列表实现负载均衡和故障转移。

image

准备工作

在调用之前,请确认已为服务配置专有网络,详情请参见网络配置

  • 每个弹性网卡会占用交换机中的一个IP地址,请确保交换机的可用IP数不小于服务实例数,以满足服务实例的IP需求。

  • 配置安全组规则,实现网络隔离和访问控制。

    重要

    客户端(如ECS)与EAS服务实例之间的网络访问受安全组规则控制。

    • 默认普通安全组内,实例之间是内网互通的。可以在为EAS服务配置VPC高速直连时,选择需要访问EAS服务的ECS实例所在安全组。

    • 当需要配置使用不同的安全组时,请设置安全组的规则支持ECS实例之间能够互通。详情请参见不同安全组的经典网络实例内网互通

通过官方SDK调用(推荐)

EAS官方SDK封装了服务发现、负载均衡和故障重试等复杂逻辑,是实现VPC高速直连调用的首选方式。

Python SDK调用

  1. 安装或升级SDK。

    pip install -U eas-prediction --user

    更多详情请参见Python SDK使用说明

  2. 编写调用代码。

    以字符串作为输入输出的程序示例如下,其他格式(TensorFlowPyTorch等)的输入输出的程序示例请参见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, RegionIdEAS服务的地域
    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调用

  1. 添加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使用说明

  2. 编写调用代码。

    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

EASVPC环境中提供了一个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
      }
    ]
  }
}

实现逻辑详解

一个健壮的自定义客户端调用应包含以下三个核心逻辑:

  1. 本地缓存实例列表并定时刷新

    重要

    服务发现服务是一个旁路的服务,不可在每次发起推理请求时调用服务发现API。

    客户端启动一个后台线程,定时(建议每5-10秒)调用服务发现API。

    • 成功时:当HTTP状态码为200且返回的实例列表不为空时,用新列表覆盖本地缓存。

    • 失败时:当API调用失败(如超时、返回非200状态码)或返回空列表时,必须沿用本地缓存切勿清空,以保证服务的可用性。

  2. 请求时负载均衡

    每次发起推理请求时,根据本地缓存的实例列表选择一个目标实例。建议采用加权轮询(Weighted Round Robin)等算法,也可根据自己的业务逻辑来进行选择。

  3. 失败重试

    发起请求时,如遇连接失败等情况,则表示服务实例可能发生异常(如用户实例发生crash等),客户端需要进行重试。在本地缓存中实例数多于1的情况下,重新从缓存中获取一个不同的实例进行重试。

完整的实现流程,请参见Python SDK的实现

相关文档

更多的服务调用方式,请参见调用方式概览