Konfigurasi aplikasi web produksi Golang

120

Bagi Anda yang menjalankan Go backend dalam produksi:

Apa tumpukan / konfigurasi Anda untuk menjalankan aplikasi web Go?

Saya belum melihat banyak tentang topik ini selain orang-orang yang menggunakan paket perpustakaan standar net / http untuk menjaga server tetap berjalan. Saya membaca menggunakan Nginx untuk mengirimkan permintaan ke server Go - nginx dengan Go

Ini tampaknya sedikit rapuh bagi saya. Misalnya, server tidak akan otomatis memulai ulang jika mesin di-restart (tanpa skrip konfigurasi tambahan).

Apakah ada penyiapan produksi yang lebih solid?

Selain maksud saya - saya merencanakan server backend REST bertenaga Go untuk proyek saya berikutnya dan ingin memastikan Go akan layak untuk meluncurkan proyek secara langsung sebelum saya berinvestasi terlalu banyak ke dalamnya.

Chaseph
sumber
3
"server tidak akan secara otomatis memulai ulang jika mesin di-restart (tanpa skrip konfigurasi tambahan)." Saya tidak berpikir ini bisa dilakukan. Idealnya Anda membuat skrip init / systemd / upstart untuk layanan tersebut. Ini adalah cara yang disarankan untuk mengontrol daemon unix.
Intermernet
Kamu benar. Saya rasa yang saya maksud adalah kontras dengan server seperti apache, yang secara otomatis mengatur fitur-fitur tersebut pada waktu penginstalan.
Chaseph

Jawaban:

134

Program Go dapat mendengarkan pada port 80 dan melayani permintaan HTTP secara langsung. Alih-alih, Anda mungkin ingin menggunakan proxy terbalik di depan program Go Anda, sehingga program ini mendengarkan di port 80 dan dan terhubung ke program Anda di port, katakanlah, 4000. Ada banyak alasan untuk melakukan yang terakhir: tidak harus menjalankan program Go Anda sebagai root, melayani situs web / layanan lain di host yang sama, penghentian SSL, load balancing, logging, dll.

Saya menggunakan HAProxy di depan. Proksi terbalik apa pun dapat berfungsi. Nginx juga merupakan opsi yang bagus (jauh lebih populer daripada HAProxy dan mampu melakukan lebih banyak hal).

HAProxy sangat mudah dikonfigurasi jika Anda membaca dokumentasinya ( versi HTML ). Seluruh haproxy.cfgfile saya untuk salah satu proyek Go saya mengikuti, jika Anda memerlukan pont awal.

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 bahkan lebih mudah.

Mengenai kontrol layanan, saya menjalankan program Go saya sebagai layanan sistem. Saya pikir semua orang melakukan itu. Server saya menjalankan Ubuntu, jadi menggunakan Upstart. Saya telah meletakkan ini di /etc/init/myapp.confuntuk Pemula untuk mengontrol program saya:

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

Aspek lainnya adalah penerapan. Salah satu opsinya adalah menerapkan hanya dengan mengirimkan file biner dari program dan aset yang diperlukan. Ini adalah solusi IMO yang cukup bagus. Saya menggunakan opsi lain: kompilasi di server. (Saya akan beralih ke penerapan dengan file biner ketika saya menyiapkan apa yang disebut sistem "Integrasi / Penerapan Berkelanjutan".)

Saya memiliki skrip shell kecil di server yang menarik kode untuk proyek saya dari repositori Git jarak jauh, membangunnya dengan Go, menyalin binari dan aset lainnya ke ~/myapp/ , dan memulai ulang layanan.

Secara keseluruhan, semuanya tidak jauh berbeda dari penyiapan server lainnya: Anda harus memiliki cara untuk menjalankan kode Anda dan membuatnya melayani permintaan HTTP. Dalam praktiknya, Go terbukti sangat stabil untuk hal ini.

Mostafa
sumber
9
Jawaban yang bagus! Contoh bagus dari semua yang diperlukan untuk penyiapan dasar yang direkomendasikan.
Intermernet
Apa yang Anda lakukan tentang rotasi log? Itulah satu-satunya alasan mengapa saya menggunakan supervisord tetapi menderita ketika ada terlalu banyak logging yang terjadi.
fiorix
@fiorix, saya cukup yakin Anda dapat membuka pertanyaan SO yang berbeda tentang rotasi log, tetapi masih jika Anda menggunakan unix dan ingin menggunakan alat standar, lihat logrotate: linuxcommand.org/man_pages/logrotate8.html . Ini digunakan oleh banyak layanan terkenal (apache, yum, dll.) Dan cukup mudah dikonfigurasi.
Doody P
Seberapa mudah membuat reverse proxy Anda sendiri di Go? Apakah ini ide yang jauh lebih buruk daripada menggunakan nginx atau haproxy? Maksud saya Go hadir dengan dukungan HTTP / HTTPS / HTTP / 2 yang hebat.
thomasrutter
58

nginx untuk:

  • Membalikkan proxy HTTP ke aplikasi Go saya
  • Penanganan file statis
  • Pengakhiran SSL
  • Header HTTP (Cache-Control, dkk)
  • Akses log (dan karenanya memanfaatkan rotasi log sistem)
  • Penulisan ulang (tanpa www, http: // ke https: //, dll.)

nginx membuatnya sangat mudah, dan meskipun Anda dapat melayani langsung dari Go berkat net/http, ada banyak "menemukan kembali roda" dan hal-hal seperti header HTTP global melibatkan beberapa boilerplate yang mungkin dapat Anda hindari.

supervisord untuk mengelola biner Go saya. Pemula Ubuntu (seperti yang disebutkan oleh Mostafa) juga bagus, tetapi saya suka supervisord karena relatif distro-agnostik dan didokumentasikan dengan baik.

Supervisord, untuk saya:

  • Menjalankan biner Go saya sesuai kebutuhan
  • Membawanya setelah terjadi kecelakaan
  • Menyimpan variabel lingkungan saya (kunci autentikasi sesi, dll.) Sebagai bagian dari satu konfigurasi.
  • Menjalankan DB saya (untuk memastikan biner Go saya tidak berjalan tanpanya)
elithrar.dll
sumber
8

Bagi mereka yang menginginkan aplikasi simple go yang dijalankan sebagai daemon, gunakan systemd (Didukung oleh banyak distro linux) daripada Upstart.

Buat file layanan di

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

Memasukkan

[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

Kemudian aktifkan dan mulai layanan

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

systemd memiliki sistem penjurnalan terpisah yang memungkinkan Anda mengikuti log untuk pemecahan masalah yang mudah.

mixdev
sumber
5

Anda dapat mengikat biner Anda ke soket ke port istimewa domain Internet (nomor port kurang dari 1024) menggunakan setcap

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

  1. Perintah ini perlu ditingkatkan. sudoseperlunya
  2. Setiap versi baru dari program Anda akan menghasilkan biner baru yang perlu diberi otorisasi ulang oleh setcap

setcap dokumentasi

cap_net_bind_service dokumentasi

Emperor_Earth
sumber