如何在 Octopus 部署期间优雅地将 Web 应用下线?

15

我有点疏忽地发现章鱼虽然非常棒,但在升级网站之前并没有采取任何可爱或聪明的措施。

在我们的解决方案中,我们有两个 Web 应用程序(一个网站和一个单独的 API Web 应用程序),它们依赖于相同的数据库,因此在一个应用程序进行升级时,另一个应用程序仍然在线,可能会在升级数据库时仍在提供网络或 API 请求。

这不太好!

更好的方法是让Octopus关闭Web应用程序,等待它们关闭后再执行升级操作,完成后将应用程序池重新启动。

如何实现呢?


什么是Octopus?是否有免费社区? - Kiquenet
1
章鱼部署 http://octopusdeploy.com/ - Jason Glover
4个回答

17

自拍回答!

让Octopus-deploy在您的部署中多加一些小心,很容易,您只需要在部署例程中添加几个额外的Execute-Powershell步骤。

添加一个新的第一步来停止应用程序池:

# Settings
#---------------
$appPoolName = "PushpayApi" # Or we could set this from an Octopus environment setting.

# Installation
#---------------
Import-Module WebAdministration     
       # see http://technet.microsoft.com/en-us/library/ee790588.aspx

cd IIS:\


if ( (Get-WebAppPoolState -Name $appPoolName).Value -eq "Stopped" )
{
    Write-Host "AppPool already stopped: " + $appPoolName
}

Write-Host "Shutting down the AppPool: " + $appPoolName
Write-Host (Get-WebAppPoolState $appPoolName).Value

# Signal to stop.
Stop-WebAppPool -Name $appPoolName

do
{
    Write-Host (Get-WebAppPoolState $appPoolName).Value
    Start-Sleep -Seconds 1
}
until ( (Get-WebAppPoolState -Name $appPoolName).Value -eq "Stopped" )
# Wait for the apppool to shut down.

然后在最后添加另一步来重新启动应用程序池:

# Settings
#---------------
$appPoolName = "PushpayApi"

# Installation
#---------------
Import-Module WebAdministration     
       # see http://technet.microsoft.com/en-us/library/ee790588.aspx

cd IIS:\

if ( (Get-WebAppPoolState -Name $appPoolName).Value -eq "Started" )
{
    Write-Host "AppPool already started: " + $appPoolName
}

Write-Host "Starting the AppPool: " + $appPoolName
Write-Host (Get-WebAppPoolState $appPoolName).Value

# To restart the app pool ... 
Start-WebAppPool -Name $appPoolName

Get-WebAppPoolState -Name $appPoolName

1
这是不是意味着在部署期间,用户在浏览器中会收到503服务器错误? - Savage
我猜你想要启动 app_offline 页面而不是关闭它。 - BillRob

11
我们采用的方法是使用一个_app_offline.htm(App Offline)文件来部署应用程序。这样,我们可以得到一个友好的消息,解释网站为什么会关闭。
然后,在部署时,我们使用微软的Webdeploy将其重命名为app_offline.htm。我们将重命名的代码放在一个PowerShell脚本中,作为我们Octopus Deployment的第一步运行。
write-host "Website: $WebSiteName"

# Take Website Offline
$path = "$WebDeployPath";
$path

$verb = "-verb:sync";
$verb

# Take root Website offline
$src = "-source:contentPath=```"$WebSiteName/_app_offline.htm```"";
$src

$dest = "-dest:contentPath=```"$WebSiteName/app_offline.htm```"";
$dest
Invoke-Expression "&'$path' $verb $src $dest"; 


# Take Sub Website 1 offline
$src = "-source:contentPath=```"$WebSiteName/WebApp1/_app_offline.htm```"";
$dest = "-dest:contentPath=```"$WebSiteName/WebApp1/app_offline.htm```"";
Invoke-Expression "&'$path' $verb $src $dest"; 

$WebSiteName通常是“默认网站”。此外,请注意,`不是单引号,而实际上是反引号字符(通常与键盘上的tilda一起找到)。

现在,如果章鱼将您的网站部署到新位置,则您的网站将自动恢复在线状态。 如果您不想要这样,可以先部署已经放置了app_offline文件的新网站。 然后,您可以使用以下脚本删除它。

write-host $WebSiteName

# & "c:\Program Files (x86)\IIS\Microsoft Web Deploy V2\msdeploy.exe" -verb:delete -dest:contentPath="$WebSiteName/app_offline.htm"
# those arn't QUOTES!!!!, they are the back accent thing.  

write-host "Website: $WebSiteName"

# Put Web app Online.
$path = "$WebDeployPath";
$path

$verb = "-verb:delete";
$verb

$dest = "-dest:contentPath=```"$WebSiteName/app_offline.htm```"";
$dest
Invoke-Expression "&'$path' $verb $dest"; 

# Put Sub Website Online
$dest = "-dest:contentPath=```"$WebSiteName/WebApp1/app_offline.htm```"";
Invoke-Expression "&'$path' $verb $dest";

1
我也尝试过那种方法,但当你的网站有后台线程时,在下一个章鱼步骤开始之前,你不能确定它们是否已经完成了工作。 - Jason Glover
2
那么听起来最理想的方法是同时使用两种? - The Muffin Man
可以创建一个临时应用程序池来托管 app_offline.htm。重新映射应用程序以使用该应用程序池进行部署,关闭实际的应用程序池,最后执行反向步骤。 - Alex M

2
停止应用程序池和/或设置App_Offline文件对我来说还不够。两者都没有给客户适当的解释为什么网站关闭了,特别是App_Offline。我需要清理bin文件夹,这会导致YSOD(http://blog.kurtschindler.net/more-app_offline-htm-woes/)。
我的解决方案: 第一个任务将部署的网站重定向到包含适当消息的不同文件夹中的index.html。最后一个任务将原始文件夹恢复。

0
更好的解决方案是使用网络负载均衡器,例如f5 LTM。您可以设置多个服务器来接收站点的流量,然后在部署时,您只需禁用NLB中的一个节点,这样所有其他流量就会转到另一台机器。
我喜欢f5,因为它非常易于脚本化。当我们部署网站时,我们不会出现任何停机情况。将所有站点流量指向当前未进行升级的服务器即可。
有一些注意事项:
您必须编写脚本来禁用NLM中池成员的下线,以便它与您的站点配合使用。如果您的站点需要会话(例如依赖于会话状态或共享对象),则必须从NLB节点中释放流量。在f5中,您只需禁用它们,然后观察连接计数是否降至零(也可脚本化)。
您必须向您的开发人员/数据库管理员强制执行策略,声明所有数据库更改都不得导致现有代码的退化或失败。这意味着您必须非常小心处理数据库和配置。这样,您就可以在开始部署网站的第一个池之前完成数据库更新。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接