2009-11-03 12 views
9

Po latach rozwoju ASP.NET jestem całkiem zaskoczony, że nie mogę znaleźć satysfakcjonującego rozwiązania.Zachowaj responsywność witryny ASP.NET IIS, gdy czas między wizytami jest długi.

Dlaczego witryna internetowa ASP.NET IIS zawsze wydaje się zasypiać (przez 2-6 sekund) po określonym czasie bezczynności (po kilku godzinach), podczas którego żadna odpowiedź HTTP nie jest wysyłana z serwera do klienta. Dzieje się tak na każdym typie witryny, jednej stronie lub wielu, db, czy też nie, bez względu na ustawienia. Jak mogę to naprawić?

Podczas czasu oczekiwania serwer nie jest zajęty i nie występują żadne niedobory pamięci wysokiej lub (.NET). Domyślam się, że ma to związek z tym, że system Windows przenosi proces IIS do tła i jego pamięci do pliku strony, ale nie jestem pewien. Ktoś ma jakiś pomysł?

EDYCJA: jednym rozwiązaniem jest wysłanie żądania HTTP raz na godzinę, ale mam nadzieję na coś bardziej konstruktywnego.
EDYCJA: Chodziło mi o to, że po kilku godzinach bezczynności, wstrzymuje się na kilka sekund na każde nowe żądanie HTTP.

+0

+1, ale należy do serverfault. –

+0

Czy kompilujesz swoją stronę? Jeśli nie, tracisz bardzo duże ulepszenia wydajności. – codethrift

+0

@theminesgreg: strony są kompilowane, debugowanie nie jest ustawione, optymalizacje są włączone dla (dowolnych) bibliotek dll. @John: Nie jestem pewien, czy to należy do serverfault, ponieważ to naprawdę sprawia mi kłopot jako programisty, ale popraw mnie, jeśli się mylę. – Abel

Odpowiedz

5

Domyślny limit czasu dla IIS to 20 minut. Oznacza to, że jeśli aplikacja ASP.NET nie otrzyma żadnych nowych żądań przez 20 minut, zamknie proces roboczy. To może zająć dużo czasu, aby ogrzać się proces z niczego - Loading zespoły do ​​pamięci, prekompilacji itd

(Edit: I ułożyła prosty klasy pomocnika, który rozwiązuje problem standardowego limitu czasu - w zasadzie aplikacja internetowa "wyłapuje" się tak często, aby utrzymać proces przy życiu Idealne podejście polega na zmianie ustawień w IIS, ale w przypadku serwerów, gdzie nie jest to możliwe, moja klasa działa całkiem dobrze - Kod u dołu)

Podczas procesu roboczego wciąż żyje, nie powinien być depriorytized. Z pewnością nie tak szybko, jak opisujesz. Możliwe jest, że możesz polegać na przedmiotach, które są buforowane przez bardzo krótki okres czasu i wypadają, gdy nie są żądane przez więcej niż kilka sekund. Nie wiedząc więcej o szczegółach aplikacji, nie można tego powiedzieć.

Profilowanie aplikacji jest jak zwykle jedynym sposobem na uzyskanie konkretnych informacji. Używanie produktu takiego jak ANTS pomoże ci określić, gdzie w kodzie aplikacja spędza najwięcej czasu, abyś mógł zlokalizować miejsce "zawieszenia".

public class KeepAlive 
{ 
    private static KeepAlive instance; 
    private static object sync = new object(); 
    private string _applicationUrl; 
    private string _cacheKey; 

    private KeepAlive(string applicationUrl) 
    { 
     _applicationUrl = applicationUrl; 
     _cacheKey = Guid.NewGuid().ToString(); 
     instance = this; 
    } 

    public static bool IsKeepingAlive 
    { 
     get 
     { 
      lock (sync) 
      { 
       return instance != null; 
      } 
     } 
    } 

    public static void Start(string applicationUrl) 
    { 
     if(IsKeepingAlive) 
     { 
      return; 
     } 
     lock (sync) 
     { 
      instance = new KeepAlive(applicationUrl); 
      instance.Insert(); 
     } 
    } 

    public static void Stop() 
    { 
     lock (sync) 
     { 
      HttpRuntime.Cache.Remove(instance._cacheKey); 
      instance = null; 
     } 
    } 

    private void Callback(string key, object value, CacheItemRemovedReason reason) 
    { 
     if (reason == CacheItemRemovedReason.Expired) 
     { 
      FetchApplicationUr(); 
      Insert(); 
     } 
    } 

    private void Insert() 
    { 
     HttpRuntime.Cache.Add(_cacheKey, 
      this, 
      null, 
      Cache.NoAbsoluteExpiration, 
      new TimeSpan(0, 10, 0), 
      CacheItemPriority.Normal, 
      this.Callback); 
    } 

    private void FetchApplicationUrl() 
    { 
     try 
     { 
      HttpWebRequest request = HttpWebRequest.Create(this._applicationUrl) as HttpWebRequest; 
      using(HttpWebResponse response = request.GetResponse() as HttpWebResponse) 
      { 
       HttpStatusCode status = response.StatusCode; 
       //log status 
      } 
     } 
     catch (Exception ex) 
     { 
      //log exception 
     } 
    } 
} 

Usage (być może w App_Start):

KeepAlive.Start("http://www.yoursite.com/"); 
+0

Wskazujesz na interesujące myśli. Zawsze zakładałem, że nigdy nie dotarł do 'Application_Start', ale co mogę wiedzieć, może się tam dostaję, ładuje biblioteki itp., A następnie wznawia. Należy pamiętać, że czas ten nie wynosi 20 minut (czas oczekiwania na sesję), dławi się na chwilę po około 3 godzinach, ale nie jestem pewien. Czas może być zmienny. To nie tylko "witryna", to "wszystkie witryny" na wielu systemach i wersjach IIS/Windows. Wszystkie są .NET 3.5 jednak. – Abel

+0

Włącz * "ale co ja wiem" * >>> miał na myśli: powinienem się zalogować, lub włączyć śledzenie lub cokolwiek innego. Znam ANTS, ale nie jestem pewien, czy może to pomóc: blokowanie wydaje się zdarzyć, zanim wszystko zostanie załadowane, co obejmuje ANTS. – Abel

+0

Po prostu zauważyłem ten sam komentarz tutaj http://www.eggheadcafe.com/software/aspnet/30548981/slow-site-startup.aspx, który wspomina ten bezczynny limit czasu. Nie dzieje się to lokalnie, tylko zdalnie w konfiguracjach, którymi nie zawsze zarządzam. Nie powinno zająć dużo czasu, aby dowiedzieć się, czy to wszystko w tym ustawieniu. – Abel

1

Jeśli używasz IIS 7 nie jest wywołanie aplikacji IIS wtyczki Warm Up z zespołu IIS, które pomogą utrzymać wszystko toasty

Napisałem numer blog post o moich doświadczeniach z nim korzystających.

+1

Interesująca wtyczka. Ponadto limit czasu 20 min można ustawić w puli aplikacji. Ustawiłem to na 24 godziny na większości serwerów, co pomaga (PS: twoja strona nie odpowiada ...) – Abel

+0

Zabawne - zakładam, że blog odbudowywał haha ​​- jak ironicznie – Doug

0

Jeśli obecnie kompilujesz tylko swój kod, możesz również chcieć sprawdzić, czy kompiluje pliki aspx w czasie kompilacji (zamiast w środowisku wykonawczym, które jest domyślne). Wierzę, że ta kompilacja w locie zajmuje większość czasu, gdy uaktywnia się uśpiona strona ASP.NET. Możesz przeczytać więcej na ten temat here.

Aktualizacja:

Pula aplikacji ginie, gdy zostanie osiągnięta wartość czas_bezczynnosci-OUT - domyślnie 20 minut (można zmienić tę wartość). Czy jesteś pewien, że interfejs użytkownika nie zostanie ponownie skompilowany po ponownym uruchomieniu aplikacji? (Nie jestem pewien, czy zmusza to do ponownej kompilacji interfejsu użytkownika).

+0

O ile twoje zdanie jest poprawne, kompilowanie stron dzieje się tylko raz , nawet jeśli nie wybierzesz prekompilacji (którą wolę, jeśli mam coś do powiedzenia w projekcie). Kwestia wymieniona w pytaniu jest spowodowana po 20 minutach bezczynności i może zostać uznana za "tryb uśpienia" puli aplikacji. Sprawdź swoje dzienniki, jeśli masz małą lokalną stronę internetową: kiedy pierwsi klienci przyjeżdżają o 4 rano, zobaczysz długi czas oczekiwania na pierwsze prośby. – Abel

+0

Jakiej wersji usług IIS używasz? i Czy masz uprawnienia administratora do IIS? – UpTheCreek

Powiązane problemy