Czy Mogę używać wątków do wykonywania długotrwałych zadań w IIS?

In an ASP.Net aplikacja, użytkownik klika przycisk na stronie internetowej i to następnie tworzy instancję obiektu na serwerze za pomocą obsługi zdarzeń i wywołuje metodę na obiekcie. Metoda przechodzi do zewnętrznego systemu, aby zrobić coś, a to może chwilę potrwać. Chciałbym więc uruchomić wywołanie tej metody w innym wątku, aby móc zwrócić kontrolę użytkownikowi Z "Your request has been submitted". Jestem w miarę szczęśliwy, że mogę to zrobić jako fire-and-forget, choć byłoby jeszcze ładniej jeśli użytkownik może nadal sprawdzać status obiektu.

Nie wiem, czy IIS pozwala mojemu wątkowi działać, nawet jeśli sesja użytkownika wygaśnie. Wyobraź sobie, że użytkownik wywołuje zdarzenie, a my tworzymy instancję obiektu na serwerze i uruchamiamy metodę w nowym wątku. Użytkownik jest zadowolony z komunikatu "twoje żądanie zostało złożone" i zamyka przeglądarkę. W końcu ta sesja użytkowników skończy się na IIS, ale wątek może nadal działać, wykonując pracę. Czy IIS zezwala na wątek aby nadal działać, czy zabije go i pozbędzie się obiektu po wygaśnięciu sesji użytkownika?

EDIT: z odpowiedzi i komentarzy rozumiem, że najlepszym sposobem na to jest przeniesienie długotrwałego przetwarzania poza IIS. Oprócz wszystkiego innego dotyczy to problemu recyklingu appdomain. W praktyce, muszę uzyskać wersję 1 od ziemi w ograniczonym czasie I musi pracować wewnątrz istniejącego frameworka, więc chciałbym uniknąć warstwy usług, stąd chęć po prostu odpal wątek wewnątrz IIS. W praktyce "długie działanie" tutaj zajmie tylko kilka minut, a współbieżność na stronie będzie niska, więc powinno być ok. Ale następna wersja zdecydowanie będzie wymagała podziału na oddzielną warstwę usług.

Author: John Saunders, 2009-02-11

10 answers

Możesz osiągnąć to, co chcesz, ale zazwyczaj jest to zły pomysł. Kilka ASP.NET silniki blog i CMS przyjmują takie podejście, ponieważ chcą być instalowane na współdzielonym systemie hostingowym, a nie uzależniać się od usługi windows, która musi być zainstalowana. Zazwyczaj rozpoczynają długi wątek w Global.asax po uruchomieniu aplikacji, i że proces wątku kolejkowane zadania.

Oprócz zmniejszenia zasobów dostępnych dla IIS/ASP.NET do przetwarzania żądań, można również masz problemy z wątku jest zabity, gdy AppDomain jest recykling, a następnie trzeba radzić sobie z trwałością zadania, gdy jest w locie, a także rozpoczęcie pracy z powrotem, gdy AppDomain wraca.

Należy pamiętać, że w wielu przypadkach AppDomain jest automatycznie przetwarzany w domyślnym interwale, a także w przypadku aktualizacji sieci.config, itp.

Jeśli poradzisz sobie z trwałością i Transakcyjnymi aspektami zabicia wątku w dowolnym momencie, możesz obejdź Recykling AppDomain poprzez zewnętrzny proces, który sprawia, że żądanie na twojej stronie w pewnym odstępie czasu - tak, że jeśli strona zostanie poddana recyklingowi, masz gwarancję, że ponownie uruchomi się automatycznie w ciągu X minut.

Ponownie, to jest zazwyczaj zły pomysł.

EDIT: Oto kilka przykładów tej techniki w działaniu:

Serwer społecznościowy: Korzystanie z usług Windows a wątek w tle do uruchamiania kodu w zaplanowanych odstępach czasu Tworzenie Wątek W Tle, Gdy Strona Zaczyna Się Po Raz Pierwszy

EDIT (z dalekiej przyszłości) - w dzisiejszych czasach użyłbym Hangfire.

 59
Author: Bryan Batchelder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 10:25:38

Nie zgadzam się z przyjętą odpowiedzią.

Używanie wątku tła (lub zadania, rozpoczynającego się od Task.Factory.StartNew) jest w porządku w ASP.NET. podobnie jak w przypadku wszystkich środowisk hostingowych, możesz chcieć zrozumieć i współpracować z obiektami regulującymi wyłączenie.

W ASP.NET, można zarejestrować pracę, która musi zostać zatrzymana przy zamykaniu za pomocą metody HostingEnvironment.RegisterObject. Zobacz Ten artykuł i komentarze do dyskusji.

Jeśli chodzi o ogólny temat, który często słyszycie, że jest to zły pomysł, rozważmy alternatywę wdrożenia usługi windows (lub innego rodzaju aplikacji pozaprocesowej):

  • koniec z banalnymi wdrożeniami z Web deploy
  • Nie można go wdrażać wyłącznie w witrynach Azure]}
  • w zależności od charakteru zadania w tle, procesy prawdopodobnie będą musiały się komunikować. Oznacza to, że albo jakaś forma IPC, albo usługa będzie musiała uzyskać dostęp do wspólnej bazy danych.

Zauważ również, że niektóre zaawansowane scenariusze mogą nawet wymagać wątek w tle, który ma być uruchomiony w tej samej przestrzeni adresowej co żądania. Widzę, że ASP.NET może to zrobić jako wielką zaletę, która stała się możliwa poprzez .NET.

 24
Author: John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-02 17:22:37

Nie chcesz używać wątku z puli wątków IIS do tego zadania, ponieważ nie będzie on w stanie przetworzyć przyszłych żądań. Można zajrzeć do asynchronicznych stron w ASP.NET 2.0 , ale to też nie byłaby właściwa odpowiedź. Zamiast tego, wygląda na to, że możesz skorzystać, patrząc na kolejkowanie wiadomości Microsoft . Zasadniczo dodałbyś szczegóły zadania do kolejki, a inny proces w tle (prawdopodobnie usługa Windows) być odpowiedzialny za wykonanie tego zadania. Ale najważniejsze jest to, że proces tła jest całkowicie odizolowany od usług IIS.

 7
Author: senfo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-11 16:58:17

Jest tu dobry wątek i przykładowy kod: http://forums.asp.net/t/1534903.aspx?PageIndex=2

Pobawiłem się nawet pomysłem wywołania strony keep alive na mojej stronie z wątku, aby pomóc utrzymać pulę aplikacji przy życiu. Pamiętaj, jeśli używasz tej metody, że potrzebujesz naprawdę dobrej obsługi odzyskiwania, ponieważ aplikacja może poddać recyklingowi w dowolnym momencie. Jak wielu już wspomniało, nie jest to właściwe podejście, jeśli masz dostęp do innych opcji usług, ale dla współdzielonych hosting może być jedną z Twoich jedynych opcji.

Aby pomóc utrzymać pulę aplikacji przy życiu, możesz złożyć wniosek do własnej witryny podczas przetwarzania wątku. Może to pomóc utrzymać pulę aplikacji przy życiu, jeśli proces działa przez długi czas.

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
Author: Daniel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 20:05:12

Zaczęliśmy tą ścieżką i faktycznie działało ok, gdy nasza aplikacja była na jednym serwerze. Gdy chcieliśmy skalować się do wielu maszyn (lub użyć wielu w3wp w sieci garen) musieliśmy ponownie ocenić i przyjrzeć się, jak zarządzać kolejką roboczą, obsługą błędów, ponownymi próbami i trudnym problemem prawidłowego blokowania, aby upewnić się, że tylko jeden serwer odbiera następny element.

... zdaliśmy sobie sprawę, że nie zajmujemy się pisaniem silników przetwarzania w tle, więc szukaliśmy istniejących rozwiązań i wylądował przy użyciu awesome oss project hangfire

Sergey Odinokov stworzył prawdziwy klejnot, który jest naprawdę łatwy do rozpoczęcia i pozwala na wymianę zaplecza, w jaki sposób praca jest utrzymywana i ustawiana w kolejce. Hangfire używa wątków tła, ale utrzymuje zadania, obsługuje ponowienia i zapewnia wgląd w kolejkę zadań. Tak więc zadania hangfire są solidne i przetrwają wszystkie kaprysy appdomains poddawane recyklingowi itp.

Jego podstawowa konfiguracja wykorzystuje sql server jako pamięć masową ale możesz zamienić się na Redis lub MSMQ, gdy jego czas na skalowanie. Ma również doskonały interfejs do wizualizacji wszystkich zadań i ich statusu, a także pozwala na ponowne kolejkowanie zadań.

Chodzi mi o to, że chociaż jest całkowicie możliwe, aby zrobić to, co chcesz w tle wątku, istnieje wiele pracy, aby to skalowalne i solidne. Jest w porządku dla prostych obciążeń, ale gdy sprawy stają się bardziej złożone, wolę użyć specjalnie zbudowanej biblioteki, niż przejść przez ten wysiłek.

Dla niektórych więcej informacji na temat dostępnych opcji znajdziesz w blogu Scotta Hanselmana , który obejmuje kilka opcji obsługi zadań w tle asp.net (dał hangfire świecącą recenzję)

Jak wspomina John warto przeczytać blog Phila Haacka na temat tego, dlaczego podejście jest problematyczne i jak z wdziękiem zatrzymać pracę nad wątkiem, gdy appdomain jest rozładowany.

 4
Author: Avner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-06 03:11:51

Proponuję użyć HangFire do takich wymagań. Its a nice fire and forget engine działa w tle, obsługuje inną architekturę, niezawodny, ponieważ jest wspierany przez pamięć trwałą.

 4
Author: Vipul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-04 12:40:16

Czy można utworzyć usługę windows do tego zadania? Następnie użyj. NET remoting z serwera www, aby wywołać usługę Windows, aby wykonać akcję? W takim razie tak bym zrobił.

Wyeliminowałoby to konieczność przekazywania danych na IIS i ograniczyłoby część jego mocy obliczeniowej.

Jeśli nie, to zmusiłbym użytkownika do siedzenia tam, podczas gdy proces jest zakończony. W ten sposób zapewnisz, że zostanie ukończona i nie zostanie zabita przez IIS.

 2
Author: David Basarab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-11 21:57:18

Wydaje się, że istnieje jeden obsługiwany sposób hostowania długotrwałej pracy w IIS. Usługi Workflow wydają się być zaprojektowane do tego celu, zwłaszcza w połączeniu z Windows Server AppFabric . Konstrukcja pozwala na recykling puli aplikacji poprzez wsparcie automatycznego utrzymywania się i wznawiania długotrwałej pracy.

 2
Author: Olly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-05 15:19:18

Możesz uruchamiać zadania w tle i będą one wykonywane nawet po zakończeniu żądania. nie pozwól, aby wyrzucono nieobciążony wyjątek . Zwykle chcesz zawsze rzucać wyjątki. Jeśli wyjątek zostanie wrzucony do nowego wątku, spowoduje to awarię IIS worker process - w3wp.exe , ponieważ nie jesteś już w kontekście żądania. To również zabije wszelkie inne zadania w tle, które masz uruchomione oprócz sesji z pamięcią w procesie, jeśli używasz oni. Byłoby to trudne do zdiagnozowania, dlatego praktyka jest zniechęcana.

 2
Author: Timothy Gonzalez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 03:21:52

Po prostu utwórz proces zastępczy, aby uruchomić zadania asynchroniczne; nie musi to być usługa windows (chociaż w większości przypadków jest to bardziej optymalne podejście. MSMQ jest ponad zabijaniem.

 1
Author: Matt Davison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-13 13:21:55