Konfiguracja aplikacji internetowej produkcji Golang

120

Dla tych z Was, którzy korzystają z backendów Go w środowisku produkcyjnym:

Jaki jest Twój stos / konfiguracja do uruchamiania aplikacji internetowej Go?

Nie widziałem zbyt wiele na ten temat poza ludźmi używającymi standardowego pakietu biblioteki net / http do podtrzymywania działania serwera. Czytałem używając Nginx do przekazywania żądań do serwera Go - nginx z Go

Wydaje mi się to trochę kruche. Na przykład serwer nie uruchomiłby się automatycznie po ponownym uruchomieniu komputera (bez dodatkowych skryptów konfiguracyjnych).

Czy istnieje solidniejsza konfiguracja produkcyjna?

Pomijając moje zamiary - planuję serwer zaplecza REST oparty na Go dla mojego następnego projektu i chcę się upewnić, że Go będzie opłacalne do uruchomienia projektu na żywo, zanim zainwestuję w niego zbyt dużo.

Chaseph
źródło
3
„serwer nie uruchomiłby się automatycznie po ponownym uruchomieniu komputera (bez dodatkowych skryptów konfiguracyjnych)”. Myślę, że nie da się tego zrobić. Idealnie byłoby, gdybyś utworzył skrypty init / systemd / upstart dla usługi. Jest to zalecany sposób kontrolowania każdego demona unixa.
Intermernet
Masz rację. Myślę, że chodziło mi o to w przeciwieństwie do serwera takiego jak Apache, który automatycznie konfiguruje te funkcje podczas instalacji.
Chaseph

Odpowiedzi:

134

Programy Go mogą nasłuchiwać na porcie 80 i bezpośrednio obsługiwać żądania HTTP. Zamiast tego możesz chcieć użyć odwrotnego proxy przed swoim programem Go, aby nasłuchiwał na porcie 80 i łączył się z twoim programem na porcie, powiedzmy, 4000. Jest wiele powodów, dla których warto to zrobić: nie trzeba uruchamiać Twój program Go jako root, obsługujący inne witryny / usługi na tym samym hoście, zakończenie SSL, równoważenie obciążenia, logowanie itp.

Używam HAProxy z przodu. Każdy zwrotny serwer proxy może działać. Nginx to również świetna opcja (znacznie bardziej popularna niż HAProxy i zdolna do więcej).

HAProxy jest bardzo łatwy w konfiguracji, jeśli przeczytasz jego dokumentację ( wersja HTML ). Mój cały haproxy.cfgplik dla jednego z moich projektów Go, na wypadek gdybyś potrzebował ponta początkowego.

global
        log     127.0.0.1       local0
        maxconn 10000
        user    haproxy
        group   haproxy
        daemon

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        retries 3
        timeout connect 5000
        timeout client  50000
        timeout server  50000

frontend http
        bind :80
        acl  is_stats  hdr(host)       -i      hastats.myapp.com
        use_backend    stats   if      is_stats
        default_backend        myapp
        capture        request header Host     len     20
        capture        request header Referer  len     50

backend myapp
        server  main    127.0.0.1:4000

backend stats
       mode     http
       stats    enable
       stats    scope   http
       stats    scope   myapp
       stats    realm   Haproxy\ Statistics
       stats    uri     /
       stats    auth    username:password

Nginx jest jeszcze łatwiejszy.

Jeśli chodzi o kontrolę usług, program Go uruchamiam jako usługę systemową. Myślę, że każdy to robi. Na moim serwerze działa Ubuntu, więc używa Upstart. Umieściłem to na /etc/init/myapp.confUpstart, aby kontrolować mój program:

start on runlevel [2345]
stop on runlevel [!2345]

chdir /home/myapp/myapp
setgid myapp
setuid myapp
exec ./myapp start 1>>_logs/stdout.log 2>>_logs/stderr.log

Kolejnym aspektem jest wdrożenie. Jedną z opcji jest wdrożenie poprzez wysłanie pliku binarnego programu i niezbędnych zasobów. To całkiem świetne rozwiązanie IMO. Ja korzystam z drugiej opcji: kompilacja na serwerze. (Przełączę się na wdrażanie z plikami binarnymi, gdy skonfiguruję tak zwany system „ciągłej integracji / wdrażania”).

Mam mały skrypt powłoki na serwerze, który pobiera kod dla mojego projektu ze zdalnego repozytorium Git, buduje go za pomocą Go, kopiuje pliki binarne i inne zasoby do ~/myapp/oraz ponownie uruchamia usługę.

Ogólnie rzecz biorąc, całość nie różni się zbytnio od jakiejkolwiek innej konfiguracji serwera: musisz mieć sposób na uruchomienie kodu i obsługę żądań HTTP. W praktyce Go okazał się bardzo stabilny w tym zakresie.

Mostafa
źródło
9
Świetna odpowiedź! Dobre przykłady wszystkiego, co jest potrzebne do zalecanej podstawowej konfiguracji.
Intermernet
Co robisz z rotacją dzienników? To właściwie jedyny powód, dla którego używam superwizora, ale cierpi, gdy jest zbyt dużo logowania.
fiorix
@fiorix, jestem prawie pewien, że mógłbyś otworzyć inne pytanie SO dotyczące rotacji logów, ale nadal, jeśli jesteś na unixie i chcesz używać standardowych narzędzi, sprawdź logrotate: linuxcommand.org/man_pages/logrotate8.html . Jest używany przez wiele dobrze znanych usług (apache, yum itp.) I jest dość łatwy w konfiguracji.
Doody P
Jak łatwo byłoby utworzyć własne odwrotne proxy w Go? Czy byłby to znacznie gorszy pomysł niż użycie nginx lub haproxy? Mam na myśli, że Go ma świetną obsługę HTTP / HTTPS / HTTP / 2.
thomasrutter
58

nginx dla:

  • Odwróć serwer proxy HTTP do mojej aplikacji Go
  • Statyczna obsługa plików
  • Zakończenie SSL
  • Nagłówki HTTP (Cache-Control i in.)
  • Dostęp do dzienników (a tym samym wykorzystanie rotacji dzienników systemowych)
  • Przepisuje (nago na www, http: // na https: // itp.)

nginx sprawia, że ​​jest to bardzo łatwe i chociaż dzięki temu możesz obsługiwać bezpośrednio z Go net/http, jest dużo „ponownego wymyślania koła” i rzeczy takie jak globalne nagłówki HTTP wymagają pewnych schematów, których prawdopodobnie możesz uniknąć.

kierownik do zarządzania moim plikiem binarnym Go. Ubuntu Upstart (o czym wspomniał Mostafa) jest również dobry, ale lubię supervisor, ponieważ jest stosunkowo niezależny od dystrybucji i jest dobrze udokumentowany.

Nadzorca, dla mnie:

  • W razie potrzeby uruchamia mój plik binarny Go
  • Podnosi to po wypadku
  • Przechowuje moje zmienne środowiskowe (klucze autoryzacji sesji itp.) Jako część pojedynczej konfiguracji.
  • Uruchamia moją bazę danych (aby upewnić się, że mój plik binarny Go nie działa bez niej)
elithrar
źródło
8

Dla tych, którzy chcą, aby prosta aplikacja go działała jako demon, użyj systemd (obsługiwanego przez wiele dystrybucji Linuksa) zamiast Upstart.

Utwórz plik usługi pod adresem

touch /etc/systemd/system/my-go-daemon.service

Wchodzić

[Unit]
Description=My Go App

[Service]
Type=simple
WorkingDirectory=/my/go/app/directory
ExecStart=/usr/lib/go run main.go 

[Install]
WantedBy=multi-user.target

Następnie włącz i uruchom usługę

systemctl enable my-go-daemon
systemctl start my-go-daemon
systemctl status my-go-daemon

systemd ma oddzielny system kronikowania, który umożliwia śledzenie dzienników w celu łatwego rozwiązywania problemów.

mixdev
źródło
5

Możesz powiązać swój plik binarny z gniazdem do uprzywilejowanych portów domeny internetowej (numery portów mniejsze niż 1024) za pomocą setcap

setcap 'cap_net_bind_service=+ep' /path/to/binary

  1. To polecenie musi zostać eskalowane. sudojako niezbędne
  2. Każda nowa wersja twojego programu spowoduje powstanie nowego pliku binarnego, który będzie wymagał ponownej autoryzacji przez setcap

setcap dokumentacja

cap_net_bind_service dokumentacja

Emperor_Earth
źródło