web-dev-qa-db-fra.com

Configuration de l'application Web de production Golang

Pour ceux d'entre vous qui exécutent Go backends en production:

Quelle est votre pile/configuration pour exécuter une application Web Go?

À ce sujet, je n'ai pas vu grand-chose en dehors des utilisateurs du paquetage net/http de la bibliothèque standard pour faire fonctionner un serveur. J'ai lu à l'aide de Nginx pour transmettre des requêtes à un serveur Go - nginx with Go

Cela me semble un peu fragile. Par exemple, le serveur ne redémarrerait pas automatiquement si la machine était redémarrée (sans scripts de configuration supplémentaires).

Existe-t-il une configuration de production plus solide?

Un côté de mon intention - je prévois un serveur back end propulsé par Go REST pour mon prochain projet et je veux être sûr que Go sera viable pour le lancement du projet en direct avant que j'investisse aussi beaucoup dedans.

116
Chaseph

Les programmes Go peuvent écouter sur le port 80 et servir directement les requêtes HTTP. Au lieu de cela, vous voudrez peut-être utiliser un proxy inverse devant votre programme Go, de manière à ce qu'il écoute sur le port 80 et se connecte à votre programme sur le port 4000. Il y a de nombreuses raisons pour faire ce dernier: ne pas avoir à exécuter votre programme Go en tant que root, servant d’autres sites Web/services sur le même hôte, terminaison SSL, équilibrage de charge, journalisation, etc.

J'utilise HAProxy devant. Tout proxy inverse pourrait fonctionner. Nginx est également une excellente option (beaucoup plus populaire que HAProxy et capable de faire plus).

HAProxy est très facile à configurer si vous lisez sa documentation ( version HTML ). Mon ensemble haproxy.cfg Un fichier pour l'un de mes projets Go suit, au cas où vous auriez besoin d'un pont de départ.

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 est encore plus facile.

En ce qui concerne le contrôle des services, je lance mon programme Go en tant que service système. Je pense que tout le monde fait ça. Mon serveur exécute Ubuntu, il utilise donc Upstart. J'ai mis ceci à /etc/init/myapp.conf pour que Upstart puisse contrôler mon programme:

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 autre aspect est le déploiement. Une option consiste à déployer simplement en envoyant un fichier binaire du programme et des actifs nécessaires. C’est une très bonne solution IMO. J'utilise l'autre option: compiler sur le serveur. (Je vais passer au déploiement avec des fichiers binaires lorsque je configure un système appelé "Continuous Integration/Deployment".)

J'ai un petit script Shell sur le serveur qui extrait le code de mon projet à partir d'un référentiel Git distant, le construit avec Go, copie les fichiers binaires et les autres éléments dans ~/myapp/ et redémarre le service.

Globalement, l’ensemble n’est pas très différent de toute autre configuration de serveur: vous devez avoir un moyen d’exécuter votre code et de le laisser répondre aux requêtes HTTP. En pratique, Go s’est avéré très stable pour ce genre de choses.

131
Mostafa

nginx pour:

  • Proxy HTTP inversé vers mon application Go
  • Traitement de fichier statique
  • Résiliation SSL
  • En-têtes HTTP (Cache-Control, et al)
  • Accéder aux journaux (et donc tirer parti de la rotation des journaux du système)
  • Réécrit (nue sur www, http: // sur https: //, etc.)

nginx rend cela très facile, et bien que vous puissiez servir directement de Go grâce à net/http, il y a beaucoup de "réinvention de la roue" et des éléments tels que les en-têtes HTTP globaux impliquent certaines choses que vous pouvez probablement éviter.

supervisord pour gérer mon binaire Go. Ubuntu Upstart (comme mentionné par Mostafa) est également bon, mais j'aime Supervord car il est relativement distro-agnostique et est bien documenté.

Supervisord, pour moi:

  • Exécute mon binaire Go au besoin
  • Le fait monter après un crash
  • Contient mes variables d'environnement (clés d'authentification de session, etc.) dans le cadre d'une seule configuration.
  • Lance ma base de données (pour m'assurer que mon binaire Go ne fonctionne pas sans elle)
57
elithrar

Pour ceux qui souhaitent utiliser une application simple en tant que démon, utilisez systemd (pris en charge par de nombreuses distributions Linux) au lieu de Upstart.

Créez un fichier de service sur

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

Entrer

[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

Puis activez et démarrez le service

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

systemd dispose d'un système de journalisation distinct qui vous permettra de conserver les journaux pour faciliter le dépannage.

6
mixdev

Vous pouvez lier votre binaire à un socket vers des ports privilégiés du domaine Internet (numéros de port inférieurs à 1024) à l'aide de setcap

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

  1. Cette commande doit être remontée. Sudo si nécessaire
  2. Chaque nouvelle version de votre programme donnera un nouveau binaire qui devra être réautorisé par setcap

setcap documentation

cap_net_bind_service documentation

4
Emperor_Earth