天天看點

Go開發 之 單端口轉發到多個端口

文章目錄

  • ​​1、背景​​
  • ​​2、正題​​
  • ​​3、源碼​​
  • ​​4、配置​​
  • ​​5、效果​​

1、背景

運維和我提到這個需求的時候,我先是一愣,第一時間想到的是nginx,然後運維說nginx沒有這個功能……之是以選擇用go語言,主要兩點:

  • 靜态語言性能夠用
  • 不用部署其它包,可以直接丢一個可執行程式和一個配置上去就能運作。

2、正題

這種東西,一看就肯定有前輩做過,于是自行github上找了一圈,果然有答案:

​​​https://github.com/vulcand/oxy​​

于是用了,上述這個包,寫程式調用一下即可。

該包引用了其它開源的包哈(也可以用go mod哈,就不用自己去下載下傳包啦~):

​​​https://github.com/gorilla/websocket​​​​https://github.com/mailgun/timetools​​​​https://github.com/sirupsen/logrus​​

3、源碼

/**
 * 2020 5 21 - sha zhen yu
 */
package main

import(
  "log"
  "strings"
  "net/http"
  "io/ioutil"
  "encoding/json"
  "github.com/vulcand/oxy/forward"
  "github.com/vulcand/oxy/testutils"
)

type Rule struct{
  Domain string `json:Domain`
  Address string `json:Address`
}
type Setting struct{
  MainPort string `json:MainPort`
  Rules []Rule `json:Rules`
}

var setting Setting
var fwd *forward.Forwarder

func redirectHandle(w http.ResponseWriter, r *http.Request){
  address := getAddress(r.Host)
  if address != "" {
    r.URL = testutils.ParseURI("http://"+address)
    log.Println("Info: "+r.Host+" => "+address)
    fwd.ServeHTTP(w, r)
  } else {
    w.WriteHeader(500)
  }
}

func getAddress(host string) string {
  for _,v := range setting.Rules {
    if strings.Compare(host,v.Domain) == 0 {
      return v.Address
    }
  }
  return ""
}

func Init(){
  log.Println("Init: start")
  var Data,err = ioutil.ReadFile("setting.json")
  if err != nil{
    log.Fatal("Read Config File Error!")
    return
  }
  err = json.Unmarshal(Data,&setting)
  if err != nil{
    log.Fatal("Read Config JSON Error!Please Check!")
    return
  }
  log.Println("Main Port: "+setting.MainPort)
  for i:=0;i<len(setting.Rules);i++{
    log.Println("Import Rule: "+setting.Rules[i].Domain+" <----> "+setting.Rules[i].Address)
  }
  log.Println("Init: end")
}

func main(){
  Init()
  fwd, _ = forward.New()
  redirect := http.HandlerFunc(redirectHandle)
  s := &http.Server{
    Addr:           ":"+setting.MainPort,
    Handler:        redirect,
  }
  log.Println("Info: Listening port "+s.Addr)
  s.ListenAndServe()
}      

4、配置

{
  "name": "HttpProxyForwarding",
  "version": "1.0.0",
  "MainPort": "80",
  "Rules": [
    {
      "Domain":"test1.shazhenyu.com",
      "Address":"193.207.242.129:81"
    },
    {
      "Domain":"test2.shazhenyu.com",
      "Address":"193.207.242.129:82"
    }
  ]
}      

5、效果