克服 SCM 端点 230s 硬编码限制的方法

Ways to overcome the 230s hard coded limit to the SCM endpoint

背景 我们有一个 PHP 应用服务和 MySQL 是使用 Azure Devops 管道 (YML) 部署的。内容本身是一个 PHP 站点,由外部供应商使用 Akeeba 将其打包到一个文件中。该包是一个 Zip 文件(可以作为标准 Zip 部署进行部署),Zip 文件内部是一个巨大的 JPA 文件。 JPA 本质上是整个网站加上数据库表、设置、文件重命名和大量其他内容,所有这些都集成到一个 JPA 文件中。 Akeeba 本质上是解压缩文件,将它们复制到正确的位置,做所有的数据库工作等等。要开始这个过程,我们可以简单地连接到特定的 URL(网站 + 路径)和 运行 PHP,它们通过 Web GUI 完成所有巧妙的解包。但是,我们希望将此阶段包含在管道中,以便该过程是端到端的完全自动化。 Akeeba 有一个 CLI 作为 Web GUI 部署的替代方案,所以它应该是这样的:

  1. 创建网络应用程序
  2. 部署网站 ZIP (zipDeploy)
  3. 使用 REST API 访问 Kudu 和 运行 相关命令 (php install.php web.jpa) 解压 jpa 并执行 MySQL 东西 - 这通常需要 30 多分钟(这是一个大网站,它有很多“东西”要做 - 但是,它最终确实有效)。

问题是 SCM REST API 有一个硬编码的 230 秒限制,如下所述:https://blog.headforcloud.com/2016/11/15/azure-app-service-hard-timeout-limit/

因此,解压阶段一直在 230 秒标记处抛出“Invoke-RestMethod : 500 - 请求超时”。

我们已经尝试了 SCM_COMMAND_IDLE_TIMEOUT 和 WEBJOBS_IDLE_TIMEOUT,但不出所料,它们没有任何区别。

$cmd=@{"command"="php .\site\wwwroot\install.php .\site\wwwroot\web.jpa .\site\wwwroot"}
Invoke-RestMethod -Uri $url -Headers @{"Authorization"="Basic $creds"} -Body (ConvertTo-Json($cmd)) -Method Post -ContentType "application/json" -TimeoutSec 7200

我可以想出一些假设的方法(有些很古怪):

  1. 除了 Kudu REST API 之外,在部署后找到另一种方法 运行 Web 应用程序内部的 CLI 命令。有这样的事吗?我用谷歌搜索并检查了 SO 但我发现的只是指向我们现在做(或尝试做)的方式的指针。
  2. 使用类似 Selenium 的工具来单击 GUI 按钮,而不是使用 CLI。 (不知道会不会超时。)
  3. 而不是 运行 通过 Kudu REST 命令,使用相同的 API 创建脚本并将其部署到 Web 服务器,启动它,然后让 REST API当脚本仍在 Web 应用程序上 运行 时退出。本质上,避免异步调用但没有回调,然后让管道以例如 5 分钟的间隔检查站点。笨重。
  4. 延长 230 秒的限制 - 但我认为 Microsoft 无法做到这一点。
  5. 在部署期间使网站尽可能快,希望将其控制在 4 分钟以内,然后缩小规模。呸!
  6. 查看 Akeeba JPA 解包实际执行的操作,在部署前对其进行解包,并执行解包过程执行的操作,但通过管道进行控制。这可能需要大量工作,并且会失去供应商的支持。
  7. 放弃自动化部署。这反而会破坏 Devops 管道的大部分目的。
  8. 改用 AWS + terraform。但是,这不是经过批准的基础架构环境。

鉴于 Microsoft 可以理解地不希望长时间 运行ning API 调用徘徊,我理解为什么存在限制。但是,我希望因此有一种机制可以通过 CLI 以另一种方式与 App Service 文件系统进行交互。有人知道怎么做吗?

TCP 级别的 4 分钟空闲超时,这是在 Azure 硬件负载平衡器上实现的。此超时不可配置且无法更改。我想提及的一件事是,这是 TCP 级别的空闲超时,这意味着如果连接仅处于空闲状态并且没有数据传输发生,则只有此超时才会发生。为了提供更多信息,如果 Web 应用程序收到请求并继续处理请求 > 4 分钟而不发回任何数据,这将触发。

分辨率

理想情况下,在 Web 应用程序中,保持底层 HTTP 请求打开并不好,4 分钟是一个合适的时间。如果您对 Web 应用程序中的后台处理有要求,那么推荐的解决方案是使用 Azure WebJobs 并让 Azure Webapp 与 Azure Webjob 交互,以便在后台处理完成后发出通知(Azure 提供了多种方式,例如 queues 触发器等,你可以选择最适合你的方法)。 Azure Webjobs 专为后台处理而设计,您可以在其中进行任意多的后台处理。我正在分享一些详细讨论 webjobs 的文章 · http://www.hanselman.com/blog/IntroducingWindowsAzureWebJobs.aspx · https://azure.microsoft.com/en-us/documentation/articles/websites-webjobs-resources/

============================================= ===============================

这完全取决于应用程序。消息 Queue 浮现在脑海中。有很多潜在的解决方案,由您决定。

============================================= ===============================

选项 #1) 您可以更改代码以发送某种 header 以继续到客户端以保持 session 打开。 示例显示在这里 这显示了带有 Expect 100-continue header 的 HTTP Header: https://msdn.microsoft.com/en-us/library/aa287673%28v=vs.71%29.aspx?f=255&MSPPError=-2147217396 这显示了如何将 Header 添加到 collection: https://msdn.microsoft.com/en-us/library/aa287502(v=vs.71).aspx

选项 #2) 进度条

选项 #3) 使连接保持更长时间活动的常见做法是使用 TCP Keep-alive。在连接上未检测到 activity 时发送数据包。通过保持 on-going 网络 activity,永远不会达到空闲超时值并保持连接很长时间

选项 #4) 您还可以尝试将应用程序托管为 IaaS VM 而不是 APP SERVICE。这可能会避免 ARR 超时问题,因为它的体系结构不同,我相信 time-out 是可配置的。