会话隔离配置

更新时间:
复制为 MD 格式

函数计算会话隔离功能是应对 AI 时代复杂应用场景的关键升级。通过实例与存储的双重隔离,可以在无服务器架构下构建安全、稳定、高效的长时应用,真正实现“按需使用、弹性扩展、安全可控”

功能概述

函数计算(Function Compute)传统上基于“短暂、无状态、事件驱动”的设计哲学,适用于短周期任务处理。然而,随着大语言模型(LLM)和生成式 AI 的兴起,越来越多的企业级应用需要支持长时间运行、上下文保持、强数据隔离的能力。

为此,函数计算推出 会话隔离(Session Isolation) 功能,在“会话”这一核心抽象之上,引入会话实例隔离会话存储隔离 两大能力,助力您构建安全、稳定、高效的 AI 应用。

  1. 会话实例隔离:开启后,系统为每个会话分配一个独立的函数实例,并强制执行 1:1 绑定关系。该实例在整个会话生命周期内仅服务此会话,结束后自动释放。

  2. 会话存储隔离:通过动态挂载技术,为每个会话分配独立的存储空间,并利用操作系统内核级的 POSIX 用户权限机制,确保数据访问边界清晰,杜绝越权访问。

该功能适用于需要上下文保持强数据隔离长期运行的 AI 应用场景。

核心能力

能力

价值

实例独占

每个会话绑定专属函数实例,确保运行环境连续性,避免共享干扰

存储隔离

为每个会话动态挂载独立 NAS 目录,结合 POSIX 权限控制,杜绝越权访问

自动释放

会话结束时自动回收资源,避免僵尸实例占用成本

灵活生命周期

支持自定义闲置超时,兼顾性能与成本

适用范围

类型

是否支持

函数类型

支持除任务函数外的所有函数类型

实例规格

仅支持 2 Core 及以上规格(如 2c4g、4c8g)

运行时

函数运行环境为内置运行时会话亲和不可选择MCP SSE 亲和

会话存储隔离(动态挂载存储)功能

内测中,使用前请提交工单申请;

会话实例隔离支持地域

除英国(伦敦)、沙特(利雅得)、韩国(首尔)、马来西亚(吉隆坡)、泰国(曼谷)、乌兰察布专属云 HDG、乌兰察布通用行业云外均支持

会话存储隔离功能支持地域

不支持合规云、日本(东京)、华北5(呼和浩特),动态挂载PolarFs目前仅支持华北2(北京)、华东2(上海)、华北6(乌兰察布)、中国香港、美国(硅谷);

为函数配置会话实例隔离

步骤一:会话实例隔离配置

您可以创建新函数并启用会话隔离,也可为已有函数配置该功能。若对现有函数进行配置,请确保其满足适用范围中的实例规格、运行时及函数类型等要求。

创建支持会话隔离的函数

以下操作仅对会话隔离相关配置进行了详细说明,如对其他配置有疑问,可以查看创建函数相关文档;

  1. 登录 函数计算控制台,在页面上方切换地域,如:华东1(杭州)

    建议在部署前查看适用范围,选择支持相关功能的地域。
  2. 进入函数列表,点击创建函数,选择任意函数类型,除任务函数以外,因其不支持会话隔离功能;

    本文以Web函数为例,其余函数配置与该类型配置操作一致,不支持任务函数。
  3. 按需进行基础配置运行环境等配置;

  4. 高级配置>隔离性、亲和性

    1. 实例隔离:开启实例隔离,并选择会话隔离,开启会话隔离的同时,系统自动开启会话亲和,您需要进一步配置会话亲和相关参数。

      说明
      • 开启会话隔离后,单实例并发Session数系统自动设置为1,且不可更改。

      • 会话隔离功能生效的同时,会话亲和功能也生效:

        如果开启会话隔离功能,同一客户端的请求都被路由到同一个函数实例上,同时,一个函数实例只能服务来自同一个客户端的请求,因此会话隔离功能既能满足会话亲和要求也能满足会话隔离要求。

    2. 会话亲和:不同亲和类型配置参考实例隔离配置实践,本文以HeaderField亲和为例,配置Header Name,例如x-affinity-header-v1,用于传递亲和值客户端标识的头部名称,其余配置保持默认或按需配置;

      您想传递的亲和标识为mySessionId,使用HTTP协议发起调用时,需要传递如下Header和值:x-affinity-header-v1: mySessionId
      说明
      • 如该函数后续会使用会话存储隔离,亲和类型需选择HeaderFieldCookie亲和;

      • 如果函数运行环境选择内置运行时,亲和类型不可选择MCP SSE亲和

  5. 点击创建

为已有函数配置会话隔离

  1. 登录 函数计算控制台,在页面上方切换目标函数所在地域,如:华东1(杭州)

    建议在部署前查看适用范围,选择的函数所在地域需要支持相关功能。
  2. 进入函数列表,选择需要配置会话隔离的函数,进入函数详情页

  3. 配置页,找到高级配置,点击最右侧编辑按钮;

  4. 配置隔离性、亲和性

    1. 实例隔离:开启实例隔离,并选择会话隔离,开启会话隔离的同时,系统自动开启会话亲和,您需要进一步配置会话亲和相关参数。

      说明
      • 开启会话隔离后,单实例并发Session数系统自动设置为1,且不可更改。

      • 会话隔离功能生效的同时,会话亲和功能也生效:

        如果开启会话隔离功能,同一客户端的请求都被路由到同一个函数实例上,同时,一个函数实例只能服务来自同一个客户端的请求,因此会话隔离功能既能满足会话亲和要求也能满足会话隔离要求。

    2. 会话亲和:不同亲和类型配置参考实例隔离配置实践,本文以HeaderField亲和为例,配置Header Name,例如x-affinity-header-v1,用于传递亲和值客户端标识的头部名称,其余配置保持默认或按需配置;

      您想传递的亲和标识为mySessionId,使用HTTP协议发起调用时,需要传递如下Header和值:x-affinity-header-v1: mySessionId
      说明
      • 如该函数后续会使用会话存储隔离,亲和类型需选择HeaderFieldCookie亲和;

      • 如果函数运行环境选择内置运行时,亲和类型不可选择MCP SSE亲和

  5. 点击部署

步骤二:效果验证

  1. 以配置HeaderField亲和为例,指定不同HTTP请求头的值调用函数进行测试

    Session1:

    curl -H "x-affinity-header-v1:Session1" https://example.{regionID}.fcapp.run

    Session2:

    curl -H "x-affinity-header-v1:Session2" https://example.{regionID}.fcapp.run

    请求说明:

    1. x-affinity-header-v1:为会话亲和配置的Header Name,根据实际配置进行替换;

    2. Session1、Session2:请求头对应的值,开启会话实例隔离后,相同值的请求都调度到同一函数实例执行,不同值的请求调度到不同的函数实例执行;

    3. https://example.{regionID}.fcapp.run:函数触发请求URL,可以在函数详情页,点击HTTP触发器查看。

  2. 结果验证:

    image

动态挂载存储

本文以文件存储NAS为例,同时还支持OSS 和 PolarFS,实际操作与文件存储NAS类似。

前置步骤

  1. 已经创建了文件存储NAS,并规划好了用于租户数据隔离的目录结构;

  2. 参考为函数配置会话实例隔离步骤,开启会话实例隔离配置;

  3. 检查函数配置,是否开启允许访问VPC配置,并选择与文件存储NAS挂载点一致的专有网络:

    • 开启配置>高级配置>网络>允许访问 VPC

    • 配置方式选择自定义配置

    • 专有网络选择挂载点所在的 VPC。

步骤一:创建带 NAS 配置的会话

  1. 安装依赖

    macOS / Linux

    # 使用 pip3 安装
    pip3 install alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util
    
    # 如遇权限问题,使用 --user 参数
    pip3 install --user alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util
    
    # macOS Homebrew Python 环境需使用 --break-system-packages
    pip3 install --break-system-packages alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util

    Windows

    # 使用 pip 安装
    pip install alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util
    
    # 或使用 Python 3 指定
    py -3 -m pip install alibabacloud_fc20230330 alibabacloud_credentials alibabacloud_tea_openapi alibabacloud_tea_util
  2. 编写创建会话的代码

    创建Python代码文件(如:creatSession.py),将下列代码复制到文件中并替换核心参数。示例演示了如何为“租户 A”创建一个会话,并将其专属的 NAS 目录 (<YOUR-NAS-SERVER-ADDR>:/tenant-a-data) 挂载到实例的 /mnt/data 路径,同时指定用户身份为 UID=1001 和 GID=1001

    核心方法及核心参数说明:

    重要

    会话动态挂载NAS和在函数配置>高级配置>存储中挂载NAS可以同时配置,但是需要注意:

    • 下文NASConfig 中定义的 User ID/Group ID必须与函数挂载配置中使用的用户(User ID)/用户组(Group ID)保持一致

    • 同一个挂载路径 (mount_dir) 不能同时用于会话动态挂载和函数挂载

    • config.endpoint

    • CreateSessionInput

      • session_ttlin_seconds:会话总生命周期(单位:秒);

      • session_idle_timeout_in_seconds:会话浅休眠(原闲置)过期时间(单位:秒);

    • client.create_session_with_options:将<函数名称>替换为创建Session的函数名称;

      • NASMountConfig:NAS 挂载配置

        • mount_dir:实例内的挂载路径,如:/home/test

        • server_addr:NAS 文件存储地址及租户专属子目录

      • user_id:为此会话指定独立的 POSIX User ID

      • group_id:为此会话指定独立的 POSIX Group ID

    # -*- coding: utf-8 -*-
    from alibabacloud_fc20230330.client import Client as FC20230330Client
    from alibabacloud_credentials.client import Client as CredentialClient
    from alibabacloud_tea_openapi import models as open_api_models
    from alibabacloud_fc20230330 import models as fc20230330_models
    from alibabacloud_tea_util import models as util_models
    
    # 1. 创建账号Client
    credential = CredentialClient()
    config = open_api_models.Config(credential=credential)
    config.endpoint = f'<账号ID>.<Endpoint>'
    client = FC20230330Client(config)
    
    # 2. 准备 NAS 挂载配置
    nas_mount_config = fc20230330_models.NASMountConfig(
        mount_dir='/mnt/data',  # 实例内的挂载路径
        server_addr='<YOUR-NAS-SERVER-ADDR>:/<tenant-a-path>'  # NAS 文件存储地址及租户专属子目录
    )
    
    # 3. 配置 NAS 和用户身份(为租户A分配独立UID/GID)
    nas_config = fc20230330_models.NASConfig(
        mount_points=[nas_mount_config],
        user_id=1001,  # 为此会话指定独立的 POSIX User ID
        group_id=1001  # 为此会话指定独立的 POSIX Group ID
    )
    
    # 4. 构造 CreateSession 请求
    create_session_input = fc20230330_models.CreateSessionInput(
        nas_config=nas_config,
        session_ttlin_seconds=3600,
        session_idle_timeout_in_seconds=600
    )
    create_session_request = fc20230330_models.CreateSessionRequest(
        body=create_session_input
    )
    
    # 5. 发起请求
    runtime = util_models.RuntimeOptions()
    response = client.create_session_with_options('<函数名称>', create_session_request, {}, runtime)
    
    # 6. 从响应中获取 sessionId
    print(response.body.to_map())
    session_id = response.body.session_id
    print(f"Session created successfully. Session ID: {session_id}")
    
  3. 运行代码

    export ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI****************
    export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<yourAccessKeySecret>
    python3 creatSession.py

    参数说明:

    • ALIBABA_CLOUD_ACCESS_KEY_ID:阿里云账号或 RAM 用户的AccessKey ID

    • ALIBABA_CLOUD_ACCESS_KEY_SECRET:阿里云账号或 RAM 用户的AccessKey Secret

  4. 返回结果示例

    {
      'containerId': 'c-********-********-************', 
      'createdTime': '2025-10-30T06:38:10Z', 
      'functionName': '****', 
      'lastModifiedTime': '2025-10-30T06:38:10Z', 
      'nasConfig': 
        {
          'groupId': 1001, 
          'mountPoints': [
            {
              'enableTLS': False, 
              'mountDir': '/home/test', 
              'serverAddr': '*-*.*.nas.aliyuncs.com:/test'
               }
                 ], 
                 'userId': 1001
                 }, 
       'qualifier': 'LATEST', 
       'sessionAffinityType': 'HEADER_FIELD', 
       'sessionId': '******************', 
       'sessionIdleTimeoutInSeconds': 600, 
       'sessionStatus': 'Active', 
       'sessionTTLInSeconds': 3600
       }
    Session created successfully. Session ID: ************

步骤二:在函数中使用挂载的 NAS

现在,调用函数时携带上一步获取的 SessionID,函数实例内部即可访问到已挂载的 /mnt/data 目录。下面以Web函数为例,修改函数内代码并重新部署:

import os
from flask import Flask, request, jsonify

# ... (app setup) ...

# 假设 NAS 挂载点在 /mnt/data
NAS_MOUNT_PATH = '/mnt/data'
app = Flask(__name__)


@app.route('/<path:path>', methods=['GET', 'POST'])
def handle_nas_request(path):
    rid = request.headers.get('x-fc-request-id')
    print(f"FC Invoke Start RequestId: {rid}")

    # 构造文件在 NAS 上的完整路径
    # 注意:需要防止路径穿越攻击
    safe_path = os.path.normpath(os.path.join(NAS_MOUNT_PATH, path))
    if not safe_path.startswith(NAS_MOUNT_PATH):
        return "Path traversal attempt detected!", 400

    response_data = {}

    if request.method == 'POST':
        # 写入文件
        body = request.data.decode('utf-8')
        try:
            with open(safe_path, 'w') as f:
                f.write(body)
            response_data['message'] = f"Successfully wrote to {safe_path}"
            print(f"Wrote to {safe_path}")
        except Exception as e:
            return str(e), 500

    elif request.method == 'GET':
        # 读取文件
        try:
            if os.path.exists(safe_path) and os.path.isfile(safe_path):
                with open(safe_path, 'r') as f:
                    content = f.read()
                response_data['content'] = content
                print(f"Read from {safe_path}")
            else:
                return f"File not found: {safe_path}", 404
        except Exception as e:
            return str(e), 500

    print(f"FC Invoke End RequestId: {rid}")
    return jsonify(response_data)  # 使用 jsonify 返回 JSON 格式的响应

# ... (if __name__ == '__main__': block) ...

步骤三:调用函数并验证

调用API InvokeFunction- 调用函数,使用会话调用函数。

核心代码示例及说明:

  • InvokeFunctionHeaders:构造请求头,在请求Header中携带上一步返回的sessionId

  • Header Key的值与为函数配置会话实例隔离设置的值保持一致(如:x-affinity-header-v1),实现会话绑定路由。

# -*- coding: utf-8 -*-
from alibabacloud_fc20230330.client import Client as FC20230330Client
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_fc20230330 import models as fc20230330_models
from alibabacloud_tea_util import models as util_models

session_id = '************'
function_name = 'my-session-nas'
# 1. 创建账号Client
credential = CredentialClient()
config = open_api_models.Config(credential=credential)
config.endpoint = f'<账号ID>.<Endpoint>'
client = FC20230330Client(config)

# 2. 构造请求头。Header Key(x-affinity-header-v1)必须与函数配置的会话亲和 Key 一致。
headers = fc20230330_models.InvokeFunctionHeaders(
    common_headers={
        "x-affinity-header-v1": session_id
    }
)

# 3. 构造调用请求(可根据需要传入 body)
invoke_request = fc20230330_models.InvokeFunctionRequest(
    body='your_request_payload'.encode('utf-8')  # 示例 payload
)

runtime = util_models.RuntimeOptions()

try:
    # 4. 发起调用
    invoke_response = client.invoke_function_with_options(
        function_name,
        invoke_request,
        headers,
        runtime
    )
    # 5. 处理响应
    print(f"Status Code: {invoke_response.status_code}")
    print(f"Response Body: {invoke_response.body.decode('utf-8')}")
except Exception as error:
    print(error.message)

后续步骤:删除会话

在任务完成后调用 DeleteSession - 删除会话资源,释放会话资源

生产环境建议

  • UID/GID 规划:为确保隔离性,必须为每个租户分配唯一的 POSIX UID;

  • 目录配额:为防止单个租户耗尽共享存储空间,建议在 NAS 侧为每个租户的根目录配置目录配额(Directory Quotas);

  • 数据垃圾回收 (GC):DeleteSession - 删除会话资源 操作不会自动删除 NAS 上的文件数据。需建立配套的异步垃圾回收机制,定期扫描并清理无主的文件目录,以回收存储空间。

功能机制详解

1. 实例与会话的 1:1 绑定

当创建新会话时,调度系统从资源池中分配一个全新未处理过请求的函数实例,在路由层建立会话 ID 与实例的映射关系;

  • 行为特征:该实例在生命周期内仅响应当前会话的请求,不接受其他任何请求;

  • 并发控制:系统自动设置单实例 Session 并发度为 1,保障 CPU、内存、本地磁盘资源完全归属该会话。

此机制适用于需要长期上下文保持的应用,如 LLM 推理、代码调试流程等。

2. 会话生命周期管理

函数实例的生命周期与会话生命周期严格同步。当会话结束时,无论实例类型如何,对应的实例都会被主动释放。会话结束包含会话到期自动释放用户主动释放两种情况:

会话到期自动释放触发条件:

类型

描述

是否可配置

闲置超时(IdleTimeout)

若用户在指定时间内无请求交互(默认 30 分钟),系统判定为闲置并优雅销毁

是,可通过配置Session idle 时长来控制超时时间(单位:秒),取值范围[0,21600]

生命周期上限(TTL)

无论是否活跃,达到最大存活时间(如 6 小时)后自动销毁

否(由系统设定)

主动释放

用户可通过调用 DeleteSession 接口主动删除会话:

DELETE /services/{serviceName}/functions/{functionName}/sessions/{sessionId}

成功后:

  • 对应实例立即释放;

  • 路由规则失效;

  • 后续使用旧会话 ID 的请求将被拒绝或触发新会话(取决于复用会话 ID 配置)。

    说明

    复用会话ID配置:调用CreateSession - 创建会话资源接口时,可通过配置disableSessionIdReuse来控制是否可以复用会话 ID。

    • 默认为false,表示可以复用,表示在 SessionID 会话过期后,可携带相同 SessionID 继续发起请求,系统将视为新会话绑定新实例;

    • 当配置为 true,表示在 SessionID 会话过期后,不可复用 SessionID

3. 动态挂载:实现存储级别的隔离

传统 NAS 挂载为静态配置,所有实例共享同一目录,存在安全隐患。动态挂载机制解决了这一问题,可用于解决 AI Agent Sandbox 多租场景下的会话持久化存储隔离的问题。在创建会话时,动态指定该会话需要挂载的 NAS 子目录。

工作原理:

该功能将 NAS 挂载操作与 CreateSession - 创建会话资源 API 调用深度集成。以 HeaderField 亲和为例,整体流程如下:

image

准备阶段:创建并配置带有存储的会话

此阶段的目标是创建一个与特定存储绑定的、隔离的会话环境,以便后续使用。

  1. 发起创建请求:后端管理服务调用 CreateSession API,并在请求中指定NAS挂载配置以及用于隔离的用户身份(UID/GID)。

  2. 准备实例与挂载:函数计算(FC)平台接收请求后,准备一个函数实例,该函数实例会根据配置执行NAS挂载操作,将专属目录挂载到实例的指定路径(例如 /mnt/data)。

  3. 绑定并返回ID:挂载成功后,平台将此实例与一个新生成的唯一SessionID进行绑定,并将该ID返回给后端服务。

调用阶段:使用已配置的会话

此阶段使用已准备好的会话环境来执行实际的业务逻辑。

  1. 发起调用请求:后端管理服务在调用 InvokeFunction API 时,通过一个特定的HTTP请求头(如 x-affinity-header-v1)传入之前获取的 SessionID

  2. 路由请求:函数计算平台的网关与调度器根据此SessionID,将请求精确地路由到已绑定的特定函数实例上。

  3. 执行代码:函数代码在该实例中执行。此时,由于环境和权限都已预先配置好,代码可以直接读写已挂载的NAS目录。

  4. 返回结果:函数执行完毕后,将结果逐层返回给最初的调用方。

关键特性:

特性

说明

目录自动创建

当挂载的远端目录不存在时,会自动创建,并将目录的所有者设为用户配置的 user_idgroup_id,同时将目录 mode 设置为 700(rwx------)

POSIX ID 权限隔离

如有需要,可以在函数代码中,将函数实例主进程的 user_id 以及 group_id 设置为动态挂载时传入的 ID 参数,这样即使租户 A 的代码试图读取属于租户 B(UID 10002)的文件,由于租户 A 的进程 UID 是 10001,Linux 内核与 NAS 服务端会直接拒绝该操作(Permission Denied)

共存机制

支持函数级静态挂载与会话级动态挂载同时存在

示例:租户 A(UID=10001)无法读取租户 B(UID=10002)的文件,即使在同一 NAS 上。

相关文档链接