2016-09-22 11 views
0

문제점 :이 서비스가 시작될 때 DB가 오프라인 인 경우 시작시 var container = new BootStrapper().Container;이이 열에서 실패하므로이 서비스가 시작되지 않습니다.db가 castle windsor 및 nhibernate 기능과 오프라인 인 경우 Windows 서비스 시작을 다시 시도하는 방법은 무엇입니까?

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(); 
} 

그것이 그것이 NHibernate에 시설 container.AddFacility<NHibernateFacility>();을 추가하고 연결 시간 초과 실패이 코드를 실행하도록이 실패하는 이유.

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>(); 
} 

Windows 서비스가 시작되면 앱 서비스가 시작되지 (가 업데이트 또는 백업이 DB에 진행되고있다 할 수있는 경우) 30초보다 오래 걸립니다.

NHibernateFacility가있는 NHibernate, Castle Windsor를 사용하고 있습니다.

상황은 나는 시도했다 : 그것은 뷰 또는 컨트롤러에 도달하기 전에 실패 때문에

  • 는 서비스 시작 이벤트에서 그것을 할 수 없습니다. 뷰 및 컨트롤러에는 Castle IXC 권장 사항에 따라 주입 된 IoCFactory 을 통해서만 IoC 컨테이너에 직접 액세스 할 수있는 이 없습니다.

  • 나는 주에 스레드를 생성하고 재시도 루프 거기를 시작하지만, 서비스가 ServiceBase.Run 방법 내에서 "대기"때문에, 내가 올바른 얻을 수없는 것하려고했습니다 으로 돌아가 재시도 루프 중에 "가짜 시작"상태가됩니다.

  • 는 서비스 시작 제한 시간을 연장 조사하지만, 그 전에 실패하고 생산 현장의 수백에서 시스템 전체 변경 옵션이 아니므로 servicebase/뷰에 액세스 할 수 없습니다.

질문 : 설계시 DB가 오프라인 일 때 Windows 서비스가 "시작"되도록하려면 어떻게해야합니까?

답변

0

위의 작업을 수행 할 수없는 NHibernate의 버그로 밝혀졌습니다. 이 NHibernate에 제대로 자신을 부트 스트랩 및 오류없이 이제 컨트롤러로 얻을 수 있습니다

cfg.SetProperty("hbm2ddl.keywords", "none"); 

: Nibernate 2.0과 3.0 사이에 당신하여 NHibernate에 3.0 + 설정에 다음 (또는이 케이스 FluentNHibernate에) 추가해야 .

1

당신은 두 가지 범주로 시동 작업을 분할해야합니다 상당히 즉시 일어나야 및/또는 실패의 경우에 스스로 가 해결되지 않습니다

  1. 작업을. 필수 구성 파일 인 이 누락되었습니다. 관리자 개입이 필요합니다.

  2. 조치를 지연하거나 더 중요한 것은 일 수있는 동작이 일시적인 오류로 인해 실패 할 수있는 동작입니다. 이러한 오류는 네트워크 오류이거나 재부팅 후 데이터베이스 서버보다 다소 빠른 속도로 시작한 것일 수 있습니다.

당신의 서비스 OnStart 코드는이 기본 구조를 따라야합니다

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. 

한 가지 방법이 기본 구조를 따르는 것입니다

OnShutdown은 shutdownRequestedEvent 신호를 보내고 은 RealMain 스레드가 종료 될 때까지 대기합니다.

RealMain 스레드가 설정 이외의 용도로 사용되지 않는 경우 모든 부트 스트랩 작업이 완료되면 을 종료해야합니다.

주의해야 할 또 다른 사항은 정상 작동 중에 일시적인 오류로 인해 자원에 대한 액세스가 일시적으로 손실되는 것을 견딜 수 있는지 확인하는 것입니다. 예를 들어 누군가가 데이터베이스 서버를 재부팅하기 때문에 서비스가 중단되지 않아야합니다. 참을성있게 기다리고 영원히 재 시도해야합니다.

어떤 경우에는 작동 할 수있는 대체 접근 방법은 실제 작업이 무엇이든 종속성으로 부트 스트랩을 처리하는 것입니다. 예를 들어 실제 작업을 시작하면 실제 작업이 데이터베이스 세션을 요청하고 세션 팩토리가 있어야합니다. 세션 팩토리가없는 경우 세션 팩토리 초기화가 시작됩니다. 세션 팩토리 을 만들 수 없으면 예외가 발생하고 전체 작업이 실패합니다. 나머지 작업은 잠시 기다린 다음 작업을 다시 시도해야합니다. 영원히 반복하십시오.

+0

처음에는 "hbm2ddl.keywords"를 "none"으로 설정해야하는 NHibernate 문제로 인해 두 번째 글 머리 기호 (두 번째 글 머리 기호는 두 번째 글 머리 기호보다 우수합니다. –

+0

예,하지만 구조가 더 넓습니다. 예를 들어, 서비스가 작업을 시작하거나 클라이언트 요청을 청취하기 전에 데이터베이스에서 정보를 읽어야 할 수 있습니다. –