Fake it... ale nie tak jak myślisz - ASP.NET Web Host
Posty z tej serii:
- Fake it… ale nie tak jak myślisz - NServiceBus Web Host
- Fake it… ale nie tak jak myślisz - ASP.NET Web Host
- Fake it… ale nie tak jak myślisz - NServiceBus Windows Service Host
- Fake it… ale nie tak jak myślisz - Build - Run Unit tests - Publish
W poprzednim artykule przeszliśmy przez funkcjonalność wdrażania aplikacji webowej, której jedynym zadaniem jest hostowanie Endpointa NServiceBus. W kontekście Systemu komentarzy na blogu wdrażany Endpoint jest właścicielem komponentu przetwarzającego dodane komentarze. System posiada też drugi komponent, który przyjmuje komentarze od użytkowników, a następnie wysyła je do wcześniej wspomnianego Endpointa. Komponent ten hostowany jest w osobnej aplikacji webowej napisanej we frameworku ASP.NET w połączeniu z frameworkiem NancyFx. Dodanie komentarza odbywa się poprzez obsługę żądania HTTP. ASP.NET przyjmuje żądanie, przekierowuje je do modułu NancyFx, który wysyła Message do Endpointa zawierającego obsługę komentarza.
W dalszej części artykułu przejdziemy przez funkcjonalności wdrażania aplikacji webowej, której zadaniem jest obsługa żądań HTTP.
Design
W odróżnieniu od aplikacji webowej hostującej Endpointa NServiceBus nie możemy tak po prostu wyłączyć aplikacji webowej obsługującej żądania HTTP. Wdrożenie trwa jakiś czas. Polega na usuwaniu aktualnych artefaktów oraz wgrywaniu nowych. W kontekście systemu komentarzy na blogu, w trakcie wdrożenia użytkownik nie mógłby dodawać komentarzy. Jedną ze strategi poradzenia sobie z taką sytuacją jest zastosowanie strategii Blue-Green-Deployment. Do zapoznania się ze szczegółami zapraszam Cię do przeczytania jednego z moich wcześniejszych artykułów.
Schemat, którego ja używam, zawiera kroki:
- Przygotuj lokalnie artefakty do wdrożenia
- Usuń artefakty:
- Jeśli aktualnie działającą wersją jest Blue, to usuń ze zdalnej lokalizacji artefakty wersji Green
- Jeśli aktualnie działającą wersją jest Green, to usuń ze zdalnej lokalizacji artefakty wersji Blue
- Wgraj artefakty z nową wersją:
- Jeśli aktualnie działającą wersją jest Blue, to wgraj nową wersję na zasób zdalny dla wersji Green
- Jeśli aktualnie działającą wersją jest Green, to wgraj nową wersję na zasób zdalny dla wersji Blue
- Wywołaj żądanie HTTP używając adresu URL dla wgranej wersji
- Ustaw przekierowanie żądań HTTP dla głównego URL na URL wgranej nowej wersji
- Wywołaj żądanie HTTP używając głównego adresu URL
Develop
Z poprzedniego artykułu wiesz już, w jaki sposób można pisać skrypty wdrożeniowe za pomocą narzędzia FAKE. Przejdźmy przez implementację zgodną z procesem opisanym w sekcji Design kodując program np. w pliku web_ftp_deploy.fsx:
W powyższym fragmencie kodu pominąłem elementy, które opisałem w poprzednim artykule. Całość implementacji możesz zobaczyć na moim GitHubie.
Podobnie jak poprzednio, tak i teraz chcemy, aby skrypt był uniwersalny. Dzięki temu będziemy mogli go wykorzystać przy wdrożeniach na różne środowiska. W pierwszej kolejności, za pomocą lokalnie zdefiniowanej funkcji retrieveParam
, pobieramy parametry podawane przy uruchamianiu skryptu. Następnie przygotowujemy artefakty do wdrożenia za pomocą dostarczanych przez FAKEa funkcji Shell.cleanDir
oraz Shell.copyDir
. Kolejnym krokiem jest wyczyszczenie zdalnego zasobu oraz wgranie artefaktów. Wykorzystujemy do tego lokalnie zdefiniowaną funkcję makeFtpAction
. Potem sprawdzamy, czy wgrana aplikacja webowa działa, odpytując ją żądaniem HTTP za pomocą funkcji Http.get
, która pochodzi z przestrzeni nazw Fake.Net
. Podany URL jest adresem wgranej aplikacji Blue lub Green. Jeśli wszystko działa, to za pomocą funkcji pochodzących z przestrzeni nazwa Fake.Core.Xml
, ustawiamy w pliku web.config przekierowanie głównego adresu URL na adres wgranej aplikacji. Ostatnim krokiem jest sprawdzenie głównego adresu URL poprzez wywołanie żądania HTTP.
Analizując powyższą implementację, mogą nasunąć Ci się dwa pytania:
- Dlaczego kod nie jest podzielony na mniejsze funkcje, w których każda realizuje konkretny krok procesu?
- Może warto przenieść lokalne funkcje
retrieveParam
orazmakeFtpAction
do osobnego pliku skryptowego, a następnie wykorzystać tę samą implementację w plikach host_ftp_deploy.fsx oraz web_ftp_deploy.fsx? - F# umożliwia takie podejście. W skrócie - uwspólnić funkcjonalność i wprowadzić do niej zależność w poszczególnych skryptach.
Odpowiedź na pierwsze pytanie brzmi: Jak najbardziej można tak zrobić, natomiast jak popatrzysz na kod, to możesz zauważyć, że czyta się go wprost od góry do dołu, w taki sam sposób, w jaki opisany jest algorytm z sekcji Design. Kolejne wywołania funkcji Trace.trace
oddzielają od siebie poszczególne kroki. W tym przypadku podział na mniejsze funkcje byłby tylko “cukrem syntaktycznym”.
Jak zapewne się domyślasz, odpowiedź na drugie pytanie brzmi: Jak najbardziej można tak zrobić. Pytanie Co powinno być uwspólnione, a co powinno być rozdzielone? jest klasycznym pytaniem w kontekście wytwarzania oprogramowania. Temat dotyczy zależności, ich definiowania, zarządzania nimi itp. Decyzje dotyczące zależności mają bardzo duży wpływ na utrzymanie oraz rozwój oprogramowania, zarówno ten początkowy, jak i późniejszy. Nie ma jednoznacznego podejścia, a przynajmniej ja się z nim nie spotkałem, w jaki sposób decydować co powinno być wspólne, a co powinno być rozdzielone. Odnosząc się do skryptów wdrożeniowych opisywanych w tej serii, założenie jest takie, aby były one maksymalnie niezależne od siebie, ponieważ realizują inne zadania. W związku z tym kod funkcji retrieveParam
oraz makeFtpAction
jest kopiowany do poszczególnych plików .fsx. Jakie są tego konsekwencje?
- Plusy:
- Jeśli w przyszłości zmieni się koncepcja implementacji konkretnego skryptu, to zmiana będzie konieczna tylko w tym skrypcie. Nie trzeba będzie myśleć o tym, czy zmiana jest w kodzie wspólnym, a jak tak, to jaki będzie miała wpływ na działanie pozostałych skryptów.
- Jeśli zmiana będzie dotyczyć skopiowanego kodu, to będzie można zmieniać skrypty jeden po drugim, testować i wdrażać niezależnie.
- Minusy
- Jeśli okaże się, że skopiowany kod zawiera błędy, to trzeba będzie je poprawić we wszystkich skopiowanych miejscach.
- Trzeba mieć wiedzę, w których miejscach jest ten sam, skopiowany kod.
- Jeśli zmiana będzie dotyczyć skopiowanego kodu, to trzeba będzie tę zmianę wprowadzić we wszystkich skopiowanych miejscach
Minusy są dla mnie do zaakceptowania, stąd decyzja o rozdzieleniu funkcji retrieveParam
oraz makeFtpAction
. Krótkie ćwiczenie dla Ciebie. Przy założeniu, że kod dla tych dwóch funkcji byłby wspólny, wypisz plusy i minusy takiego podejścia. Czy widzisz jakiś związek z powyższymi Plusami i Minusami?
Test & Deploy
Tak jak poprzednio, skrypt testujemy za pomocą PowerShella, pisząc osobny .ps1 na każde środowisko wdrożeniowe. O danym środowisku decydują parametry wejściowe dla skryptu FAKEa np.
To tyle, jeśli chodzi o funkcjonalność wdrażania aplikacji webowej obsługującej żądania HTTP. W następnym artykule pokaże Ci przykład skryptu, który umożliwia wdrażanie Endpointa NServiceBus jako Windows Service.
=