
后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载本文以samples/Deployment/AzureAppService示例为研究对象详细讲解如何将托管 ASP.NET Core 应用与 Orleans Silo 的多实例购物车应用部署到 Azure App Service涵盖 Bicep 基础设施、私有端点发现、存储集群、Entra 认证、slot 滚动发布、GitHub Actions OIDC 等关键环节。阅读本文后你可以复刻一套生产可用的 Orleans on Azure App Service 部署流水线并理解其底层原理。该示例部署了一个多实例的 Orleans 购物车应用Orleans.ShoppingCart支持 Windows 与 Linux 两种 Azure App Service 平台并在 README.md 中给出了完整的部署操作步骤。示例验证并演示了以下能力三个 App Service worker 上共同承载 ASP.NET Core 应用与 Orleans Silocohosted 模式每个实例从WEBSITE_PRIVATE_IP与WEBSITE_PRIVATE_PORTS环境变量发现私有 Orleans 端点生产与暂存staging分别使用独立的虚拟网络集成子网通过用户分配的托管标识user-assigned managed identity访问 Azure Table Storage 完成集群clustering与 grain 状态持久化App Service 健康检查、启动预热warm-up、优雅关闭与基于槽位slot的滚动发布Microsoft Entra 认证与基于应用角色app role的商品管理授权Application Insights 日志与请求/依赖遥测基于 OpenID ConnectOIDC的 GitHub Actions 部署替代部署客户端密钥。[!IMPORTANT] 仅靠 App Service 的 HTTP 横向扩展不足以支撑 Orleans。示例为每个实例分配一个私有 Silo 端口并通过区域级虚拟网络集成regional virtual network integration使 Silo 之间能够直接以 TCP 相连。选择部署平台Windows 与 Linux示例同时提供两套入口模板二者都调用infra/flex下的共享模块部署完全相同的应用仅平台相关配置不同平台模板平台特有配置Windowsinfra/windows/main.bicepWindows App Service 计划与netFrameworkVersionLinuxinfra/linux/main.bicepLinux 计划reserved: true与linuxFxVersion两个平台的入口模板参数几乎一致appName、location、serviceId、authenticationTenantId、authenticationClientId、authenticationClientSecret、workerCount、assignStorageRoles、allowSharedKeyAccess唯一的差异是传给flex/main.bicep的operatingSystem参数。从源码可以看出平台差异集中在 app-service.bicep 中Linux 平台App Service 计划kind: linux且reserved: true站点kind: app,linux运行时栈为linuxFxVersion: DOTNETCORE|10.0额外关闭部署期间构建SCM_DO_BUILD_DURING_DEPLOYMENTfalse。Windows 平台App Service 计划kind: app站点kind: app运行时栈为netFrameworkVersion: v10.0额外设置WEBSITE_ADD_SITENAME_BINDINGS_IN_APPHOST_CONFIG1。注意DOTNETCORE|10.0、v10.0、net10.0是部署字面量对应 .NET 10 运行时并非 Orleans 产品版本标识。global.json仓库根目录选定了构建所需的 .NET SDK。两个平台的实例都会监听本机所有接口并向 Orleans 通告动态分配的私有地址与端口每个 worker 使用只读环境变量WEBSITE_INSTANCE_ID作为 Orleans Silo 名称便于诊断定位。无论选择哪种拓扑生产环境使用前都应先横向扩展并验证每个已通告 Silo 端点之间的 TCP 直连可达性。ZIP 部署会把发布产物放到 Windows 的D:\home\site\wwwroot或 Linux 的/home/site/wwwroot。应用不依赖这些路径也不在本地持久化 grain 状态——持久化状态统一存储在 Azure Table Storage 中。本地运行开发模式拓扑仓库根目录的global.json选定了所需的 .NET SDK。在本地以开发模式运行 Silodotnet run --project .\Silo\Orleans.ShoppingCart.Silo.csproj --environment ASPNETCORE_ENVIRONMENTDevelopment相对仓库根目录上述项目路径为 samples/Deployment/AzureAppService/Silo/Orleans.ShoppingCart.Silo.csproj。开发模式在 Program.cs 中刻意使用 localhost 集群与内存存储if (builder.Environment.IsDevelopment()) { builder.UseOrleans(siloBuilder { siloBuilder .UseLocalhostClustering() .AddMemoryGrainStorage(shopping-cart); }); }除Development以外的任何环境都会进入ConfigureProductionOrleans分支要求配置 App Service 私有端点变量与 Azure Storage绝不回退到单主机生产集群。若缺少任一必需设置GetRequiredSetting 会直接抛出InvalidOperationException。本地运行时商店前台可用但商品管理不可用——本地执行时没有 App Service 认证注入的可信X-MS-CLIENT-PRINCIPAL头。配置 Microsoft Entra 认证为 App Service AuthenticationEasy Auth创建 Microsoft Entra 应用注册添加一个值value为ProductAdministrator的应用角色允许分配给用户或组创建客户端密钥client secret并记录其值通过企业应用enterprise application把该应用角色分配给商品管理员添加生产与暂存两个 Web 重定向 URI均以/.auth/login/aad/callback结尾。生产与暂存的确切主机名是部署输出deployment outputs因此可以先完成基础设施部署、补充重定向 URI再部署应用。认证层面的设计要点见 app-service.bicepglobalValidation.requireAuthentication: false即允许匿名访问商店前台平台注入主体头principal header后应用仅信任该平台头/products路由受保护未授权用户的导航项被隐藏ProductService 在调用 grain 修改状态前会再次执行授权检查ProductManagement策略 ProductAdministrator角色形成纵深防御Silo 关闭了 Orleans 客户端网关gateway port 为 0见下文因此无法绕过上述检查通过直连 Orleans 客户端修改商品目录。手动部署准备环境安装 Azure CLI 并登录然后选择操作系统$location westus3 $resourceGroup orleans-shopping-cart $appName globally-unique-lowercase-name-up-to-16-characters $operatingSystem linux # Use windows for Windows App Service. $authenticationTenantId microsoft-entra-tenant-id $authenticationClientId app-registration-client-id $authenticationClientSecret app-registration-client-secret az login az group create --name $resourceGroup --location $locationLinux 平台需先确认目标区域支持配置的内置 .NET 运行时az webapp list-runtimes --os linux | Select-String DOTNETCORE部署所选模板az deployment group create --resource-group $resourceGroup --template-file .\infra\$operatingSystem\main.bicep --parameters appName$appName location$location authenticationTenantId$authenticationTenantId authenticationClientId$authenticationClientId authenticationClientSecret$authenticationClientSecret仓库根目录下模板路径为 samples/Deployment/AzureAppService/infra/$operatingSystem/main.bicep$operatingSystem取windows或linux。authenticationClientSecret参数被标记为secure()Azure 不会在部署历史中保留其明文值。生产环境中应在其过期前轮换并优先考虑使用 Key Vault 引用或为生产与暂存分别创建独立的应用注册。首次部署属于引导bootstrap操作部署者的身份需要创建资源与角色分配的权限。模板会将应用用户分配的托管标识在示例存储账户上授予Storage Table Data Contributor角色见 storage-role.bicep。发布并部署到暂存槽$publish Join-Path $env:TEMP orleans-shopping-cart-publish $package Join-Path $env:TEMP orleans-shopping-cart.zip dotnet publish .\Silo\Orleans.ShoppingCart.Silo.csproj --configuration Release --framework net10.0 --output $publish Compress-Archive -Path $publish\* -DestinationPath $package -Force $stagingSlot ${appName}stg az webapp deploy --name $appName --resource-group $resourceGroup --slot $stagingSlot --type zip --src-path $package --clean true --restart true读取暂存槽的确切主机名并验证就绪状态$stagingHost az webapp show --name $appName --resource-group $resourceGroup --slot $stagingSlot --query defaultHostName --output tsv Invoke-WebRequest https://$stagingHost/health/ready向应用注册补充两个回调 URL然后执行槽位交换az webapp deployment slot swap --name $appName --resource-group $resourceGroup --slot $stagingSlot --target-slot production首次基础设施部署后托管标识的角色分配可能需要几分钟才会生效。后端基础设施剖析Bicep 模块化设计infra/flex下的共享模块构成了部署的核心infra/ ├── flex/ │ ├── main.bicep # 编排 VNet、存储、日志与 App Service │ ├── app-service.bicep # App Service 计划、站点、槽位、认证、应用设置 │ ├── storage.bicep # 存储账户与网络隔离 │ ├── storage-role.bicep # Storage Table Data Contributor 角色分配 │ └── logs-and-insights.bicep ├── linux/main.bicep # Linux 平台入口 └── windows/main.bicep # Windows 平台入口虚拟网络与子网隔离flex/main.bicep 创建名为${appName}-vnet的虚拟网络地址空间覆盖172.17.0.0/16与192.168.0.0/16并划分两个委托给Microsoft.Web/serverFarms的子网default子网172.17.0.0/24——生产站点使用staging子网192.168.0.0/24——暂存槽位使用。两个子网都配置了指向Microsoft.Storage的服务终结点service endpoint使 VNet 内的流量可直接访问存储服务。App Service 站点与槽位app-service.bicep 是最复杂的模块核心配置包括站点配置siteConfigalwaysOn: true、healthCheckPath: /health/ready、http20Enabled: true、minTlsVersion: 1.2、numberOfWorkers: workerCount、vnetPrivatePortsCount: 1、webSocketsEnabled: true、ftpsState: Disabled。私有端口vnetPrivatePortsCount: 1为每个实例分配一个私有 TCP 端口这是多实例 Orleans 集群在 App Service 上连通的关键。共享应用设置生产与暂存槽位均设置设置名值作用AZURE_CLIENT_ID托管标识的 clientId指定DefaultAzureCredential使用的托管标识APPLICATIONINSIGHTS_CONNECTION_STRINGApp Insights 连接字符串日志与遥测ASPNETCORE_FORWARDEDHEADERS_ENABLEDtrue转发头处理MICROSOFT_PROVIDER_AUTHENTICATION_SECRET认证客户端密钥Easy Auth 使用ORLEANS_AZURE_STORAGE_URI存储表服务 URI集群与持久化ORLEANS_SERVICE_IDShoppingCartServiceOrleans 服务 ID跨部署稳定WEBSITE_HEALTHCHECK_MAXPINGFAILURES2健康检查判定阈值WEBSITE_SWAP_WARMUP_PING_PATH/WEBSITE_WARMUP_PATH/health/ready槽位交换与启动预热路径WEBSITE_SWAP_WARMUP_PING_STATUSES/WEBSITE_WARMUP_STATUSES200预热成功的状态码集群 ID 按槽位区分生产站点设置ORLEANS_CLUSTER_IDDefault暂存槽设置ORLEANS_CLUSTER_IDStaging保证两个槽位形成相互隔离的 Orleans 集群。槽位配置粘性slot stickyslotConfigNames将AZURE_CLIENT_ID、MICROSOFT_PROVIDER_AUTHENTICATION_SECRET、ORLEANS_CLUSTER_ID声明为槽位专属设置交换时不会被生产配置覆盖。托管标识创建${appName}-identity用户分配托管标识生产站点与暂存槽都将其设为UserAssigned身份。存储账户的默认拒绝网络storage.bicep 创建的存储账户StorageV2、Standard_LRS默认对公共网络采取拒绝策略networkAcls.defaultAction: Deny仅放行生产与暂存两个子网virtualNetworkRules。同时allowBlobPublicAccess: false禁止 Blob 公共访问allowSharedKeyAccess可通过参数控制迁移场景下可临时开启defaultToOAuthAuthentication: true默认走 OAuth 认证配合托管标识minimumTlsVersion: TLS1_2、supportsHttpsTrafficOnly: true。遥测与日志logs-and-insights.bicep 创建${appName}-logsLog Analytics 工作空间保留 30 天PerGB2018计费与${appName}-insightsApplication Insightsweb类型二者关联后输出appInsightsConnectionString供 App Service 使用。应用侧运行配置Program.cs 的生产分支Silo/Program.cs 的ConfigureProductionOrleans是理解整套部署逻辑的关键读取必需环境变量ORLEANS_CLUSTER_ID、ORLEANS_SERVICE_ID、ORLEANS_AZURE_STORAGE_URI、AZURE_CLIENT_ID、WEBSITE_PRIVATE_IP、WEBSITE_PRIVATE_PORTS任一缺失即抛异常解析私有端口从WEBSITE_PRIVATE_PORTS逗号分隔读取第一个端口作为 Silo 端口构建存储客户端DefaultAzureCredential指定ManagedIdentityClientIdTableServiceClient指向存储表服务 URI配置 OrleansSiloName取WEBSITE_INSTANCE_ID回退到机器名ClusterOptionsClusterId与ServiceId来自环境变量ConfigureEndpoints(privateIp, siloPort, gatewayPort: 0, listenOnAnyHostAddress: true)Silo 监听所有本地接口通告私有 IP 与私有端口关闭客户端网关UseAzureStorageClustering集群表名为${clusterId}ClusteringAddAzureTableGrainStorage(shopping-cart)持久化表名为${clusterId}Persistence。由此可以确认生产与暂存各使用独立的 Azure Table 集群表与持久化表表名以各自 cluster ID 为前缀而serviceId在两个槽位间保持稳定的ShoppingCartService保证 grain 版本兼容性。健康检查与优雅关闭应用暴露两个健康端点Program.csGET /health/live存活探针始终返回 200GET /health/ready就绪探针仅当 AppServiceLifecycle 的IsReady为 true 时返回 200否则返回 503。AppServiceLifecycle实现IHostedLifecycleService宿主StartedAsync后置位 ready主机与 Silo 均已启动StoppingAsync时清除 ready——从而保证应用只在完全就绪后接收流量并在关闭前从负载均衡摘除。宿主同时将HostOptions.ShutdownTimeout配置为 30 秒Program.cs。App Service 可能更早终止 worker因此正确性必须容忍 Silo 丢失与未知调用结果。配置 GitHub ActionsOIDC 免密钥部署前置条件先用默认参数assignStorageRolestrue完成一次 手动基础设施部署之后才能使用常规工作流。仓库内的工作流刻意传入assignStorageRolesfalse使其 OIDC 身份无需创建角色分配的权限——它不是引导型工作流。复制工作流将仓库中的 samples/Deployment/AzureAppService/infra/deploy.yml 复制到.github/workflows/deploy-app-service.yml。配置环境变量与机密为production环境配置 GitHub OIDC 与 Azure 的联合federation并添加以下环境变量变量值AUTHENTICATION_CLIENT_IDApp Service 认证应用注册的客户端 IDAUTHENTICATION_TENANT_ID用户认证使用的 Microsoft Entra 租户 IDAZURE_APP_NAME全局唯一的 App Service 名称AZURE_APP_SERVICE_OSwindows或linuxAZURE_CLIENT_ID联合部署身份的客户端 IDAZURE_RESOURCE_GROUP_LOCATIONAzure 区域AZURE_RESOURCE_GROUP_NAME已存在的目标资源组AZURE_SUBSCRIPTION_IDAzure 订阅 IDAZURE_TENANT_IDAzure 部署使用的 Microsoft Entra 租户 IDAUTHENTICATION_CLIENT_SECRET以 GitHub 环境机密secret形式添加。该密钥用于 App Service 用户认证GitHub 侧对 Azure 的部署走 OIDC不使用客户端密钥。工作流内部流程从 deploy.yml 源码可以看到完整的流水线权限最小化permissions仅声明contents: read与id-token: writeconcurrency组保证同一时刻只有一个生产部署进行cancel-in-progress: false不打断进行中的部署检出与构建actions/checkoutactions/setup-dotnet按仓库根目录global.json选择 SDKdotnet publish --framework net10.0后压缩为 zipOIDC 登录Azure/login使用AZURE_CLIENT_ID、AZURE_TENANT_ID、AZURE_SUBSCRIPTION_ID三个变量无需任何客户端密钥校验平台shell 步骤强制AZURE_APP_SERVICE_OS必须为windows或linux否则报错退出部署基础设施调用az deployment group create参数中固定allowSharedKeyAccessfalse与assignStorageRolesfalse并从输出中解析生产/暂存主机名与暂存槽名写入GITHUB_OUTPUT部署暂存槽az webapp deploy --slot staging --clean true --restart true等待暂存就绪curl --retry 30 --retry-all-errors轮询https://staging_host/health/ready交换槽位az webapp deployment slot swap --slot staging --target-slot production验证生产就绪再次轮询生产主机名的/health/ready。工作流以assignStorageRolesfalse部署因此其 Azure 身份无需在引导后具备创建角色分配的权限。为该身份在目标资源组授予Contributor或更优做法是授予一个仅覆盖 Bicep 模板中资源的自定义角色。升级现有 Windows 部署共享密钥迁移到托管标识Windows 模板会保留现有 App Service 计划与存储账户名称、ShoppingCartService服务 ID、Default与Staging集群 ID以及现有的成员关系与持久化表名。如果现有部署仍使用存储账户密钥不要直接先运行完整模板。请按以下顺序迁移创建${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。另外注意不要把一个已有的 App Service 计划在 Windows 与 Linux 之间切换。应部署独立应用并迁移流量。运维行为要点生产与暂存使用分离的委托子网与槽位粘性的集群 ID两个槽位跨部署保持稳定的ShoppingCartService服务 ID每个集群使用独立的 Azure Table 成员关系表与 grain 状态表{clusterId}Clustering与{clusterId}Persistence应用仅在宿主与 Silo 启动完成后报告就绪关闭前移除就绪状态宿主允许 Orleans 关闭最多 30 秒App Service 可能更早终止 worker因此正确性必须容忍 Silo 丢失与未知调用结果HTTPS 与 TLS 设置保护 HTTP 入口流量示例未对 Orleans 私有 Silo TCP 流量加密若威胁模型要求在虚拟网络内加密传输请为 Orleans 添加 TLSApplication Insights 接收 ASP.NET Core、依赖、异常、应用与 Orleans 日志Linux App Service 在 sidecar 容器中运行 Easy AuthWindows 使用进程内 App Service 模块两者注入相同的主体头契约X-MS-CLIENT-PRINCIPAL。应用模型Grain 身份与序列化字段在示例中传给GetGrainIProductGrain(product.Id)的product.Id是商品 grain 的身份标识。而ProductDetails上标注的[Id(n)]特性用于标识序列化字段序号供 Orleans 版本容忍version-tolerant的序列化器使用——它们不定义 grain 身份。二者职责不同理解这一点有助于正确设计 Orleans 接口与状态类型。示例的授权链路完整呈现了防御纵深Blazor 前端隐藏未授权入口 →/products路由强制认证与角色 → ProductService 在修改 grain 状态前再次执行ProductManagement策略授权 → Silo 关闭客户端网关杜绝绕过直连。生产与暂存环境的完整资源编排、应用设置与部署流水线均可从samples/Deployment/AzureAppService/infra/目录与 Silo/Program.cs 中直接查阅、复刻。赞分享后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载相关推荐Orleans 集群部署到 Azure App Service基于私有实例端点的 Windows/Linux 完整实战指南Orleans 集群部署到 Azure App Service基于私有实例端点的 Windows/Linux 完整实战指南 Azure App Service后端微服务在 Windows Azure App Service 上部署 Orleans 集群购物车示例的完整实战指南在 Windows Azure App Service 上部署 Orleans 集群购物车示例的完整实战指南 本指南基于 Orleans 官方仓库中的 Win后端微服务在 Linux Azure App Service 上部署 Orleans 集群Bicep 基础设施、托管标识与槽位滚动发布实战在 Linux Azure App Service 上部署 Orleans 集群Bicep 基础设施、托管标识与槽位滚动发布实战 本指南基于 Orleans后端微服务上一篇MaxViT XLarge TF 512实战教程10个图像分类应用场景示例下一篇Retrom元数据自动下载功能揭秘IGDB集成与艺术资源优化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考