Fixed sticky session bug

- Fixed sticky session bug in new active fallback lb implementation
This commit is contained in:
Toby Chui 2025-02-14 22:53:29 +08:00
parent 32f60dfba6
commit 5d8bec7f24
4 changed files with 39 additions and 7 deletions

View File

@ -109,6 +109,11 @@ func GetUpstreamsAsString(upstreams []*Upstream) string {
return strings.Join(targets, ", ")
}
// Reset the current session store and clear all previous sessions
func (m *RouteManager) ResetSessions() {
m.SessionStore = sessions.NewCookieStore([]byte(m.Options.SystemUUID))
}
func (m *RouteManager) Close() {
//Close the session store
m.SessionStore.MaxAge(0)

View File

@ -67,5 +67,6 @@ func (m *RouteManager) FilterOfflineOrigins(origins []*Upstream) []*Upstream {
onlineOrigins = append(onlineOrigins, origin)
}
}
return onlineOrigins
}

View File

@ -24,7 +24,7 @@ func (m *RouteManager) GetRequestUpstreamTarget(w http.ResponseWriter, r *http.R
if useStickySession {
//Use stick session, check which origins this request previously used
targetOriginId, err := m.getSessionHandler(r, origins)
if err != nil || !m.IsTargetOnline(origins[targetOriginId].OriginIpOrDomain) {
if err != nil {
// No valid session found or origin is offline
// Filter the offline origins
origins = m.FilterOfflineOrigins(origins)
@ -39,14 +39,18 @@ func (m *RouteManager) GetRequestUpstreamTarget(w http.ResponseWriter, r *http.R
targetOrigin = origins[0]
index = 0
}
//fmt.Println("DEBUG: (Sticky Session) Registering session origin " + origins[index].OriginIpOrDomain)
m.setSessionHandler(w, r, targetOrigin.OriginIpOrDomain, index)
return targetOrigin, nil
}
//Valid session found and origin is online
//fmt.Println("DEBUG: (Sticky Session) Picking origin " + origins[targetOriginId].OriginIpOrDomain)
return origins[targetOriginId], nil
}
//No sticky session, get a random origin
m.clearSessionHandler(w, r) //Clear the session
//Filter the offline origins
origins = m.FilterOfflineOrigins(origins)
@ -89,6 +93,20 @@ func (m *RouteManager) setSessionHandler(w http.ResponseWriter, r *http.Request,
return nil
}
func (m *RouteManager) clearSessionHandler(w http.ResponseWriter, r *http.Request) error {
session, err := m.SessionStore.Get(r, "STICKYSESSION")
if err != nil {
return err
}
session.Options.MaxAge = -1
session.Options.Path = "/"
err = session.Save(r, w)
if err != nil {
return err
}
return nil
}
// Get the previous connected origin from session
func (m *RouteManager) getSessionHandler(r *http.Request, upstreams []*Upstream) (int, error) {
// Get existing session
@ -105,15 +123,22 @@ func (m *RouteManager) getSessionHandler(r *http.Request, upstreams []*Upstream)
return -1, errors.New("no session has been set")
}
originDomain := originDomainRaw.(string)
originID := originIDRaw.(int)
//originID := originIDRaw.(int)
//Check if it has been modified
if len(upstreams) < originID || upstreams[originID].OriginIpOrDomain != originDomain {
//Mismatch or upstreams has been updated
return -1, errors.New("upstreams has been changed")
//Check if the upstream still exists
for i, upstream := range upstreams {
if upstream.OriginIpOrDomain == originDomain {
if !m.IsTargetOnline(originDomain) {
//Origin is offline
return -1, errors.New("origin is offline")
}
//Ok, the origin is still online
return i, nil
}
}
return originID, nil
return -1, errors.New("origin is no longer exists")
}
/* Functions related to random upstream picking */

View File

@ -595,6 +595,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
return
}
targetProxyEntry.Remove()
loadBalancer.ResetSessions()
dynamicProxyRouter.AddProxyRouteToRuntime(readyRoutingRule)
//Save it to file