Wdrażanie nowego kodu na żywo

29

Jaka jest najlepsza praktyka wdrażania nowego kodu w witrynie działającej na żywo (e-commerce)?

Na razie zatrzymałem apache na +/- 10 sekund podczas zmiany nazwy katalogu public_html_newna public_htmlstary i na stary public_html_old. To powoduje krótkie przestoje, zanim ponownie uruchomię Apache.

To samo pytanie dotyczy użycia Git do pobrania nowego repozytorium do katalogu na żywo. Czy mogę pobrać repo, gdy strona jest aktywna? Co powiesz na to, że muszę też skopiować bazę danych?

Podczas kompresji tar (kopii zapasowej) witryny działającej na żywo zauważyłem, że nastąpiły zmiany w katalogu multimediów. To wskazało mi, że pliki zmieniają się okresowo. A jeśli zmiany te mogą przeszkadzać, jeśli Apache nie zostanie zatrzymany podczas wdrażania.

nicoX
źródło

Odpowiedzi:

13

Korzystanie z modułu równoważenia obciążenia jest dobrym pomysłem. Jeśli witryna jest wystarczająco ważna, aby martwić się o kilka sekund przestoju, wystarczy, aby martwić się tolerancją na awarie.

Poza tym, jeśli jest to system UNIX, możesz zawiesić Apache podczas zmiany nazwy (lub aktualizacji dowiązania symbolicznego itp.):

killall -STOP httpd  # Pause all httpd processes
mv public_html public_html_orig
mv public_html_new public_html
killall -CONT httpd  # Resume all httpd processes

Dzięki temu Apache nie będzie akceptował nowych żądań podczas zmiany nazwy. Jeśli wolisz dowiązania symboliczne lub inne podejście, możesz zastosować ten sam pomysł:

killall -STOP httpd  # Pause all httpd processes
rm /var/www/html
ln -s /var/www/version/03 /var/www/html
killall -CONT httpd  # Resume all httpd processes

Pamiętaj, że wszelkie oczekujące połączenia lub pakiety będą się kolejkować w systemie operacyjnym. W przypadku bardzo obciążonej witryny rozważ dostrojenie ListenBacklog, jeśli jest to odpowiednie dla twojego typu roboczego httpd, i sprawdź ustawienia systemu operacyjnego związane z zaległościami TCP nasłuchu.

Możesz także zmienić DocumentRoot w httpd.conf i wykonać płynny restart ( apachectl graceful). Wadą tego jest zwiększone ryzyko błędów, ponieważ trzeba będzie również zaktualizować dowolną Directorykonfigurację.

GargantuChet
źródło
Czy sesja pauzy nadal będzie działać?
nicoX
4
Przestaje podawać czas procesora dla Apache. Jeśli spróbujesz uzyskać dostęp do witryny w przeglądarce, gdy Apache jest wstrzymany, przeglądarka będzie oczekiwać na połączenie, dopóki Apache nie zostanie wznowiony (lub przeglądarka przekroczy limit czasu, jeśli Apache zostanie wstrzymany na dłuższy czas). Jeśli ktoś jest w trakcie pobierania pliku, Apache przestanie wysyłać dane, gdy jest on wstrzymany, ponownie, ponieważ nie dostaje żadnego czasu procesora. Ponownie spowoduje to problemy tylko wtedy, gdy Apache zostanie zatrzymany na tak długo, że upłynie limit czasu przesyłania.
GargantuChet
5
Innymi słowy, witryna przestanie odpowiadać, gdy Apache zostanie wstrzymany, ale operacje oczekujące zakończą się po wznowieniu. Użytkownicy nie otrzymają „odmowy połączenia”, a pobieranie nie zostanie przerwane, ale operacje będą kontynuowane dopiero po wznowieniu Apache. Zapewni to zakończenie istniejących transakcji, ale nowe żądania zostaną obsłużone dopiero po przeniesieniu nowych treści na miejsce.
GargantuChet,
1
Pamiętaj, że na każdej stronie o dużym ruchu może to bardzo łatwo zabić twoją usługę Apache. 200 rq / s bardzo łatwo niszczy pulę połączeń, gdy tylko „odblokujesz” proces Apache po ruchu (jeśli ruch trwa chwilę)
CloudWeavers
1
Na stronie o dużym natężeniu ruchu pojawi się mnóstwo żądań w locie, aby zakończyć pracę po wznowieniu Apache. Spowolni to przetwarzanie nowych wniosków. Jest to również dobry argument za tym, aby upewnić się, że ustawienia Apache (maksymalna liczba wątków / serwerów / klientów) są rozsądne i odpowiednio wyregulować zaległości TCP. Chociaż jestem zdezorientowany, co rozumiesz przez „zabicie” usługi. Apache jest bardzo przestrajalny.
GargantuChet,
32

Najszybszym i najłatwiejszym jest użycie katalogu wersji takiego jak

/var/www/version/01
/var/www/version/02

i użyj aktualnego dowiązania symbolicznego jako twojego html_root:

/var/www/html -> /var/www/version/02

Ta technika doskonale integruje się z systemem kontroli wersji (svn, git, mercurial, ...), ponieważ możesz sprawdzać gałęzie i tagi, zmieniać łącze symboliczne i ponownie ładować Apache. Przestoju jest minimalny przy użyciu tej techniki i umożliwia bardzo łatwy wycofywania .

Dobrze integruje się również z bardziej złożonym systemem wdrażania, takim jak pakiety RPM lub infrastruktura zarządzania zmianami konfiguracji (szef kuchni, kukiełka itp.).

CloudWeavers
źródło
4
Najprostsze rozwiązanie jest zawsze najlepsze ... :-) Oczywiście nie zapomnij wspomnieć, że mogą być potrzebne niektóre FollowSymlinks i takie flagi apache w konfiguracjach.
Peter mówi, że przywróć Monikę
Zachowaj szczególną ostrożność w tym, co powiedział @PeterHorvath. Apache może stać się bardzo zrzędliwy podczas pracy z linkami DocumentRoots. Pamiętaj, aby dokładnie przetestować!
mhutter
@mhutter Dzięki :-) Naprawdę problematyczne jest to, że włączenie FollowSymlinks na Apache może powodować problemy z bezpieczeństwem ...
mówi Peterer przywrócić Monikę
Aktualizacja dowiązania symbolicznego nie jest operacją atomową. Nawet używając czegoś takiegoln -snf zatkanie oryginalnego dowiązania symbolicznego, podstawową operacją jest unlinki symlink. Istnieje szansa, że ​​użytkownicy otrzymają 404 podczas aktualizacji. Nie jest to lepsze niż zmiana nazwy oryginalnego katalogu na bok i zmiana nazwy nowego na miejsce (zakładając, że nie przenosisz systemów plików). Zobacz odpowiedź powyżej ze znacznikiem wyboru obok, która rozwiązuje ten problem.
GargantuChet,
14

Powinna również działać zmiana nazwy katalogów bez wyłączania Apache. To znacznie skróci okno. mv public_html public_html_old && mv public_html_new public_htmlpowinien zakończyć się w ułamku sekundy.

Kilka wad polega na tym, że takie podejście da 404każdemu żądaniu, które wciąż zdarza się podczas okna. A jeśli uruchomisz powyższe polecenie bez public_html_newkatalogu, zakończy się ono niepowodzeniem i pozostawi stronę z podaniem 404na każde żądanie.

Robienie tego atomowo z katalogami nie jest obsługiwane. Ale możesz to zrobić za pomocą dowiązań symbolicznych. Zamiast mieć katalog o nazwie public_html, nazwij go public_html.version-numberi wywołaj dowiązanie symboliczne public_htmlwskazujące na ten katalog. Teraz możesz utworzyć katalog o nazwie public_html.new-version-numberi nowe łącze symboliczne o nazwie public_html.new.

Następnie możesz zmienić nazwę public_html.newna, public_htmlaby przełączać atomowo. Zauważ, że mvjest „zbyt inteligentny”, aby wykonać tę zmianę nazwy, ale można to zrobić za pomocą os.renamePythona lub czegokolwiek innego, co wywoła wywołanie renamesystemowe, nie próbując być mądrym.

To, co zrobić z bazą danych, zależy od bazy danych, z której korzystasz i do czego jej używasz. Musisz podać o wiele więcej szczegółów na temat bazy danych, abyśmy mogli udzielić ci właściwej odpowiedzi na tę część pytania.

kasperd
źródło
1
W moim systemie Debian mvma -Topcję, która uniemożliwia śledzenie dowiązania symbolicznego. To pozwoli Ci atomowo przemianować public_html.newna public_htmlzakładając, oba są miękkie linki.
GargantuChet
11

Symlinks i mv to twoi przyjaciele, jednak jeśli naprawdę chcesz uniknąć sytuacji, w której użytkownicy końcowi otrzymają stronę błędu podczas wdrażania nowej wersji, powinieneś mieć odwrotny serwer proxy lub moduł równoważenia obciążenia przed co najmniej 2 serwerami zaplecza (apache) w Twoim przypadku).

Podczas wdrażania wystarczy zatrzymać jeden backend na raz, wdrożyć nowy kod, zrestartować go, a następnie wykonać iterację na pozostałych backendach.

Użytkownicy końcowi zawsze będą kierowani do dobrych backendów przez proxy.

Giovanni Toraldo
źródło
4
Właśnie pracowałem nad tą odpowiedzią, kiedy zobaczyłem, że już ją opublikowałeś. Serwery Balancer + 2 sprawiają, że proces jest niewidoczny i łatwiejszy do odzyskania po złym uaktualnieniu ...
Bart Silverstrim
9

Jeśli regularnie wprowadzasz zmiany w systemie produkcyjnym, zadbam o uporządkowany cykl życia. Dobrą praktyką jest Capistrano http://capistranorb.com/ . Jest to rozwiązanie typu open source do wdrażania oprogramowania na co najmniej jednym serwerze na kilku platformach i konfiguracjach.

Dla Magento istnieje nawet wtyczka: https://github.com/augustash/capistrano-ash/wiki/Magento-Example

W przypadku pojedynczego serwera i prawie płynnych przejść zalecam użycie dowiązań symbolicznych.

Skiaddict
źródło
4

Sposób, w jaki to robię, polega na zatwierdzaniu zmian z lokalnego środowiska programistycznego do internetowego repozytorium Git, takiego jak Github. Moje środowisko produkcyjne działa ze zdalnego repozytorium, więc wszystko, co muszę zrobić, to ssh na serwerze i uruchomić, git pullaby sprowadzić najnowsze zmiany. Nie musisz zatrzymywać serwera.

Jeśli masz w projekcie pliki, których ustawienia i / lub treść różnią się od wersji lokalnej (np. Pliki konfiguracyjne i przesyłanie multimediów), możesz użyć zmiennych środowiskowych i / lub dodać te pliki / katalogi do .gitignorepliku, aby zapobiec synchronizacji z repozytorium.

harryg
źródło
3

Mój pierwszy pomysł to:

# deploy into public_html_new, and then:
rsync -vaH --delete public_html_new/ public_html/

Dobrym rozwiązaniem było użycie rsync. Zmieniło tylko naprawdę zmienione pliki. Uwaga, ukośniki na końcu ścieżek są tutaj ważne.

Zwykle apache nie wymaga restartu, to nie jest świat Java. Sprawdza zmiany każdego pliku php na żądanie i automatycznie odczytuje (i ponownie tokenizuje) przy zmianie.

Pull Git był podobny, choć nieco trudniejszy do napisania. Oczywiście umożliwiło to szerokie spektrum różnych możliwości wykrywania łączenia / zmiany.

To rozwiązanie będzie bezproblemowo tylko wtedy, gdy nie będzie tak naprawdę poważnych zmian - jeśli są duże zmiany we wdrożeniu, nie można wyeliminować odrobiny zagrożenia, ponieważ nie ma nieistotnego odstępu czasu, kiedy kod zostanie częściowo zmieniony a w szczególności nie.

Jeśli są duże zmiany, moja propozycja była twoim początkowym rozwiązaniem (dwie zmiany nazwy).


Oto trochę hardcorowe, ale w 100% atomowe rozwiązanie:

(1) wykonaj naprzemienne podłączanie niektórych systemów plików, w których odbywa się magento:

mount /dev/sdXY /mnt/tmp

(2) wykonaj --bindpodłączenie swojej public_html_new do public_html:

mount --bind /path/to/public_html_new /path/to/public_html

Od tego momentu apache zobaczy Twoje nowe wdrożenie. Każda zmiana 404 jest niemożliwa.

(3) wykonaj synchronizację z rsync, ale w alternatywnym punkcie montowania):

rsync -vaH --delete /mnt/tmp/path/to/public_html_new/ /mnt/tmp/path/to/public_html/

(4) zdejmij mocowanie bindowania

umount /path/to/public_html
Peter mówi, że przywraca Monikę
źródło
Czy polecenie usunie public_html i wdroży w nim public_html_new?
nicoX,
@nicoX Nie, skopiuje tylko zmiany.
Peter mówi, że przywróć Monikę
@nicoX Przechodzi przez obie struktury katalogów, a jeśli znajdzie różnicę (nowy plik, zmodyfikowany plik, usunięty plik), modyfikuje drugi katalog tak, aby pasował do pierwszego, w razie potrzeby. Rezultat, jeśli usunąłeś public_html, a następnie przeniosłeś public_html_new na swoje miejsce, ale bez żadnej możliwości tymczasowego problemu 404.
Peter mówi, że przywróć Monikę
1
Nie, to nie jest dobry pomysł. W zależności od zmian może być krótki okres, w którym kod public_htmljest niespójny i nie chcesz zaryzykować.
Sven
@SvW Masz rację, mój pomysł jest w porządku, jeśli wprowadzono tylko drobne zmiany. Odpowiednio rozszerzyłem swoją odpowiedź.
Peter mówi, że przywróć Monikę
1

Przenoszenie / zastępowanie http_publicfolderu można wykonać za pomocą prostego mvlubln -s poleceń lub równoważne, gdy serwer http ciągle pracuje. Możesz wykonać skrypty, aby znacznie skrócić czas przestoju, ale jeśli zautomatyzujesz ten proces, dokładnie sprawdź kody zwrotne swoich poleceń w skrypcie.

To powiedziawszy, jeśli nie chcesz przestoju, Twoja aplikacja musi również go obsługiwać. Większość aplikacji korzysta z bazy danych w celu zachowania trwałości. Zablokowanie wersji N aplikacji w wersji N + 1 (lub odwrotnej) modelu danych może zepsuć się, jeśli zespół programistyczny tego nie przewidzi.

Z doświadczenia, utrzymanie takiej spójności poprzez uaktualnienia nie jest dane dla większości aplikacji. Prawidłowe wyłączenie, pomimo przestoju, jest dobrym sposobem na uniknięcie problemów ze spójnością.

Uriel
źródło