webmain.go
package main
import (
"log"
"net/http"
"os"
"os/signal"
"strings"
)
type web1Handler struct{}
func (*web1Handler) GetIp(r *http.Request) string {
ips := r.Header.Get("x-forwarded-for")
if ips != "" {
ips_list := strings.Split(ips, ",")
if len(ips_list) > 0 && ips_list[0] != "" {
return ips_list[0]
}
}
return r.RemoteAddr;
}
func (this *web1Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
//_, _ = writer.Write([]byte("web1"))
//BasicAuth
/*auth := request.Header.Get("Authorization")
if auth == "" {
writer.Header().Set("WWW-Authenticate", `Basic realm="请输入用户名密码...."`)
writer.WriteHeader(http.StatusUnauthorized)
return
}
auth_list := strings.Split(auth, " ")
if len(auth_list) == 2 && auth_list[0] == "Basic" {
res, err := base64.StdEncoding.DecodeString(auth_list[1])
if err == nil && string(res) == "frans:zxc" {
//_, _ = writer.Write([]byte("<h1>Frans Web IP:" + request.RemoteAddr + "</h1>"))
_, _ = writer.Write([]byte("<h1>Frans Web IP:" + this.GetIp(request) + "</h1>"))
return
}
}*/
_, _ = writer.Write([]byte("web1....."))
}
type web2Handler struct{}
func (web2Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
_, _ = writer.Write([]byte("web2"))
}
type web3Handler struct{}
func (web3Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
_, _ = writer.Write([]byte("web3"))
}
func main() {
//make信号通道
c := make(chan os.Signal)
go (func() {
_ = http.ListenAndServe(":9091", &web1Handler{})
})();
go (func() {
_ = http.ListenAndServe(":9092", web2Handler{})
})();
go (func() {
_ = http.ListenAndServe(":9093", web3Handler{})
})();
//监听信号
signal.Notify(c, os.Interrupt)
//读取通道是否有值 (阻塞)
s := <-c
log.Println(s);
}
proxy.go
package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
"practice/util"
)
/*func cloneHeader(src http.Header, dest *http.Header) {
for k, v := range src {
dest.Set(k, v[0])
}
}*/
type ProxyHandler struct{}
func (*ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
}
}()
//target, _ := url.Parse(slb.SelectByRand().Host) //随机算法
//target, _ := url.Parse(slb.SelectByIPHash(r.RemoteAddr).Host) //IPHash算法
//target, _ := url.Parse(util.Slb.SelectByWeightRand().Host) //IPHash算法
target, _ := url.Parse(util.Slb.RoundRobin().Host) //IPHash算法
proxy := httputil.NewSingleHostReverseProxy(target)
proxy.ServeHTTP(w, r)
/*if r.URL.Path == "/a" {
util.RequestUrl(w, r, "http://localhost:9091")
return
}
if r.RequestURI == "/b" {
util.RequestUrl(w, r, "http://localhost:9092")
return
}*/
//遍历已经读取好了的配置文件
/*for k, v := range util.ProxyConfig {
if matched, _ := regexp.MatchString(k, r.URL.Path); matched == true {
//util.RequestUrl(w, r, v) //开始反向代理
//使用golang内置反向代理
target, _ := url.Parse(v)
proxy := httputil.NewSingleHostReverseProxy(target)
proxy.ServeHTTP(w, r)
return
}
}*/
_, _ = w.Write([]byte("Golang is Working ..."))
}
func main() {
_ = http.ListenAndServe(":8080", &ProxyHandler{})
}
util/config.go
package util
import (
"github.com/go-ini/ini"
"log"
"os"
)
var ProxyConfig map[string]string
type EnvConfig *os.File
func init() {
ProxyConfig = make(map[string]string)
EnvConfig, err := ini.Load("env")
if err != nil {
log.Println(err)
return
}
proxy, _ := EnvConfig.GetSection("proxy")
if proxy != nil {
secs := proxy.ChildSections()
for _, sec := range secs {
path, _ := sec.GetKey("path")
pass, _ := sec.GetKey("pass")
if path != nil && pass != nil {
ProxyConfig[path.Value()] = pass.Value()
}
}
}
}
util/func.go
package util
import (
"io/ioutil"
"net/http"
)
func CloneHeader(src http.Header, dest *http.Header) {
for k, v := range src {
dest.Set(k, v[0])
}
}
func RequestUrl(w http.ResponseWriter, r *http.Request, url string) {
newReq, _ := http.NewRequest(r.Method, url, r.Body)
CloneHeader(r.Header, &newReq.Header)
//增加头信息
newReq.Header.Add("x-forwarded-for", r.RemoteAddr)
newResp, _ := http.DefaultClient.Do(newReq)
getHeader := w.Header()
CloneHeader(newResp.Header, &getHeader)
w.WriteHeader(newResp.StatusCode)
defer newResp.Body.Close()
respTxt, _ := ioutil.ReadAll(newResp.Body)
_, _ = w.Write(respTxt)
}
util/loadBalance.go (算法都在此文件)
package util
import (
"hash/crc32"
"math/rand"
"time"
)
type HttpServer struct {
Host string
Weight int
}
func NewHttpServer(host string, weight int) *HttpServer {
return &HttpServer{Host: host, Weight: weight}
}
type LoadBalance struct {
Servers []*HttpServer
CurrIndex int
}
func NewLoadBalance() *LoadBalance {
return &LoadBalance{Servers: make([]*HttpServer, 0)}
}
func (this *LoadBalance) AddServer(server *HttpServer) {
this.Servers = append(this.Servers, server)
}
//随机算法
func (this *LoadBalance) SelectByRand() *HttpServer {
rand.Seed(time.Now().UnixNano()) //设置种子
//fmt.Println(rand.Intn(2)) // 表示只在 2以下获取随机数 只能取到 0 1 两个数
idx := rand.Intn(len(this.Servers));
return this.Servers[idx]
}
//Hash算法
func (this *LoadBalance) SelectByIPHash(ip string) *HttpServer {
idx := int(crc32.ChecksumIEEE([]byte(ip))) % len(this.Servers)
return this.Servers[idx]
}
//随机加权重算法
func (this *LoadBalance) SelectByWeightRand() *HttpServer {
rand.Seed(time.Now().UnixNano())
idx := rand.Intn(len(ServerIndexes))
return this.Servers[ServerIndexes[idx]]
}
//随机算法
func (this *LoadBalance) RoundRobin() *HttpServer {
server := this.Servers[this.CurrIndex]
this.CurrIndex++
if this.CurrIndex >= len(this.Servers) {
this.CurrIndex = 0
}
return server;
}
//加权随机算法
func (this *LoadBalance) RoundRobinByWeight() *HttpServer {
server := this.Servers[ServerIndexes[this.CurrIndex]]
this.CurrIndex = (this.CurrIndex + 1) % len(ServerIndexes)
return server;
}
var (
Slb *LoadBalance
ServerIndexes []int
)
//初始化
func init() {
Slb = NewLoadBalance()
Slb.AddServer(NewHttpServer("http://localhost:9091", 5))
Slb.AddServer(NewHttpServer("http://localhost:9092", 15))
Slb.AddServer(NewHttpServer("http://localhost:9093", 20))
for index, server := range Slb.Servers {
if server.Weight > 0 {
for i := 0; i < server.Weight; i++ {
ServerIndexes = append(ServerIndexes, index)
}
}
}
}
复制代码可以跑起来。
有疑问加站长微信联系(非本文作者)