Configuration de l'application Web de production Golang

120

Pour ceux d'entre vous exécutant des backends Go en production:

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

Je n'ai pas vu grand-chose sur ce sujet à part les gens qui utilisent le package net / http de la bibliothèque standard pour maintenir un serveur en marche. J'ai lu en utilisant Nginx pour transmettre des demandes à un serveur Go - Nginx avec 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 aparté sur mon intention - je prévois un serveur backend REST alimenté par Go pour mon prochain projet et je veux m'assurer que Go sera viable pour le lancement du projet en direct avant que j'investisse trop dans celui-ci.

Chaseph
la source
3
"le serveur ne redémarrerait pas automatiquement si la machine était redémarrée (sans scripts de configuration supplémentaires)." Je ne pense pas que cela puisse être fait. Idéalement, vous avez créé des scripts init / systemd / upstart pour le service. C'est la méthode recommandée pour contrôler tout démon Unix.
Intermernet le
Tu as raison. Je suppose que je l'ai voulu dire par contraste avec un serveur tel qu'apache, qui configure automatiquement ces fonctionnalités au moment de l'installation.
Chaseph

Réponses:

134

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, afin qu'il écoute sur le port 80 et se connecte à votre programme sur le port, par exemple 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 en façade. Tout proxy inverse pourrait fonctionner. Nginx est également une excellente option (beaucoup plus populaire que HAProxy et capable d'en faire plus).

HAProxy est très simple à configurer si vous lisez sa documentation ( version HTML ). Mon haproxy.cfgdossier complet pour l'un de mes projets Go suit, au cas où vous auriez besoin d'un point 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, j'exécute 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.confpour Upstart pour 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 en envoyant simplement le fichier binaire du programme et des ressources nécessaires. C'est une très bonne solution IMO. J'utilise l'autre option: la compilation sur serveur. (Je passerai au déploiement avec des fichiers binaires lorsque je configurerai un système dit d '«intégration / déploiement continu».)

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 binaires et autres actifs ~/myapp/et redémarre le service.

Dans l'ensemble, le tout 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 faire servir des requêtes HTTP. En pratique, Go s'est avéré très stable pour ce genre de choses.

Mostafa
la source
9
Très bonne réponse! Bons exemples de tout ce qui est nécessaire pour une configuration de base recommandée.
Intermernet
Que faites-vous de la rotation des journaux? C'est à peu près la seule raison pour laquelle j'utilise Supervisord, mais cela souffre quand il y a trop de journalisation.
fiorix
@fiorix, je suis à peu près sûr que vous pourriez ouvrir une autre question SO sur la rotation des journaux, mais si vous êtes sous unix et que vous souhaitez utiliser des outils standard, consultez logrotate: linuxcommand.org/man_pages/logrotate8.html . Ceci est utilisé par de nombreux services bien connus (apache, yum, etc.) et est assez facile à configurer.
Doody P
Serait-il facile de créer votre propre proxy inverse dans Go? Serait-ce une idée bien pire que d'utiliser nginx ou haproxy? Je veux dire que Go est livré avec un excellent support HTTP / HTTPS / HTTP / 2.
thomasrutter
58

nginx pour:

  • Inverser le proxy HTTP vers mon application Go
  • Gestion statique des fichiers
  • Résiliation SSL
  • En-têtes HTTP (Cache-Control, et. Al)
  • Accéder aux journaux (et donc tirer parti de la rotation des journaux système)
  • Réécritures (nue sur www, http: // sur https: //, etc.)

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

superviseur pour gérer mon binaire Go. Upstart d'Ubuntu (comme mentionné par Mostafa) est également bon, mais j'aime superviser car il est relativement indépendant de la distribution et est bien documenté.

Supervisord, pour moi:

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

Pour ceux qui veulent une application go simple exécutée 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 a un système de journalisation séparé qui vous permettra de suivre les journaux pour faciliter le dépannage.

mixdev
la source
5

Vous pouvez lier votre binaire à une socket aux ports privilégiés du domaine Internet (numéros de port inférieurs à 1024) en utilisant setcap

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

  1. Cette commande doit être escaladée. sudole cas échéant
  2. Chaque nouvelle version de votre programme entraînera un nouveau binaire qui devra être réautorisé par setcap

setcap Documentation

cap_net_bind_service Documentation

Empereur_Terre
la source