R14-T, Informatyka, ASP.NET


Rozdział 14.
Wykorzystanie ulepszonych mechanizmów obsługi pamięci podręcznej ASP.NET

W poprzednich rozdziałach tej części książki przedstawione zostały różne metody dostępu do danych. Rozdziały 8., 9., 10. oraz 12. były poświęcone wykorzystaniu baz danych, rozdział 11. językowi XML, a 13. — wykorzystaniu plików. Także w tym rozdziale będziemy kontynuowali omawianie zagadnień związanych z dostępem do danych, a konkretnie — opiszę co można zrobić z informacjami gdy zostaną już pobrane.

Przechowywanie danych w pamięci podręcznej (ang. caching) jest techniką powszechnie wykorzystywaną w przetwarzaniu komputerowym, służącą do poprawy efektywności działania poprzez przechowywanie najczęściej wykorzystywanych informacji w pamięci. ASP.NET udostępnia wiele różnych mechanizmów służących do przechowywania danych w pamięci podręcznej. W tym rozdziale omówione zostaną następujące zagadnienia:

Czym jest przechowywanie informacji w pamięci podręcznej?

Przechowywanie danych w pamięci podręcznej jest stosowanym przez komputery sposobem szybkiego przypominania sobie informacji. Dane wykorzystywane bardzo często (a nawet nieco rzadziej), są zapisywane w miejscu, z którego komputer może je pobrać znacznie szybciej niż z oryginalnego miejsca ich przechowywania. Pamięć podręczna działa jak „kieszeń na informacje”, do której komputer ma łatwy i szybki dostęp. Korzyści jakie daje stosowanie pamięci podręcznej zostały przedstawione na rysunku 14.1.

Rysunek 14.1. Pamięć podręczna to miejsce przechowywania informacji, do którego komputer ma łatwy dostęp.

Opis rysunku

1. … — 1. Pobranie informacji z oryginalnego miejsca ich przechowywania (witryny WWW)

2. … — 2. Zapisanie informacji w miejscu do którego można łatwo uzyskać dostęp (na przykład, na dysku twardym)

3. … — 3. Wykorzystanie informacji w aplikacji

Cache — Pamięć podręczna

Browser — Przeglądarka

Każdy kto kiedykolwiek używał przeglądarki WWW powinien znać już ideę przechowywania danych w pamięci podręcznej. W momencie wyświetlania strony, przeglądarka zapisuje ją bowiem (wraz ze wszelkimi, używanymi na niej rysunkami) w specjalnym miejscu na dysku twardym. Fakt ten, jest ważny dla użytkownika z dwóch powodów. Po pierwsze, przy kolejnej wizycie na tej samej stronie przeglądarka nie będzie już musiała pobierać jej (oraz użytych na niej obrazków) z witryny, lecz z lokalnego dysku. A po drugie, dzięki temu możliwe jest przeglądnięcie strony bez konieczności ponownego jej odwiedzania na Internecie. Przykład ten przedstawia dwa najważniejsze zagadnienia związane z przechowywaniem informacji w pamięci podręcznej — szybkość dostępu do informacji oraz możliwość dostępu do nich gdy w normalnych okolicznościach nie było by to możliwe.

Nowe określenie

Rozważania te skłaniają do zadania interesującego pytania: Co się dzieje gdy informacje przechowywane w pamięci podręcznej stają się zbyt stare? Co się stanie w przypadku gdy serwer WWW zastąpi stronę lub rysunek jego nowszą wersją? Ponieważ pamięć podręczna jest pierwszym miejscem w którym komputer będzie szukał informacji, oznacza to że pobrana zostanie stara wersja pliku. W takim przypadku zawartość pamięci podręcznej musi zostać zaktualizowana — okres jej przydatności upłynął.

Jak ASP.NET wykorzystuje pamięć podręczną

ASP.NET dysponuje wieloma, wbudowanymi mechanizmami obsługi pamięci podręcznej. Przechowywanie informacji w pamięci podręcznej jest bardzo ważne dla aplikacji internetowych, gdyż szybkość przesyłu danych przez Internet może być bardzo mała. Przechowując dane, ASP.NET daje aplikacjom pisanym w tej technologii, niezwykle potrzebną możliwość poprawienia efektywności działania. ASP.NET daje także programistom możliwość modyfikowania ustawień działania pamięci podręcznej.

Należy zwrócić uwagę, iż w ASP.NET dane zapisywane w pamięci podręcznej mogą być przechowywane w dwóch, ogólnie pojętych miejscach — po stronie klienta bądź na serwerze. Przechowywanie danych w pamięci podręcznej realizowane przez przeglądarkę WWW odbywa się po stronie klienta — w tym przypadku wszystkie informacje są przechowywane na komputerze użytkownika, a cały proces jest inicjowany i zarządzany przez przeglądarkę. Z drugiej strony, przechowywanie danych w pamięci podręcznej na serwerze jest obsługiwane przez serwer WWW i wykorzystuje jego zasoby; w tym przypadku przeglądarka nie ma żadnej kontroli nad zapamiętywanymi informacjami.

W tym rozdziale zajmiemy się właśnie przechowywaniem danych w pamięci podręcznej na serwerze. Przekonasz się, iż rozwiązanie to jest znacznie bardziej elastyczne i ma więcej zalet niż zapamiętywanie danych w przeglądarce. Różnice pomiędzy obiema metodami zostały przedstawione na rysunku 14.2.

Rysunek 14.2. Różnice pomiędzy przechowywaniem informacji w pamięci podręcznej po stronie klienta oraz na serwerze

Opis rysunku

Client-side caching — Przechowywanie informacji w pamięci podręcznej po stronie klienta

Server — Serwer

Client — Klient

Step 1 Retrieve…— Etap 1. Pobranie danych z serwera

Step 2 Cache to hard…— Etap 2. Zapisanie danych na dysku twardym

Step 3 Retrieve… — Etap 3. Pobranie danych z dysku twardego przy obsłudze kolejnych żądań

Server-side caching — Przechowywanie informacji w pamięci podręcznej na serwerze

Server — Serwer

Client — Klient

ASP.NET Engine — Mechanizm ASP.NET

Step 1 … — Etap 1. Przesłanie danych przez ASP.NET

Step 2 … — Etap 2. Zapisanie danych w pamięci podręcznej

Step 3 … — Etap 3. Przesłanie danych z pamięci podręcznej przy obsłudze kolejnych żądań.

Czytając ten rozdział przekonasz się również, że możliwości przechowywania informacji w pamięci podręcznej nie ograniczają się wyłącznie do stron WWW i obrazów, lecz obejmują dane wielu różnych typów.

Przechowywanie stron w pamięci podręcznej

W momencie obsługi żądań kierowanych do stron ASP.NET, strony te są kompilowane. Jeśli kiedykolwiek tworzyłeś aplikacje w dowolnym języku programowania wymagającym kompilacji kodu źródłowego, to doskonale wiesz, iż proces kompilacji zajmuje nieco czasu i mocy obliczeniowej komputera. Gdyby strona ASP.NET musiała być kompilowana za każdym razem gdy zostanie odebrane skierowane do niej żądanie, to efektywność działania aplikacji ASP.NET byłaby niezwykle niska.

Na szczęście, gdy strony ASP.NET zostaną skompilowane, są one przechowywane w pamięci podręcznej na serwerze. To właśnie te skompilowane strony są wykorzystywane przy obsłudze nadsyłanych żądań. Użytkownik zaobserwuje zmniejszenie efektywności działania wynikające z konieczności kompilacji strony wyłącznie w momencie obsługi pierwszego skierowanego do niej żądania; wszystkie kolejne żądania dotyczące tej samej strony będą obsługiwane znacznie szybciej.

Maszyna wirtualna CLR przegląda kod źródłowy stron ASP.NET w poszukiwaniu wszelkich zmian. Jeśli zawartość oryginalnego pliku .aspx zostanie zmodyfikowana, fakt ten zostanie odkryty, a ASP.NET unieważni kod przechowywany w pamięci podręcznej i zapisze w niej jego nową wersję.

A zatem, ASP.NET poprawia efektywność działania aplikacji przechowując w pamięci podręcznej skompilowane strony, dzięki czemu nie trzeba ich kompilować przy obsłudze wszystkich żądań.

Przechowywanie ustawień konfiguracyjnych

Jeśli czytając tę książkę tworzyłeś jednocześnie przykładowe aplikacje ASP.NET, mogłeś zauważyć jeszcze jeden czynnik spowalniający ich działanie. Otóż podczas pierwszego uruchamiania aplikacji — czyli podczas obsługi pierwszego żądania skierowanego do którejkolwiek ze stron przechowywanych w katalogu wirtualnym — ASP.NET musi pobrać wszystkie ustawienia konfiguracyjne podane w pliku web.config (więcej informacji na ten temat znajdziesz w rozdziale 18., pt.: „Konfiguracja i wdrażanie aplikacji ASP.NET”. W zależności od stopnia złożoności aplikacji, czynność ta może zająć nieco czasu.

Przyjrzyjmy się systemowemu plikowi web.config (zazwyczaj jest on zapisany w folderze C:\WinNT\Microsoft.NET\Framework\wersja\config.web). Jak widać plik ten może być całkiem złożony. Zazwyczaj pliki te mają ponad 450 wierszy długości! Wszystkie te ustawienia konfiguracyjne są zapamiętywane w pamięci podręcznej w chwili uruchamiania aplikacji, dzięki czemu ASP.NET może znacznie szybciej wykorzystywać informacje konfiguracyjne podczas obsługi stron wchodzących w skład aplikacji, niż w przypadku gdyby informacje te nie były zapamiętywane.

Zapisywanie w pamięci podręcznej wyników i danych

Zapamiętywanie w pamięci podręcznej wyników jest procesem polegającym na zapisaniu zawartości wygenerowanej przez dynamiczne strony ASP.NET; na przykład, może to dotyczyć obliczonych wartości a nawet elementów sterujących DataGrid. Zapamiętywanie wyników nie jest wykonywane automatycznie, lecz można je łatwo zrealizować. Informacje na ten temat znajdziesz w dalszej części rozdziału, w podrozdziale pt.: „Jak korzystać z pamięci podręcznej”.

Notatka
Nie należy mylić przechowywania danych w pamięci podręcznej z buforowaniem. Bufory są wykorzystywane do tymczasowego przechowywania wyników do momentu zakończenia przetwarzania. W odpowiednim momencie bufory są opróżniane. Pamięć podręczna wykorzystywana jest w celu przechowania informacji na dłuższy okres czasu, tak aby można ich było powtórnie użyć. Obie te metody mogą się mylić początkującym programistom.

Zapisywanie danych w pamięci podręcznej umożliwia zapamiętywanie informacji dowolnych typów, poczynając od rekordów baz danych, a kończąc na elementach sterujących tworzonych przez użytkowników. Rozwiązanie to przypomina nieco zapisywanie wyników w pamięci podręcznej, jednak jego możliwości nie ograniczają się wyłącznie do zapamiętywania samych wyników wygenerowanych przez stronę ASP.NET. Ta metoda wykorzystania pamięci podręcznej nie jest używana automatycznie, a zatem tylko od programisty zależy co zostanie zapamiętane.

Jak korzystać z pamięci podręcznej

ASP.NET umożliwia kontrolowanie sposobów przechowywania w pamięci podręcznej zarówno wyników jak i danych. Dzięki temu istnieje możliwość dostosowania sposobów działania pamięci podręcznej do potrzeb konkretnej aplikacji. Każda z tych metod udostępnia nieco inne mechanizmy wykorzystania pamięci podręcznej, a zatem niezwykle ważnym zagadnieniem jest poznanie ich wszystkich.

W trzech kolejnych podrozdziałach opisane zostaną trzy różne metody przechowywania danych w pamięci podręcznej udostępniane przez ASP.NET. Każda z nich ma swoje zalety i wady. Na szczęście jednak, ich wykorzystanie nie przysparza najmniejszych problemów. Zatem już wkrótce będziesz mógł w pełni korzystać z możliwości pamięci podręcznej!

Zapamiętywanie wyników wykonania stron ASP.NET

Włączenie zapisywania wyników wykonania stron ASP.NET w pamięci podręcznej jest bardzo proste — sprowadza się ono do wykorzystania dyrektywy OutoutCache:

<%@ OutputCache Duration="czasSkładowania" Location="miejsceSkładowania" %>

Umieszczenie tej dyrektywy w kodzie strony ASP.NET spowoduje, że wygenerowane przez nią wyniki zostaną zapisane w pamięci podręcznej, w miejscu określony przy użyciu parametru miejsceSkładowania i pozostaną tam przez okres czasu określony przy użyciu parametru czasSkładowania (i wyrażony w sekundach). Parametrowi Location można przypisać jedną z wartości przedstawionych w tabeli 14.1. (Należy pamiętać, iż jest to parametr opcjonalny).

Tabela 14.1. Wartości parametru Location

Wartość

Opis

Any

Pamięć podręczna wyników może być umieszczona w każdym z dostępnych miejsc. To domyślna wartość tego parametru.

Client

Pamięć podręczna wyników będzie umieszczona na komputerze użytkownika.

Downstream

Pamięć podręczna będzie umieszczona na serwerze znajdującym się „poniżej” serwera który obsługuje żądania (czyli pomiędzy nim a komputerem użytkownika). Wartość ta jest stosowana w przypadku korzystania z serwerów pośredniczących.

None

Wyników tej strony nie należy przechowywać w pamięci podręcznej.

Server

Pamięć podręczna będzie umieszczona na serwerze obsługującym żądania.

Gdy przechowywanie wyników w pamięci podręcznej jest włączone, to wszystkie generowane informacje są zapisywane nie w pamięci, lecz na dysku twardym komputera określonego za pomocą parametru Location. Ma to ogromny wpływ na efektywność. Oznacza to również, że przechowywanie wyników daje niemal nieograniczone możliwości, gdyż nie wykorzystuje żadnych cennych zasobów.

Przeanalizujmy teraz konkretny przykład. Strona przedstawiona na listingu 14.1 wyświetla prostą wiadomość powitalną oraz aktualny czas.

Listing 14.1. Wykorzystanie przechowywania wyników w pamięci podręcznej

Analiza

Powyższy przykład przypomina zwyczajną stronę ASP.NET z dodatkową dyrektywą OutputCache. Dyrektywa ta powoduje, że wyniki wykonania strony zostaną zapisane w pamięci podręcznej i przechowane przez 30 sekund. Po upłynięciu tego okresu czasu zawartość pamięci podręcznej zostanie unieważniona, a kolejne żądanie spowoduje ponowne wykonanie strony i zapamiętanie wygenerowanych przez nią wyników. Wyniki wykonania powyższej strony zostały przedstawione na rysunku 14.3.

0x01 graphic

--> Rysunek 14.3.[Author:p8R] Wyniki zapamiętania w pamięci podręcznej informacji o aktualnym czasie

Zwróć uwagę na informacje o czasie wyświetlone na wynikowej stronie. Po kliknięciu przycisku Odśwież w przeglądarce, informacje te nie ulegną zmianie. Dziej się tak dlatego, iż strona jest pobierana z pamięci podręcznej na serwerze, a jej kod nie jest wykonywany. Wyniki przechowywane w pamięci podręcznej zostaną unieważnione po 30 sekundach, dlatego też, jeśli ponowne odwiedzenie strony po upłynięciu 30 sekund spowoduje wyświetlenie bieżącego czasu.

Mechanizmy przechowywania wyników w pamięci podręcznej są jednak znacznie potężniejsze niż można by przypuszczać na podstawie tego prostego przykładu. Na przykład, pamięć podręczna może porównać łańcuch zapytania dodany do adresu strony i na tej podstawie określić co należy zapamiętać. Zmodyfikujmy nieco naszą przykładową stronę, aby zademonstrować ten efekt.

Listing 14.2. Zapamiętywanie łańcucha zapytania

Analiza

W wierszu 6. listingu 14.2 została dodana metoda umożliwiająca pobranie wartości parametru id. W tym przykładzie został także wydłużony czas przechowywania wyników w pamięci podręcznej, dzięki czemu będziemy mieli więcej czasu na wypróbowanie działania przykładu, zanim zawartość pamięci zostanie unieważniona. Zapisz powyższy kod w pliku o nazwie listing1402.aspx i wyświetl ją w przeglądarce podając swoje imię w łańcuchu zapytania (na przykład: http://localhost//rozdzial13/listing1402.aspx?id=Chris). Teraz we wiadomości powitalnej powinno się pojawić podane imię. Należy także zwrócić uwagę na informacje o czasie — nawet po kliknięciu przycisku Odśwież nie ulegną one zmianie.

A teraz zmodyfikujmy nieco adres URL — listing1402.aspx?id=Zenek. W przeglądarce zostanie wyświetlona strona zawierająca nową wiadomość powitalną i bardziej aktualny czas. Odśwież tę stronę kilka razy, aby upewnić się, że jest ona przechowywana w pamięci podręcznej.

A teraz ponownie wpisz początkowy adres URL — listing1402.aspx?id=Chris. W przeglądarce pojawi się strona z oryginalną wiadomością powitalną i oryginalnym czasem! Na szczęście nie podróżujesz wstecz w czasie, lecz zażądałeś strony, która już jest przechowywana w pamięci podręcznej. Na rysunku 14.4 przedstawiłem wyniki uzyskane po wykonaniu opisanych wcześniej trzech żądań dotyczących tej samej strony.

0x01 graphic

Rysunek 14.4. ASP.NET odczytuje parametry łańcucha zapytania aby określić sposób przechowywania stron w pamięci podręcznej

Nowe określenie

ASP.NET odczytuje parametry przekazywane w łańcuchu zapytania, aby określić czy żądana strona znajduje się już w pamięci podręcznej. Jeśli łańcuch zapytania uległ zmianie, to ASP.NET rejestruje brak trafienia, co oznacza, że strony nie odnaleziono w pamięci. W tym przypadku ASP.NET ponownie wykonuje kod strony i zapamiętuje wygenerowane przez nią wyniki. (Należy zauważyć, iż brak trafienia zachodzi także w przypadku gdy upłynie termin ważności wyników przechowywanych w pamięci podręcznej, co sprawi, że strona zostanie ponownie wykonana.)

Notatka
Oznacza to, że żądania zawierające dwa parametry o tych samych wartościach lecz zapisane w innej kolejności spowodują zapisanie w pamięci podręcznej dwóch różnych stron: Na przykład:

strona.aspx?imie=XX&nazwisko=YY

Zażądanie wyświetlenia strony o poniższym adresie spowoduje dodanie jej wyników do pamięci podręcznej:

strona.aspx?nazwisko=YY&imie=XX

Sposób działania tego mechanizmu można kontrolować dodając do dyrektywy OutputCache nowe parametry — VaryByParam, VaryByHeader oraz VaryByCustom. Jako wartości tych parametrów można podać listę zmiennych, których należy użyć przy rozróżnianiu wyników przechowywanych w pamięci podręcznej; przy czym poszczególne elementy tej listy są od siebie oddzielane przecinkami. Na przykład, poniższa dyrektywa informuje ASP.NET że wyniki stron należy uważać za różne, tylko jeśli zmieni się wartość parametru imie:

<%@ OutputCache Duration="600" VaryByParam="imie" %>

Dodaj powyższą dyrektywę do przykładu przedstawionego na listingu 14.2 i wyświetl tę stronę w przeglądarce posługując się następującym adresem URL: http://localhost/rozdzial14/listing1402.aspx?imie=Chris&nazwisko=Payne. Zwróć uwagę na czas wyświetlony na stronie.

A teraz zmień adres URL zapisując go w następującej postaci: listing1402.aspx?imie=Chris&nazwisko=Saravia i odśwież stronę wyświetlaną w przeglądarce. Zauważ, że czas wyświetlony na stronie się nie zmienił, gdyż strona z łańcuchem zapytania zawierającym parametr imie o wartości Chris, jest już zapisana w pamięci podręcznej. W tym przypadku wartości parametru nazwisko są ignorowane. Można dodać ten parametr do dyrektywy OutpuCache, tak aby strona była zapamiętywana w pamięci podręcznej na podstawie wartości obu parametrów:

<%@ OutputCache Duration="600" VaryByParam="imie,nazwisko" %>

Należy wiedzieć, że jeśli parametr VaryByParam zostanie pominięty, to domyślne działanie dyrektywy będzie polegało na zapamiętywaniu stron na podstawie wszystkich parametrów przekazywanych w łańcuchu zapytania. Parametr VaryByParam zostanie bardziej szczegółowo opisany w podrozdziale „Mechanizmy uzależniania pamięci podręcznej od innych informacji”. Parametr VaryByHeader działa podobnie jak VaryByParam, lecz zapisuje strony w pamięci podręcznej na podstawie wartości nagłówków HTTP a nie parametrów przekazywanych w łańcuchu zapytania. Ponieważ nie omawiałem zagadnień związanych z określaniem wartości nagłówków HTTP nie będę także opisywał parametru VaryByHeader. W końcu ostatni z parametrów dyrektywy OutputCacheVaryByCustom — pozwala na zapisywanie stron w pamięci podręcznej na podstawie innych czynników niż parametry łańcucha zapytania oraz nagłówki HTTP — na przykład, na podstawie nazwy bądź numeru wersji przeglądarki.

Na przykład, możliwości te mogą się przydać na witrynie sprzedającej bilety na koncerty. W pierwszej kolejności użytkownik wybiera województwo w jakim koncert się odbędzie oraz cenę jaką jest skłonny zapłacić za bilet. Informacje te zostają zapisane w łańcuchu zapytania. Kolejna strona pobiera z bazy danych i wyświetla listę wszystkich zaplanowanych koncertów, posortowaną według daty koncertu i zapisuje ją w pamięci podręcznej. Strona ta powinna być zapisywana w pamięci podręcznej wyłącznie na podstawie wybranego województwa. Informacje wyświetlane na tej stronie nie mają bowiem żadnego związku z kwotą jaką użytkownik jest skłonny zapłacić za bilet. Umieszczając w dyrektywie OutputCache jedynie parametr VaryByParam="wojewodztwo" i pomijając parametr zapytania kwota, można ograniczyć ilość stron przechowywanych w pamięci podręcznej oraz ilość wykorzystywanych zasobów.

Elementy sterujące użytkownika

W pamięci podręcznej można także zapisywać elementy sterujące użytkowników. Na przykład, jeśli chcemy zapamiętać tylko wybrany fragment strony, na przykład element sterujący DataGrid, można umieścić go w elemencie sterującym użytkownika i, w dyrektywie OutpuCache, określić opcje umożliwiające zapisanie go w pamięci podręcznej. Rozwiązanie to nazywane jest zapisywaniem w pamięci podręcznej fragmentów stron (ang.: fragment caching).

Możliwość ta jest niezwykle przydatna w tych wszystkich sytuacjach gdy w pamięci podręcznej należy zapisywać tylko wybrane fragmenty stron. Na przykład, załóżmy, że stworzyliśmy prosty element sterujący wyświetlający dwa pola tekstowe, służące do podania nazwy użytkownika oraz hasła. Element ten nie musi być generowany przy obsłudze wszystkich żądań, gdyż nigdy się nie zmienia. Dlatego też można go zapisać w pamięci podręcznej. Jednak strona używająca elementu sterującego użytkownika może zawierać jakieś ważne informacje, takie jak czas, bądź dane wygenerowane specjalnie dala danego użytkownika. W takim przypadku zapamiętanie w pamięci podręcznej całej strony nie jest dobrym rozwiązaniem, gdyż w przeglądarce użytkownika byłyby wyświetlane nieaktualne informacje. A zatem w pamięci podręcznej powinny się znaleźć wyłącznie elementy, które nie ulegają zmianie; takie jak elementy sterujące użytkownika.

Ponieważ mechanizm zapisu fragmentów stron w pamięci podręcznej jest jedynie bardziej zaawansowaną formą zapamiętywania wyników, więc wszystkie zapamiętywane informacje są przechowywane na dysku. Rozwiązanie to wymaga użycia bardzo niewielu zasobów serwera. Na listingu 14.03 przedstawiona została definicja bardzo prostego elementu sterującego użytkownika (więcej informacji na temat ich tworzenia znajdziesz w rozdziale 6., pt.: „Ciąg dalszy wiadomości na temat tworzenia formularzy internetowych”).

Listing 14.03. Element sterujący użytkownika przechowywany w pamięci podręcznej (control.ascx)

Analiza

Przedstawiony powyżej element sterujący wyświetla jedynie etykietę prezentującą godzinę o której element został wykonany po raz ostatni. Należy zwrócić uwagę, iż dyrektywa OutpuCache umieszczona w wierszu 2. określa, że element będzie przechowywany w pamięci podręcznej przez 30 sekund. Zapisz kod tego elementu sterującego w pliku o nazwie control.ascx. Na listingu 14.4. została przedstawiona strona ASP.NET wykorzystująca element sterujący control.ascx.

Listing 14.4. Wykorzystanie elementu sterującego użytkownika.

Analiza

Także ta strona ASP.NET jest bardzo prosta. W wierszu 2. jest rejestrowany element sterujący użytkownika. Procedura Page_Load prezentuje godzinę, o której strona została wykonana. Element sterujący użytkownika został wykorzystany w wierszu 13. Należy zwrócić uwagę, iż w kodzie tej strony nie została umieszczona dyrektywa OutputCache — wykorzystaliśmy ją jedynie w elemencie sterującym z listingu 14.3.

Gdy wyświetlimy tę stronę w przeglądarce, wyświetlone czasy dostępu do elementu sterującego oraz do samej strony powinny być takie same. Jednak po odświeżeniu strony pojawią się różnice w wyświetlonych na niej godzinach. Element sterujący jest przechowywany w pamięci podręcznej, a zatem zostanie wyświetlona jest poprzednia wersja. Z drugiej strony, sama strona nie jest przechowywana w pamięci podręcznej, co oznacza, że czas dostępu do niej będzie aktualizowany. Te różnice zostały zaprezentowane na rysunku 14.5.

0x01 graphic

Rysunek 14.5. Praktyczne wykorzystanie selektywnego zapisywania informacji w pamięci podręcznej

Ostrzeżenie
Ponieważ element sterujący użytkownika jest przechowywany w pamięci podręcznej, zatem wszelkie próby programowego zmodyfikowania go na stronie ASP.NET mogą spowodować wystąpienie błędów. Błędy mogą się pojawić, na przykład, po przypisaniu elementowi sterującemu nowego identyfikatora (
id) lub zmianie którejś z jego właściwości. Element jest przechowywany w pamięci podręcznej, a zatem jego kod nie jest przetwarzany w trakcie obsługi żądań i wszelkie próby jego modyfikacji nie dadzą oczekiwanych rezultatów.

Może się wydawać, iż jest to ogromna wada mechanizmów wykorzystania pamięci podręcznej, jednak jeśli będziesz z nich korzystał w odpowiedni sposób, to nigdy nie napotkasz żadnych problemów. W pamięci podręcznej powinny być zapisywane wyłącznie te elementy stron, które nie ulegają zmianie. Zazwyczaj sposób ich wykorzystywania w stronach ASP.NET także nie ulega zmianie. Jeśli okaże się, że będziesz musiał zmienić coś w elemencie sterującym przechowywanym w pamięci podręcznej, to może w ogóle nie powinieneś go zapamiętywać.

Możliwość zapisywania w pamięci podręcznej wybranych fragmentów stron ASP.NET jest niezwykle przydatna. Jednak następnej części rozdziału przekonasz się, że jeszcze bardziej przydatnym narzędziem jest obiekt Cache.

Zapisywanie obiektów w pamięci podręcznej

Obiekty klasy Cache można wykorzystać do programowego dodawania innych obiektów do pamięci podręcznej, co może poprawić efektywność działania aplikacji. Wyobraź sobie proces tworzenia dużego elementu sterującego DataGrid — na pewno zabiera on wiele czasu. Trzeba najpierw nawiązać połączenie ze źródłem danych, pobrać je, a następnie utworzyć i zapisać informacje w samym elemencie DataGrid. Czy nie byłoby wspaniale gdyby istniała możliwość wykonania tego procesu tylko raz i zapisania uzyskanego obiektu DataGrid w pamięci podręcznej? W rzeczywistości jednym z najczęściej wykorzystywanych zastosowań obiektów Cache jest właśnie zapamiętywanie informacji pobieranych z baz danych.

Obiekt klasy Cache jest tworzony w momencie uruchamiania aplikacji. W odróżnieniu od zapamiętywania wyników stron, obiekty umieszczane w obiektach Cache są przechowywane w pamięci komputera. A zatem, w zależności od wielkości obiektów, zapisywanie ich w pamięci podręcznej może doprowadzić do spadku efektywności działania serwera. Z tego powodu obiekty klasy Cache powinny być wykorzystywane rzadziej i z większą rozwagą niż mechanizmy przechowywania wyników w pamięci podręcznej.

Być może zacząłeś się zastanawiać dlaczego, w takim razie, w ogóle używać obiektów Cache. Cóż, mają one trzy podstawowe zalety w porównaniu z mechanizmami zapamiętywania wyników. Po pierwsze, przy ich pomocy można zapisać w pamięci podręcznej dowolny obiekt — nasze możliwości nie ograniczają się do zapisywania całych stron bądź elementów sterujących użytkownika. Dzięki obiektom Cache można bardziej wybiórczo wykorzystywać pamięć podręczną, na przykład zapisywać w niej informacje pobrane z bazy danych lub wybrane elementy sterujące serwera. Po drugie, obiekty klasy Cache powalają na wykorzystania „modyfikowalnego czasu upłynięcia ważności” obiektów przechowywanych w pamięci podręcznej. I w końcu ostatnią zaletą stosowania obiektów Cache jest możliwość określania zależności obiektów przechowywanych w pamięci podręcznej. Oznacza to, iż możesz zażądać, aby informacje przechowywane w pamięci podręcznej były zależne od innego, wybranego elementu. Na przykład, przechowywany w pamięci element sterujący DataGrid może być zależny od umieszczonych w nim informacji. Jeśli źródło danych zostanie zmodyfikowane, zależny od niego element sterujący DataGrid zostanie uznany za nieważny i stworzony ponownie. Więcej informacji na ten temat podam w dalszej części rozdziału, pt.: „Zależności informacji przechowywanych w pamięci podręcznej”.

Listing 14.5 przedstawia przykład strony wykorzystującej obiekty klasy Cache do zapamiętania w pamięci podręcznej informacji pobranych z bazy danych. W momencie pierwszego wyświetlenia tej strony, z bazy danych są pobierane informacje, które następnie zostają skojarzone z elementem sterującym DataGrid. Informacje te zostaną także zapisane w pamięci podręcznej, dzięki czemu podczas obsługi kolejnego żądania będzie można je pobrać bezpośrednio z pamięci. W ten sposób nasza przykładowa storna będzie wykonywana znacznie szybciej.

Listing 14.5. Użycie obiektu Cache do zapisania w pamięci podręcznej informacji pobranych z bazy danych.

Analiza

Procedura Page_Load zdefiniowana w wierszach od 6. do 10. wygląda dosyć standardowo. Najważniejsze czynności są jednak wykonywane w procedurze CreateData zdefiniowanej w wierszach do 12. do 39.

W tym przykładzie w pamięci podręcznej chcemy zapisać obiekt DataView zawierający informacje pobrane z bazy danych, dzięki czemu, przy obsłudze kolejnych żądań, dostęp do nich będzie znacznie łatwiejszy. W tym celu, w wierszu 13. tworzony jest obiekt DataView. W wierszu 15. próbujemy pobrać ten obiekt z pamięci podręcznej (czyli obiektu Cache). Jeśli jednak w pamięci nie ma żadnego obiektu o podanej nazwie (sytuacja taka powinna mieć miejsce podczas pierwszego wywołania strony), to zmiennej source zostanie przypisana wartość nothing.

Wartość zmiennej source jest sprawdzana w warunku zapisanym w wierszu 17. Jeśli jest ona równa nothing (co oznacza, że z pamięci podręcznej nie zostały pobrane żadne informacje), będziemy musieli pobrać odpowiednie informacje z bazy danych. Stosowne czynności są wykonywane przez kod zapisany w wierszach od 18. do 27. — cały ten proces powinieneś już doskonale znać. W wierszu 29. w zmiennej source zapisywany jest nowy obiekt DataView utworzony na podstawie informacji pobranych z bazy; a w wierszu 30. obiekt ten jest zapisywany w pamięci podręcznej. W efekcie, ten konkretny sposób prezentacji pobranych informacji zostaje zapisany w pamięci podręcznej, a to z kolei oznacza, że zapamiętane zostały także pobrane z bazy informacje. W wierszach 32. oraz 34. wyświetlany jest komunikat skąd pochodzą informacje wyświetlone na stronie.

Aby przetestować tę aplikację warto by także mieć możliwość ręcznego wyczyszczenia zawartości pamięci podręcznej. Służy do tego procedura ExpireCache zdefiniowana w wierszach od 41. do 44. Procedura ta zostanie wywołana za każdym razem gdy użytkownik kliknie przycisk zdefiniowany w wierszach 51. i 52. Metoda Remove klasy Cache usuwa z pamięci podręcznej wybrany obiekt. W naszym przypadku usuwany jest obiekt o nazwie „DataView”. Drugą i ostatnią czynnością wykonywaną przez procedurę ExpireCache jest wywołanie procedury CreateData, które spowoduje ponowne pobrania informacji z bazy danych i ich wyświetlenie.

Notatka
Metoda
Remove zwraca obiekt który ma zostać usunięty z pamięci podręcznej. Dzięki temu, w razie konieczności, na obiekcie tym można wykonać jakieś dodatkowe czynności. Na przykład, kod umieszczony w wierszu 42. ostatniego przykładu można by zastąpić następującym:

dim dv as DataView = Cache.Remove("DataView")

Dzięki temu na zwróconym obiekcie tym można wykonać jakieś końcowe czynności, nim ostatecznie zostanie on usunięty z pamięci podręcznej; na przykład, po raz ostatni pobrać z niego dane.

Jeśli w wywołaniu metody Remove zostanie podana nazwa obiektu którego nie ma w pamięci podręcznej, to metoda zwróci wartość nothing.

Po wywołaniu metody Remove i usunięciu z pamięci podręcznej obiektu DataView, należy ponownie pobrać informacje z bazy danych. Oznacza to, że zostanie podjęta próba wykonania kodu umieszczonego wewnątrz instrukcji if z wiersza 17. Na rysunku 14.6 przedstawione zostały wyniki pierwszego wykonania strony z listingu 14.5, natomiast na rysunku 14.7 — wyniki uzyskane po odświeżeniu strony wyświetlonej w przeglądarce.

W przypadku pierwszego wyświetlenia strony, powinien się na niej pojawić komunikat „Informacje pobrane bezpośrednio z bazy danych”. Odświeżenie strony spowoduje, że wyświetlony komunikat zmieni się na: „Informacje pobrane z pamięci podręcznej”. Kliknięcie wyświetlonego na stronie przycisku Wyczyść pamięć podręczną spowoduje ponowne początkowego komunikatu. W zależności od konfiguracji komputera, będzie można zauważyć większą lub mniejszą zmianę w efektywności działania tej strony wynikającą z użycia pamięci podręcznej. Choć w naszym przypadku różnica ta może nie być ogromna, to jednak trzeba sobie wyobrazić co się stanie jeśli tę stronę będą próbowały jednocześnie pobrać dziesiątki tysięcy użytkowników. Korzyści jakie daje przechowywanie danych w pamięci podręcznej rosną wykładniczo wraz ze wzrostem obciążenia witryny.

0x01 graphic

Rysunek 14.6. Informacje przeznaczone do przechowania w pamięci podręcznej pobrane z bazy danych

0x01 graphic

Rysunek 14.7. Podczas obsługi kolejnych żądań skierowanych do tej samej strony informacje są pobierane z pamięci podręcznej

Notatka
Warto zwrócić uwagę, iż kliknięcie przycisku
Odśwież w przeglądarce po kliknięciu przycisku Wyczyść pamięć podręczną spowoduje, że przeglądarka zada pytanie czy należy ponownie przesłać dane z formularza. Kliknięcie przycisku Tak sprawi, iż na serwer ponownie zostaną przesłane informacje o kliknięciu przycisku Wyczyść pamięć podręczną, a to z kolei spowoduje wyczyszczenie pamięci podręcznej. W ten sposób, nieświadomi niczego użytkownicy mogą się zastanawiać dlaczego na stronie wciąż jest wyświetlana informacja o pobraniu danych z bazy danych, a nie z pamięci podręcznej.

Aby odświeżyć stronę po kliknięciu przycisku Wyczyść pamięć podręczną, należy ponownie wpisać jej adres na pasku adresu przeglądarki. Można także umieścić na stronie połączenie wskazujące na nią samą. Kliknięcie takiego połączenia spowoduje odświeżenie strony.

Istnieją trzy różne sposoby zapisywania danych w pamięci podręcznej. Pierwszy z nich został przedstawiony w ostatnim przykładzie. Dwa następne bazują na wykorzystaniu metod Add oraz Insert. Są one bardzo podobne do siebie, choć metoda Insert daje większe możliwości. Poniżej przedstawiłem składnię wywołania metody Add:

Cache.Add(klucz, wartość, zależności, bezwzgDataWygWażnosci, _

zmiennyCzasWygWażności, priorytet, zmniejszeniePriorytetu, _

onRemoveCallBack)

Metoda ta ma wiele argumentów, które poniżej szczegółowo opiszę. Pierwsze dwa z nich — klucz oraz wartość — były wykorzystywane także w poprzednim przykładzie. Klucz to nazwa obiektu, który ma zostać zapisany w pamięci podręcznej, a wartość to ten obiekt. Argument zależności zostanie dokładniej opisany w dalszej części rozdziału. BezwzgDataWygWażności to bezwzględna data określająca kiedy ma upłynąć ważność elementu przechowywanego w pamięci podręcznej, na przykład „June 6, 2002” (czyli 6 czerwca 2002 roku).

Argument zmiennyCzasWygWażności przypomina nieco argument bezwzgDataWygWażności, z tym iż określany przez niego moment wygaśnięcia ważności elementu przechowywanego w pamięci podręcznej jest zmieniany po otrzymaniu każdego żądania dotyczącego stron. Na przykład, jeśli wykorzystując argument bezwzgDataWygWażności określimy, że element ma zostać usunięty z pamięci podręcznej za pięć godzin od chwili obecnej, po pięciu godzinach zostanie on z niej usunięty bez względu na to co się będzie działo w międzyczasie. W przypadku użycia argumentu zmiennyCzasWygWażności element zostanie usunięty z pamięci podręcznej dopiero po upłynięciu pięciu godzin od czasu otrzymania ostatniego żądania skierowanego do danej strony. Oznacza to, że jeśli ktoś zażąda wyświetlenia strony 4 godziny od chwili obecnej, to obiekt zostanie usunięty 5 godzin od tego momentu — czyli 9 godziny od chwili obecnej. A zatem, czas wygaśnięcia ważności elementu przechowywanego w pamięci podręcznej zmienia się wraz z obsługą kolejnych żądań. Przy określaniu wartości tego argumentu wykorzystywane są obiekty klasy TimeSpan.

Argument priorytet określa w jaki sposób, w określonych sytuacjach (na przykład, w razie braku pamięci), obiekty będą usuwane z pamięci podręcznej. Ogólnie rzecz biorąc elementy o wyższym priorytecie będą przechowywane w pamięci podręcznej dłużej, niż obiekty o niższym priorytecie. Priorytet elementu odpowiada kosztowi jego zachowania w pamięci. Im stworzenie elementu jest bardziej kosztowe pod względem czasu i wykorzystywanych zasobów, tym dłużej element ten powinien być przechowywany w pamięci podręcznej.

Argument zmniejszeniePrioryteu określa z jaką szybkością priorytet elementu będzie malał wraz z upływem czasu — innymi słowy jak ważny będzie dany element za 20 minut, gdy zasoby pamięci serwera zaczną się wyczerpywać. Ostatni argument wywołania metody AddonRemoveCallBack — jest metodą, którą należy wywołać w momencie usuwania danego elementu z pamięci podręcznej.

A teraz dodajmy nasz obiekt DataView do pamięci podręcznej przy użyciu metody Add. W tym celu zamieńmy wiersz 30. listingu 14.5 w poniższy sposób (zmodyfikowany kod przykładu znajduje się w pliku listing1405-v2.aspx):

Cache.Add("DataView", source, nothing, DateTime.new.AddMinutes(1), _

TimeSpan.Zero, CacheItemPriority.High, _

CacheItemPriorityDecay.Slow, addressof HandleRemove)

Analiza

Powyższe wywołanie metody Add dodaje do pamięci podręcznej zmienną source zawierającą obiekt DataView, których chcemy zapamiętać. W wywołaniu określamy, że obiekt nie będzie miał żadnych zależności, a bezwzględna data upłynięcia ważności zostaje ustawiona na minutę po momencie wywołania metody. Zmienny czas upłynięcia ważności obiektu zostaje ustawiony na 0, co w praktyce oznacza iż nie będzie on brany pod uwagę. Priorytetowi obiektu zapisywanego w pamięci podręcznej zostaje przypisana wartość High (oznaczająca wysoki priorytet), a szybkości zmniejszania priorytetu — wartość Slow (określająca, że będzie on zmniejszany powoli). Dostępne wartości argumentów priorytet oraz zmniejszeniePriorytetu zostały przedstawione w tabeli 14.2. Ostatni argument wywołania metody Add określa procedurę jaka zostanie wywołana w momencie usuwania danego obiektu z pamięci podręcznej. (W przypadku, gdy nie mamy zamiaru obsługiwać tego zdarzenia, argumentowi temu można przypisać wartość nothing.) Jeśli argumentem tym będzie nazwa nieistniejącej procedury, to podczas wykonywania strony pojawi się błąd.

Poniżej przedstawiony został ogólny sposób definicji procedury HandleRemove:

sub HandleRemove(klucz as string, wartosc as object, _

powod as CacheItemRemovedReason)

'... kod

end sub

Do tej metody jest przekazywany klucz oraz obiekt który został usunięty z pamięci, jak również powód jego usunięcia. Argument powod może przyjmować jedną z następujących wartości:

W tabeli 14.2 przedstawione zostały dostępne wartości określające priorytet elementu pamięci podręcznej oraz szybkość zmniejszania tego priorytetu (wartości te należą odpowiednio do typów wyliczeniowych CacheItemPriority oraz CacheItemPriorityDecay).

Tabela 14.2. Wartości argumentów określających priorytet oraz szybkość zmniejszania priorytetu.

Priorytet

Opis

AboveNormal

Prawdopodobieństwo usunięcia tych elementów z pamięci podręcznej jest mniejsze niż w przypadku elementów o priorytecie Normal.

BelowNormal

Prawdopodobieństwo usunięcia tych elementów z pamięci podręcznej jest większe niż w przypadku elementów o priorytecie Normal.

Default

Ta wartość odpowiada priorytetowi Normal.

High

Prawdopodobieństwo usunięcia elementów o tym priorytecie z pamięci podręcznej jest najmniejsze.

Low

Prawdopodobieństwo usunięcia elementów o tym priorytecie z pamięci podręcznej jest największe.

Normal

Podstawowa wartość priorytetu.

NotRemovable

Te elementy w ogóle nie będą usuwane z pamięci podręcznej.

Szybkość zmniejszania priorytetu

Opis

Default

Odpowiada wartości Medium.

Fast

W przypadku sporadycznego odwoływania się do tych elementów, prawdopodobieństwo usunięcia ich z pamięci podręcznej jest największe.

Medium

Podstawowa wartość.

Never

Te elementy nigdy nie będą usuwane z pamięci podręcznej.

Slow

W przypadku sporadycznego odwoływania się do tych elementów, prawdopodobieństwo usunięcia ich z pamięci podręcznej jest najmniejsze.

Notatka
Należy pamiętać, iż wartości opisane w tabeli 14.2 mają znaczenie wyłącznie w przypadku gdy elementy są usuwane z pamięci podręcznej automatycznie, w wyniku ograniczenia ilości dostępnej pamięci. W przypadku ręcznego usuwania elementów z pamięci podręcznej wartości te nie odgrywają żadnego znaczenia.

Wywołanie metody Insert klasy Cache ma taka samą postać, lecz niektóre z jej argumentów są opcjonalne. Poniżej przedstawione zostały wszystkie dostępne sposoby wywołania tej metody:

Cache.Insert(klucz, wartość)

Cache.Insert(klucz, wartość, zależności)

Cache.Insert(klucz, wartość, zależności, bezwzgDataWygWażnosci, _

zmiennyCzasWygWażności)

Cache.Insert(klucz, wartość, zależności, bezwzgDataWygWażnosci, _

zmiennyCzasWygWażności, priorytet, zmniejszeniePriorytetu, _

onRemoveCallBack)

Ostrzeżenie
Dodanie lub wstawienie do pamięci podręcznej elementu o takiej samej nazwie jak nazwa elementu już zapisanego w pamięci spowoduje że element zapisany w pamięci zostanie zastąpiony nowym.

Dzięki temu mechanizmowi można zapisywać w pamięci podręcznej niemal wszystkie fragmenty stron ASP.NET — poczynając od obiektów DataView, poprzez elementy sterujące DataGrid, a na elementach sterujących użytkownika kończąc.

Zależności informacji przechowywanych w pamięci podręcznej

Mechanizmy obsługi pamięci podręcznej w ASP.NET umożliwiają określenie, że elementy zapisywane w pamięci za pośrednictwem obiektów klasy Cache, mogą zależeć od innych elementów. Na przykład, załóżmy, że utworzyliśmy obiekt DataView na podstawie danych przechowywanych w pliku XML. Jeśli plik XML ulegnie zmianie, będziemy chcieli, aby zmieniła się także zawartość obiektu DataView. Zależności pamięci podręcznej od zewnętrznych źródeł danych zostały przedstawione na rysunku 14.8.

Rysunek 14.8. Zależności pozwalają aby zawartość pamięci podręcznej była zależna od zewnętrznego źródła danych

Opis rysunku

Cache — Pamięć podręczna

XML File — Plik XML

DataView — Obiekt prezentujący dane (DataView)

Invalid! — Zawartość nieważna!

1. … — 1. Pobranie danych z pliku

2. … — 2. Zapisanie danych w pamięci podręcznej

3. … — 3. Określenie i dodanie zależności

4. … — 4. Przesłanie danych do przeglądarki

5. … — 5. Modyfikacja pliku

6. … — 6. Ponowne pobranie danych i przejście do etapu 2.

Bez zależności przedstawionych na rysunku 14.8, pamięć podręczna nie miałaby pojęcia o tym, iż dane zostały zmienione, a użytkownik wciąż otrzymywałby nieaktualne informacje.

Elementy pamięci podręcznej mogą zależeć od plików, folderów bądź też innych elementów przechowywanych w pamięci podręcznej. Zmodyfikujmy zatem przykład z listingu 14.5 w taki sposób, aby pobierał dane z pliku XML stworzonego w rozdziale 11, pt.: „Użycie XML w ASP.NET”; dodatkowo wprowadzimy także zależność informacji przechowywanych w pamięci podręcznej do pliku z którego zostały pobrane. --> Kod przykładu został przedstawiony na listingu 14.6.

Listing 14.6.[Author:p8R] Wykorzystanie zależności przy obsłudze pamięci podręcznej

Analiza

Fragment kodu definiujący postać wynikową strony WWW nie został w żaden sposób zmodyfikowany (za wyjątkiem usunięcia przycisku Wyczyść pamięć podręczną). Większość pozostałej części kodu także nie uległa zmianie w porównaniu z listingiem 14.5. Przyjrzyjmy się jednak różnicom pomiędzy obydwoma przykładami.

W wierszach do 22. do 27. pobierane są dane z pliku XML; w przykładzie z listingu 14.5 informacje były pobierane z bazy danych. Niemniej jednak, podobnie jak w poprzednim przypadku, także i teraz informacje są umieszczane w obiekcie DataSet. (Należy zwrócić uwagę, iż w nowej wersji przykładu koniecznie trzeba zaimportować przestrzeń nazw System.IO.) W wierszu 29. tworzony jest nowy obiekt CacheDependency związany z plikiem books.xml, z którego korzystaliśmy w rozdziale 11. W dalszej części kodu wyświetlany jest komunikat informujący skąd zostały pobrane informacje, a pobrane informacje są wiązane z elementem sterującym DataGrid.

Sam sposób działania strony nie uległ zmianie w porównaniu z poprzednim przykładem. Podczas obsługi pierwszego żądania dotyczącego danej strony tworzony jest obiekt DataView, a zapisywane w nim informacje są pobierane bezpośrednio z pliku XML. Podczas obsługi kolejnych żądań dane będą pobierane z pamięci podręcznej. Otwórzmy teraz nasz przykładowy plik XML w dowolnym edytorze (na przykład Notatniku) i dodajmy do niego nowy rekord. Gdy ponownie zażądamy wyświetlenia strony, zostanie wyświetlony komunikat informujący, że dane zostały pobrane z pliku. W przypadku gdyby zależność (obiekt CacheDependency) nie została utworzona, mechanizmy obsługi pamięci podręcznej w ASP.NET nie wiedziałyby jak sprawdzić czy dane zostały zmienione i cały czas przekazywały użytkownikom zapamiętane, nieaktualne informacje. Na rysunku 14.9 przedstawione zostały wyniki wygenerowane przez stronę po zmodyfikowaniu pliku XML.

0x01 graphic

Rysunek 14.9. Uaktualnienie pliku od którego zależy element pamięci podręcznej powoduje unieważnienie tego elementu i jego powtórne utworzenie.

Użycie klasy HttpCachePolicy

We wcześniejszej części rozdziału przedstawiłem podstawowe informacje dotyczące sposobów przechowywania stron w pamięci podręcznej. Prawdopodobnie, przedstawione możliwości byłyby w stanie zaspokoić Twoje potrzeby, jednak ASP.NET udostępnia kolejną klasę, która zapewnia znacznie większe możliwości kontroli nad sposobem działania mechanizmów obsługi pamięci podręcznej. Klasa ta nosi nazwę HttpCachePolicy.

Dostęp do obiektu tej tek klasy można uzyskać za pośrednictwem właściwości Cache obiektu HttpResponse (Response.Cache). Klasa HttpCachePolicy zawiera zaawansowane metody umożliwiające precyzyjne określenie sposobu obsługi pamięci podręcznej. Obiekty tej klasy zarządzają pamięcią podręczną przy wykorzystaniu nagłówków HTTP, co oznacza, że kontrolują sposób przechowywania strony w pamięci podręcznej. Różnica pomiędzy wykorzystaniem obiektów klasy HttpCachePolicy a zwyczajnym zapamiętywaniem w pamięci podręcznej wyników wykonania strony polega na tym, iż klasa HttpCachePolicy daje możliwość uzyskania znacznie większej kontroli nad mechanizmem obsługi pamięci podręcznej.

Operacje na pamięci podręcznej

Klasa HttpCachePolicy udostępnia kilka metod służących do operowania datą wygaśnięcia ważności informacji przechowywanych w pamięci podręcznej. Dzięki niej, umieszczanie dyrektywy OutputCache w kodzie strony ASP.NET nie będzie konieczne.

Pierwsza z tych metod — SetExpires — określa bezwzględny czas wygaśnięcia ważności zawartości pamięci podręcznej. Przykładowo, poniższe wywołanie informuje, że ważność zawartość pamięci podręcznej ma upłynąć po 30 sekundach.

Response.Cache.SetExpires(DateTime.Now.AddSeconds(30))

Poniższe wywołanie metody SetExpires sprawi, że zawartość pamięci podręcznej utraci ważność o godzinie 15.00, lokalnego czasu:

Response.Cache.SetExpires("3:00 PM".ToDateTime())

Kolejnym sposobem określenia bezwzględnego czasu wygaśnięcia ważności zawartości pamięci podręcznej, jest użycie metody SetMaxAge. Metoda ta określa jak długo informacje mogą być przechowywane w pamięci podręcznej zanim zostaną unieważnione. Na przykład, poniższe wywołanie informuje, że zawartość pamięci podręcznej ma zostać unieważniona po 30 minutach (pierwszym argumentem wywołania metody jest ilość godzin, drugim ilość minut, a ostatnim ilość sekund):

Response.Cache.SetMaxAge(new TimeSpan(0,30,0))

Obie te metody są do siebie bardzo podobne. Pierwszej z nich — SetExpires — należy używać gdy znana jest dokładna godzina o której wartość pamięci podręcznej ma utracić ważność (nawet jeśli jest on wyrażony względem aktualnego czasu). Drugiej z metod — SetMaxAge — gdy dokładna godzina o której należy unieważnić zawartość pamięci podręcznej nie jest znana lub nie ma znaczenia; jednak gdy zawartość pamięci musi zostać unieważniona po pewnym okresie czasu. Warto także zauważyć, że metoda SetExpires pobiera argument typu DateTime, natomiast metoda SetMaxAge — typu TimeSpan.

Obiekty klasy HttpCachePolicy umożliwiają także określanie wartości zmiennego czasu upłynięcia ważności elementów przechowywanych w pamięci podręcznej. (O zmiennym czasie upłynięcia ważności pisałem we wcześniejszej części rozdziału, pt.: „Zapisywanie obiektów w pamięci podręcznej”.) Aby umożliwić zastosowanie zmiennego czasu wygaśnięcia ważności, wystarczy podać wartość true w wywołaniu metody SetSlidingExpiration:

Response.Cache.SetSlidingExpiration(true)

W tym przypadku zawartość pamięci podręcznej zostanie unieważniona po upłynięciu okresu czasu, który jest aktualizowany wraz z otrzymywaniem kolejnych żądań.

Istnieje także możliwość określania czy oraz gdzie będzie przechowywana pamięć podręczna. Metoda SetCacheability pozwala określić kto będzie miał prawo do zapisywania stron w pamięci podręcznej. Wartości jakie można przekazać w wywołaniu tej metody zostały opisane w tabeli 14.3.

Tabela 14.3. Wartości określające prawa do korzystania z pamięci podręcznej.

Typ

Opis

NoCache

Nikt nie ma prawa do zapisywania danych w pamięci podręcznej. Klient musi potwierdzić ważność elementu pamięci podręcznej na serwerze.

Private

Określa, że klient może zapisać odpowiedź w pamięci podręcznej, jednak nie mogą tego robić serwery pośredniczące. Jest to wartość domyślna argumentu metody SetCacheability.

Public

Określa że zarówno klienci jak i serwery pośredniczące mogą zapisywać odpowiedzi w pamięci podręcznej.

Notatka
Warto zwrócić uwagę, iż w przypadku użycia zmiennego czasu upłynięcia ważności zawartości pamięci podręcznej (podania wartości
true w wywołaniu metody SetSlidingExpiration), czas ten należy określić w sposób względny (czyli jako okres czasu liczony od chwili obsługi żądania, po upłynięciu którego zawartość pamięci podręcznej zostanie unieważniona). Na przykład, wykonanie poniższego fragmentu kodu nie spowoduje użycia zmiennego czasu upłynięcia ważności:

Response.Cache.SetExpires("11/21/01 3:00:00PM".ToDateTime)

Response.Cache.SetSlidingExpiration(true)

W powyższym przypadku ASP.NET nie jest w stanie określić długości okresu czasu po jakim należy unieważnić zawartość pamięci podręcznej. Przykład poprawnego sposobu określenia zmiennego czasu upłynięcia ważności przedstawiłem poniżej:

Response.Cache.SetExpires(DateTime.Now.AddSeconds(30))

Response.Cache.SetSlidingExpiration(true)

W tym przypadku zmienny czas upłynięcia ważności danych przechowywanych w pamięci podręcznej, zostanie ustawiony na 30 sekund po chwili zakończenia obsługi ostatniego żądania.

Właściwość ta jest przydatna w sytuacjach gdy wiadomo gdzie są kierowane odpowiedzi oraz jak mają być traktowane. Na przykład, jeśli są one kierowane na sieć poprzez serwer pośredniczący, to można zapobiec zapamiętywaniu ich na tym serwerze. W ten sposób klienty nie będą korzystały z „pośredniej” pamięci podręcznej:

Response.Cache.SetCacheability(HttpCacheability.Private)

Na podobnej zasadzie, wywołanie metody SetNoServerCaching całkowicie uniemożliwia przechowywanie dokumentu w pamięci podręcznej na serwerze. Wszystkie kolejne żądania dotyczące danego dokumentu będą obsługiwane bez wykorzystania pamięci podręcznej. Oto przykład wykorzystania tej metody:

Response.Cache.SetNoServerCaching()

Notatka
Być może zastanawiasz się, gdzie należy umieścić wszystkie te instrukcje wykorzystujące właściwość
Response.Cache. W tym przypadku masz dużą swobodę — można je bowiem umieścić w dowolnej metodzie zapisane w bloku deklarowania kodu. Zazwyczaj jednak instrukcje te umieszczane są na samym początku procedury Page_Load, dzięki czemu całość danych wynikowych generowanych przez stronę ASP.NET zostanie poprawnie obsłużona.

Mechanizmy uzależniania zapisu danych w pamięci podręcznej od innych informacji

Czy przypominasz sobie podane wcześniej informacje o mechanizmach obsługi pamięci podręcznej oraz o sprawdzaniu parametrów łańcucha zapytania kontrolowanym przy użyciu parametru VaryByParam? Domyślnie ASP.NET zapisuje wyniki obsługi każdego żądania o unikalnym łańcuchu zapytania jako niezależny element pamięci podręcznej. Jednak zachowanie to można bardzo łatwo zmieniać.

Właściwość VaryByParams obiektu HttpCachePolicy dostępnego za pośrednictwem właściwości Response.Cache określa, na podstawie parametrów podawanych przez stronę ASP.NET (bądź to za pośrednictwem łańcucha zapytania, bądź wartości pól formularzy), w jaki sposób należy przechowywać obiekty w pamięci podręcznej. Przykład wykorzystania tej właściwości przedstawiony został na listingu 14.7.

--> Listing 14.7. Wykorzystanie parametrów do określania działania pamięci podręcznej[Author:p8R]

Analiza

Przykład przedstawiony na powyższym listingu przypomina nieco przykład z listingu 14.2; przy czym został do niego dodany fragment kodu operujący na właściwościach VaryByParams (zapisany w wierszach od 12. do 15.). Wywołując tę stronę należy podać dwa parametry — imie oraz nazwisko — reprezentujące odpowiednio imię oraz nazwisko użytkownika. Wyniki pierwszego wykonania strony zostały przedstawione na rysunku 14.10.

0x01 graphic

Rysunek 14.10. Prezentacja elementów właściwości VaryByParams

Jak widać na powyższym rysunku, elementy imie oraz nazwisko właściwości VaryByParams (odpowiadające parametrom łańcucha zapytania o tych samych nazwach) zawierają wartości false. Oznacza to, że w pamięci podręcznej, dla każdego parametru jest dostępna odrębna wersja dokumentu. Przechowywane w pamięci wersje dokumentów różnią się w zależności od wartości parametru.

To domyślny sposób działania mechanizmów obsługi pamięci podręcznej, z którym spotkaliśmy się już wcześniej, w części pod tytułem „Zapamiętywanie wyników wykonania stron ASP.NET”. Podanie unikalnych wartości parametrów imie oraz nazwisko spowoduje zapisanie w pamięci podręcznej nowej wersji strony. Podanie użytej wcześniej kombinacji parametrów spowoduje natomiast pobranie wersji przechowywanej w pamięci podręcznej.

W tym miejscu zaczyna się robić interesująco. Dodajmy poniższy wiersz kodu do na samym początku procedury Page_Load:

Response.Cache.VaryByParams.Item("imie")=true

A teraz spróbujmy zmienić wartości parametrów podanych w łańcuchu zapytania. Podanie nowej wartości parametru imie spowoduje zapisanie w pamięci podręcznej nowej wersji strony. Jednak podanie nowej wartości parametru nazwisko przy jednoczesnym pozostawieniu użytej wcześniej wartości parametru imie nie spowoduje zapamiętania nowej wersji strony. W takim przypadku zostanie zwrócona wcześniejsza wersja strony, o czym można się przekonać na podstawie wyświetlonego na niej czasu. Różnica ta została przedstawiona na rysunku 14.11.

0x01 graphic

Rysunek 14.11. Modyfikacja parametru nazwisko nie powoduje zapamiętania nowej wersji strony.

Na powyższym przykładzie, przypisując elementowi właściwości VaryByParams wartość true poinformowaliśmy ASP.NET, iż należy zapamiętać nową wersję strony wyłącznie w sytuacji gdy zmieni się wartość parametru imie. Podobnie, użycie następującej instrukcji spowoduje, że ASP.NET będzie zapamiętywać strony wyłącznie w przypadku podania nowej wartości parametru nazwisko:

Response.Cache.VaryByParams.Item("nazwisko") = true

Właściwość VaryByParams jest niezwykle przydatna. Wyobraźmy sobie na przykład, iż strony są zapisywane w pamięci podręcznej na witrynie, określającej status podatkowy użytkownika na postawie stanu w którym dana osoba mieszka. W łańcuchu zapytania przekazywany jest skrót nazwy stanu oraz nazwa użytkownika. Jednak dla określenia statusu podatkowego znaczenie ma jedynie informacja o stanie. Zapisywanie stron w pamięci podręcznej na podstawie nazwy użytkownika jest w tym przypadku niepotrzebne. A zatem, aby aktualizować zawartość pamięci podręcznej wyłącznie w przypadku zażądania strony dotyczącej nowego stanu, moglibyśmy posłużyć się następującym wywołaniem:

Response.Cache.VaryByParams.Item("stan") = true

Możliwości te, wykorzystane w poprawny sposób, mogą przynieść ogromne korzyści dla efektywności działania aplikacji.

Dostępna jest także właściwość umożliwiająca uzależnienie zapisywania stron w pamięci podręcznej na postawie nagłówków HTTP; nosi ona nazwę VaryByHeaders. Właściwość ta działa analogicznie do atrybutu VaryByHeader opisanego w części rozdziału poświęconej zapamiętywaniu wyników realizacji stron. W niniejszej książce nie opisywałem wszystkich dostępnych nagłówków HTTP, dlatego też te zagadnienia będziesz musiał poznać samemu. Obiekt HttpCachePolicy dostępny za pośrednictwem właściwości Response.Cache nie udostępnia żadnej właściwości odpowiadającej parametrowi VaryByCustom dyrektywy OutputCache. Dostępna jest jednak metoda SetVaryByCustom, która ma podobne działanie. (Więcej informacji na ten temat znajdziesz w dokumentacji .NET SDK.)

Efektywne korzystanie z pamięci podręcznej

Pamięć podręczna może w ogromnym stopniu poprawić efektywność działania aplikacji ASP.NET. W aplikacjach o bardzo dużym obciążeniu, zapamiętywanie stron nawet na okres jednej minuty może ogromnie pomóc. Jeśli każdy element zapisany w pamięci podręcznej może skrócić obsługę żądania o jedną sekundę, to wyobraź sobie jakie korzyści może dać wykorzystanie pamięci podręcznej w przypadku gdy witryna obsługuje setki żądań na minutę.

Ogólnie rzecz biorąc, w pamięci podręcznej można z powodzeniem przechowywać bardzo wiele informacji, na przykład informacje pobierane z baz danych lub plików, wyniki złożonych obliczeń oraz ustawienia konfiguracyjne aplikacji.

Jednak zdarzają się także przypadki, gdy wykorzystanie pamięci podręcznej nie jest najlepszym rozwiązaniem. Wyobraź sobie internetową witrynę giełdową, która musi prezentować informacje z ostatnich sekund. Zapisywanie takich informacji w pamięci podręcznej nie byłoby dobrym rozwiązaniem, chyba że jednocześnie byłyby wykorzystywane odpowiednie zależności.

Tak

Nie

Zapisuj w pamięci podręcznej często wykorzystywane informacje, które rzadko kiedy są modyfikowane.

Zapisuj w pamięci podręcznej ustawienia i obiekty, które są wykorzystywane w wielu miejscach aplikacji a jednocześnie nie są w żaden sposób modyfikowane.

Nie zapisuj w pamięci podręcznej informacji personalnych dotyczących użytkowników korzystających z aplikacji, na przykład haseł. Inni użytkownicy bardzo łatwo mogliby uzyskać do nich dostęp.

Nie zapisuj w pamięci podręcznej stron, których zawartość zależy od czasu. Użytkownicy mogą nie rozumieć dlaczego ich zegarki się spóźniają.

Nie zapisuj w pamięci podręcznej obiektów, które użytkownicy mogą zmodyfikować w dowolnym momencie, takich jak „koszyki” w internetowych sklepach.

To nie jest ASP!

Oryginalna wersja technologii ASP umożliwiała jedynie kontrolę zarządzania pamięcią podręczną po stronie klienta. Służyły do tego właściwości Response.Expires oraz Response.ExpiresAbsolute. ASP.NET pozwala na kontrolę sposobów działania mechanizmów obsługi pamięci podręcznej zarówno po stronie serwera jak i klienta. To jedna z największych zmian jakie wprowadzono w ASP.NET w porównaniu z poprzednimi wersjami technologii ASP. Teraz programiści dysponują mechanizmem obsługi pamięci podręcznej o bardzo potężnych możliwościach, którym można zarządzać bardzo łatwo i na wiele sposobów (w tym także programistycznie). Tak potężne mechanizmy wykorzystania pamięci podręcznej mogą w ogromnym stopniu poprawić efektywność działania aplikacji.

2 Część I Podstawy obsługi systemu WhizBang (Nagłówek strony)

2 Dokument2

UWAGA!! Numeracja w oryginale książki jest zła!! Rys. 14.2 jest już na str. 463.

Zmiana w stosunku do oryginału, ze względu na treść notatki umieszczonej po przykładzie.

UWAGA!! Numeracja listingów w oryginale nie była ciągła - zmieniłem tak aby była

Nie wiem dlaczego ale ten przykład nie chce działać zgodnie z opisem podanym przez autora!!! Zawsze wyświetlają się wartości True.



Wyszukiwarka

Podobne podstrony:
R15-T, Informatyka, ASP.NET
R12-T, Informatyka, ASP.NET
R13-T, Informatyka, ASP.NET
R20-T, Informatyka, ASP.NET
R17-T, Informatyka, ASP.NET
R11-T, Informatyka, ASP.NET
R21-T, Informatyka, ASP.NET
informatyka asp net 3 5 tworzenie portali internetowych w nurcie web 2 0 omar al zabir ebook
informatyka asp net ajax programowanie w nurcie web 2 0 christian wenz ebook
informatyka asp net mvc 4 programowanie jess chadwick ebook
informatyka asp net mvc 3 framework zaawansowane programowanie steven sanderson ebook
BizAgi Studio Cz, 5 Stworzeni aplikacji zewn trznej w ASP NET
ASP NET 2 0 Tworzenie witryn internetowych z wykorzystaniem C i Visual Basica aspntw
asp net introduction MM6QQFHOGEVK7FULUA
C i ASP NET Szybki start
ASP NET Vademecum profesjonalisty
asp net introduction to microsoft asp net 3R522NRLFCX55WSTS6WZOFPHBH4HEKDTR3EY47Q

więcej podobnych podstron