在一个 IP 上托管多个 Golang 站点并根据域请求提供服务?

Posted

技术标签:

【中文标题】在一个 IP 上托管多个 Golang 站点并根据域请求提供服务?【英文标题】:Host Multiple Golang Sites on One IP and Serve Depending on Domain Request? 【发布时间】:2017-02-15 02:11:20 【问题描述】:

我正在运行安装了 Ubuntu 的 VPS。如何在url中不指定端口(xxx.xxx.xxx.xxx:8084)的情况下,使用同一个VPS(同一个IP)服务多个Golang网站?

例如,Golang 应用 1 正在侦听端口 8084Golang 应用 2 正在侦听端口 8060。我希望在有人从域 example1.com 请求时服务 Golang 应用程序 1,当有人从域 example2.com 请求时服务 Golang 应用程序 2。

我确信你可以使用 nginx 做到这一点,但我无法弄清楚如何。

【问题讨论】:

nginx.com/resources/admin-guide/reverse-proxy 【参考方案1】:

Nginx 免费解决方案。

首先你可以重定向connections on port 80 as a normal user

sudo apt-get install iptables-persistent
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8000
sudo netfilter-persistent save
sudo netfilter-persistent reload

然后使用gorilla/mux 或类似方法为每个主机创建一个路由,甚至从中获取一个“子路由器”

r := mux.NewRouter()
s := r.Host("www.example.com").Subrouter()

所以完整的解决方案是

package main

import (
    "net/http"
    "github.com/gorilla/mux"
    "fmt"
)

func Example1IndexHandler(w http.ResponseWriter, r *http.Request) 
    fmt.Fprintf(w, "Hello www.example1.com!") // send data to client side


func Example2IndexHandler(w http.ResponseWriter, r *http.Request) 
    fmt.Fprintf(w, "Hello www.example2.com!") // send data to client side


func main() 
    r := mux.NewRouter()
    s1 := r.Host("www.example1.com").Subrouter()
    s2 := r.Host("www.example2.com").Subrouter()

    s1.HandleFunc("/", Example1IndexHandler)
    s2.HandleFunc("/", Example2IndexHandler)

    http.ListenAndServe(":8000", nil)

【讨论】:

我知道这是如何工作的,但是要托管多个网站,这种方法可能有点混乱。 这完全取决于架构设计。以microservices 为例。我并不是说反向代理是一个坏主意,只是需要考虑更多选项。【参考方案2】:

请尝试以下代码,

server 
   ...
   server_name www.example1.com example1.com;
   ...
   location / 
      proxy_pass app_ip:8084;
   
   ...


...

server 
   ...
   server_name www.example2.com example2.com;
   ...
   location / 
      proxy_pass app_ip:8060;
   
   ...

app_ip 是托管相同机器的机器的 ip,如果在同一台机器上,请输入 http://127.0.0.1http://localhost

【讨论】:

这是给 Nginx 的? 是的,先生,它是用于 nginx, 抱歉耽搁了,我只是在设置,我现在就试试! 罗杰先生, 对于每个站点,我应该声明一个新的 server 还是只让 1 个 server 管理我的所有 go-sites?【参考方案3】:

您不需要任何第三方路由器。只需创建一个实现 http.Handler 接口的主机交换机。

import (
    "fmt"
    "log"
    "net/http"
)

type HostSwitch map[string]http.Handler

// Implement the ServerHTTP method
func (hs HostSwitch) ServeHTTP(w http.ResponseWriter, r *http.Request) 
    if handler, ok := hs[r.Host]; ok && handler != nil 
        handler.ServeHTTP(w, r)
     else 
        http.Error(w, "Forbidden", http.StatusForbidden)
    

我希望这能给你这个想法。如果您需要完整的代码示例https://play.golang.org/p/bMbKPGE7LhT

您也可以在my blog上阅读更多相关信息

【讨论】:

感谢这个解决方案,一直在寻找使用 go 而不是 nginx 或 apache 的东西。

以上是关于在一个 IP 上托管多个 Golang 站点并根据域请求提供服务?的主要内容,如果未能解决你的问题,请参考以下文章

在多个绑定上托管 IIS 站点时如何获取正确的本地地址 URI?

在端口 80 上托管多个网站

使用 apache 在单个 VPS 上托管多个 laravel 5.5 项目?

多个站点的 Linux 服务器子域

在 Netlify 上托管时设置电子邮件

IIS 中的多个站点。 HTTPS 冲突