Zaktualizuj witrynę .NET bez ponownego ładowania

13

Kiedyś rozwijać stron internetowych w PHPi ASP classica jeśli coś trzeba było zmienić. Możesz po prostu zmienić jeden / kilka plików i nikt tak naprawdę tego nie zauważy. Być może ktoś poprosi o zmianę pliku podczas przesyłania, ale to około pół sekundy marginesu. W przypadku większości mniejszych witryn nie stanowi to problemu.

Ale najnowsze witryny są kompilowane C# MVCi kiedy wprowadzasz zmiany w kodzie, musisz odbudować swoją stronę i przesłać zmienione DLLpliki. Ale kiedy zmienisz DLLpliki, uruchomi ponownie witrynę i zresetuje wszystkie aktywne sessions. Musi także ponownie załadować wszystko, a w przypadku dużych witryn ładowanie wszystkiego może potrwać kilka minut. Wszyscy, którzy przeglądali witrynę, zauważą i muszą się ponownie zalogować.

Główne aktualizacje witryny nie są tak częste, więc nie stanowi to problemu. Ale mamy regularne „małe” aktualizacje promocji. Jak „Wypełnij ten formularz i uzyskaj trzy miesiące bezpłatnego członkostwa” lub „Pierwsze 10, aby załadować obraz ... otrzyma cenę”. Myślę, że dostaniesz dryf. Niektóre promocje są podobne i mogą być obsługiwane za pomocą modułu, który wyświetla odpowiednie informacje na podstawie ustawień, ale dość często wymaga niestandardowego kodu.

Myślałem o systemie, w którym każda promocja jest własnym DLLplikiem opartym na interfejsie, a następnie DLLdynamicznie ładuję za pomocą Type.GetType, Activator.CreateInstancei InvokeMember. Chociaż to może zadziałać, zastanawiam się, czy to właściwa droga.

Więc moje pytanie: jak aktualizować .NETwitrynę w locie, bez ponownego ładowania całej witryny i porzucania sesji (np. Recyklingu puli aplikacji).

Hugo Delsing
źródło
W odpowiedzi na Twój komentarz z nagrodami: duże witryny, nad którymi pracuję, obsługują małe zmiany w kodzie w taki sam sposób, jak obsługują duże zmiany w kodzie: poprzez równoważenia obciążenia i sesje poza procesem - ponieważ cały kod wdrożony na żywo musi przejść przez proces recenzji / wylogowania i nie możemy po prostu upuścić kodu na serwerach.
Wydaje

Odpowiedzi:

11

Zajrzyj do „Inicjalizacji aplikacji” IIS 7.5, Windows 2008 R2 (trudniejsze do skonfigurowania) IIS 8, Windows 2012

Inicjalizacja aplikacji pozwala na ponowne uruchomienie dowolnej aplikacji (puli aplikacji poza witryną) i używanie starej, wciąż działającej poprzedniej aplikacji podczas rozgrzewania nowej aplikacji. Po uruchomieniu nowej aplikacji (określonej przez adresy URL, które można ustawić) zacznie ona używać nowej aplikacji i zamknie poprzednią. Korzystanie z inicjalizacji aplikacji w połączeniu z metodami zapewniającymi pozostanie sesji w restartach puli aplikacji może umożliwić bezproblemowe ponowne uruchomienie witryny. (Zhaph ma dobrą notatkę na temat klucza maszynowego.)

Oprócz powyższych łączy do konfiguracji inicjowania aplikacji, będziesz chciał sprawdzić, co powoduje ponowne uruchomienie witryny - ponieważ ponowne uruchomienie witryny nie korzysta z inicjalizacji aplikacji, ponowne uruchomienie witryny nie będzie płynne.

Możesz skonfigurować IIS, aby aktualizacja DLL nie wyzwalała natychmiastowego restartu witryny ani nie zmieniała pliku web.config (wysokie wartości ChangeNotification w httpRuntime i zewnętrznych plikach konfiguracyjnych, odpowiednio do twojej witryny).

Ostatecznym rezultatem jest to, że możesz zaktualizować biblioteki DLL / kod bez restartu witryny, a następnie wymusić restart aplikacji , który użyje rozgrzania tła AppInitialization do płynnej zmiany kodu.

Wykonanie tych rzeczy na koncercie działa całkiem dobrze, aby zapewnić bezproblemowe ponowne uruchomienie.

jeffreypriebe
źródło
Dobry zestaw kroków - na pewno coś do rozważenia :)
Zhaph - Ben Duguid
Brzmi jak to, czego szukałem. Zamierzam spróbować i skonfigurować. Dzięki
Hugo Delsing,
@ HugoDelsing Mam nadzieję, że działa świetnie dla Ciebie.
jeffreypriebe
Dziękuję, tego właśnie użyłem i działa świetnie.
Hugo Delsing
@ HugoDelsing Cieszę się, że to również zadziałało.
jeffreypriebe
5

Istnieje wiele sposobów radzenia sobie z tym, o co prosisz, oraz kilka różnych aspektów pytania:

Obsługuj małe aktualizacje promocji

To, czego naprawdę tu szukasz, to system zarządzania treścią lub podobny, który pozwala edytować zawartość w locie (pomyśl Wordpress / Drupal lub z punktu widzenia .NET N2 CMS, Umbraco, Orchard itp.), Jednak tam są pewne rzeczy, które możesz wypróbować, jeśli nie wybrałeś tej trasy.

Ponieważ ASP.NET naprawdę ładuje się ponownie tylko po dotknięciu niektórych typów plików (web.config (s), głównie zawartości /bin/i /app_code/folderów) - i ma konfigurowalny limit dla „innych zmian plików” (w zasadzie po modyfikacji wiele plików w Twojej witrynie pula aplikacji uruchomi się ponownie - NumRecompilesBeforeAppRestart) możesz popatrzeć na coś, w którym sprawdzasz inny folder dla niektórych statycznych (tj. .html) plików, które pobierasz i wyświetlasz w razie potrzeby, lub wykorzystujesz LoadControlmetodę, która przyjmuje .ascxkontrola użytkownika i dynamicznie ładuje go - jak określić, które na wystawie to inna kwestia bardziej nadaje się do StackOverflow - jednak polecam rozwiązanie oparte konwencji nazewnictwa.

Możesz również rozważyć użycie czegoś takiego jak Managed Extensibility Framework (MEF - który jest pełną częścią frameworku .NET od wersji 4), który pozwala napisać architekturę opartą na wtyczkach i określić folder poza /bin/katalogiem do monitorowania nowe .DLLs - chociaż nie próbowałem tego, aby sprawdzić, czy pozwoli to uniknąć problemu z ponownym uruchomieniem aplikacji, wykorzystałem to z dobrym skutkiem w środowisku internetowym, aby dodać wspólną funkcjonalność do witryny.

Jeśli to nie przemawia, jedyną inną opcją, o której mogę pomyśleć, byłoby dodanie formantów jako „kodu z przodu”, tak jak to zrobiliśmy w klasycznej ASP - tj. Z <script runat="server">blokiem zamiast skompilowanej klasy „za kodem” że zawiera logikę do uruchomienia sterowania - to usunie potrzebę zmiany DLL, kosztem pewnego raz pierwszy utraty wydajności, kontrola jest kompilowany w locie - znowu trzeba zrównoważyć to z NumRecompilesBeforeAppRestartgdyby ciebie wprowadzam wiele drobnych zmian.

Jak utrwalić sesje po ponownym uruchomieniu aplikacji?

Jest to prawdopodobnie łatwiejszy problem do rozwiązania i obejmuje trzy kluczowe kroki:

  1. Skonfiguruj Klucz MachineKey (IIS7, ale nadal ma wartość 8), aby był stałą wartością AutoGenerate- oznacza to, że gdy AppPool zostanie zregenerowany, użyje tego samego klucza, dzięki czemu będzie mógł odszyfrować pliki cookie sesji, stan wyświetlania itp. recykling.
  2. Każda konfiguracja państwo Server lub konfiguracji bazy danych do przechowywania stanu sesji .
  3. Przełącz się z używania InProcna StateServerlub SQLServerw elemencie SessionState w pliku web.config.

W ten sposób będziesz mieć trwałe sesje, które przetrwają restart aplikacji. Nie są to jednak „darmowe” - wszystko, co przechowujesz w sesji, musi być teraz możliwe do serializacji, a ty poniesiesz niewielki spadek wydajności, ponieważ każde ładowanie strony będzie wymagać dodatkowych podróży w sieci, aby uzyskać i potencjalnie zwolnić dane sesji.

Jeśli jednak jesteś w sytuacji, w której uruchomienie aplikacji trwa po „kilku minutach”, możesz rozważyć przejście na środowisko z równoważeniem obciążenia lub przynajmniej konfigurację przejściową / na żywo z możliwością wymiany podczas pracy (takich jak te dostarczone przez Azure / AWS / itp.) - w ten sposób możesz przełączyć serwer w tryb offline podczas jego aktualizacji lub przygotować go z nowym kodem, a następnie zamienić go - pod warunkiem, że wykonałeś kroki w celu rozwiązania problemu udostępnionego sesje (patrz wyżej) będzie to działać dobrze, bez wpływu na użytkowników.

Zhaph - Ben Duguid
źródło
Dziękuję za twoją długą odpowiedź. Niestety CMSnie to, czego chcę. Nie chcę zmieniać treści, chcę zmieniać kod. Część dotycząca sesji była tylko przykładem. Zmiana nie rozwiąże problemu, że witryna nie działa przez minutę lub dwie podczas ponownego ładowania DLLplików. Ta MEFczęść była interesująca, ale jest to rozwiązanie dla systemu, o którym myślałem. Więc +1 za wysiłek, ale niestety tak naprawdę nie jest to odpowiedź na moje pytanie.
Hugo Delsing,
1
Zaktualizowałem swoją odpowiedź, aby rozwiązać kilka z tych kwestii: MEF został wydany przez MS i jest pełną częścią frameworka .NET od wersji 4. Możesz spróbować użyć kodu z przodu dla nowych elementów sterujących, alternatywnie zastosuj konfigurację z równoważeniem obciążenia / przemieszczania na żywo, która umożliwiłaby uruchomienie i uruchomienie serwera, a następnie zamianę.
Zhaph - Ben Duguid
1
Przedstawiłem alternatywne rozwiązanie przy użyciu inicjalizacji aplikacji. Korzyścią jest to, że cała konfiguracja kodu i serwera jest „normalna” bez specjalnego równoważenia obciążenia lub dynamicznego ładowania kontroli, dzięki czemu środowisko pracy jest prostsze. Oczywiście konfiguracja równoważenia obciążenia / przemieszczania na żywo może być przydatna z innych powodów.
jeffreypriebe