客户端可能在任何时候移动他们的生产服务器。因为有很多原因做这个。一些理由可能是:
几天前我们把生产服务器从一个数据中心移动到另一个数据中心。当时,我们遇到了许多挑战。在阐述挑战前,我想描述一下我们的新老服务器的生产服务器环境。
我们的旧生产服务器是32位的Windows 2003 Server、SQL Server 2005和带有互联网信息服务(IIS)6.0版本的Reporting Service 2005 版本。我们移动旧生产服务器到一个新环境--64位Windows 2008 Server、SQL Server 2008和带有IIS 7.5版本的集成模式的Reporting Service (SSRS) 2008。在开始移动之前我们觉得这对我们来说是很简单的任务。但是在执行的时候我们发现我们遇到了很多挑战,那个时期真的是我们的非常艰难的时期。因此我决定与大家分享,在将来任何人都可能做相似的工作,那么,他/她或他的队伍将从中受益。
开始执行前,我们需要备份旧的服务器数据库,复制代码文件(二进制和资源文件)、配置文件和其他文件,并且压缩他们和移动他们到新服务器。 大约需要5/6的时间去做这些事。做这些的时候,我们不想让客户端访问我们的网站/应用去改变任何东西。实际上我们脱机我们的生产网站。但是我们给我们的顾客必须展示正确的信息,即使他们知道服务器正在维护、他们仅仅需要等几次。我们建立了一个静止不变的html文件假定它的名字是MaintenanceAlert.htm。现在的问题时什么时候、怎样去重定向到它?答案是当客户端访问我们的网站或任何书签页面时,我们重定向到这个页面。 怎样去重定向呢?一个解决方案可能是我们从文件后的母板页代码重定向。
1 |
Response.Redirect(“MaintenanceAlert.html", false ); |
但问题是,我们有多份母板页而且我们需要全部改变和把他部署到生产服务器上,在完成了任务后,我们需要回滚到旧的母板页上。因此,我们认为这不是个完美的解决方案。我们在寻找一个不让代码改变的方法,我们能从网站上找到方法来做些什么呢? 配置(config)文件。如果这样做了,他对我们将变得非常的容易。在用google搜索后我们发现了一个用的链接 Http Redirection
1 |
< httpRedirect enabled = "true" destination = "Maintenance.htm" |
2 |
exactDestination = "true" httpResponseStatus = "Permanent" /> |
httpRedirect网站。配置条目将所有请求重定向到维护.htm页面。
我们有另一个问题,我们得有一个Hello.htm的页面在我们的网站上。这篇文章将被负载平衡器公司使用。如果有任何请求从这个网页上来,我们不应该重定向。另一个网页配置条目将解决这个问题。
1 |
< location path = "Hello.htm" > |
2 |
< system.webServer > |
3 |
< httpRedirect enabled="false /> |
4 |
</ system.webServer > |
5 |
</ location > |
这将为Hello.htm网页重写http重定向的默认行为。
我们都知道每一个网站/应用都有个web.config 文件。这个配置文件包含很多配置值,像数据库连接线、邮件设置、超文本处理机、超文本模块注册、应用程序设置键值对、第三方组件注册等等。在现实生活中,这个网站配置文件变得非常大。它的大小在一天天的增大。为了保持web.config文件小和简单,我们把连接线和应用程序设置值放在两个不同的文件中。这个文件设置看起来像
1 |
< connectionString configSource = "connection.config" /> |
2 |
< appSettings configSource = "AppSettings.config" /> |
1 |
< add key = "smtpHost" value = "192.168.0.1" /> |
1 |
< add key = "mailServer" value = "192.168.0.1" /> |
1 |
< connectionString configSource = "ConnectionString.config" /> |
在测试我们的新网站时,我们发现网站的日志文件没有写。我们不能确定问题出在哪儿。调查之后,我们意识到我们需要对日志管理者授予必要的权限。哪个使用者需要这个权限呢?用户在其下运行的网站应用程序池帐户(在本例中我们运行网络服务)必须授予权限。
在我们的任务调度器中,我们创建了不同的必要权限的用户帐户来运行调度程序的可执行文件。在开发时期,我们看见许多开发者当面临权限有关的问题时,他允许每个人对他的个人电脑都有完全控制权限和修理权限。但是实际上这个方法忽视了一个问题。如果我们在我们的生产服务器中这样做了那么我们就对我们的整个系统打开了一个安全门,而且在未来这有可能发生很多安全问题。我发现了一个对安全问题最好方法的有效链接
http://technet.microsoft.com/en-us/library/cc779601%28v=ws.10%29.aspx
我们对异步请求使用通用的http处理程序而不是从我们的服务器中删除资源。这个处理程序将不包含“删除”http动/谓词。因此使用这个处理程序将不会删除任何资源文件。但是,如果有些需要删除,怎么做呢?我们仅仅需向处理程序添加“删除”动/谓词命令即可。预先,我们在旧的生产服务器中做了实验。但在我们的质量工程师汇报他不能在服务器中删除任何资源之前的很长一段时间我们忘了做这个事情。在调查这个问题之后我们发现我们忘了增加那个删除动/谓词了,添加这个词后我们解决了这个问题。
我们开发了一个网站,用于处理用户身份验证。我们的网站中有少数依赖该网站进行用户身份验证。如果用户身份验证通过,身份验证cookie返回请求的网站。多个站点共享相同的cookie,并允许用户访问该cookie认证的多个站点,简单来说就是登录一次便可访问其他多个站点。我们称之为统一登录。迁移完成后,我们发现我们的网站无法登录。只有一个消息传来-"用户无效"。首先,我们猜测数据库连接字符串是错误的。经过检查,我们发现每一个配置都是正确的。我们没有解决问题。我在本地PC上创建了一个统一登录的环境,发现它工作的很好。我审查了代码但依旧没有发现问题。我们知道进行身份验证登录网站时使用的是WCF安全服务。我们将容错模式"关闭"后在生产环境中独立运行,发现抛出DiretoryNotExists异常,但在我们当前的代码库中,我们没有发现任何这样的目录。我在svn库中需求帮助。我审查了旧版本的代码,发现在一个地方,它读取XML文件,并添加到文件缓存依赖对象。我们搜索这个文件夹发现这个目录在旧服务器上有,但新服务器上没有。我们明白了旧的生产代码没有被更新。我们从我们的临时服务器重新部署这些代码并修复了问题。
我刚才提到我们的旧服务器是32位的Windows 2003操作系统,而新的服务器是64位的Windows 2008服务器。迁移只是简单的将我们的代码从旧服务器复制到新的服务器。网站按预期工作。我们有10-12运行Windows任务调度程序的可执行文件,本来可正常工作,但QA工程师报告一些我们可以按需运行通过ajax请求的调度不能正常工作。调查时,我们发现,双击运行它时它没有运行并且不抛出任何错误消息。我们审查了代码和运行exe文件页面的Web方法
Process.Start("Publish.exe");
我们搜索事件日志、错误日志以及网站日志试图发现导致这个情况的原因,但没有发现任何有用的资源。经过多次问题我们明白了,我们的网站应用程序池运行在64位上。但我们的临时服务器是32位。我们使用SVN代码库中建立的可执行文件是32位的。当我们将应用程序池从64位换到32位它是工作正常的,我们定位了问题。我们重置回64位应用程序池,并在64位开发PC上重编译了我们的调度程序,重新部署到新的生产服务器,工作以前正常。
Ajax pro 是一个基于.NET的ajax交互组件。如果你想知道更多这个组件的细节,请点击下面的链接进行访问。
我们使用AjaxPro和Jqery库进行ajax的实时交互。在先前的服务器上,我们发现工作得很好。但是在我们新的生产环境里,我们发现Ajaxpro不工作了,但是jquery工作良好,我找到2个解决这个问题得比较好的链接。
其实在以前的IIS6.0,我们注册组件在下面的节点。
1 |
< httpHandlers > |
2 |
< add verb = "POST,GET" path = "ajaxpro/*.ashx" |
3 |
type = "AjaxPro.AjaxHandlerFactory, AjaxPro.2" /> |
4 |
</ httpHandlers > |
1 |
< system.webServer > |
2 |
< handlers > |
3 |
< add name = "AjaxPro" verb = "*" path = "ajaxpro/*.ashx" |
4 |
type = "AjaxPro.AjaxhandlerFactory, AjaxPro.2 resourceType=" unspecified" /> |
5 |
</ handlers > |
6 |
</ system.webServer > |
我们使用System.Transactions.TransactionScope对象执行我们的事务。
但是当我们测试的时候发现这个错误。
我们开始收集这个问题,发现下面这个又有的链接。
我们的web服务器和数据库是两个不同的物理服务器。
我们需要在两台服务器都需要开启事务,然后我们发现他工作正常了。
在我们的开发和登台服务器(译注:staging server登台服务器,交付准备服务器)环境中,我们使用的是http。但在生产服务器环境中,我们使用https来进行安全通信。在测试新服务器的过程中,我们发现有个奇怪的错误冒出来。我们看到的错误,在crome浏览器中看起来是这样的
在 Internet Explorer这个错误像这样
我们着手研究这个错误,找到了2个非常有用的链接。
我们明白了是哪里做错了。我们使用的是cdn上http形式的jquey路径
http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js
所以在我们的https网站中,浏览器抛出了不安全内容的警告。
我们仅仅只是将CDN定位中http替换为https便修复了这个问题。
https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js
在迁移和配置完新的邮件服务器后,我们发现我们的邮件不能发生。在我们的配置文件中,smtphost间值是使用的localhost。在调查的时候,我们发现了两个非常有用的链接。
我们替换了配置节点中的localhost为127.0.0.1,发现邮件发送正确了。
(译注:SSRs,SQL Server Reporting Services)
从老服务器下载所有rdl文件,在上传到新服务器的时候,我发现有2个文件没有上传。文件抛出异常。异常信息是“ssrs报表私有位置未找到私有程序集custom.dll”。经过研究我们发现有2个rdl文件使用私有程序集custom.dll。SSRS报表从它的私有程序集目录的位置查找那个dll文件。这个位置是
1 |
%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies |
在将那个dll分发到这个目录之后,rdl文件便正常上传并解决了我们的问题。
在sql服务器的存储过程中,我们使用了clr函数。我们还使用了一些第三方sql clr函数。结果在测试新服务器的时,发生了一个异常“你的数据库未启用SQL CLR”(SQL CLR not enabled to your database)。在排查这个问题的过程中,我找到了一个非常好的链接启用CLR的过程
在给我们的生产服务器启用sql服务器clr选项以后,这个问题就解决了。
在部署完成所有的报表到新的生产服务器后,报表仍然不显示。在调查的时候,我们发现了这个有用的链接。
我们创建了一个系统用户账号,并且分配了新的用户和角色分配给报表文件夹,发现每个报表都可以显示了。
在做报表测试的时候,我们发现一个非常有趣的问题。报表默认导航图标(First, Previous, Next, Last)不显示。在那时我们非常迷惑,应为那时sql server默认的图片。我们不知道怎么来修复这个问题,在那段时间里,我们发现2个非常有用的链接。
我们才明白那是IIS6和IIS7相关的问题,我们需要注册这个处理程序到iis7。
1 |
< handlers > |
2 |
< add name = "ReportViewerWebControlHandler" preCondition = "integratedMode" |
3 |
verb = "*" path = "Reserved.ReportViewerControl.axd" |
4 |
type="Microsoft.Reporting.WebForms.HttpHandler, |
5 |
Microsoft.ReportViewer.WebForms, Version = 8 .0.0.0, |
6 |
Culture = neutral , PublicKeyToken = b03f5f7f11d50a3a " /> |
7 |
</ handlers > |
在注册完这个处理程序到iis7之后,我们发现默认的图片显示问题得到了解决
我们开始测试新迁移的服务器网站时,旧服务器仍在运行,而且两台服务器的dns名字是一样的。那么怎样测试新网站呢?一个解决办法是添加主机条目。但仅仅主机条目并不能解决这个问题。首先我们应该关闭所有浏览器。
然后在命令提示窗口执行dnsflush命令。接着我们就可以打开浏览器,通过url访问网站,观察远端ip并确保请求被发送到新服务器。
我很难覆盖到迁移生产环境服务器时所面对的所有场景。但我已经尽力覆盖了迁移旧服务器到新服务器过程中的尽可能多的场景。我希望在不久的将来,如果有人做类似的工作时,这篇文章可以帮助他。
联系客服