Configurazione dell'applicazione web di produzione Golang


120

Per quelli di voi che eseguono backend Go in produzione:

Qual è il tuo stack / configurazione per l'esecuzione di un'applicazione web Go?

Non ho visto molto su questo argomento oltre alle persone che usano il pacchetto net / http della libreria standard per mantenere in esecuzione un server. Ho letto di usare Nginx per passare richieste a un server Go - nginx con Go

Questo mi sembra un po 'fragile. Ad esempio, il server non si riavvierebbe automaticamente se la macchina fosse riavviata (senza script di configurazione aggiuntivi).

Esiste una configurazione di produzione più solida?

A parte il mio intento: sto pianificando un server backend REST basato su Go per il mio prossimo progetto e voglio assicurarmi che Go sia fattibile per il lancio del progetto dal vivo prima di investire troppo in esso.


3
"il server non si riavvia automaticamente se la macchina viene riavviata (senza script di configurazione aggiuntivi)." Non credo che si possa fare. Idealmente avresti creato script init / systemd / upstart per il servizio. Questo è il modo consigliato per controllare qualsiasi demone unix.
Intermernet

Hai ragione. Immagino di volerlo dire in contrasto con un server come Apache, che imposta automaticamente quelle funzionalità al momento dell'installazione.
Chaseph

Risposte:


134

I programmi Go possono ascoltare sulla porta 80 e servire direttamente le richieste HTTP. Invece, potresti voler usare un proxy inverso davanti al tuo programma Go, in modo che sia in ascolto sulla porta 80 e si connetta al tuo programma sulla porta, diciamo, 4000. Ci sono molte ragioni per fare quest'ultimo: non dover eseguire il tuo programma Go come root, che serve altri siti web / servizi sullo stesso host, terminazione SSL, bilanciamento del carico, registrazione, ecc.

Uso HAProxy davanti. Qualsiasi proxy inverso potrebbe funzionare. Nginx è anche un'ottima opzione (molto più popolare di HAProxy e in grado di fare di più).

HAProxy è molto facile da configurare se leggi la sua documentazione ( versione HTML ). haproxy.cfgSegue il mio intero file per uno dei miei progetti Go, nel caso abbiate bisogno di un punto di partenza.

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 è ancora più semplice.

Per quanto riguarda il controllo del servizio, eseguo il mio programma Go come servizio di sistema. Penso che lo facciano tutti. Il mio server esegue Ubuntu, quindi utilizza Upstart. L'ho inserito in /etc/init/myapp.confUpstart per controllare il mio programma:

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

Un altro aspetto è la distribuzione. Un'opzione è distribuire inviando semplicemente il file binario del programma e le risorse necessarie. Questa è un'ottima soluzione IMO. Uso l'altra opzione: compilare sul server. (Passerò alla distribuzione con file binari quando imposterò un cosiddetto sistema di "integrazione / distribuzione continua".)

Ho un piccolo script di shell sul server che estrae il codice per il mio progetto da un repository Git remoto, lo compila con Go, copia i file binari e altre risorse ~/myapp/e riavvia il servizio.

Nel complesso, l'intera cosa non è molto diversa da qualsiasi altra configurazione del server: devi avere un modo per eseguire il tuo codice e farlo servire alle richieste HTTP. In pratica, Go si è dimostrato molto stabile per queste cose.


9
Bella risposta! Buoni esempi di tutto il necessario per una configurazione di base consigliata.
Intermernet

Cosa fai con la rotazione dei log? Questo è praticamente l'unico motivo per cui uso supervisord, ma soffre quando ci sono troppe registrazioni in corso.
fiorix

@fiorix, sono abbastanza sicuro che potresti aprire una domanda SO diversa sulla rotazione dei log, ma comunque se sei su unix e vuoi usare strumenti standard, controlla logrotate: linuxcommand.org/man_pages/logrotate8.html . Viene utilizzato da molti dei servizi ben noti (apache, yum, ecc.) Ed è abbastanza facile da configurare.
Doody P

Quanto sarebbe facile creare il proprio proxy inverso in Go? Sarebbe un'idea significativamente peggiore rispetto all'utilizzo di nginx o haproxy? Voglio dire, Go viene fornito con un ottimo supporto HTTP / HTTPS / HTTP / 2.
thomasrutter

58

nginx per:

  • Reverse HTTP proxy per la mia applicazione Go
  • Gestione dei file statici
  • Terminazione SSL
  • Intestazioni HTTP (Cache-Control, et. Al)
  • Accedi ai log (e quindi sfruttando la rotazione dei log di sistema)
  • Riscrive (da nudo a www, http: // a https: //, ecc.)

nginx lo rende molto semplice, e sebbene tu possa servire direttamente da Go grazie a net/http, c'è un sacco di "reinventare la ruota" e cose come le intestazioni HTTP globali coinvolgono alcuni boilerplate che probabilmente puoi evitare.

supervisord per la gestione del mio file binario Go. Anche Upstart di Ubuntu (come menzionato da Mostafa) è buono, ma mi piace supervisord perché è relativamente indipendente dalla distribuzione ed è ben documentato.

Supervisord, per me:

  • Esegue il mio binario Go secondo necessità
  • Lo fa apparire dopo un incidente
  • Contiene le mie variabili ambientali (chiavi di autenticazione della sessione, ecc.) Come parte di una singola configurazione.
  • Esegue il mio DB (per assicurarmi che il mio binario Go non funzioni senza di esso)

8

Per coloro che desiderano che un'app semplice venga eseguita come daemon, utilizzare systemd (Supportato da molte distribuzioni Linux) invece di Upstart.

Crea un file di servizio in

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

accedere

[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

Quindi abilitare e avviare il servizio

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

systemd ha un sistema di journaling separato che ti consentirà di coda log per una facile risoluzione dei problemi.


5

Puoi associare il tuo binario a un socket alle porte privilegiate del dominio Internet (numeri di porta inferiori a 1024) utilizzando setcap

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

  1. Questo comando deve essere intensificato. sudocome necessario
  2. Ogni nuova versione del programma risulterà in un nuovo binario che dovrà essere nuovamente autorizzato da setcap

setcap documentazione

cap_net_bind_service documentazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.