遗憾的是,我无法在生产服务器上部署基本的Golang WebApp。经过许多文档和教程后,我了解到我需要将Golang WebApp作为守护进程运行。
首先要做的事情是:生产服务器是运行Ubuntu 16.04的单个IP,基于Apache的多个VirtualHosts /etc/apache2/sites-enabled/
。
Golang环境变量
# set golang environment vars
export GOROOT=/usr/local/go
# set multiple gopaths seperated by ":"
export GOPATH=/var/www/go_projects/gotest.domain2.com
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
# set PATH so it includes user's private bin directories
PATH="$HOME/bin:$HOME/.local/bin:$PATH"
Systemd守护程序文件
[Unit]
Description=GoTest Webserver
[Service]
Type=simple
WorkingDirectory=/var/www/go_projects/gotest.domain2.com
ExecStart=/var/www/go_projects/gotest.domain2.com/main #binary file
[Install]
WantedBy=multi-user.target
VirtualHost Conf
<VirtualHost *:80>
ServerName gotest.domain.com
DocumentRoot /var/www/go_projects/gotest.domain2.com
<Directory /var/www/go_projects/gotest.domain2.com>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
转到文件
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
遗憾的是http://gotest.domain2.com上的程序未执行。它列出了DocumentRoot
手动运行返回
admin@xyz:/var/www/go_projects/gotest.domain2.com$ ./main
2018/02/18 15:52:58 listen tcp :8080: bind: address already in use
我缺少什么或部署方法主要是错误的? 干杯!
编辑: 正如Michael Ernst所建议的那样,我尝试改变端口/代理设置,结果如下:
http://gotest.domain2.com leads to 503 Service Unavailable
以下是sudo netstat -talpen
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 16367 1250/sshd
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 0 473536 26340/master
tcp 0 0 0.0.0.0:143 0.0.0.0:* LISTEN 0 16604 1417/dovecot
tcp 0 0 0.0.0.0:2000 0.0.0.0:* LISTEN 5001 17289 1652/asterisk
tcp 0 xx.xx.xx.xx:22 xx.xx.xx.xx:6126 ESTABLISHED 0 615988 13025/sshd: admin [
tcp6 0 0 :::22 :::* LISTEN 0 16369 1250/sshd
tcp6 0 0 :::25 :::* LISTEN 0 473537 26340/master
tcp6 0 0 :::3306 :::* LISTEN 111 17564 1391/mysqld
tcp6 0 0 :::143 :::* LISTEN 0 16605 1417/dovecot
tcp6 0 0 :::80 :::* LISTEN 0 612412 12554/apache2
tcp6 0 0 xx.xx.xx.xx:80 xx.xx.xx.xx:6128 FIN_WAIT2 0 0 -
tcp6 0 0 xx.xx.xx.xx:80 xx.xx.xx.xx:6129 ESTABLISHED 33 615029 12561/apache2
知道问题出在哪里?
答案 0 :(得分:2)
至于配置apache:
您需要启动go应用程序并在apache配置中反向代理请求到端口8080(您编写的go守护进程监听)。 go应用程序需要始终运行,因此您可能希望在系统启动时启动它。与从apache调用的php不同,go应该以二进制文件的形式运行。
关于您的端口问题:
确保您的应用程序尚未启动,并且没有其他应用程序正在侦听端口8080.(您可以使用netstat -talpen
查看)
编辑: 端口8080通常是http代理。是否有代理或其他应用程序在这一点上运行?
编辑: 你可以像这样配置你的apache:
<VirtualHost *:80>
ProxyPreserveHost On
ProxyRequests Off
ServerName www.example.com
ServerAlias example.com
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
您可能还希望使go-application的端口可配置,以便在需要更改端口时不需要重新编译代码。您也可以绑定到localhost接口,这样,如果您没有配置防火墙,人们只能通过apache访问go应用程序而不能直接与go应用程序通信
// define the flag
port := flags.Int("port", 8080, "port to listen on")
// parse the flags
flags.Parse();
// here you might want to add code to make sure the port is valid.
// start webserver
log.Fatal(http.ListenAndServe("localhost:"+strconv.Atoi(*port), nil))