mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-10 21:12:26 +08:00
init commit
This commit is contained in:
119
wind/proxy/proxy.go
Normal file
119
wind/proxy/proxy.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/logger"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"wind/entity"
|
||||
)
|
||||
|
||||
type Proxy struct {
|
||||
service Service
|
||||
}
|
||||
|
||||
// 服务
|
||||
type Service struct {
|
||||
// 服务地址列表map
|
||||
serviceAddrMap *entity.AddressMap
|
||||
// 服务负载均衡索引map
|
||||
serviceLoadBalanceIndexMap map[string]int
|
||||
serviceLoadBalanceIndexMapLock sync.Mutex
|
||||
}
|
||||
|
||||
func NewProxy(addressMap *entity.AddressMap) (r *Proxy) {
|
||||
r = new(Proxy)
|
||||
r.service.serviceAddrMap = addressMap
|
||||
go r.startServer()
|
||||
return r
|
||||
}
|
||||
|
||||
// 路由转发处理
|
||||
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
logger.LOG.Debug("[proxy:ServeHTTP] Request: %v", *r)
|
||||
urlParamDiv := strings.Index(r.RequestURI, "?")
|
||||
var reqUrl string
|
||||
if urlParamDiv != -1 {
|
||||
reqUrl = (r.RequestURI)[:urlParamDiv]
|
||||
} else {
|
||||
reqUrl = r.RequestURI
|
||||
}
|
||||
var svcNameStr = ""
|
||||
var stripPrefix = 0
|
||||
// 匹配服务
|
||||
for _, v := range config.CONF.Routes {
|
||||
if strings.Contains(reqUrl, v.ServicePredicates) {
|
||||
svcNameStr = v.ServiceName
|
||||
stripPrefix = v.StripPrefix
|
||||
break
|
||||
}
|
||||
}
|
||||
// 匹配服务失败
|
||||
if len(svcNameStr) == 0 {
|
||||
logger.LOG.Info("[proxy:ServeHTTP] 404 Not Found")
|
||||
_, _ = fmt.Fprintf(w, "404 Not Found")
|
||||
return
|
||||
}
|
||||
path := reqUrl
|
||||
// 去除路径前缀
|
||||
for i := 0; i < stripPrefix; i++ {
|
||||
path = path[strings.Index(path, "/")+1:]
|
||||
path = path[strings.Index(path, "/"):]
|
||||
}
|
||||
r.URL.Path = path
|
||||
var remote *url.URL
|
||||
p.service.serviceAddrMap.Lock.RLock()
|
||||
serviceAddr := p.service.serviceAddrMap.Map[svcNameStr]
|
||||
p.service.serviceAddrMap.Lock.RUnlock()
|
||||
// 服务不可用
|
||||
if len(serviceAddr) == 0 {
|
||||
logger.LOG.Info("[proxy:ServeHTTP] 503 Service Unavailable")
|
||||
_, _ = fmt.Fprintf(w, "503 Service Unavailable")
|
||||
return
|
||||
}
|
||||
p.service.serviceLoadBalanceIndexMapLock.Lock()
|
||||
serviceLoadBalanceIndex := p.service.serviceLoadBalanceIndexMap[svcNameStr]
|
||||
p.service.serviceLoadBalanceIndexMapLock.Unlock()
|
||||
// 下一个待轮询的服务已下线
|
||||
if int(serviceLoadBalanceIndex) >= len(serviceAddr) {
|
||||
logger.LOG.Info("[proxy:ServeHTTP] serviceLoadBalanceIndex out of range, len is: %d, but value is: %d", len(serviceAddr), serviceLoadBalanceIndex)
|
||||
serviceLoadBalanceIndex = 0
|
||||
}
|
||||
logger.LOG.Debug("[proxy:ServeHTTP] serviceLoadBalanceIndex: %d", serviceLoadBalanceIndex)
|
||||
remote, _ = url.Parse(string(serviceAddr[serviceLoadBalanceIndex]))
|
||||
logger.LOG.Debug("[proxy:ServeHTTP] remote: %v", remote)
|
||||
// 轮询
|
||||
p.service.serviceLoadBalanceIndexMapLock.Lock()
|
||||
if int(p.service.serviceLoadBalanceIndexMap[svcNameStr]) < len(serviceAddr)-1 {
|
||||
p.service.serviceLoadBalanceIndexMap[svcNameStr] += 1
|
||||
} else {
|
||||
p.service.serviceLoadBalanceIndexMap[svcNameStr] = 0
|
||||
}
|
||||
p.service.serviceLoadBalanceIndexMapLock.Unlock()
|
||||
proxy := httputil.NewSingleHostReverseProxy(remote)
|
||||
//p.log.Debug("Response: %v", w)
|
||||
proxy.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// 启动http路由转发
|
||||
func (p *Proxy) startServer() {
|
||||
// 初始化服务负载均衡索引map
|
||||
p.service.serviceLoadBalanceIndexMap = make(map[string]int)
|
||||
for _, v := range config.CONF.Routes {
|
||||
p.service.serviceLoadBalanceIndexMap[v.ServiceName] = 0
|
||||
}
|
||||
port := strconv.FormatInt(int64(config.CONF.HttpPort), 10)
|
||||
logger.LOG.Info("[proxy:startServer] start listen port: %s", port)
|
||||
portStr := ":" + port
|
||||
// 启动
|
||||
err := http.ListenAndServe(portStr, p)
|
||||
if err != nil {
|
||||
logger.LOG.Error("[proxy:startServer] ListenAndServe fail ! err: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user