mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-24 17:28:31 +02:00
refactor(loadbalancer): implement sticky sessions and improve algorithm separation
- Refactor load balancer interface to separate server selection (ChooseServer) from request handling - Add cookie-based sticky session support with configurable max-age and secure cookie handling - Integrate idlewatcher requests with automatic sticky session assignment - Improve algorithm implementations: * Replace fnv with xxhash3 for better performance in IP hash and server keys * Add proper bounds checking and error handling in all algorithms * Separate concerns between server selection and request processing - Add Sticky and StickyMaxAge fields to LoadBalancerConfig - Create dedicated sticky.go for session management utilities
This commit is contained in:
50
internal/net/gphttp/loadbalancer/sticky.go
Normal file
50
internal/net/gphttp/loadbalancer/sticky.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package loadbalancer
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bytedance/gopkg/util/xxhash3"
|
||||
"github.com/yusing/godoxy/internal/types"
|
||||
)
|
||||
|
||||
func hashServerKey(key string) string {
|
||||
h := xxhash3.HashString(key)
|
||||
as8bytes := *(*[8]byte)(unsafe.Pointer(&h))
|
||||
return hex.EncodeToString(as8bytes[:])
|
||||
}
|
||||
|
||||
// getStickyServer extracts the sticky session cookie and returns the corresponding server
|
||||
func getStickyServer(r *http.Request, srvs []types.LoadBalancerServer) types.LoadBalancerServer {
|
||||
cookie, err := r.Cookie("godoxy_lb_sticky")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
serverKeyHash := cookie.Value
|
||||
for _, srv := range srvs {
|
||||
if hashServerKey(srv.Key()) == serverKeyHash {
|
||||
return srv
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setStickyCookie sets a cookie to maintain sticky session with a specific server
|
||||
func setStickyCookie(rw http.ResponseWriter, r *http.Request, srv types.LoadBalancerServer, maxAge time.Duration) {
|
||||
http.SetCookie(rw, &http.Cookie{
|
||||
Name: "godoxy_lb_sticky",
|
||||
Value: hashServerKey(srv.Key()),
|
||||
Path: "/",
|
||||
MaxAge: int(maxAge.Seconds()),
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
HttpOnly: true,
|
||||
Secure: isSecure(r),
|
||||
})
|
||||
}
|
||||
|
||||
func isSecure(r *http.Request) bool {
|
||||
return r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"
|
||||
}
|
||||
Reference in New Issue
Block a user