美文网首页
golang 网络编程实践

golang 网络编程实践

作者: 我爱张智容 | 来源:发表于2020-07-14 23:46 被阅读0次

    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)
                }
            }
        }
    
    }
    
    

    复制代码可以跑起来。

    相关文章

      网友评论

          本文标题:golang 网络编程实践

          本文链接:https://www.haomeiwen.com/subject/nftchktx.html