Konfiguration der Golang-Produktionswebanwendung

120

Für diejenigen unter Ihnen, die Go-Backends in der Produktion ausführen:

Was ist Ihr Stack / Ihre Konfiguration zum Ausführen einer Go-Webanwendung?

Ich habe zu diesem Thema nicht viel gesehen, außer Leuten, die das Net / http-Paket der Standardbibliothek verwenden, um einen Server am Laufen zu halten. Ich habe mit Nginx gelesen, um Anfragen an einen Go-Server zu übergeben - Nginx mit Go

Das scheint mir ein wenig zerbrechlich zu sein. Beispielsweise würde der Server nicht automatisch neu gestartet, wenn der Computer neu gestartet würde (ohne zusätzliche Konfigurationsskripte).

Gibt es ein solideres Produktionssetup?

Abgesehen von meiner Absicht - ich plane einen Go-basierten REST-Backend-Server für mein nächstes Projekt und möchte sicherstellen, dass Go für den Live-Start des Projekts geeignet ist, bevor ich zu viel in ihn investiere.

Chaseph
quelle
3
"Der Server würde nicht automatisch neu gestartet, wenn der Computer neu gestartet würde (ohne zusätzliche Konfigurationsskripte)." Ich glaube nicht, dass dies möglich ist. Idealerweise haben Sie init / systemd / upstart-Skripte für den Dienst erstellt. Dies ist die empfohlene Methode zur Steuerung eines Unix-Daemons.
Intermernet
Du hast Recht. Ich denke, ich meinte es im Gegensatz zu einem Server wie Apache, der diese Funktionen bei der Installation automatisch einrichtet.
Chaseph

Antworten:

134

Go-Programme können Port 80 abhören und HTTP-Anforderungen direkt bedienen. Stattdessen möchten Sie möglicherweise einen Reverse-Proxy vor Ihrem Go-Programm verwenden, damit dieser Port 80 überwacht und über Port 4000 eine Verbindung zu Ihrem Programm herstellt. Es gibt viele Gründe, letzteres zu tun: Sie müssen nicht ausgeführt werden Ihr Go-Programm als Root, das andere Websites / Dienste auf demselben Host bereitstellt, SSL-Beendigung, Lastausgleich, Protokollierung usw.

Ich benutze HAProxy vorne. Jeder Reverse-Proxy könnte funktionieren. Nginx ist auch eine großartige Option (viel beliebter als HAProxy und in der Lage, mehr zu tun).

HAProxy ist sehr einfach zu konfigurieren, wenn Sie die Dokumentation ( HTML-Version ) lesen . Meine gesamte haproxy.cfgDatei für eines meiner Go-Projekte folgt, falls Sie einen Startpunkt benötigen.

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 ist noch einfacher.

In Bezug auf die Dienststeuerung führe ich mein Go-Programm als Systemdienst aus. Ich denke, jeder macht das. Auf meinem Server wird Ubuntu ausgeführt, daher wird Upstart verwendet. Ich habe dies /etc/init/myapp.conffür Upstart festgelegt, um mein Programm zu steuern:

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

Ein weiterer Aspekt ist die Bereitstellung. Eine Option ist die Bereitstellung, indem nur eine Binärdatei des Programms und der erforderlichen Assets gesendet wird. Dies ist eine ziemlich gute Lösung IMO. Ich benutze die andere Option: Kompilieren auf dem Server. (Ich werde auf die Bereitstellung mit Binärdateien umsteigen, wenn ich ein sogenanntes "Continuous Integration / Deployment" -System einrichte.)

Ich habe ein kleines Shell-Skript auf dem Server, das Code für mein Projekt aus einem entfernten Git-Repository abruft, ihn mit Go erstellt, die Binärdateien und andere Assets kopiert ~/myapp/und den Dienst neu startet.

Insgesamt unterscheidet sich das Ganze nicht wesentlich von anderen Server-Setups: Sie müssen eine Möglichkeit haben, Ihren Code auszuführen und HTTP-Anforderungen bedienen zu lassen. In der Praxis hat sich Go für dieses Zeug als sehr stabil erwiesen.

Mostafa
quelle
9
Gute Antwort! Gute Beispiele für alles, was für eine empfohlene Grundeinstellung benötigt wird.
Intermernet
Was tun Sie gegen die Protokollrotation? Das ist so ziemlich der einzige Grund, warum ich Supervisord benutze, aber es leidet, wenn zu viel Protokollierung stattfindet.
Fiorix
@fiorix, ich bin mir ziemlich sicher, dass Sie eine andere SO-Frage zur Protokollrotation öffnen könnten. Wenn Sie jedoch unter Unix arbeiten und Standardtools verwenden möchten, lesen Sie logrotate: linuxcommand.org/man_pages/logrotate8.html . Dies wird von vielen bekannten Diensten (Apache, Yum usw.) verwendet und ist ziemlich einfach zu konfigurieren.
Doody P
Wie einfach wäre es, in Go einen eigenen Reverse-Proxy zu erstellen? Wäre dies eine wesentlich schlechtere Idee als die Verwendung von Nginx oder Haproxy? Ich meine, Go kommt mit großartiger HTTP / HTTPS / HTTP / 2-Unterstützung.
Thomasrutter
58

Nginx für:

  • Reverse HTTP-Proxy zu meiner Go-Anwendung
  • Behandlung statischer Dateien
  • SSL-Beendigung
  • HTTP-Header (Cache-Control et al.)
  • Zugriffsprotokolle (und damit Nutzung der Systemprotokollrotation)
  • Umschreiben (nackt zu www, http: // zu https: // usw.)

nginx macht dies sehr einfach, und obwohl Sie dank Go direkt von Go aus bedienen können net/http, gibt es eine Menge "Neuerfindung des Rads" und Dinge wie globale HTTP-Header beinhalten einige Boilerplates, die Sie wahrscheinlich vermeiden können.

Supervisor für die Verwaltung meiner Go-Binärdatei. Ubuntus Upstart (wie von Mostafa erwähnt) ist ebenfalls gut, aber ich mag Supervisord, da es relativ distro-agnostisch und gut dokumentiert ist.

Supervisord, für mich:

  • Führt meine Go-Binärdatei nach Bedarf aus
  • Bringt es nach einem Absturz auf
  • Enthält meine Umgebungsvariablen (Sitzungsauthentifizierungsschlüssel usw.) als Teil einer einzelnen Konfiguration.
  • Führt meine Datenbank aus (um sicherzustellen, dass meine Go-Binärdatei nicht ohne sie ausgeführt wird)
Elithrar
quelle
8

Für diejenigen, die eine einfache Go-App als Daemon ausführen möchten, verwenden Sie systemd (unterstützt von vielen Linux-Distributionen) anstelle von Upstart.

Erstellen Sie eine Servicedatei unter

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

Eingeben

[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

Aktivieren und starten Sie dann den Dienst

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

systemd verfügt über ein separates Journaling-System, mit dem Sie Protokolle zur einfachen Fehlerbehebung erstellen können.

mixdev
quelle
5

Sie können Ihre Binärdatei an einen Socket an privilegierte Ports mit Internetdomäne (Portnummern unter 1024) binden setcap

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

  1. Dieser Befehl muss eskaliert werden. sudowie nötig
  2. Jede neue Version Ihres Programms führt zu einer neuen Binärdatei, die von erneut autorisiert werden muss setcap

setcap Dokumentation

cap_net_bind_service Dokumentation

Emperor_Earth
quelle