Golang 生产 Web 应用程序配置

Posted

技术标签:

【中文标题】Golang 生产 Web 应用程序配置【英文标题】:Golang production web application configuration 【发布时间】:2013-06-30 16:42:04 【问题描述】:

对于那些在生产中运行 Go 后端的人:

运行 Go Web 应用程序的堆栈/配置是什么?

除了人们使用标准库 net/http 包来保持服务器运行之外,我还没有看到太多关于这个主题的内容。我读到使用 nginx 将请求传递给 Go 服务器 - nginx with Go

这对我来说似乎有点脆弱。例如,如果机器重新启动,服务器不会自动重新启动(无需额外的配置脚本)。

有更可靠的生产设置吗?

顺便说一下我的意图 - 我正在为我的下一个项目计划一个支持 Go 的 REST 后端服务器,并希望在我投入过多之前确保 Go 在启动项目之前是可行的。

【问题讨论】:

"如果机器重新启动,服务器不会自动重新启动(无需额外的配置脚本)。"我不认为这是可以做到的。理想情况下,您已经为服务创建了 init / systemd / upstart 脚本。这是控制任何 unix 守护进程的推荐方式。 没错。我想我的意思是与 apache 等服务器形成对比,后者会在安装时自动设置这些功能。 【参考方案1】:

Go 程序可以监听 80 端口并直接处理 HTTP 请求。相反,您可能希望在 Go 程序前面使用反向代理,以便它侦听端口 80 并连接到端口上的程序,例如 4000。这样做有很多原因:不必运行您的 Go 程序以 root 身份为同一主机上的其他网站/服务提供服务、SSL 终止、负载平衡、日志记录等。

我在前面使用HAProxy。任何反向代理都可以工作。 Nginx 也是一个不错的选择(比 HAProxy 更受欢迎并且能够做更多事情)。

如果您阅读它的documentation (html version),HAProxy 很容易配置。我的一个 Go 项目的整个 haproxy.cfg 文件如下,以防你需要一个起始点。

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 更简单。

关于服务控制,我将 Go 程序作为系统服务运行。我想每个人都这样做。我的服务器运行 Ubuntu,所以它使用 Upstart。我把这个放在/etc/init/myapp.conf 让Upstart 来控制我的程序:

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

另一个方面是部署。一种选择是仅通过发送程序的二进制文件和必要的资产来进行部署。这是一个非常棒的解决方案 IMO。我使用另一个选项:在服务器上编译。 (当我设置所谓的“持续集成/部署”系统时,我将切换到使用二进制文件进行部署。)

我在服务器上有一个小 shell 脚本,它从远程 Git 存储库为我的项目提取代码,使用 Go 构建它,将二进制文件和其他资产复制到 ~/myapp/,然后重新启动服务。

总的来说,整个事情与任何其他服务器设置没有太大区别:您必须有一种方法来运行您的代码并让它服务于 HTTP 请求。在实践中,Go 被证明是非常稳定的。

【讨论】:

很好的答案!推荐的基本设置所需的一切的好例子。 你对日志轮换做了什么?这几乎是我使用 supervisord 的唯一原因,但是当有太多日志记录时它会受到影响。 @fiorix,我很确定您可以打开一个关于日志轮换的不同 SO 问题,但如果您使用的是 unix 并且想要使用标准工具,请查看 logrotate:linuxcommand.org/man_pages/logrotate8.html。这被许多知名服务(apache、yum 等)使用,并且相当容易配置。 在 Go 中创建自己的反向代理有多容易?这会比使用 nginx 或 haproxy 更糟糕吗?我的意思是 Go 提供了很好的 HTTP/HTTPS/HTTP/2 支持。【参考方案2】:

nginx 为:

反向 HTTP 代理到我的 Go 应用程序 静态文件处理 SSL 终止 HTTP 标头(Cache-Control 等) 访问日志(并因此利用系统日志轮换) 重写(裸到 www、http:// 到 https:// 等)

nginx 让这一切变得非常简单,尽管感谢 net/http,您可以直接从 Go 中提供服务,但有很多“重新发明***”,并且像全局 HTTP 标头这样的东西涉及一些您可以避免的样板。

supervisord 用于管理我的 Go 二进制文件。 Ubuntu 的 Upstart(如 Mostafa 所述)也不错,但我喜欢 supervisord,因为它与发行版相对无关并且有据可查。

主管,对我来说:

根据需要运行我的 Go 二进制文件 在崩溃后启动它 将我的环境变量(会话身份验证密钥等)保存为单个配置的一部分。 运行我的数据库(以确保没有它我的 Go 二进制文件不会运行)

【讨论】:

【参考方案3】:

您可以使用 setcap 将二进制文件绑定到 Internet 域特权端口(端口号小于 1024)的套接字

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

    此命令需要升级。 sudo 必要时 程序的每个新版本都会产生一个新的二进制文件,需要setcap 重新授权

setcap documentation

cap_net_bind_service documentation

【讨论】:

【参考方案4】:

对于那些想要简单的 go 应用程序作为守护程序运行的人,使用 systemd(许多 Linux 发行版支持)而不是 Upstart。

在以下位置创建服务文件

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

输入

[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

然后启用并启动服务

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

systemd 有一个单独的日志系统,可以让您跟踪日志以便于排除故障。

【讨论】:

以上是关于Golang 生产 Web 应用程序配置的主要内容,如果未能解决你的问题,请参考以下文章

在多包中使用记录器/配置 Golang 生产的最佳实践

GoLang开源生态

Go+Vue.js快速搭建Web应用

[golang]单向channel的应用“生产消费者模型”

如何部署Golang应用

golang 使用golang构建Web应用程序的字段验证实例