[ASP.NET] Web에서 예약된 작업실행

2015. 1. 9. 10:32WEB

때때로, 특정 시간에 어떤 코드를 실행해야 할 때가 있습니다. 또는 일정간격으로 규칙적인 작업을 반복해야 하는 경우도 있습니다. 특정 시간에 이메일을 발송하거나, 트래픽을 분석하거나, 보고서를 작성하거나, 초기화, 유지보수 작업 등등 이 있겠지요.

ASP.NET은 예약된 작업실행을 위한 특별한 방법을 제시하고 있지 않습니다. 또한 HTTP Protocol은 오로지 요청이 발생했을 때 그에 대한 응답코드를 실행할 수 있을 뿐이기에 예약된 작업을 실행하는데 적합하지 않습니다.

이러한 문제를 해결하기 위한 방법은 크게 2가지로 분류됩니다.

  1. 순수 ASP.NET을 이용하는 방법입니다. Timer, Cache 만료, 또는 쓰레드를 이용한 방법입니다.
  2. 외부 프로그램을 이용하는 방법입니다.  서버의 작업스케줄러, Windows Service, 기타 외부프로그램을 통한 방법이 있겠습니다.

여기에서는 순수 ASP.NET을 통한 3가지 방법에 대해 안내 드리고자 합니다. 만약 외부 프로그램을 이용한 방법을 알고 싶으시다면, Task Schedulr or Windows service in ASP.NET 문서를 참고하세요.

Thread를 통한 예약된 작업실행

Thread를 통한 방법은 매우 간단합니다. Global.asax의 Application_Start 이벤트에서, Thread를 하나 생성하고 일정한 간격으로 코드를 계속 실행하는 것입니다.

void scheduledTask()
{
    while (true)
    {
        //작업코드 작성..

        //12시간 마다 실행
        System.Threading.Thread.Sleep(TimeSpan.FromHours(12));
    }
}
protected void Application_Start()
{
    System.Threading.Thread taskThread = new System.Threading.Thread(scheduledTask);
    taskThread.Start();
}

Timer를 통한 예약된 작업실행

void timScheduledTask_Elapsed(object sender, ElapsedEventArgs e)
{
    //작업코드 작성..
}
protected void Application_Start()
{
    System.Timers.Timer timScheduledTask = new System.Timers.Timer();
    timScheduledTask.Interval = 60 * 1000; //1분마다 실행
    timScheduledTask.Enabled = true;

    timScheduledTask.Elapsed += new System.Timers.ElapsedEventHandler(timScheduledTask_Elapsed);
}

Timer를 쓰는 것이 Thread를 이용한 방법보다 더 깔끔하고 단순해 보입니다. 하지만, 실제로는 Web Application에서 Timer는 불안정하게 동작합니다. Shared Hosting환경에서는 20-30분 가량 후에 Timer의 동작이 멈추게 됩니다. 왜냐하면 Hosting Provider가 주기적으로 사용되는 자원을 줄이고 기존 Web Application을 재사용하려고 시도하기 때문입니다.

Cache Expiration을 트리거로 활용한 예약된 작업실행

ASP.NET의 Cache Expiration을 활용하는 방법입니다. Cache되는 내용은 별로 중요하지 않으며, 단지 Cache가 일정한 시간 후 만료될 때 수행되는 Event를 활용하는 방법입니다.

protected void Application_Start()
{
    setScheduleTask();
}

static void setScheduleTask()
{
    HttpRuntime.Cache.Add(
        "ScheduledTask",
        1, //Cache할 값
        null, Cache.NoAbsoluteExpiration,
        TimeSpan.FromHours(1), //1시간 후 실행
        CacheItemPriority.NotRemovable,
        new CacheItemRemovedCallback(doScheduledTask));
}
static void doScheduledTask(string key, Object value, CacheItemRemovedReason reason)
{
    //작업코드 작성..

    //캐쉬 재실행
    setScheduleTask();
}

고려사항

순수 ASP.NET을 통한 예약된 작업실행은 단순함에 있어 장점이 있지만, 다음과 같은 고려사항이 있을 수 있습니다.

  • ASP.NET은 기본적으로 NETWORK SERVICE 또는 ASPNET 계정을 통해서 동작하기 때문에, 특정 작업수행에 제한이 있을 수 있습니다.
  • ASP.NET은 다양한 예측할 수 없는 이유로 재시작하거나 멈추거나, 특정 코드 수행도중 중단되거나, 실행이 지연될 수 도 있습니다. 예를 들어, 사이트 방문자가 없을 경우 IIS는 Web Application을 중단시킬 수 있습니다. 또한 서버 관리자, 운영자가 Web Application을 재시작하거나 중단시킬 수도 있습니다. IIS의 특정 기능은 Web Site를 주기적으로 재시작시키기도 합니다.

    요구되는 신뢰성, 무결성, 원자성(All or nothing) 수준에 따라 사용의 고려가 필요합니다.
  • 부하가 있거나 불안정한 작업은 Web Application에 영향을 미치기 때문에 피해야 합니다.
  • Shared Hosting 등 분산 호스팅 환경에 대한 고려가 필요합니다. 분산된 환경에서 중복 실행되어도 괜찮은 작업입니까?