C# 如果db与castle windsor和nhibernate协作室脱机,如何重试windows服务启动?
问题:如果启动此服务时DB处于脱机状态,则此服务将不会启动,因为它在此行中失败:C# 如果db与castle windsor和nhibernate协作室脱机,如何重试windows服务启动?,c#,nhibernate,fluent-nhibernate,castle-windsor,C#,Nhibernate,Fluent Nhibernate,Castle Windsor,问题:如果启动此服务时DB处于脱机状态,则此服务将不会启动,因为它在此行中失败:var container=new BootStrapper().container启动时 private static void Main(string[] args) { Logger.Info("Engine Service is bootstrapping..."); AppDomain.CurrentDomain.UnhandledException += UncaughtException
var container=new BootStrapper().container代码>启动时
private static void Main(string[] args)
{
Logger.Info("Engine Service is bootstrapping...");
AppDomain.CurrentDomain.UnhandledException += UncaughtExceptions.DomainException;
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
var container = new BootStrapper().Container;
var controller = container.Resolve<EngineController>();
ServiceBase.Run(controller.MainView as ServiceBase);
container.Dispose();
}
private static void Main(字符串[]args)
{
Info(“引擎服务正在引导…”);
AppDomain.CurrentDomain.UnhandledException+=UncaughtExceptions.DomainException;
目录.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
var container=new BootStrapper().container;
var controller=container.Resolve();
运行(controller.MainView作为ServiceBase);
container.Dispose();
}
它失败的原因是它在添加nhibernate facilitycontainer.AddFacility()的地方运行此代码代码>并因连接超时而失败
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var isAutoTxFacilityRegistered = container.Kernel.GetFacilities().Any(f => f is AutoTxFacility);
if (!isAutoTxFacilityRegistered) container.AddFacility<AutoTxFacility>();
container.Register(
Component.For<INHibernateInstaller>().ImplementedBy<CieFluentInstaller>().IsDefault().LifestyleTransient(),
Classes.FromThisAssembly().Pick().WithService.DefaultInterfaces().LifestyleTransient()
);
var isNHibernateFacilityRegistered = container.Kernel.GetFacilities().Any(f => f is NHibernateFacility);
if (!isNHibernateFacilityRegistered) container.AddFacility<NHibernateFacility>();
}
public void安装(IWindsorContainer,IConfigurationStore)
{
var isAutoTxFacilityRegistered=container.Kernel.GetFacilities().Any(f=>f是AutoTxFacility);
如果(!isAutoTxFacilityRegistered)container.AddFacility();
集装箱。登记(
Component.For().ImplementedBy().IsDefault().LifestyleTransient(),
Classes.FromThisAssembly().Pick().WithService.DefaultInterfaces().Lifestyle())
);
var isNHibernateFacilityRegistered=container.Kernel.GetFacilities().Any(f=>f是NHibernateFacility);
if(!isNHibernateFacilityRegistered)container.AddFacility();
}
如果windows服务启动时间超过30秒(如果在DB上执行更新或备份,则可能会超过30秒),则应用程序服务无法启动
我用的是FluentNhibernate,NHibernate,温莎城堡和NHibernate
我尝试过的事情:
- 无法从服务启动事件执行此操作,因为它在启动之前失败
获取视图或控制器。视图和控制器没有任何属性
仅通过注入的IoC工厂直接访问IoC容器
按照温莎城堡的建议
- 我已经尝试在主线程中生成一个线程,并从那里开始
重试循环,但因为服务在
方法,我似乎无法获得正确的返回
在重试循环中使其成为“假启动”
- 已调查延长服务启动超时,但无法访问
servicebase/view,因为它在此之前失败,并且是系统范围的
在数百个生产现场进行更改不是一个选项
问题:在给定设计的情况下,如何使DB脱机时windows服务“启动” 您需要将启动操作分为两类:
必须立即发生和/或无法自行修复的操作
万一失败了。诸如强制配置文件之类的内容
缺少,需要管理员干预
我们可以推迟的行动,或者更重要的是,可以推迟的行动
由于暂时性错误而失败。此类错误可能是网络故障或其他原因
经过一段时间后,我们的启动速度刚好比数据库服务器快一些
重新启动
您的服务OnStart
代码应遵循以下基本结构:
OnStart:
Perform the immediate category 1 tasks and exit if any of these fail.
Launch the main application thread.
ManualResetEvent shutdownRequestedEvent = new ManualResetEvent()
RealMain:
while (!shutdownRequestedEvent.WaitOne(0) && !bootstrapPerformed)
{
try
{
PerformBootstrap()
bootstrapPerformed = true
}
catch (Exception ex)
{
LogError(ex)
}
if (!bootstrapPerformed)
shutdownRequestedEvent.WaitOne(some timeout)
}
Second bootstrap action similar to above, etc.
Third bootstrap action similar to above, etc.
Eventually, start performing real work, while listening to
the shutdownRequestedEvent.
“主应用程序线程”的一种方法是遵循以下基本原则
结构:
OnStart:
Perform the immediate category 1 tasks and exit if any of these fail.
Launch the main application thread.
ManualResetEvent shutdownRequestedEvent = new ManualResetEvent()
RealMain:
while (!shutdownRequestedEvent.WaitOne(0) && !bootstrapPerformed)
{
try
{
PerformBootstrap()
bootstrapPerformed = true
}
catch (Exception ex)
{
LogError(ex)
}
if (!bootstrapPerformed)
shutdownRequestedEvent.WaitOne(some timeout)
}
Second bootstrap action similar to above, etc.
Third bootstrap action similar to above, etc.
Eventually, start performing real work, while listening to
the shutdownRequestedEvent.
关闭时的服务将发出关闭请求事件的信号,然后
等待RealMain线程退出
如果RealMain线程除了setup之外没有其他用途,那么它可能应该
完成所有引导任务后,允许退出
另一件需要注意的事情是,确保您的服务在正常运行期间能够承受由于暂时性错误而导致的对资源的临时访问丢失。例如,您的服务不应该因为有人重新启动数据库服务器而崩溃。它应该耐心等待,然后永远重试
在某些情况下,另一种可行的方法是将引导作为实际任务的依赖项来处理。例如,启动真正的任务,真正的任务将请求一个数据库会话,为了得到我们必须有会话工厂,如果我们还没有会话工厂,启动会话工厂初始化。如果会话工厂
无法创建,出现异常,整个任务失败。剩下的
现在的工作是等待一段时间,然后重试该任务。永远重复。原来是NHibernate中的一个bug,阻止了执行上述任何操作。在Nibernate 2.0和3.0之间,您必须将以下内容添加到NHibernate v3.0+配置中(或者在本例中为FluentNHibernate):
这使NHibernate能够正确地引导自身并立即无误地到达控制器。虽然这是一个好主意,但由于NHibernate问题要求先将“hbm2ddl.keywords”设置为“none”,因此它的效果并不比我的第二个要点(它们非常相似)好。是的,但我的结构有更广泛的应用。例如,服务可能需要从数据库中读取信息,然后才能开始执行其工作或开始侦听客户端请求。