mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-23 08:48:32 +02:00
refactor(misc): enhance performance on bytes pool, entrypoint, access log and route context handling
- Introduced benchmark tests for Entrypoint and ReverseProxy to evaluate performance. - Updated Entrypoint's ServeHTTP method to improve route context management. - Added new test file for entrypoint benchmarks and refined existing tests for route handling.
This commit is contained in:
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/yusing/go-proxy/internal/route/routes"
|
||||
"github.com/yusing/go-proxy/internal/task"
|
||||
"github.com/yusing/go-proxy/internal/types"
|
||||
"github.com/yusing/go-proxy/internal/utils/strutils"
|
||||
)
|
||||
|
||||
type Entrypoint struct {
|
||||
@@ -73,12 +72,13 @@ func (ep *Entrypoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w = accesslog.NewResponseRecorder(w)
|
||||
defer ep.accessLogger.Log(r, w.(*accesslog.ResponseRecorder).Response())
|
||||
}
|
||||
mux, err := ep.findRouteFunc(r.Host)
|
||||
route, err := ep.findRouteFunc(r.Host)
|
||||
if err == nil {
|
||||
r = routes.WithRouteContext(r, route)
|
||||
if ep.middleware != nil {
|
||||
ep.middleware.ServeHTTP(mux.ServeHTTP, w, routes.WithRouteContext(r, mux))
|
||||
ep.middleware.ServeHTTP(route.ServeHTTP, w, r)
|
||||
} else {
|
||||
mux.ServeHTTP(w, r)
|
||||
route.ServeHTTP(w, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -106,20 +106,23 @@ func (ep *Entrypoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func findRouteAnyDomain(host string) (types.HTTPRoute, error) {
|
||||
hostSplit := strutils.SplitRune(host, '.')
|
||||
target := hostSplit[0]
|
||||
|
||||
if r, ok := routes.GetHTTPRouteOrExact(target, host); ok {
|
||||
idx := strings.IndexByte(host, '.')
|
||||
if idx != -1 {
|
||||
target := host[:idx]
|
||||
if r, ok := routes.HTTP.Get(target); ok {
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
if r, ok := routes.HTTP.Get(host); ok {
|
||||
return r, nil
|
||||
}
|
||||
return nil, fmt.Errorf("%w: %s", ErrNoSuchRoute, target)
|
||||
return nil, fmt.Errorf("%w: %s", ErrNoSuchRoute, host)
|
||||
}
|
||||
|
||||
func findRouteByDomains(domains []string) func(host string) (types.HTTPRoute, error) {
|
||||
return func(host string) (types.HTTPRoute, error) {
|
||||
for _, domain := range domains {
|
||||
if strings.HasSuffix(host, domain) {
|
||||
target := strings.TrimSuffix(host, domain)
|
||||
if target, ok := strings.CutSuffix(host, domain); ok {
|
||||
if r, ok := routes.HTTP.Get(target); ok {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
154
internal/entrypoint/entrypoint_benchmark_test.go
Normal file
154
internal/entrypoint/entrypoint_benchmark_test.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package entrypoint
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/route"
|
||||
"github.com/yusing/go-proxy/internal/route/routes"
|
||||
"github.com/yusing/go-proxy/internal/task"
|
||||
"github.com/yusing/go-proxy/internal/types"
|
||||
)
|
||||
|
||||
type noopResponseWriter struct {
|
||||
statusCode int
|
||||
written []byte
|
||||
}
|
||||
|
||||
func (w *noopResponseWriter) Header() http.Header {
|
||||
return http.Header{}
|
||||
}
|
||||
func (w *noopResponseWriter) Write(b []byte) (int, error) {
|
||||
w.written = b
|
||||
return len(b), nil
|
||||
}
|
||||
func (w *noopResponseWriter) WriteHeader(statusCode int) {
|
||||
w.statusCode = statusCode
|
||||
}
|
||||
|
||||
type noopTransport struct{}
|
||||
|
||||
func (t noopTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(strings.NewReader("1")),
|
||||
Request: req,
|
||||
Header: http.Header{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func BenchmarkEntrypointReal(b *testing.B) {
|
||||
var ep Entrypoint
|
||||
var req = http.Request{
|
||||
Method: "GET",
|
||||
URL: &url.URL{Path: "/", RawPath: "/"},
|
||||
Host: "test.domain.tld",
|
||||
}
|
||||
ep.SetFindRouteDomains([]string{})
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Length", "1")
|
||||
w.Write([]byte("1"))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
url, err := url.Parse(srv.URL)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(url.Host)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
portInt, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
r := &route.Route{
|
||||
Alias: "test",
|
||||
Scheme: "http",
|
||||
Host: host,
|
||||
Port: route.Port{Proxy: portInt},
|
||||
HealthCheck: &types.HealthCheckConfig{Disable: true},
|
||||
}
|
||||
|
||||
err = r.Validate()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
err = r.Start(task.RootTask("test", false))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
var w noopResponseWriter
|
||||
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
ep.ServeHTTP(&w, &req)
|
||||
// if w.statusCode != http.StatusOK {
|
||||
// b.Fatalf("status code is not 200: %d", w.statusCode)
|
||||
// }
|
||||
// if string(w.written) != "1" {
|
||||
// b.Fatalf("written is not 1: %s", string(w.written))
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEntrypoint(b *testing.B) {
|
||||
var ep Entrypoint
|
||||
var req = http.Request{
|
||||
Method: "GET",
|
||||
URL: &url.URL{Path: "/", RawPath: "/"},
|
||||
Host: "test.domain.tld",
|
||||
}
|
||||
ep.SetFindRouteDomains([]string{})
|
||||
|
||||
r := &route.Route{
|
||||
Alias: "test",
|
||||
Scheme: "http",
|
||||
Host: "localhost",
|
||||
Port: route.Port{
|
||||
Proxy: 8080,
|
||||
},
|
||||
HealthCheck: &types.HealthCheckConfig{
|
||||
Disable: true,
|
||||
},
|
||||
}
|
||||
|
||||
err := r.Validate()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
err = r.Start(task.RootTask("test", false))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
rev, ok := routes.HTTP.Get("test")
|
||||
if !ok {
|
||||
b.Fatal("route not found")
|
||||
}
|
||||
rev.(types.ReverseProxyRoute).ReverseProxy().Transport = noopTransport{}
|
||||
|
||||
var w noopResponseWriter
|
||||
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
ep.ServeHTTP(&w, &req)
|
||||
if w.statusCode != http.StatusOK {
|
||||
b.Fatalf("status code is not 200: %d", w.statusCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ func addRoute(alias string) {
|
||||
routes.HTTP.Add(&route.ReveseProxyRoute{
|
||||
Route: &route.Route{
|
||||
Alias: alias,
|
||||
Port: route.Port{
|
||||
Proxy: 80,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user