对于那些在生产中运行Go后端的人:
运行Go Web应用程序的堆栈/配置是什么?
除了使用标准库net / http包来保持服务器运行的人之外,我还没有看到这个主题。我阅读使用Nginx将请求传递给Go服务器 - nginx with Go
这对我来说似乎有点脆弱。例如,如果重新启动计算机,服务器将不会自动重新启动(没有其他配置脚本)。
是否有更稳固的生产设置?
除了我的意图之外 - 我正在为我的下一个项目计划一个Go支持的REST后端服务器,并希望确保Go能够在我投入太多资金之前实现启动项目。
答案 0 :(得分:131)
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已被证明对这些东西非常稳定。
答案 1 :(得分:57)
nginx:
nginx让这很容易,虽然你可以直接从Go服务,感谢net/http
,但是有很多“重新发明轮子”,而像全局HTTP头这样的东西涉及到一些你可以避免的样板。
supervisord用于管理我的Go二进制文件。 Ubuntu的Upstart(正如Mostafa所提到的)也很好,但我喜欢supervisord,因为它相对与驱动程序无关并且有很好的文档记录。
Supervisord,对我来说:
答案 2 :(得分:6)
对于那些想要将简单的应用程序作为守护程序运行的人,请使用 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有一个单独的日记系统,可以让你记录日志,以便轻松解决问题。
答案 3 :(得分:4)
您可以使用setcap
setcap 'cap_net_bind_service=+ep' /path/to/binary
sudo
setcap