2010-04-23 46 views
2

我开发了中间件,它为我们组织内多个平台上的多个客户端应用程序提供RPC功能。中间件用C#编写,并作为Windows NT服务运行。它处理文件访问网络共享,数据库访问等事情。中间件托管在运行Windows Server 2008的两个高端系统上。Windows NT服务关机问题

当我们的服务器管理员之一去重新启动计算机时,主要执行Windows更新,在我的NT服务方面,系统的行为方式存在严重问题。我的服务旨在立即停止监听新连接,立即开始拒绝现有连接上的新请求,并在SCM发出OnStop或OnShutdown请求的情况下尽快关闭。但是,为保持系统完整性,目前正在进行的操作可以在合理的时间内继续进行。通常,服务器在30秒内关闭(例如,在手动停止服务时)。但是,当指示系统重新启动时,我的服务立即失去对网络驱动器和UNC路径的访问权限,从而导致任何打开文件的数据完整性问题以及对这些位置的部分写入。我的服务确实将Workstation(因此SMB重定向器)列为依赖项,因此如果Windows遵守这些依赖关系,我认为我的服务需要在Workstation/Redirector停止之前停止。

基本上,我的应用程序被迫崩溃并烧坏,失败的远程过程调用,并最终在超时时间过后(似乎大约20-30秒)被操作系统强制终止。

与Windows应用程序不同,我的Windows NT服务似乎没有任何权限来阻止正在进行的系统关闭,延迟系统关闭,甚至只是有机会在存在之前保存任何挂起的网络共享磁盘写入强行断开和关闭。在这种环境下,NT服务开发人员应该如何拥有任何类型的应用程序完整性?为什么Forms应用程序在关闭之前得到完成业务的所有机会,而服务似乎没有这种好处?

我曾尝试:通过P

调用SetProcessShutdownParameters /调用尝试通知我关机更快的应用程序,以避免重定向器关闭我之前做。

使用小于或等于两分钟限制的值调用ServiceBase.RequestAdditionalTime。

扭捏WaitToKillServiceTimeout的

一切我能想到的,使我的服务关闭快。

但是最后,我仍然遇到了30秒的问题时间,其中我的服务似乎还没有收到OnShutdown事件的通知,但由于重定向器不再为我的网络共享提供服务,请求失败要求。

这个问题是如何解决的?我能做些什么来延迟或停止关机,或者至少被允许在没有重定向服务的情况下关闭我的活动任务?我可以理解微软正在试图做些什么来防止服务拖垮他们并显示关闭,但这似乎是Windows客户端操作系统的一个伟大目标,而不是服务器。我不希望我的服务器快速关闭,我希望操作的完整性和优雅的关闭。

在此先感谢您提供的任何帮助。

更新:我已经做了确切的时间。在测试关机时,我在23:55:58得到了关机通知,并注意到23:56:02失去了网络共享连接。所以在4秒钟内,我失去了保存任何活动状态的能力。

+1

真的不是您的问题的答案,但是所有其他失败模式(如路由器崩溃或远程文件服务器突然重新启动)呢?你不需要处理所有这些吗? – 2010-04-23 06:43:00

+0

除了Workstation之外,可能还会将Netman添加到您的依赖项中,值得一试。 – Filburt 2010-04-23 06:51:48

+0

在前端,我在多台刀片服务器上运行该中间件服务的多个副本,并在它们前面安装高度可用的冗余F5负载平衡器对,并配置为在紧时间进行重新选择。我们的网络旨在为路由器(主要是第3层交换机接口)提供HSRP冗余,交换机之间的中继线采用LACP等。我关心的主要文件服务器运行在Microsoft故障转移群集中,后端是EMC光纤通道SAN。我们在硬件方面一直非常稳固。这就是这个“简单”的软件问题,它正在扼杀它。 – 2010-04-23 06:53:03

回答

1

这个问题:https://serverfault.com/questions/34427/windows-service-dependencies在ServerFault应该回答你自己的。它链接到这篇文章:http://blogs.technet.com/askperf/archive/2008/02/04/ws2008-service-shutdown-and-crash-handling.aspx,这应该有助于您获得关机前通知和服务关机订购。

+0

我已经在注册表中为我的服务配置了预关闭通知,但我无法弄清楚如何在C#.NET NT服务中注册PRESHUTDOWN通知。我尝试使用为ACCEPT_PRESHUTDOWN设置的结构p/invoke SetServiceStatus,但它没有任何影响,或者我无法通过OnCustomCommand获取该事件。 – 2010-04-23 08:15:11

+0

问题是:你什么时候调用SetServiceStatus?问题在于,当OnStart返回时(为了告诉SCM服务状态为RUNNING),ServiceBase以它自己的接受命令的概念进行操作。所以,我想你需要从OnStart生成一个线程(我猜你已经这么做了),并用自己的接受命令列表再次调用SetServiceStatus。 – Timores 2010-04-24 15:36:42