后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载Azure App Service 是托管 .NET 应用的 PaaS 服务但它默认的 HTTP 负载均衡模型无法直接承载 Orleans 的 silo 间长连接 TCP 通信。本文基于当前仓库的 Orleans 购物车样例 及其官方部署文档Azure App Service 目标总览、Windows 指南、Linux 指南系统讲解如何在 Windows 或 Linux 的 App Service 上运行一个生产可用的多实例 Orleans 集群从拓扑设计、私有实例端点发现、托管标识与 Azure Table Storage 集成到 Bicep 基础设施、槽位slot灰度发布、健康检查与优雅关闭、GitHub OIDC 持续交付。读完本文你将掌握一套可复制、可验证的 App Service 承载 Orleans 的完整方案并理解每一步背后的源码级原理。Orleans 购物车样例的应用模型Blazor 前端经服务层调用 Inventory/Product/Shopping Cart Grain每个 Grain 维护独立状态整体横向扩展为分布式集群。为什么 App Service 承载 Orleans 需要特殊拓扑Orleans silo 之间通过长连接 TCP 直接通信这与 App Service 前端负责的 HTTP 流量模型完全不同。App Service 自带的 HTTP 负载均衡无法为 silo 之间的通信提供连通性因此官方采用的核心方案是每个 worker 上共置cohost一个应用进程与一个 Orleans silo运行在专用的多实例计划中每个 worker 通过环境变量公布其私有实例地址WEBSITE_PRIVATE_IP和动态分配的私有端口WEBSITE_PRIVATE_PORTS首个值区域级虚拟网络集成Regional virtual network integration为 worker 提供私有地址与出站虚拟网络路径Azure Table Storage承载共享的集群成员关系membership与持久的 grain 状态共置本地 Orleans 客户端禁用 Orleans 网关gateway。该拓扑面向的是应用内直接调用 silo的形态HTTP 流量走 App Service 前端Orleans 内部通信走各 worker 的私有端点。若确实需要受信任的外部 Orleans 客户端则需分配并验证第二个私有端口作为网关并确保每个客户端网络都能路由到所有公布的网关映射。需要注意的是Orleans 网关本身不是终端用户认证边界——如果应用需要外部 Orleans 客户端只应为完全受信任的应用客户端启用并公布第二个私有端口未受信任的调用方应保持在经过认证的 API 之后。支持拓扑与关键平台设置官方维护的拓扑在 samples/Deployment/AzureAppService 中具有以下特征一个专用 Premium v3 App Service 计划样例中至少三个 workerBicep 参数workerCount最小值为 3每个 worker 上运行一个应用进程与一个 Orleans silo以WEBSITE_PRIVATE_IP和逗号分隔的WEBSITE_PRIVATE_PORTS分配中的第一个端口作为公布的 silo 端点共置本地 Orleans 客户端禁用网关Azure Table Storage 负责聚类与 grain 状态通过托管标识授权访问生产与暂存使用分离的集群 IDcluster ID共享稳定的服务 IDservice ID。样例的入口代码位于 Silo/Program.cs其生产环境配置完整展示了端点发现与外部聚类var privateIp IPAddress.Parse(GetRequiredSetting(builder, WEBSITE_PRIVATE_IP)); var privatePorts GetRequiredSetting(builder, WEBSITE_PRIVATE_PORTS) .Split(,, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); if (privatePorts.Length 1 || !int.TryParse(privatePorts[0], NumberStyles.None, CultureInfo.InvariantCulture, out var siloPort)) { throw new InvalidOperationException( WEBSITE_PRIVATE_PORTS must contain at least one TCP port.); } builder.UseOrleans(siloBuilder { siloBuilder .ConfigureSiloOptions(options { options.SiloName builder.Configuration[WEBSITE_INSTANCE_ID] ?? Environment.MachineName; }) .ConfigureClusterOptions(options { options.ClusterId clusterId; options.ServiceId serviceId; }) .ConfigureEndpoints( privateIp, siloPort, gatewayPort: 0, listenOnAnyHostAddress: true) .UseAzureStorageClustering(options { options.TableServiceClient tableServiceClient; options.TableName ${clusterId}Clustering; }) .AddAzureTableGrainStorage( shopping-cart, options { options.TableServiceClient tableServiceClient; options.TableName ${clusterId}Persistence; }); });这段代码是整篇方案的命门其关键点包括公布地址与监听地址分离ConfigureEndpoints(privateIp, siloPort, gatewayPort: 0, listenOnAnyHostAddress: true)公布的私有 IP 未必能在本地直接绑定因此必须监听所有本地接口listenOnAnyHostAddress: true。禁用网关gatewayPort: 0关闭 Orleans 客户端网关强制所有目录变更经由 Easy Auth 保护的 Web 应用进入而不是未认证的 Orleans 客户端连接。实例名取自平台只读环境变量WEBSITE_INSTANCE_ID用作 Orleans silo 名称便于诊断时关联到具体 worker。表名绑定集群 ID成员关系表为{clusterId}Clustering持久化表为{clusterId}Persistence生产与暂存各自使用独立表。必要配置缺失即启动失败GetRequiredSetting对缺失的生产配置直接抛出InvalidOperationException杜绝静默降级为单机的隐患。ConfigureEndpoints这一模式同样被文档片段 docs/site/src/content/docs/snippets/compiled/Deployment/DeploymentSnippets.cs 引用为可复用代码片段。生产环境必需的环境变量任何非 Development 环境都必须配置以下变量缺失即启动失败变量用途WEBSITE_PRIVATE_IPworker 的私有实例地址作为公布的 silo 地址WEBSITE_PRIVATE_PORTS逗号分隔的私有端口分配取第一个作为 silo 端口ORLEANS_SERVICE_ID稳定的服务 ID跨槽位不变ORLEANS_CLUSTER_ID集群 ID槽位粘性生产/暂存不同ORLEANS_AZURE_STORAGE_URIAzure Table Storage 的 Table 服务 URIAZURE_CLIENT_ID用户分配的托管标识客户端 ID平台差异Windows 与 Linux 的取舍官方提供了同一套应用、Bicep 模块、暂存槽位工作流、托管标识、健康端点和运维模型下的两个入口模板仅在平台特定行为上分流目标指南平台特定行为Windows App ServiceDeploy Orleans to Azure App Service on WindowsIIS 集成、Windows 路径与进程模型、Windows App Service 认证模块Linux App ServiceDeploy Orleans to Azure App Service on Linux内置 Linux .NET 栈、容器启动截止时间与路径、App Service 认证 sidecar在 Bicep 模板层面差异集中在 infra/flex/app-service.bicep 的平台设置上Linux计划使用kind: linux与reserved: true站点使用linuxFxVersion: DOTNETCORE|10.0并额外设置SCM_DO_BUILD_DURING_DEPLOYMENTfalse让 Oryx 直接运行预发布的二进制文件而不是重新还原构建Windows站点设置netFrameworkVersion: v10.0并设置WEBSITE_ADD_SITENAME_BINDINGS_IN_APPHOST_CONFIG1辅助 IIS 绑定。Windows 与 Linux 的入口模板 infra/windows/main.bicep 与 infra/linux/main.bicep 结构一致均委托给共享的 infra/flex/main.bicep仅通过operatingSystem参数分流。Linux 特有的验证要求WEBSITE_PRIVATE_IP与WEBSITE_PRIVATE_PORTS是文档化的通用 App Service 设置并非 Windows 专属。但微软并未文档化 Orleans 在 Linux 上的映射保证因此部署验证是强制性的扩展到至少三个 worker确认每个 worker 都获得独立的WEBSITE_PRIVATE_IP与至少一个WEBSITE_PRIVATE_PORTS值检查 Orleans 成员关系确认每个 silo 公布的就是这些值测试所有公布的 silo 端点之间的双向 TCP 连通性在扩容、缩容、重启与槽位交换期间重复上述检查。[!IMPORTANT] 区域级虚拟网络集成本质上是出站功能。不要想当然地认为启用它就能证明入站私有端口可达——必须先在扩展后的计划上验证私有端口行为。另外Linux 上 App Service 认证Easy Auth以ambassador sidecar形式运行Windows 则是进程内 IIS 模块但两种平台注入的认证主体请求头X-MS-CLIENT-PRINCIPAL契约一致。Linux 容器启动若超出平台限制可在支持范围内调整WEBSITES_CONTAINER_START_TIME_LIMIT而不是在 Orleans 启动完成前就返回就绪状态。环境资格确认上线前的五项检查在选定操作系统、区域、计划层级、网络配置与规模后应建立生产证据扩展到至少三个 worker确认每个 worker 都收到不同的私有地址与所需私有端口数量将每一条活跃的 Orleans 成员关系行与一个 worker 实例一一对应测试所有公布的 silo 端点之间的双向 TCP 连通性在扩容、缩容、worker 替换、重启与槽位交换期间重复检查。区域级虚拟网络集成为 worker 提供私有地址和出站虚拟网络路径分配的私有端口建立目标特定的入站 silo 路径。集成子网要按计划规模、升级和 worker 替换预留容量应为计划最大规模的两倍左右进行子网大小规划新部署以/26作为实际可行的最小值样例使用两个独立的/24委派子网见 infra/flex/main.bicep。App Service 会将多个计划 worker 分布到平台故障域。若可用性目标包含区域故障zone failure应在受支持的 Premium 计划上启用 App Service 区域冗余zone redundancy并确认所选区域、规模单元、层级与 worker 数量满足平台要求。样例创建了多个 Premium v3 worker但把区域冗余留作环境特定的生产改造项。前置条件与本地运行开始前需要准备一个 Azure 订阅以及创建资源和角色分配的权限仓库global.json选定的 .NET SDK带 Bicep 的 Azure CLI当前仓库的克隆一个用于 App Service 认证Easy Auth的 Microsoft Entra 应用注册。设置本地部署变量PowerShell$location westus3 $resourceGroup orleans-shopping-cart # Linux 样例使用 orleans-shopping-cart-linux $appName globally-unique-lowercase-name-up-to-16-characters $authenticationTenantId microsoft-entra-tenant-id $authenticationClientId app-registration-client-id $authenticationClientSecret app-registration-client-secret本地开发运行dotnet run --project .\samples\Deployment\AzureAppService\Silo\Orleans.ShoppingCart.Silo.csproj --environment ASPNETCORE_ENVIRONMENTDevelopmentDevelopment 模式使用 localhost 聚类与内存状态见 Program.cs 中UseLocalhostClustering().AddMemoryGrainStorage(shopping-cart)但绝不会在缺少生产配置时回退为单主机集群。本地可以匿名访问商店前台但产品管理不可用——因为本地没有 App Service 注入的可信主体头。配置用户认证与授权Easy Auth在 App Service 认证的应用注册中完成四步添加一个值为ProductAdministrator、允许成员类型包含用户或组的应用角色创建一个客户端密钥client secret通过企业应用把该角色分配给产品管理员添加生产与暂存两套 Web 重定向 URI以/.auth/login/aad/callback结尾。确切的 hostname 是部署输出因此可以先部署基础设施、后补重定向 URI在用户登录前完成即可。认证模型的关键约束Easy Auth 允许匿名访问商店前台并在X-MS-CLIENT-PRINCIPAL中注入认证声明。应用只接受Entraaad主体限制并解析该请求头保护/products路由对未授权用户隐藏导航项并在服务层每次产品变更前重新授权。该解析器信任 App Service 已完成令牌校验并移除了伪造的外部身份请求头——不要把它复用到不受信任的反向代理之后也不要暴露绕过 Easy Auth 的路径直达应用进程。样例的认证处理器与授权策略分别位于 Silo/Authentication/AppServiceAuthenticationHandler.cs 与 Silo/Authorization/AuthorizationPolicies.cs。部署基础设施Bicep登录并部署所选操作系统的入口模板以 Windows 为例az login az group create --name $resourceGroup --location $location az deployment group create --resource-group $resourceGroup --template-file .\samples\Deployment\AzureAppService\infra\windows\main.bicep --parameters appName$appName location$location authenticationTenantId$authenticationTenantId authenticationClientId$authenticationClientId authenticationClientSecret$authenticationClientSecretLinux 只需把模板换成.\samples\Deployment\AzureAppService\infra\linux\main.bicep其余参数一致。模板infra/flex/main.bicep 及其子模块会创建一个三 worker 的 Premium v3 计划与生产/暂存槽位一个虚拟网络含两个独立的/24委派子网生产与暂存分别委派给Microsoft.Web/serverFarms并带Microsoft.Storage服务终结点一个仅限这些子网访问、禁用共享密钥授权的存储账户一个共享的用户分配托管标识并分配Storage Table Data Contributor角色两个槽位的 App Service 认证Log Analytics 与基于工作区的 Application Insights。两个关键参数在 infra/flex/main.bicep 中定义参数默认值说明workerCount3最小值为 3对应至少三个 worker 的验证要求assignStorageRolestrue首次部署为true引导常规部署传falseallowSharedKeyAccessfalse禁用存储共享密钥访问仅用托管标识首次部署是特权引导操作因为它会创建数据面角色分配常规部署传assignStorageRolesfalse其身份无需roleAssignments/write权限。托管标识分配可能需要几分钟才能传播首次应用启动可能因标识尚无法访问表数据而失败这是预期行为。认证密钥在 Bicep 中被标记为secure()见 infra/windows/main.bicep 与 infra/linux/main.bicep并作为槽位粘性slot-sticky的应用设置存储设置名为MICROSOFT_PROVIDER_AUTHENTICATION_SECRET见 infra/flex/app-service.bicep。应在过期前轮换生产环境更推荐 Key Vault 引用以及生产/暂存分离的应用注册。槽位粘性设置由 infra/flex/app-service.bicep 中的slotConfigNames声明AZURE_CLIENT_ID、认证密钥设置与ORLEANS_CLUSTER_ID均为粘性设置生产槽位集群 ID 为Default、暂存槽位为Staging而ORLEANS_SERVICE_ID两个槽位保持一致ShoppingCartService。发布并部署到暂存槽位$publish Join-Path $env:TEMP orleans-shopping-cart-publish $package Join-Path $env:TEMP orleans-shopping-cart.zip dotnet publish .\samples\Deployment\AzureAppService\Silo\Orleans.ShoppingCart.Silo.csproj --configuration Release --framework net10.0 --output $publish Compress-Archive -Path $publish\* -DestinationPath $package -Force az webapp deploy --name $appName --resource-group $resourceGroup --slot ${appName}stg --type zip --src-path $package --clean true --restart true要点ZIP 内是发布目录的内容而非目录本身App Service 将其解压到 Windows 的D:\home\site\wwwroot或 Linux 的/home/site/wwwroot区分大小写。样例不依赖这两个位置也不在其上保存持久数据——Orleans grain 状态始终在 Azure Table Storage。把生产与暂存回调 URL 加入应用注册后等待暂存部署输出 hostname 的就绪探测https://staging-default-hostname/health/ready槽位交换与滚动升级az webapp deployment slot swap --name $appName --resource-group $resourceGroup --slot ${appName}stg --target-slot production交换机制的关键在于两个槽位保持稳定的ShoppingCartService服务 IDORLEANS_CLUSTER_ID是槽位粘性的每个集群使用独立的成员关系与持久化表。交换时 App Service 会把生产设置应用到暂存并在切换流量前预热每个暂存 worker——新 silo 在流量切换前就加入了生产集群。因此新旧 silo 会短暂共存grain 接口、序列化负载、状态与外部行为必须互相兼容。对于不兼容的发布应部署独立的应用与集群 ID绝不能让不兼容的集群拥有同一份可变状态也不要尝试把现有 App Service 计划从 Windows 切换到 Linux——应部署独立应用并在验证后迁移流量。使用 GitHub Actions OIDC 持续交付将样例工作流 infra/deploy.yml 复制到.github/workflows/deploy-app-service.yml为受保护的 GitHubproduction环境创建联合部署身份配置必填审阅人、限制部署分支不要创建--sdk-auth凭据也不要存储 Azure 凭据 JSON 文档。配置如下 GitHub 环境变量变量用途AUTHENTICATION_CLIENT_IDApp Service 认证客户端 IDAUTHENTICATION_TENANT_ID用户认证所在租户AZURE_APP_NAME全局唯一的 App Service 名称AZURE_APP_SERVICE_OSwindows或linuxAZURE_CLIENT_ID联合部署身份客户端 IDAZURE_RESOURCE_GROUP_LOCATIONAzure 区域AZURE_RESOURCE_GROUP_NAME目标资源组AZURE_SUBSCRIPTION_ID订阅 IDAZURE_TENANT_IDAzure 部署所在租户AUTHENTICATION_CLIENT_SECRET作为受保护的环境密钥添加——它属于 Easy Auth 应用注册Azure 部署本身使用短期 OIDC 凭据。工作流将 actions 固定到不可变的提交 SHA仅授予contents: read与id-token: write部署所选 Bicep 入口发布到暂存等待就绪交换并验证生产。其常规 Azure 身份不需要角色分配权限在目标资源组上授予 Contributor或更优地授予仅限模板所更新资源的自定义角色。工作流中值得注意的工程细节部署基础设施步骤显式传assignStorageRolesfalse见 infra/deploy.yml因为引导工作已由首次手动部署完成等待就绪步骤用curl --retry 30 --retry-all-errors轮询/health/ready见 infra/deploy.yml。健康检查与优雅关闭就绪与存活端点样例在 Program.cs 中定义了两个端点app.MapGet(/health/live, () Results.Ok()); app.MapGet( /health/ready, (AppServiceLifecycle lifecycle) lifecycle.IsReady ? Results.Ok() : Results.StatusCode(StatusCodes.Status503ServiceUnavailable));/health/ready只在.NET 主机与 Orleans silo 都启动完成后返回成功并在关闭开始时变为不可用——它同时服务启动预热、槽位预热与 App Service 健康检查/health/live是廉价的本地进程检查故意不依赖共享存储因此共享存储故障不会导致所有 worker 被反复重启。就绪状态由 Silo/Health/AppServiceLifecycle.cs 中实现IHostedLifecycleService的AppServiceLifecycle类驱动在StartedAsync中置_isReady true在StoppingAsync中置_isReady false。关闭时限与优雅性主机为 Orleans 离开成员关系留出最多 30 秒HostOptions.ShutdownTimeout TimeSpan.FromSeconds(30)见 Program.cs。App Service 可能更早终止 worker因此应用正确性必须容忍 silo 丢失与未知调用结果grain 调用可能永远没有响应。Bicep 模板在 infra/flex/app-service.bicep 中配置了配套的平台设置设置值作用healthCheckPath/health/readyApp Service 健康检查路径WEBSITE_WARMUP_PATH/WEBSITE_WARMUP_STATUSES/health/ready/200启动预热WEBSITE_SWAP_WARMUP_PING_PATH/WEBSITE_SWAP_WARMUP_PING_STATUSES/health/ready/200槽位交换预热WEBSITE_HEALTHCHECK_MAXPINGFAILURES2健康检查最大失败次数alwaysOntrue保持 worker 常驻安全与可观测性安全基线模板强制强制 HTTPS 与 TLS 1.2 或更高、禁用 FTPS、禁用存储共享密钥授权、将存储网络访问限制在集成子网内、托管标识授权表访问。HTTPS 保护的是公共 Web 端点样例的私有 Orleans silo 连接本身未加密。当威胁模型要求在虚拟网络内部加密时应使用网络控制并配置 Orleans TLS。此外需注意Blazor Server 共置 UI 依赖 HTTP 客户端亲和性模板中clientAffinityEnabled: true而 Orleans 传输独立于 HTTP 亲和性使用私有 silo 端点。可观测性Application Insights 接收请求、依赖、异常、应用与 Orleans 日志。运维查询中应纳入WEBSITE_INSTANCE_ID、集群 ID、槽位与部署元数据。需要监控的指标包括就绪的 worker/silo 数量、成员关系变化、延迟、拒绝rejections、存储授权/限流、worker 资源、重启与槽位操作。生产清单按关注点逐项核验总览级生产清单适用于 Windows 与 Linux关注点App Service 预期结果拓扑与网络每个 worker 公布其私有实例地址与分配的 silo 端口且每个 worker 都能连接到每个活跃的成员端点依赖与数据Azure Table 聚类与持久 grain 状态使用环境特定的表使用提醒reminder与流stream提供程序时需显式配置身份与密钥用户分配托管标识获得窄化的数据面角色App Service 认证与部署身份保持分离密钥使用受保护设置或 Key Vault 引用健康与生命周期启动预热与/health/ready在 Orleans 启动后完成就绪状态在宿主关闭前变为不可用使用可用的 App Service 终止间隔扩展与韧性计划保留经过测试的最小 worker 数与备用容量故障域分布与所需区域冗余已文档化在负载下验证扩展、替换、区域或 worker 丢失及依赖故障行为升级与回滚兼容版本在暂存槽位预热并在交换期间加入生产集群不兼容版本使用独立应用与集群 ID可观测性与事故Application Insights、Log Analytics、Orleans 遥测、App Service 实例元数据、成员证据与槽位操作相互关联基础设施交付Bicep 与 GitHub OIDC 工作流可复现基础设施并通过暂存部署不可变的应用工件Windows 特有补充运行时存储访问使用托管标识App Service 认证、常规部署与特权引导凭据保持分离并在过期前轮换兼容版本使用带混合版本验证的暂存槽位交换Keep HTTP 客户端亲和性以支持共置的 Blazor Server UI跨 Windows/Linux 迁移需部署独立应用并在验证后切换流量。Linux 特有补充容器启动、健康检查、槽位预热、就绪移除与有界主机关闭共同反映应用生命周期可观测性额外关联容器事件子网按计划规模与替换容量规划至少保留三个 worker并在负载下验证故障恢复与滚动升级持久 grain 数据应独立于成员数据备份。升级既有部署与运维要点从存储密钥迁移到托管标识若既有部署仍在使用存储账户密钥不要先运行完整模板按以下顺序迁移创建${appName}-identity分配给应用与${appName}stg槽位并在${appName}storage上授予Storage Table Data Contributor把AZURE_CLIENT_ID、ORLEANS_AZURE_STORAGE_URI、ORLEANS_SERVICE_IDShoppingCartService与既有槽位特定集群 ID 合并进两个槽位把托管标识构建部署到暂存等待就绪后交换进生产在回滚窗口内保持共享密钥访问开启旧的生产构建此时运行在暂存两个槽位都运行托管标识构建后以allowSharedKeyAccessfalse assignStorageRolesfalse部署infra/windows/main.bicep。运维行为速览生产与暂存使用独立委派子网与槽位粘性集群 ID两个槽位跨部署保持稳定的ShoppingCartService服务 ID每个集群使用独立的 Azure Table 成员关系与 grain 状态表应用仅在主机与 silo 启动后返回就绪并在关闭前移除就绪主机允许最多 30 秒的 Orleans 关闭时间但 App Service 可能提前终止 worker正确性必须容忍 silo 丢失与未知调用结果HTTPS/TLS 保护 HTTP 入站流量样例的私有 Orleans silo TCP 流量未加密若威胁模型要求虚拟网络内传输加密需添加 Orleans TLSDOTNETCORE|10.0、v10.0与net10.0是部署字面量不是Orleans 产品版本标识——升级运行时与目标框架时应一起更新这些字面量。进一步阅读围绕 App Service 部署官方还提供了配套的专题指南可在 docs/site/src/content/docs/deployment 中继续深入生产就绪清单拓扑、网络与聚类健康与可观测性容量规划与扩展优雅关闭与升级部署故障排查部署目标选择完整样例代码位于 samples/Deployment/AzureAppService其 README 提供了手动部署的 PowerShell 全过程Bicep 基础设施在 infra/flex 目录下按模块拆分便于按需复用。赞分享后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载相关推荐GriddyCode当代码编辑器遇见个性化表达编程也能如此有温度GriddyCode当代码编辑器遇见个性化表达编程也能如此有温度 你是否曾觉得自己与代码编辑器之间总是隔着一层无法打破的玻璃墙那些千篇一律的界面、固定不前端构建工具前端构建后端如何用XposedRimetHelper实现钉钉虚拟定位完整指南如何用XposedRimetHelper实现钉钉虚拟定位完整指南 还在为每天必须到公司打卡而烦恼吗XposedRimetHelper是一款基于Xposed框插件系统逆向工程在 SLURM 集群上部署 Ray基于 ray symmetric-run 的端到端实战指南在 SLURM 集群上部署 Ray基于 ray symmetric run 的端到端实战指南 SLURMSimple Linux Utility for R人工智能分布式训练强化学习任务调度模型推理服务后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考