VPC高速直连调用

EAS支持通过Python官方SDK或自行实现调用逻辑的方式对服务进行VPC高速直连调用。本文详细介绍这两种调用方式的实现方法。

调用原理

VPC高速直连调用、公网调用及VPC地址调用的链路如下图所示。

image

开启服务运行所在资源组的VPC高速直连功能后,EAS会在您指定的安全组内绑定辅助网卡,打通您的VPCEAS服务实例之间的网络。之后您可以在自己的VPC中直接访问EAS实例,无需通过网关访问服务,避免了四层SLB和七层网络转发。同时,EAS预置的RPC实现了HTTP相关协议栈,对于高QPS(Queries Per Second)的大流量服务(例如图像服务),可以大幅度提高访问性能、降低访问延时。

前提条件

如果您使用专属资源组部署服务,则部署服务前,需要为专属资源组开通VPC高速直连功能,详情请参见配置网络连通

重要

安全组控制ECS实例机器的出入流量,用户的ECS实例和EAS服务实例之间的网络互通也受安全组的配置控制。默认普通安全组内,实例之间是内网互通的,您可以在配置VPC高速直连时,选择需要访问在线服务的ECS实例所在安全组,从而支持实例之间网络互通。当需要配置使用不同的安全组时,请设置安全组的规则支持ECS实例之间能够互通。

调用方式

为方便用户调用服务,EAS提供了以下两种方式实现VPC高速直连调用:

  • 使用官方SDK调用

    EAS封装了调用逻辑并提供了Python SDK、Java SDKGolang SDK的调用方法,您可以直接使用SDK实现VPC高速直连调用。

  • 自行实现调用逻辑

    推荐使用官方SDK调用服务,从而有效减少编写调用逻辑的时间并提高服务调用稳定性。如果您需要使用其他语言或希望自己编写实现调用逻辑,下文也提供了方法指导供您参考。此外,自行实现调用逻辑需要根据不同框架构建服务请求,详情请参见构建通用Processor服务请求

使用官方SDK调用

Python SDK调用

使用Python官方SDK调用服务的方法如下:

  1. 安装。

    pip install -U eas-prediction --user

    Python SDK的调用详情请参见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
    if __name__ == '__main__':
        client = PredictClient('http://pai-eas-vpc.cn-shanghai.aliyuncs.com', 'mnist_saved_model_example')
        # 替换为服务Token。您可以单击目标服务的服务方式列下的调用信息来查看Token信息。
        client.set_token('M2FhNjJlZDBmMzBmMzE4NjFiNzZhMmUxY2IxZjkyMDczNzAzYjFi****')
        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)
        for x in range(0, 1000000):
            resp = client.predict(req)
            print(resp)
    

    其中client = PredictClient()的函数入参分别为高速直连Endpoint地址(endpoint参数),服务的名称(service_name参数)。高速直连Endpoint地址和地域绑定的,他的格式是pai-eas-vpc.{RegionId}.aliyuncs.com,例如华东2(上海)地域的高速直连Endpoint地址为pai-eas-vpc.cn-shanghai.aliyuncs.com

Java SDK调用

使用Java官方SDK调用服务的方法如下:

  1. 添加依赖项,EAS SDK的最新版本以Maven仓库中显示的为准。

    <dependency>
      <groupId>com.aliyun.openservices.eas</groupId>
      <artifactId>eas-sdk</artifactId>
      <version>2.0.13</version>
    </dependency>

    Java SDK的调用详情请参见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方法,设置pai-eas-vpc.{region_id}.aliyuncs.com的域名进行访问,例如华东2(上海)为cn-shanghai。
            client.setDirectEndpoint("pai-eas-vpc.cn-shanghai.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() {
    // 设置pai-eas-vpc.{region_id}.aliyuncs.com的域名进行访问,例如华东2(上海)为cn-shanghai。请替换为目标服务所在地域和服务名称。
    client := eas.NewPredictClient("pai-eas-vpc.cn-shanghai.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)
        }
    }
}

自行实现调用逻辑

推荐您使用PAI提供的官方SDK来进行直连访问,如果您有特殊业务场景的需求,需要使用其他语言或希望自己编写调用逻辑,则可以参见如下方法,自行实现直连访问功能,采用HTTP接口调用。EAS提供服务发现机制,在VPC环境中,通过如下地址即可获得服务的后端地址列表。

地域

地址

华东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/

例如访问华东1(杭州)的mnist_saved_model_example服务(该服务有两个Instance),示例如下。

$curl http://pai-eas-vpc.cn-hangzhou.aliyuncs.com/exported/apis/eas.alibaba-inc.k8s.io/v1/upstreams/mnist_saved_model_example

获得的服务后端地址列表如下。

{
  "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
      }
    ]
  }
}

如上所示,通过服务发现可以获得客户模型服务mnist_saved_model_example的两个实例的ipportweight信息。相关的IP在用户部署服务时选择的VPC中即可直接连通。

对于通过服务发现来进行直连访问的方法请参考如下步骤:

  1. 客户端代码中建立后台线程,定时访问上述的服务发现服务,建议每5秒访问一次,获取当前服务最新的实例列表,并将其保存在本地缓存中。

  2. 在发起推理请求时,从本地缓存中获取一个实例IP+端口发起访问,可使用Weighted Round Robin算法进行获取,也可根据自己的业务逻辑来进行选择。

  3. 发起请求时,如遇连接失败等情况,则表示服务实例可能发生异常(如用户实例发生crash等),客户端需要进行重试,重新从缓存中获取一个新的实例,在本地缓存中实例数多于1的情况下,新IP+Port组合应该避免与已经失败的IP+Port相同,即确保更换一个实例进行重试。

重要

在使用服务发现进行直连访问时,请遵循下面几条原则,否则可能导致服务访问异常:

  1. 服务发现服务是一个旁路的服务,不可在每次发起请求时对服务发现服务进行请求。

  2. 访问服务发现服务时,在返回状态码为200且返回实例数不为空时,再更新缓存,返回非200时,千万不能清空缓存。

  3. 直连的方式负载均衡和重试逻辑都需要在客户端侧完成,稳定性依赖客户端实现,平台侧不负责直连场景的客户端请求容错,在实现时请严格遵循上述的步骤来实现容错逻辑,否则平台侧无法保障SLA。

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

相关文档

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