要部署我们网站的新版本,我们执行以下操作:
- 压缩新代码,并将其上传到服务器。
- 在实时服务器上,从 IIS 网站目录中删除所有实时代码。
- 将新的代码压缩文件解压到现在为空的 IIS 目录中
这个过程都是脚本化的,并且发生得很快,但是当旧文件被删除并部署新文件时,仍然可能有 10-20 秒的停机时间。
关于 0 秒停机方法的任何建议?
要部署我们网站的新版本,我们执行以下操作:
这个过程都是脚本化的,并且发生得很快,但是当旧文件被删除并部署新文件时,仍然可能有 10-20 秒的停机时间。
关于 0 秒停机方法的任何建议?
您需要 2 台服务器和一个负载均衡器。以下是步骤:
问题是,即使在这种情况下,如果您使用“粘性会话”,您仍然会重新启动应用程序并丢失会话。如果您有数据库会话或状态服务器,那么一切都应该没问题。
Microsoft Web 部署工具在某种程度上支持这一点:
启用 Windows 事务文件系统 (TxF) 支持。当启用 TxF 支持时,文件操作是原子的;也就是说,它们要么成功,要么完全失败。这可确保数据完整性并防止数据或文件以“中途”或损坏状态存在。在 MS Deploy 中,默认情况下禁用 TxF。
事务似乎是针对整个同步的。此外,TxF 是 Windows Server 2008 的一项功能,因此此事务功能不适用于早期版本。
我相信可以使用文件夹作为版本和 IIS 元数据库来修改脚本以实现 0 停机时间:
此方法提供以下好处:
通过将 IIS 中的应用程序请求路由用作不同端口上两个本地 IIS 站点之间的软件负载平衡器,您可以在单个服务器上实现零停机时间部署。这被称为蓝绿色部署策略,在任何给定时间,负载均衡器中只有两个站点中的一个可用。部署到“关闭”的站点,对其进行预热,然后将其带入负载均衡器(通常通过应用程序请求路由健康检查),然后将启动的原始站点从“池”中取出(再次通过使其健康检查失败)。
我最近经历了这个,我想出的解决方案是在 IIS 中设置两个站点并在它们之间切换。
对于我的配置,我为每个 A 和 B 站点都有一个 Web 目录,如下所示:c:\Intranet\Live A\Interface c:\Intranet\Live B\Interface
在 IIS 中,我有两个相同的站点(相同的端口、身份验证等),每个站点都有自己的应用程序池。其中一个站点正在运行 (A),另一个站点已停止 (B)。直播的也有直播主机头。
在部署到现场时,我只是发布到 STOPPED 站点的位置。因为我可以使用 B 站点的端口访问它,所以我可以预热站点,这样第一个用户就不会导致应用程序启动。然后使用批处理文件将实时主机标头复制到 B,停止 A 并启动 B。
使用 Microsoft.Web.Administration 的 ServerManager 类,您可以开发自己的部署代理。
诀窍是更改 VirtualDirectory 的 PhysicalPath,从而在新旧 Web 应用程序之间进行在线原子切换。
请注意,这可能会导致新旧 AppDomain 并行执行!
问题是如何同步对数据库等的更改。
通过使用旧的或新的 PhysicalPaths 轮询 AppDomain 的存在,可以检测旧的 AppDomain 何时终止,以及新的 AppDomain 是否已启动。
要强制启动 AppDomain,您必须发出 HTTP 请求(IIS 7.5 支持自动启动功能)
现在您需要一种方法来阻止对新 AppDomain 的请求。我使用了一个命名互斥体 - 它由部署代理创建和拥有,由新 Web 应用程序的 Application_Start 等待,然后在数据库更新完成后由部署代理释放。
(我在网络应用程序中使用标记文件来启用互斥等待行为)一旦新的网络应用程序运行,我就会删除标记文件。
好的,因为每个人都在反对我在 2008 年写的答案* ...
我会在 2014 年告诉你我们现在是如何做到的。我们不再使用网站,因为我们现在使用的是 ASP.NET MVC。
我们当然不需要负载均衡器和两台服务器来完成这项工作,如果您维护的每个网站都有 3 台服务器,那很好,但对于大多数网站来说,这完全是矫枉过正。
此外,我们不依赖微软最新的向导——太慢,隐藏的魔法太多,而且太容易改变它的名字。
我们是这样做的:
我们有一个后期构建步骤,将生成的 DLL 复制到“bin-pub”文件夹中。
我们使用 Beyond Compare(非常好**)来验证和同步更改的文件(通过 FTP,因为它得到了广泛的支持)到生产服务器
我们在网站上有一个安全 URL,其中包含一个按钮,该按钮将“bin-pub”中的所有内容复制到“bin”(首先进行备份以启用快速回滚)。此时应用程序会自行重启。然后我们的 ORM 检查是否有任何表或列需要添加并创建它们。
那只是几毫秒的停机时间。应用程序重新启动可能需要一两秒钟,但在重新启动期间请求被缓冲,因此实际上停机时间为零。
整个部署过程需要 5 秒到 30 分钟不等,具体取决于更改了多少文件以及要查看多少更改。
这样,您不必将整个网站复制到不同的目录,而只需将 bin 文件夹。您还可以完全控制流程并准确了解正在发生的变化。
**我们总是快速关注我们正在部署的更改 - 作为最后一分钟的仔细检查,因此我们知道要测试什么,如果有任何问题我们准备好了。我们使用 Beyond Compare 是因为它可以让您轻松地通过 FTP 比较文件。如果没有 BC,我永远不会这样做,你不知道你在覆盖什么。
*滚动到底部以查看它:(顺便说一句,我不再推荐网站,因为它们构建速度较慢,并且可能会在编译一半的临时文件时严重崩溃。我们过去使用它们是因为它们允许逐个文件更敏捷部署。非常快速地解决一个小问题,您可以准确地看到您正在部署的内容(如果使用 Beyond Compare,当然 - 否则忘记它)。
我能想到的唯一零停机方法涉及在至少 2 台服务器上托管。
对于单个服务器,我会稍微改进一下 George 的答案,如下所示:
第 4 步将导致 IIS 工作进程进行回收。
如果您不使用 InProc 会话,这只是零停机时间;如果可以,请改用 SQL 模式(更好的是,完全避免会话状态)。
当然,当有多个服务器和/或数据库更改时,它会涉及更多......
扩展 sklivvz 的答案,它依赖于某种负载平衡器(或只是同一服务器上的备用副本)
通过创建数据库快照/副本可以引入一些冒烟测试,但这并不总是可行的。
如果可能和需要使用“路由差异”,例如不同的租户 URL:s (customerX.myapp.net) 或不同的用户,首先部署到不知情的豚鼠组。如果没有任何问题,请发布给所有人。
由于涉及数据库迁移,因此通常不可能回滚到以前的版本。
有一些方法可以让应用程序在这些场景中运行得更好,例如使用事件队列和回放机制,但由于我们正在讨论将更改部署到正在使用的东西,所以真的没有万无一失的方法。
我就是这样做的:
绝对最低系统要求:
1 台服务器
工作流程:
开始事务 myupdate
try
Web-Service: Tell all applications on all web-servers to go into primary read-only mode
Application switch to primary read-only mode, and responds
Web sockets begin notifying all clients
Wait for all applications to respond
wait (custom short interval)
Web-Service: Tell all applications on all web-servers to go into secondary read-only mode
Application switch to secondary read-only mode (data-entry fuse)
Updatedb - secondary read-only mode (switches database to read-only)
Web-Service: Create backup of database
Web-Service: Restore backup to new database
Web-Service: Update new database with new schema
Deploy new application to apt-repository
(for windows, you will have to write your own custom deployment web-service)
ssh into every machine in array_of_new_webapps
run apt-get update
then either
apt-get dist-upgrade
OR
apt-get install <packagename>
OR
apt-get install --only-upgrade <packagename>
depending on what you need
-- This deploys the new application to all new chroots (or servers/VMs)
Test: Test new application under test.domain.xxx
-- everything that fails should throw an exception here
commit myupdate;
Web-Service: Tell all applications to send web-socket request to reload the pages to all clients at time x (+/- random number)
@client: notify of reload and that this causes loss of unsafed data, with option to abort
@ time x: Switch load balancer from array_of_old_webapps to array_of_new_webapps
Decomission/Recycle array_of_old_webapps, etc.
catch
rollback myupdate
switch to read-write mode
Web-Service: Tell all applications to send web-socket request to unblock read-only mode
end try
我经常使用的没有停机时间的解决方法是:
将正在运行的 .NET 核心应用程序 dll 重命名为 filename.dll.backup
上传新的 .dll(网络应用程序可用并在文件上传时为请求提供服务)
上传完成后,回收应用程序池。需要 RDP 访问服务器或功能以在您的主机控制面板中回收应用程序池。
IIS 在回收时与应用程序池重叠,因此在回收期间通常不会有任何停机时间。因此,请求仍然会在不知道应用程序池已被回收的情况下进入,并且请求可以无缝地服务而不会停机。
我仍在寻找比这更好的方法..!! :)
我建议将旧文件保留在那里并简单地覆盖它们。这样,停机时间仅限于单个文件覆盖时间,并且一次只丢失一个文件。
不过,不确定这对“Web 应用程序”是否有帮助(我认为您是在说这就是您正在使用的),这就是我们总是使用“网站”的原因。此外,“网站”部署不会重新启动您的站点并删除所有用户会话。