wip: 完成 client api 分析
This commit is contained in:
63
internal/gateway/gateway.go
Normal file
63
internal/gateway/gateway.go
Normal file
@ -0,0 +1,63 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"esway/internal/middleware/analysis"
|
||||
"esway/internal/middleware/logger"
|
||||
"esway/internal/opt"
|
||||
"esway/internal/tool"
|
||||
|
||||
"github.com/loveuer/nf"
|
||||
)
|
||||
|
||||
func Start(ctx context.Context) error {
|
||||
ch := make(chan struct{})
|
||||
app := nf.New(nf.Config{
|
||||
BodyLimit: 4 * 1024 * 1024,
|
||||
DisableLogger: true,
|
||||
DisableBanner: true,
|
||||
DisableMessagePrint: true,
|
||||
})
|
||||
|
||||
h, err := proxy(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app.Use(logger.New(logger.Config{IgnoreFn: func(c *nf.Ctx) bool {
|
||||
path := c.Path()
|
||||
if strings.HasPrefix(path, "/.") || strings.HasPrefix(path, "/_") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}}))
|
||||
app.Use(analysis.New())
|
||||
|
||||
app.Any("/*any", h)
|
||||
|
||||
ln, err := net.Listen("tcp", opt.Cfg.Listen.Gateway)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gateway listen at %s err: %s", opt.Cfg.Listen.Gateway, err.Error())
|
||||
}
|
||||
|
||||
go func() {
|
||||
ch <- struct{}{}
|
||||
fmt.Printf("esway: gateway listen at %s\n", opt.Cfg.Listen.Gateway)
|
||||
_ = app.RunListener(ln)
|
||||
}()
|
||||
<-ch
|
||||
|
||||
go func() {
|
||||
ch <- struct{}{}
|
||||
<-ctx.Done()
|
||||
_ = app.Shutdown(tool.Timeout(2))
|
||||
}()
|
||||
<-ch
|
||||
|
||||
return nil
|
||||
}
|
51
internal/gateway/proxy.go
Normal file
51
internal/gateway/proxy.go
Normal file
@ -0,0 +1,51 @@
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"sync/atomic"
|
||||
|
||||
"esway/internal/log"
|
||||
"esway/internal/opt"
|
||||
|
||||
"github.com/loveuer/nf"
|
||||
)
|
||||
|
||||
func proxy(ctx context.Context) (nf.HandlerFunc, error) {
|
||||
if len(opt.Cfg.Endpoints) == 0 {
|
||||
return nil, fmt.Errorf("gateway: 必须要指定 elasticsearch endpoints")
|
||||
}
|
||||
|
||||
urls := make([]*url.URL, 0)
|
||||
for _, item := range opt.Cfg.Endpoints {
|
||||
ins, err := url.Parse(item)
|
||||
if err != nil {
|
||||
log.Warn(ctx, "gateway: endpoint invalid, endpoint = %s, err = %s", item, err.Error())
|
||||
}
|
||||
|
||||
urls = append(urls, ins)
|
||||
}
|
||||
|
||||
if len(urls) == 0 {
|
||||
return nil, fmt.Errorf("gateway: no valid elasticsearch endpoint")
|
||||
}
|
||||
|
||||
svcs := make([]*httputil.ReverseProxy, len(urls))
|
||||
for idx, item := range urls {
|
||||
svcs[idx] = httputil.NewSingleHostReverseProxy(item)
|
||||
}
|
||||
|
||||
var (
|
||||
round int64 = 0
|
||||
length = int64(len(svcs))
|
||||
)
|
||||
return func(c *nf.Ctx) error {
|
||||
svc := svcs[atomic.SwapInt64(&round, (round+1)%length)]
|
||||
|
||||
svc.ServeHTTP(c.Writer, c.Request)
|
||||
|
||||
return nil
|
||||
}, nil
|
||||
}
|
Reference in New Issue
Block a user