mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-22 16:28:30 +02:00
- 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
51 lines
1.3 KiB
Go
51 lines
1.3 KiB
Go
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"
|
|
}
|