improve http handler

This commit is contained in:
ginuerzh
2021-10-31 12:41:53 +08:00
parent 248f7e4318
commit 64736585ee
11 changed files with 435 additions and 127 deletions

View File

@ -16,6 +16,121 @@ import (
"github.com/go-gost/gost/pkg/service"
)
func buildService(cfg *config.Config) (services []*service.Service) {
if cfg == nil || len(cfg.Services) == 0 {
return
}
chains := buildChain(cfg)
for _, svc := range cfg.Services {
listenerLogger := log.WithFields(map[string]interface{}{
"kind": "listener",
"type": svc.Listener.Type,
"service": svc.Name,
})
ln := registry.GetListener(svc.Listener.Type)(
listener.AddrOption(svc.Addr),
listener.LoggerOption(listenerLogger),
)
if err := ln.Init(metadata.MapMetadata(svc.Listener.Metadata)); err != nil {
listenerLogger.Fatal("init:", err)
}
var chain *chain.Chain
for _, ch := range chains {
if svc.Chain == ch.Name {
chain = ch
break
}
}
handlerLogger := log.WithFields(map[string]interface{}{
"kind": "handler",
"type": svc.Handler.Type,
"service": svc.Name,
})
h := registry.GetHandler(svc.Handler.Type)(
handler.ChainOption(chain),
handler.LoggerOption(handlerLogger),
)
if err := h.Init(metadata.MapMetadata(svc.Handler.Metadata)); err != nil {
handlerLogger.Fatal("init:", err)
}
s := (&service.Service{}).
WithListener(ln).
WithHandler(h)
services = append(services, s)
}
return
}
func buildChain(cfg *config.Config) (chains []*chain.Chain) {
if cfg == nil || len(cfg.Chains) == 0 {
return nil
}
for _, ch := range cfg.Chains {
c := &chain.Chain{
Name: ch.Name,
}
selector := selectorFromConfig(ch.LB)
for _, hop := range ch.Hops {
group := &chain.NodeGroup{}
for _, v := range hop.Nodes {
node := chain.NewNode(v.Name, v.Addr)
connectorLogger := log.WithFields(map[string]interface{}{
"kind": "connector",
"type": v.Connector.Type,
"hop": hop.Name,
"node": node.Name(),
})
cr := registry.GetConnector(v.Connector.Type)(
connector.LoggerOption(connectorLogger),
)
if err := cr.Init(metadata.MapMetadata(v.Connector.Metadata)); err != nil {
connectorLogger.Fatal("init:", err)
}
dialerLogger := log.WithFields(map[string]interface{}{
"kind": "dialer",
"type": v.Dialer.Type,
"hop": hop.Name,
"node": node.Name(),
})
d := registry.GetDialer(v.Dialer.Type)(
dialer.LoggerOption(dialerLogger),
)
if err := d.Init(metadata.MapMetadata(v.Dialer.Metadata)); err != nil {
dialerLogger.Fatal("init:", err)
}
tr := (&chain.Transport{}).
WithConnector(cr).
WithDialer(d)
node.WithTransport(tr)
group.AddNode(node)
}
sel := selector
if s := selectorFromConfig(hop.LB); s != nil {
sel = s
}
group.WithSelector(sel)
c.AddNodeGroup(group)
}
chains = append(chains, c)
}
return
}
func logFromConfig(cfg *config.LogConfig) logger.Logger {
opts := []logger.LoggerOption{
logger.FormatLoggerOption(logger.LogFormat(cfg.Format)),
@ -41,100 +156,29 @@ func logFromConfig(cfg *config.LogConfig) logger.Logger {
return logger.NewLogger(opts...)
}
func buildService(cfg *config.Config) (services []*service.Service) {
if cfg == nil || len(cfg.Services) == 0 {
return
}
chains := buildChain(cfg)
for _, svc := range cfg.Services {
s := &service.Service{}
ln := registry.GetListener(svc.Listener.Type)(
listener.AddrOption(svc.Addr),
listener.LoggerOption(
log.WithFields(map[string]interface{}{
"kind": "listener",
"type": svc.Listener.Type,
}),
),
)
ln.Init(metadata.MapMetadata(svc.Listener.Metadata))
s.WithListener(ln)
var chain *chain.Chain
for _, ch := range chains {
if svc.Chain == ch.Name {
chain = ch
break
}
}
h := registry.GetHandler(svc.Handler.Type)(
handler.ChainOption(chain),
handler.LoggerOption(
log.WithFields(map[string]interface{}{
"kind": "handler",
"type": svc.Handler.Type,
}),
),
)
h.Init(metadata.MapMetadata(svc.Handler.Metadata))
s.WithHandler(h)
services = append(services, s)
}
return
}
func buildChain(cfg *config.Config) (chains []*chain.Chain) {
if cfg == nil || len(cfg.Chains) == 0 {
func selectorFromConfig(cfg *config.LoadbalancingConfig) chain.Selector {
if cfg == nil {
return nil
}
for _, ch := range cfg.Chains {
c := &chain.Chain{
Name: ch.Name,
}
for _, hop := range ch.Hops {
group := &chain.NodeGroup{}
for _, v := range hop.Nodes {
node := chain.NewNode(v.Name, v.Addr)
tr := &chain.Transport{}
cr := registry.GetConnector(v.Connector.Type)(
connector.LoggerOption(
log.WithFields(map[string]interface{}{
"kind": "connector",
"type": v.Connector.Type,
}),
),
)
cr.Init(metadata.MapMetadata(v.Connector.Metadata))
tr.WithConnector(cr)
d := registry.GetDialer(v.Dialer.Type)(
dialer.LoggerOption(
log.WithFields(map[string]interface{}{
"kind": "dialer",
"type": v.Dialer.Type,
}),
),
)
d.Init(metadata.MapMetadata(v.Dialer.Metadata))
tr.WithDialer(d)
node.WithTransport(tr)
group.AddNode(node)
}
c.AddNodeGroup(group)
}
chains = append(chains, c)
var strategy chain.Strategy
switch cfg.Strategy {
case "round":
strategy = &chain.RoundRobinStrategy{}
case "random":
strategy = &chain.RandomStrategy{}
case "fifio":
strategy = &chain.FIFOStrategy{}
default:
strategy = &chain.RoundRobinStrategy{}
}
return
return chain.NewSelector(
strategy,
&chain.InvalidFilter{},
&chain.FailFilter{
MaxFails: cfg.MaxFails,
FailTimeout: cfg.FailTimeout,
},
)
}

View File

@ -4,46 +4,77 @@ log:
format: json # text, json
services:
- url: "http://gost:gost@:8000"
- name: http+tcp
url: "http://gost:gost@:8000"
addr: ":8000"
handler:
type: http
metadata:
proxyAgent: "gost/3.0"
retry: 3
auths:
- user1:pass1
- user2:pass2
# probeResist: code:404 # code, web, host, file
# knock: example.com
listener:
type: tcp
metadata:
keepAlive: 15s
# chain: chain01
chain: chain01
chains:
- name: chain01
# chain level load balancing
lb:
strategy: round
filters:
- filter1
maxFails: 1
failTimeout: 30s
hops:
- name: level01
- name: hop01
# hop level load balancing
lb:
strategy: rand
filters:
- filter1
strategy: round
maxFails: 1
failTimeout: 30s
nodes:
- name: node01
addr: ":8080"
url: "http://gost:gost@:8080"
addr: ":8081"
url: "http://gost:gost@:8081"
connector:
type: http
metadata:
userAgent: "gost/3.0"
auth: username:password
auth: user1:pass1
dialer:
type: tcp
metadata: {}
- name: node02
addr: ":8082"
url: "http://gost:gost@:8082"
connector:
type: http
metadata:
userAgent: "gost/3.0"
auth: user1:pass1
dialer:
type: tcp
metadata: {}
- name: hop02
# hop level load balancing
lb:
strategy: round
maxFails: 1
failTimeout: 30s
nodes:
- name: node03
addr: ":8083"
url: "http://gost:gost@:8083"
connector:
type: http
metadata:
userAgent: "gost/3.0"
auth: user1:pass1
dialer:
type: tcp
metadata: {}

View File

@ -1,6 +1,8 @@
package main
import (
stdlog "log"
"github.com/go-gost/gost/pkg/config"
"github.com/go-gost/gost/pkg/logger"
)
@ -10,6 +12,7 @@ var (
)
func main() {
stdlog.SetFlags(stdlog.LstdFlags | stdlog.Lshortfile)
cfg := &config.Config{}
if err := cfg.Load(); err != nil {
log.Fatal(err)