通过终端节点私网访问阿里云百炼模型或应用 API

为了在 VPC 内直接调用阿里云百炼的模型或应用 API,且确保流量不经过公网,可以创建私网终端节点,将通信完全限制在阿里云内网。

工作原理

在专有网络(VPC)中创建接口终端节点后,阿里云私网连接服务(PrivateLink)将为您的VPC与阿里云百炼建立一条私网连接(终端节点连接)。该连接为单向设计,仅允许您的 VPC 内的资源主动访问阿里云百炼,阿里云百炼无法通过此连接反向访问您 VPC 内的资源。

VPC 内的计算资源访问终端节点时,流量将通过 PrivateLink 转发至阿里云百炼服务端,不经过公网。

image

终端节点须与阿里云百炼服务位于同一地域,如需从其他地域的VPC内进行私网访问,请参考跨地域私网访问阿里云百炼 API

阿里云百炼服务所在地域:

  • 公共云:华北2(北京)、新加坡

  • 金融云:华东 2 金融云(上海),如需使用,请联系技术支持人员添加白名单。

通过终端节点访问阿里云百炼 API

步骤一:创建接口终端节点

公共云

  1. 登录终端节点控制台

    如果首次使用终端节点,按照界面指引开通私网连接服务。
  2. 接口终端节点页签下,单击创建终端节点,并配置以下各项参数,其他参数保持默认即可。

    • 所属地域:根据阿里云百炼服务地域选择华北2(北京)”或“新加坡

    • 节点名称:可自定义,例如“阿里云百炼私网连接点”。

    • 终端节点类型:选择接口终端节点

    • 终端节点服务:选择阿里云服务,在下方输入框中筛选后选中com.aliyuncs.dashscope

      image

    • 专有网络:选择计划用于访问阿里云百炼服务的 VPC。终端节点将被创建到 VPC 内,VPC 内的 ECS、容器等资源才能通过私网域名访问阿里云百炼服务。

    • 可用区与交换机:接口终端节点会在所选交换机对应的可用区中,创建终端节点网卡(Endpoint ENI)用于接收来自 VPC 内部的私网流量。建议至少选择两个不同可用区的交换机,以实现高可用:当某个可用区发生故障时,流量可自动切换至其他可用区的网卡,避免服务中断。

    • 安全组:选择关联到终端节点网卡的安全组,用于控制谁可以访问该终端节点。因此请确保安全组在入方向允许 80(http)、443(https)访问。

  3. 单击确定创建,完成创建。

金融云

金融云内使用此功能,需要先联系技术支持人员添加白名单。完成白名单添加后,按如下步骤操作:

  1. 登录终端节点控制台

  2. 在顶部菜单栏处,选择终端节点所在的地域“华东 2 金融云”。

    image

  3. 接口终端节点页签下,单击创建终端节点,并配置以下各项参数,其他参数保持默认即可。

    • 所属地域:选择“华东 2 金融云”。

    • 节点名称:可自定义,例如“阿里云百炼私网连接点”。

    • 终端节点类型:选择接口终端节点

    • 终端节点服务:点击选择可用服务,然后在“终端节点服务ID”列表中选中目标终端节点服务ID,例如“epsrv-zm0qfzkk1lcxfr******”。

      image

    • 专有网络:选择计划用于访问阿里云百炼服务的 VPC。终端节点将被创建到 VPC 内,VPC 内的 ECS、容器等资源才能通过私网域名访问阿里云百炼服务。

    • 可用区与交换机:接口终端节点会在所选交换机对应的可用区中,创建终端节点网卡(Endpoint ENI)用于接收来自 VPC 内部的私网流量。建议至少选择两个不同可用区的交换机,以实现高可用:当某个可用区发生故障时,流量可自动切换至其他可用区的网卡,避免服务中断。

    • 安全组:选择关联到终端节点网卡的安全组,用于控制谁可以访问该终端节点。因此请确保安全组在入方向允许 80(http)、443(https)访问。

  4. 单击确定创建,完成创建。

步骤二:获取终端节点服务域名

公共云

完成接口终端节点创建后,可以在接口终端节点的详情页中获取服务域名,用于后续私网访问阿里云百炼 API。

默认服务域名仅支持 HTTP 协议,如需 HTTPS 访问,可使用自定义服务域名

image

金融云

完成接口终端节点创建后,可以在接口终端节点的详情页中获取默认服务域名,用于后续私网访问阿里云百炼 API。

image

步骤三:调用验证

将阿里云百炼 API base_url 中的域名,替换为上一步骤中获取到的终端节点服务域名,然后在对应 VPC 发起调用即可。

公共云

以 OpenAI 兼容模式调用北京地域的通义千问文本模型为例:

  • 替换前:https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions

  • 替换后:

    • 默认域名:http://ep-***.dashscope.cn-beijing.privatelink.aliyuncs.com/compatible-mode/v1/chat/completions

    • 自定义服务域名:https://vpc-cn-beijing.dashscope.aliyuncs.com/compatible-mode/v1/chat/completions

调用示例:

HTTP

# 将原始域名替换为上一步骤中获取到的终端节点服务域名
curl -X POST http://ep-***.dashscope.cn-beijing.privatelink.aliyuncs.com/compatible-mode/v1/chat/completions \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
    "model": "qwen-flash",
    "messages": [
        {
            "role": "system",
            "content": "You are a helpful assistant."
        },
        {
            "role": "user", 
            "content": "你是谁?"
        }
    ]
}'

OpenAI Python SDK

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 将原始域名替换为上一步骤中获取到的终端节点服务域名
    base_url="http://ep-***.dashscope.cn-beijing.privatelink.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
    model="qwen-flash",
    messages=[
        {'role': 'system', 'content': 'You are a helpful assistant.'},
        {'role': 'user', 'content': '你是谁?'}],
)
print(completion.model_dump_json())

DashScope Python SDK

import os
from http import HTTPStatus
# 建议dashscope SDK 的版本 >= 1.14.0
import dashscope
from dashscope import Generation

# 将原始域名替换为上一步骤中获取到的终端节点服务域名
dashscope.base_http_api_url = "http://ep-***.dashscope.cn-beijing.privatelink.aliyuncs.com/api/v1"
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
messages = [{
    'role': 'user', 'content': '你是谁?'
}]
response = Generation.call(
    model="qwen-flash",
    messages=messages,
    result_format='message'
)
if response.status_code == HTTPStatus.OK:
    print(response)
else:
    print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
        response.request_id, response.status_code,
        response.code, response.message
    ))

DashScope Java SDK

// 建议DashScope SDK的版本 >= 2.12.0
import java.util.Arrays;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.protocol.Protocol;
import com.alibaba.dashscope.utils.JsonUtils;

public class Main {
    public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
        // 将原始域名替换为上一步骤中获取到的终端节点服务域名
        Generation gen = new Generation(Protocol.HTTP.getValue(), "http://ep-***.dashscope.cn-beijing.privatelink.aliyuncs.com/api/v1");
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("You are a helpful assistant.")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("你是谁?")
                .build();
        GenerationParam param = GenerationParam.builder()
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .model("qwen-flash")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .build();
        return gen.call(param);
    }
    public static void main(String[] args) {
        try {
            GenerationResult result = callWithMessage();
            System.out.println(JsonUtils.toJson(result));
        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            // 打印错误信息
            System.err.println("An error occurred while calling the generation service: " + e.getMessage());
        }
    }
}
调用前,需要您已完成获取API Key。如需要直接传入 API Key,请将$DASHSCOPE_API_KEY 替换为您的 API Key。

金融云

以 OpenAI 兼容模式调用通义千问文本模型为例:

  • 替换前:https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions

  • 替换后:http://ep-***.epsrv-***.dashscope.cn-shanghai-finance-1.privatelink.aliyuncs.com/compatible-mode/v1/chat/completions

调用示例:

HTTP

# 将原始域名替换为上一步骤中获取到的终端节点服务域名
curl -X POST http://ep-***.epsrv-***.dashscope.cn-shanghai-finance-1.privatelink.aliyuncs.com/compatible-mode/v1/chat/completions \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
    "model": "qwen-plus",
    "messages": [
        {
            "role": "system",
            "content": "You are a helpful assistant."
        },
        {
            "role": "user", 
            "content": "你是谁?"
        }
    ]
}'

OpenAI Python SDK

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 将原始域名替换为上一步骤中获取到的终端节点服务域名
    base_url="http://ep-***.epsrv-***.dashscope.cn-shanghai-finance-1.privatelink.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
    model="qwen-plus",
    messages=[
        {'role': 'system', 'content': 'You are a helpful assistant.'},
        {'role': 'user', 'content': '你是谁?'}],
)
print(completion.model_dump_json())

DashScope Python SDK

import os
from http import HTTPStatus
# 建议dashscope SDK 的版本 >= 1.14.0
import dashscope
from dashscope import Generation

# 将原始域名替换为上一步骤中获取到的终端节点服务域名
dashscope.base_http_api_url = "http://ep-***.epsrv-***.dashscope.cn-shanghai-finance-1.privatelink.aliyuncs.com/api/v1"
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
messages = [{
    'role': 'user', 'content': '你是谁?'
}]
response = Generation.call(
    model="qwen-plus",
    messages=messages,
    result_format='message'
)
if response.status_code == HTTPStatus.OK:
    print(response)
else:
    print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
        response.request_id, response.status_code,
        response.code, response.message
    ))

DashScope Java SDK

// 建议DashScope SDK的版本 >= 2.12.0
import java.util.Arrays;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.protocol.Protocol;
import com.alibaba.dashscope.utils.JsonUtils;

public class Main {
    public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
        // 将原始域名替换为上一步骤中获取到的终端节点服务域名
        Generation gen = new Generation(Protocol.HTTP.getValue(), "http://ep-***.epsrv-***.dashscope.cn-shanghai-finance-1.privatelink.aliyuncs.com/api/v1");
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("You are a helpful assistant.")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("你是谁?")
                .build();
        GenerationParam param = GenerationParam.builder()
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .model("qwen-plus")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .build();
        return gen.call(param);
    }
    public static void main(String[] args) {
        try {
            GenerationResult result = callWithMessage();
            System.out.println(JsonUtils.toJson(result));
        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            // 打印错误信息
            System.err.println("An error occurred while calling the generation service: " + e.getMessage());
        }
    }
}
调用前,需要您已完成获取API Key。如需要直接传入 API Key,请将$DASHSCOPE_API_KEY 替换为您的 API Key。

跨地域私网访问阿里云百炼 API

终端节点必须与阿里云百炼服务位于同一地域,如需从其他地域的VPC内进行私网访问,需要完成以下配置:

  1. 参考前文,完成通过终端节点访问阿里云百炼 API的配置。

  2. 通过云企业网(CEN)配置跨地域VPC互通。需要注意:

    • 请在两端选择不同网段的 VPC,避免网段冲突导致互通失败。

    • 中国大陆和其他地域之间通过 CEN 实现跨地域 VPC 互通,需要按照控制台提示提交申请。审批时间通常为 1~2 工作日,更多问题可查阅跨境常见问题

  3. 在终端节点关联的安全组中,添加入方向规则,允许发起端内的资源访问 80、443 端口。

配置完成后,在发起端 VPC 内访问前文中配置好的终端节点默认服务域名时,转发路由器(TR)会将流量路由至阿里云百炼服务所在地域的终端节点,实现跨地域私网访问阿里云百炼 API。

image

默认情况下,终端节点的默认服务域名可以在跨地域互联的 VPC 内直接被访问,但自定义服务域名仅在终端节点所在地域 VPC 内有效。因此,如需在发起端通过自定义域名私网访问阿里云百炼 API ,可参考快速使用内网域名解析,创建一个与自定义服务域名同名的内网域名,将该域名通过 CNAME 记录解析至该终端节点的默认服务域名:

  1. 添加一条和自定义服务域名同名的内网权威域名,如:vpc-cn-beijing.dashscope.aliyuncs.com,生效范围选择发起端 VPC。

  2. 添加解析记录:记录类型选择 CNAME,主机记录输入@,记录值填写目标终端节点的默认服务域名,如:ep-***.dashscope.cn-beijing.privatelink.aliyuncs.com

配置完成后,即可在发起端 VPC 内通过自定义服务域名访问阿里云百炼 API。

计费说明

使用私网连接(PrivateLink)、云企业网(CEN)以及内网域名解析(Private Hosted Zone)会产生额外费用,可参考对应计费说明来了解和评估成本:

常见问题

  1. 为什么我的 ECS 实例无法通过私网链接访问阿里云百炼 API?

    请按照以下步骤排查:

    1. 确认是否在同一 VPC。

      如果ECS实例的 VPC,与配置终端节点的 VPC 不同,则无法通过私网访问阿里云百炼 API,需要先配置 VPC互连

    2. 检查终端节点关联的安全组,确认已添加入方向规则,允许来自发起端ECS实例所在网段对 80(HTTP)或 443(HTTPS)端口的访问。

    3. 确认终端节点服务域名。

      通过默认服务域名私网访问阿里云百炼平台仅支持 HTTP。

  2. 终端节点能否从公网访问?

    不可以。私网连接(PrivateLink)仅用于在阿里云内网建立私有连接。终端节点不具备公网访问能力,终端节点网卡也无法绑定弹性公网IP (EIP)。