스레드를 사용하여 IIS에서 장기 실행 작업을 수행 할 수 있습니까?


85

ASP.Net 응용 프로그램에서 사용자는 웹 페이지의 단추를 클릭 한 다음 이벤트 처리기를 통해 서버의 개체를 인스턴스화하고 개체에 대한 메서드를 호출합니다. 이 방법은 작업을 수행하기 위해 외부 시스템으로 이동하며 시간이 걸릴 수 있습니다. 그래서 제가하고 싶은 것은 다른 스레드에서 해당 메서드 호출을 실행하여 "요청이 제출되었습니다"를 사용하여 사용자에게 제어를 반환 할 수 있도록하는 것입니다. 사용자가 상태를 위해 객체를 계속 폴링 할 수 있다면 더 좋을 것이지만, 나는 이것을 실행하고 잊어 버리는 것으로 합리적으로 행복합니다.

내가 모르는 것은 사용자 세션이 만료 되더라도 IIS에서 내 스레드가 계속 실행되도록 허용하는지 여부입니다. 사용자가 이벤트를 실행하고 서버에서 개체를 인스턴스화하고 새 스레드에서 메서드를 실행한다고 상상해보십시오. 사용자는 "요청이 제출되었습니다"메시지에 만족하고 브라우저를 닫습니다. 결국이 사용자 세션은 IIS에서 시간 초과되지만 스레드는 여전히 실행 중일 수 있습니다. IIS는 스레드가 계속 실행되도록 허용합니까 아니면 스레드를 죽이고 사용자 세션이 만료되면 개체를 폐기합니까?

편집 : 답변과 의견을 통해이 작업을 수행하는 가장 좋은 방법은 장기 실행 처리를 IIS 외부로 이동하는 것임을 이해합니다. 다른 모든 것 외에도 이것은 appdomain 재활용 문제를 다룹니다. 실제로는 제한된 시간 내에 버전 1을 시작해야하고 기존 프레임 워크 내에서 작업해야하므로 서비스 계층을 피하고 싶기 때문에 IIS 내부에서 스레드를 시작하고 싶습니다. 실제로 여기서 "장기 실행"은 몇 분 밖에 걸리지 않으며 웹 사이트의 동시성이 낮아서 괜찮을 것입니다. 그러나 다음 버전은 확실히 별도의 서비스 계층으로 분할해야합니다.


1
처리해야 할 사항과 호스팅 환경에 대한 자세한 내용이 있습니까? 예를 들어 서비스를 설치할 수 있습니까?
senfo

항상 Async 및 Await 프로그래밍 방법 (Visual Studio 2012+)을 사용할 수 있습니다 . 스레드를 직접 관리하는 것보다 훨씬 깨끗합니다.
SausageFingers

답변:


65

원하는 것을 달성 할 수 있지만 일반적으로 나쁜 생각입니다. 여러 ASP.NET 블로그 및 CMS 엔진은 공유 호스팅 시스템에 설치할 수 있고 설치해야하는 Windows 서비스에 종속되지 않기를 원하기 때문에이 접근 방식을 사용합니다. 일반적으로 앱이 시작될 때 Global.asax에서 장기 실행 스레드를 시작하고 해당 스레드 프로세스가 작업을 대기열에 추가합니다.

요청을 처리하기 위해 IIS / ASP.NET에서 사용할 수있는 리소스를 줄이는 것 외에도 AppDomain이 재활용 될 때 스레드가 종료되는 문제가 발생하므로 작업이 진행중인 동안 작업의 지속성을 처리해야합니다. AppDomain이 백업되면 작업 백업을 시작합니다.

대부분의 경우 AppDomain은 web.config 등을 업데이트하는 경우뿐만 아니라 기본 간격으로 자동으로 재활용됩니다.

언제든지 종료되는 스레드의 지속성 및 트랜잭션 측면을 처리 할 수있는 경우 사이트에서 일정 간격으로 요청을 수행하는 외부 프로세스를 사용하여 AppDomain 재활용을 피할 수 있습니다. 따라서 사이트가 재활용되는 경우 X 분 내에 자동으로 다시 시작되도록 보장합니다.

다시 말하지만 이것은 일반적으로 나쁜 생각입니다.

편집 : 다음은이 기술의 몇 가지 예입니다.

커뮤니티 서버 : Windows 서비스와 백그라운드 스레드를 사용하여 예약 된 간격으로 코드 실행 웹 사이트가 처음 시작될 때 백그라운드 스레드 생성

편집 (먼 미래에서)-요즘 나는 Hangfire를 사용할 입니다.


1
감사합니다, 이것은 통찰력이 있습니다. 재활용은 확실한 킬러이며, 나는 당신이 내가 말하는 무엇 걸릴 수 있습니다 빠른 하드 앤 것은으로이 작업을 수행하지만 위험한입니다.
Frans

: 네, 여기이 확인 professionalaspnet.com/archive/2007/09/02/...을 그리고 여기에 지역 사회에 서버가 같은 일을 처리하는 방법에 대한 스레드 : dev.communityserver.com/forums/t/459942.aspx
브라이언 BATCHELDER

제 경우에는 IIS에게 절대 재활용하지 않고 사이트를 유휴 상태로 유지하지 않도록 지시 할 수있었습니다. 이를 통해 제가이 가정하에 작업 할 수 있었고 배포하는 동안과 계획된 유지 관리가 발생할 때마다 사이트가 재활용 될 수있었습니다. 내가 관리자 유형 사이트를하고 있었기 때문에 이것은 나에게 완벽하게 작동했습니다.
Brett

1
이것이 너무 많은 찬성표를 가지고 있다는 것이 이상합니다. 이것이 가능하다는 것은 ASP.NET의 매우 멋진 점 중 하나입니다. 모든 요청이 생성 할 수있는 모든 백그라운드 스레드와 함께 동일한 AppDomain에서 제공된다는 것입니다. 이것이 "나쁜 생각"인 주어진 이유 중 어느 것도 나를 설득력있게 생각하지 않습니다. 예, AppDomains는 다운 될 수 있지만 ASP.NET 환경에 고유 한 것은 아닙니다. 호스팅 환경을 잘 활용해야합니다 (Google for HostingEnvironment.RegisterObject).
John

3
.NET 4.5.2에는 QueueBackgroundWorkItem백그라운드 작업을 쉽게 등록 할 수 있는 새로운 기능이 추가되었으므로 답변을 다시 업데이트 할 수 있습니다.
Scott Chamberlain

39

나는 받아 들여진 대답에 동의하지 않는다.

Task.Factory.StartNewASP.NET 에서는 백그라운드 스레드 (또는로 시작되는 작업 )를 사용하는 것이 좋습니다. 모든 호스팅 환경과 마찬가지로 종료를 관리하는 시설을 이해하고 협력 할 수 있습니다.

ASP.NET에서는이 HostingEnvironment.RegisterObject메서드를 사용하여 종료시 정상적으로 중지하는 데 필요한 작업을 등록 할 수 있습니다 . 이 기사 와 토론에 대한 의견을 참조하십시오 .

(Gerard가 그의 의견에서 지적했듯이, 작업 할 배경 항목에 대한 스케줄러를 등록 HostingEnvironment.QueueBackgroundWorkItem하라는 요청 도 있습니다 RegisterObject. 전체적으로 새 메서드는 작업 기반이므로 더 좋습니다.)

나쁜 생각이라고 자주 듣는 일반적인 테마에 대해서는 Windows 서비스 (또는 다른 종류의 추가 프로세스 응용 프로그램)를 배포하는 대안을 고려하십시오.

  • 웹 배포로 더 이상 사소한 배포가 필요하지 않습니다.
  • 순수하게 Azure 웹 사이트에 배포 할 수 없음
  • 백그라운드 작업의 특성에 따라 프로세스가 통신해야 할 수 있습니다. 이는 일종의 IPC 또는 서비스가 공통 데이터베이스에 액세스해야 함을 의미합니다.

일부 고급 시나리오에서는 요청과 동일한 주소 공간에서 실행되는 백그라운드 스레드가 필요할 수도 있습니다. 나는 ASP.NET이 이것을 할 수 있다는 사실이 .NET을 통해 가능해진 큰 장점이라고 생각합니다.


이것은 훌륭합니다. 완료하는 데 30 초 정도 걸리는 작업이 있습니다. 작업을 완료 할 수 있도록 앱 풀을 충분히 지연해야하는 경우에 적합합니다.
Scuba Steve

1
닷넷 프레임 워크에서 4.5.2 당신은 또한 사용할 수 있습니다 HostingEnvironment.QueueBackgroundWorkItem (액션 <CancellationToken>)
제라드 카보

내 관찰에 따르면 IIS는 결국 실행중인 ASP.NET Web API를 종료하고 새 요청이 들어올 때까지 다시 시작하지 않는 것 같습니다. 따라서 내 스레드가 응용 프로그램을 시작해야하는 지정된 시간에 실행조차하지 않습니다. 내가 틀렸나 요?
David Sopko 19-12-12

7

이 작업에 IIS 스레드 풀의 스레드를 사용하면 해당 스레드가 향후 요청을 처리 할 수 ​​없게되므로 사용하지 않을 것입니다. ASP.NET 2.0에서 비동기 페이지를 살펴볼 수는 있지만 그 역시 정답이 아닙니다. 대신 Microsoft Message Queuing을 살펴 보는 것이 좋습니다. 기본적으로 작업 세부 정보를 대기열에 추가하고 다른 백그라운드 프로세스 (Windows 서비스)가 해당 작업을 수행합니다. 그러나 결론은 백그라운드 프로세스가 IIS와 완전히 분리되어 있다는 것입니다.


아, MSMQ-제가 오랫동안 좋아하는 기술 중 하나입니다. 통찰력과 링크에 감사드립니다.
Frans

6

이러한 요구 사항에 HangFire 를 사용하는 것이 좋습니다 . 멋진 화재 및 잊어 버림 엔진은 백그라운드에서 실행되며 지속성 저장소로 뒷받침되기 때문에 안정적인 다른 아키텍처를 지원합니다.


5

여기에 좋은 스레드와 샘플 코드가 있습니다. http://forums.asp.net/t/1534903.aspx?PageIndex=2

앱 풀을 유지하는 데 도움이되도록 스레드에서 내 웹 사이트의 연결 유지 페이지를 호출하는 아이디어도 가지고 있습니다. 이 방법을 사용하는 경우 응용 프로그램이 언제든지 재활용 될 수 있으므로 정말 좋은 복구 처리가 필요합니다. 많은 사람들이 언급했듯이 이것은 다른 서비스 옵션에 대한 액세스 권한이있는 경우 올바른 접근 방식이 아니지만 공유 호스팅의 경우 유일한 옵션 중 하나 일 수 있습니다.

앱 풀을 활성 상태로 유지하기 위해 스레드가 처리되는 동안 자신의 사이트에 요청할 수 있습니다. 이렇게하면 프로세스가 오래 실행되는 경우 앱 풀을 활성 상태로 유지하는 데 도움이 될 수 있습니다.

string tempStr = GetUrlPageSource("http://www.mysite.com/keepalive.aspx");


    public static string GetUrlPageSource(string url)
    {
        string returnString = "";

        try
        {
            Uri uri = new Uri(url);
            if (uri.Scheme == Uri.UriSchemeHttp)
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
                CookieContainer cookieJar = new CookieContainer();

                req.CookieContainer = cookieJar;

                //set the request timeout to 60 seconds
                req.Timeout = 60000;
                req.UserAgent = "MyAgent";

                //we do not want to request a persistent connection
                req.KeepAlive = false;

                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                Stream stream = resp.GetResponseStream();
                StreamReader sr = new StreamReader(stream);

                returnString = sr.ReadToEnd();

                sr.Close();
                stream.Close();
                resp.Close();
            }
        }
        catch
        {
            returnString = "";
        }

        return returnString;
    }

5

우리는이 경로를 시작했고, 앱이 하나의 서버에있을 때 실제로 정상적으로 작동했습니다. 여러 머신으로 확장 (또는 웹 가렌에서 여러 w3wp 사용)하고 싶을 때 작업 대기열 관리 방법, 오류 처리, 재시도 및 올바른 잠금의 까다로운 문제를 재평가하고 살펴 봐야했습니다. 서버는 다음 항목을 선택합니다.

... 우리는 백그라운드 처리 엔진을 작성하는 사업에 종사하지 않는다는 것을 깨달았으므로 기존 솔루션을 찾고 멋진 OSS 프로젝트 행 파이어를 사용하여 시작 했습니다.

Sergey Odinokov는 시작하기가 정말 쉬운 진짜 보석을 만들었으며 작업이 지속되고 대기하는 방식의 백엔드를 교체 할 수 있습니다. Hangfire는 백그라운드 스레드를 사용하지만 작업을 지속하고 재 시도를 처리하며 작업 대기열에 대한 가시성을 제공합니다. 따라서 행 파이어 작업은 강력하고 재활용되는 앱 도메인의 모든 변덕에서 살아남습니다.

기본 설정은 SQL 서버를 저장소로 사용하지만 확장 할 때 Redis 또는 MSMQ로 교체 할 수 있습니다. 또한 모든 작업과 해당 상태를 시각화하고 작업을 다시 대기열에 넣을 수있는 뛰어난 UI가 있습니다.

내 요점은 백그라운드 스레드에서 원하는 것을 수행하는 것이 완전히 가능하지만 확장 가능하고 견고하게 만들기위한 많은 작업이 있다는 것입니다. 단순한 워크로드에는 좋지만 상황이 더 복잡해지면 이러한 노력을 거치지 않고 목적에 맞게 구축 된 라이브러리를 사용하는 것을 선호합니다.

사용 가능한 옵션에 대한 자세한 내용 은 asp.net에서 백그라운드 작업을 처리하는 몇 가지 옵션을 다루는 Scott Hanselman의 블로그 를 확인하십시오 . (그는 hangfire에 빛나는 리뷰를주었습니다)

또한 John이 언급 한대로 접근 방식이 문제가되는 이유와 appdomain이 언로드 될 때 스레드에서 작업을 정상적으로 중지하는 방법에 대한 Phil Haack의 블로그 를 읽을 가치가 있습니다.


2

이 작업을 수행하는 Windows 서비스를 만들 수 있습니까? 그런 다음 웹 서버에서 .NET 원격을 사용하여 Windows 서비스를 호출하여 작업을 수행합니까? 그럴 경우 내가 할 일입니다.

이렇게하면 IIS에서 릴레이 할 필요가없고 처리 능력의 일부가 제한됩니다.

그렇지 않다면 프로세스가 완료되는 동안 사용자가 거기에 앉도록 강요합니다. 이렇게하면 완료되고 IIS에 의해 종료되지 않습니다.


2

IIS에서 장기 실행 작업을 호스팅하는 지원되는 방법이있는 것 같습니다. 워크 플로 서비스 는 특히 Windows Server AppFabric 과 함께이를 위해 설계된 것 같습니다 . 이 디자인은 장기 실행 작업의 자동 지속 및 재개를 지원하여 응용 프로그램 풀 재활용을 허용합니다.


2

백그라운드에서 작업을 실행할 수 있으며 요청이 끝난 후에도 완료됩니다. 잡히지 않은 예외를 던지지 마십시오 . 일반적으로 항상 예외를 던지기를 원합니다. 새 스레드에서 예외가 발생 하면 더 이상 요청 컨텍스트에 있지 않기 때문에 IIS 작업자 프로세스 (w3wp.exe) 가 중단 됩니다. 또한 프로세스 내 메모리 지원 세션을 사용하는 경우 실행중인 다른 백그라운드 작업도 종료됩니다. 이것은 진단하기 어려울 것이므로 연습이 권장되지 않습니다.


1

비동기 작업을 실행하는 대리 프로세스를 생성하기 만하면됩니다. Windows 서비스 일 필요는 없습니다 (대부분의 경우 더 최적의 접근 방식 임에도 불구하고 MSMQ는 완전히 종료됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.