反向代理以及負載均衡算法知識:
https://www.cnblogs.com/sunlong88/p/13512362.html
多層代理實現:

實現一個多層代理
一層代理 go run ichunt_micro_service/test/reverseProxy/one/oneAgent.go
二層代理 go run ichunt_micro_service/test/reverseProxy/two/twoAgent.go
真實ip go run ichunt_micro_service/test/reverseProxy/realServer.go
代理實現
func main() { rs1 := "http://127.0.0.1:2002" url1, err1 := url.Parse(rs1) if err1 != nil { log.Println(err1) } urls := []*url.URL{url1} proxy := NewMultipleHostsReverseProxy(urls) log.Println("Starting httpserver at " + addr) log.Fatal(http.ListenAndServe(addr, proxy)) } var transport = &http.Transport{ DialContext: (&net.Dialer{ Timeout: 30 * time.Second, //連接超時 KeepAlive: 30 * time.Second, //長連接超時時間 }).DialContext, MaxIdleConns: 100, //最大空閑連接 IdleConnTimeout: 90 * time.Second, //空閑超時時間 TLSHandshakeTimeout: 10 * time.Second, //tls握手超時時間 ExpectContinueTimeout: 1 * time.Second, //100-continue 超時時間 } func NewMultipleHostsReverseProxy(targets []*url.URL) *httputil.ReverseProxy { //請求協調者 director := func(req *http.Request) { //url_rewrite //127.0.0.1:2002/dir/abc ==> 127.0.0.1:2003/base/abc ?? //127.0.0.1:2002/dir/abc ==> 127.0.0.1:2002/abc //127.0.0.1:2002/abc ==> 127.0.0.1:2003/base/abc re, _ := regexp.Compile("^/dir(.*)"); req.URL.Path = re.ReplaceAllString(req.URL.Path, "$1") //隨機負載均衡 targetIndex := rand.Intn(len(targets)) target := targets[targetIndex] targetQuery := target.RawQuery req.URL.Scheme = target.Scheme req.URL.Host = target.Host // url地址重寫:重寫前:/aa 重寫后:/base/aa req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) if targetQuery == "" || req.URL.RawQuery == "" { req.URL.RawQuery = targetQuery + req.URL.RawQuery } else { req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery } if _, ok := req.Header["User-Agent"]; !ok { req.Header.Set("User-Agent", "user-agent") } //只在第一代理中設置此header頭 req.Header.Set("X-Real-Ip", req.RemoteAddr) } //更改內容 modifyFunc := func(resp *http.Response) error { //請求以下命令:curl 'http://127.0.0.1:2002/error' if resp.StatusCode != 200 { //獲取內容 oldPayload, err := ioutil.ReadAll(resp.Body) if err != nil { return err } //追加內容 newPayload := []byte("StatusCode error:" + string(oldPayload)) resp.Body = ioutil.NopCloser(bytes.NewBuffer(newPayload)) resp.ContentLength = int64(len(newPayload)) resp.Header.Set("Content-Length", strconv.FormatInt(int64(len(newPayload)), 10)) } return nil } //錯誤回調 :關閉real_server時測試,錯誤回調 errFunc := func(w http.ResponseWriter, r *http.Request, err error) { http.Error(w, "ErrorHandler error:"+err.Error(), 500) } return &httputil.ReverseProxy{ Director: director, Transport: transport, ModifyResponse: modifyFunc, ErrorHandler: errFunc} } func singleJoiningSlash(a, b string) string { aslash := strings.HasSuffix(a, "/") bslash := strings.HasPrefix(b, "/") switch { case aslash && bslash: return a + b[1:] case !aslash && !bslash: return a + "/" + b } return a + b }
反向代理,通過負載均衡獲取服務地址
運行實際服務 127.0.0.1:2003 127.0.0.1:2004
go run ichunt_micro_service/test/reverseProxy/realServer.go
啟動反向代理:內置負載均衡器 go run ichunt_micro_service/test/load_balance/main.go
//負載均衡獲取服務地址 load_balance.LoadBanlanceFactory(load_balance.LbWeightRoundRobin)
func main() { rb := load_balance.LoadBanlanceFactory(load_balance.LbWeightRoundRobin) if err := rb.Add("http://127.0.0.1:2003/", "10"); err != nil { log.Println(err) } if err := rb.Add("http://127.0.0.1:2004/", "20"); err != nil { log.Println(err) } proxy := NewMultipleHostsReverseProxy(rb) log.Println("Starting httpserver at " + addr) log.Fatal(http.ListenAndServe(addr, proxy)) }
內置幾種負載均衡算法:
hash算法 基於url和ip地址的hash
package load_balance import ( "fmt" "testing" ) func TestNewConsistentHashBanlance(t *testing.T) { rb := NewConsistentHashBanlance(10, nil) rb.Add("127.0.0.1:2003") //0 rb.Add("127.0.0.1:2004") //1 rb.Add("127.0.0.1:2005") //2 rb.Add("127.0.0.1:2006") //3 rb.Add("127.0.0.1:2007") //4 //url hash fmt.Println(rb.Get("http://127.0.0.1:2002/base/getinfo")) fmt.Println(rb.Get("http://127.0.0.1:2002/base/error")) fmt.Println(rb.Get("http://127.0.0.1:2002/base/getinfo")) fmt.Println(rb.Get("http://127.0.0.1:2002/base/changepwd")) //ip hash fmt.Println(rb.Get("127.0.0.1")) fmt.Println(rb.Get("192.168.0.1")) fmt.Println(rb.Get("127.0.0.1")) }
隨機算法
package load_balance import ( "fmt" "testing" ) func TestRandomBalance(t *testing.T) { rb := &RandomBalance{} rb.Add("127.0.0.1:2003") //0 rb.Add("127.0.0.1:2004") //1 rb.Add("127.0.0.1:2005") //2 rb.Add("127.0.0.1:2006") //3 rb.Add("127.0.0.1:2007") //4 fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) }
輪詢算法:
package load_balance import ( "fmt" "testing" ) func Test_main(t *testing.T) { rb := &RoundRobinBalance{} rb.Add("127.0.0.1:2003") //0 rb.Add("127.0.0.1:2004") //1 rb.Add("127.0.0.1:2005") //2 rb.Add("127.0.0.1:2006") //3 rb.Add("127.0.0.1:2007") //4 fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) }
加權輪詢算法:
package load_balance import ( "fmt" "testing" ) func TestLB(t *testing.T) { rb := &WeightRoundRobinBalance{} rb.Add("127.0.0.1:2003", "4") //0 rb.Add("127.0.0.1:2004", "3") //1 rb.Add("127.0.0.1:2005", "2") //2 fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) fmt.Println(rb.Next()) }
項目代碼:
https://github.com/sunlongv520/golang-loadbalance-reverseproxy
