124

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

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

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

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

是否有更可靠的生产设置?

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

4

4 回答 4

137

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

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

如果您阅读它的文档HTML 版本),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.confUpstart 来控制我的程序:

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 被证明对于这些东西非常稳定。

于 2013-07-03T07:49:54.237 回答
59

nginx 用于:

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

nginx 使这变得非常简单,虽然您可以直接从 Go 中提供服务net/http,但是有很多“重新发明轮子”,并且像全局 HTTP 标头这样的东西涉及一些您可能可以避免的样板。

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

主管,对我来说:

  • 根据需要运行我的 Go 二进制文件
  • 崩溃后将其调出
  • 将我的环境变量(会话身份验证密钥等)作为单个配置的一部分。
  • 运行我的数据库(以确保没有它我的 Go 二进制文件不会运行)
于 2013-07-04T03:38:55.320 回答
10

对于那些想要简单的 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 有一个单独的日志系统,可以让您跟踪日志以便于排除故障。

于 2017-05-26T23:20:05.123 回答
6

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

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

  1. 此命令需要升级。sudo有必要的
  2. 程序的每个新版本都会产生一个新的二进制文件,需要由setcap

setcap文件

cap_net_bind_service文件

于 2016-10-13T18:17:03.207 回答