Spring boot Zuul中的粘性会话功能区规则始终具有空请求

Spring boot Zuul中的粘性会话功能区规则始终具有空请求,spring-boot,spring-cloud,netflix-zuul,spring-cloud-netflix,netflix-ribbon,Spring Boot,Spring Cloud,Netflix Zuul,Spring Cloud Netflix,Netflix Ribbon,我试图在Zuul代理服务中实现粘性会话负载平衡器规则。我正在使用此示例中的代码: 我似乎已正确配置了所有内容,并且规则正在我的调试器中触发,但对RequestContext.getCurrentContext().getResponse()的调用始终返回null,因此从未找到cookie,因此规则从未生效 Zuul配置的其余部分正在100%工作。我的流量已被代理和路由,我可以很好地使用该应用程序,但粘性会话规则不起作用 我是否还缺少另一个步骤来将请求正确地连接到此规则 我的路线配置: zuul.

我试图在Zuul代理服务中实现粘性会话负载平衡器规则。我正在使用此示例中的代码:

我似乎已正确配置了所有内容,并且规则正在我的调试器中触发,但对RequestContext.getCurrentContext().getResponse()的调用始终返回null,因此从未找到cookie,因此规则从未生效

Zuul配置的其余部分正在100%工作。我的流量已被代理和路由,我可以很好地使用该应用程序,但粘性会话规则不起作用

我是否还缺少另一个步骤来将请求正确地连接到此规则

我的路线配置:

zuul.routes.appname.path=/appname/**
zuul.routes.appname.sensitiveHeaders=
zuul.routes.appname.stripPrefix=false
zuul.routes.appname.retryable=true
zuul.add-host-header=true
zuul.routes.appname.service-id=APP_NAME
hystrix.command.APP_NAME.execution.isolation.strategy=THREAD
hystrix.command.APP_NAME.execution.isolation.thread.timeoutInMilliseconds=125000

APP_NAME.ribbon.ServerListRefreshInterval=10000
APP_NAME.ribbon.retryableStatusCodes=500
APP_NAME.ribbon.MaxAutoRetries=5
APP_NAME.ribbon.MaxAutoRetriesNextServer=1
APP_NAME.ribbon.OkToRetryOnAllOperations=true
APP_NAME.ribbon.ReadTimeout=5000
APP_NAME.ribbon.ConnectTimeout=5000
APP_NAME.ribbon.EnablePrimeConnections=true
APP_NAME.ribbon.NFLoadBalancerRuleClassName=my.package.name.StickySessionRule
应用程序:

@EnableZuulProxy
@SpringBootApplication
public class ApplicationGateway {

    public static void main(String[] args) {
        SpringApplication.run(ApplicationGateway.class, args);
    }

    @Bean
    public LocationRewriteFilter locationRewriteFilter() {
        return new LocationRewriteFilter();
    }
}
编辑:根据要求,代码:

import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.zuul.context.RequestContext;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @author Alejandro Duarte.
 */
public class StickySessionRule extends ZoneAvoidanceRule {

    public static final String COOKIE_NAME_SUFFIX = "-" + StickySessionRule.class.getSimpleName();

    @Override
    public Server choose(Object key) {
        Optional<Cookie> cookie = getCookie(key);

        if (cookie.isPresent()) {
            Cookie hash = cookie.get();
            List<Server> servers = getLoadBalancer().getReachableServers();
            Optional<Server> server = servers.stream()
                    .filter(s -> s.isAlive() && s.isReadyToServe())
                    .filter(s -> hash.getValue().equals("" + s.hashCode()))
                    .findFirst();

            if (server.isPresent()) {
                return server.get();
            }
        }

        return useNewServer(key);
    }

    private Server useNewServer(Object key) {
        Server server = super.choose(key);
        HttpServletResponse response = RequestContext.getCurrentContext().getResponse();
        if (response != null) {
            String cookieName = getCookieName(server);
            Cookie newCookie = new Cookie(cookieName, "" + server.hashCode());
            newCookie.setPath("/");
            response.addCookie(newCookie);
        }
        return server;
    }

    private Optional<Cookie> getCookie(Object key) {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        if (request != null) {
            Server server = super.choose(key);
            String cookieName = getCookieName(server);
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                return Arrays.stream(cookies)
                        .filter(c -> c.getName().equals(cookieName))
                        .findFirst();
            }
        }

        return Optional.empty();
    }

    private String getCookieName(Server server) {
        return server.getMetaInfo().getAppName() + COOKIE_NAME_SUFFIX;
    }

}
导入com.netflix.loadbalancer.Server;
导入com.netflix.loadbalancer.ZoneAvoidanceRule;
导入com.netflix.zuul.context.RequestContext;
导入javax.servlet.http.Cookie;
导入javax.servlet.http.HttpServletRequest;
导入javax.servlet.http.HttpServletResponse;
导入java.util.array;
导入java.util.List;
导入java.util.Optional;
/**
*@作者亚历杭德罗·杜阿尔特。
*/
公共类StickySessionRule扩展了ZoneAvoidanceRule{
公共静态最终字符串COOKIE_NAME_SUFFIX=“-”+StickySessionRule.class.getSimpleName();
@凌驾
公共服务器选择(对象密钥){
可选cookie=getCookie(键);
if(cookie.isPresent()){
Cookie hash=Cookie.get();
列表服务器=getLoadBalancer().getReachableServers();
可选服务器=servers.stream()
.filter(s->s.isAlive()和&s.isReadyToServe())
.filter(s->hash.getValue().equals(“+s.hashCode()))
.findFirst();
if(server.isPresent()){
return server.get();
}
}
返回useNewServer(键);
}
专用服务器useNewServer(对象密钥){
服务器=超级。选择(键);
HttpServletResponse=RequestContext.getCurrentContext().getResponse();
if(响应!=null){
字符串cookieName=getCookieName(服务器);
Cookie newCookie=新Cookie(cookieName,“+server.hashCode());
newCookie.setPath(“/”);
addCookie(newCookie);
}
返回服务器;
}
私有可选getCookie(对象密钥){
HttpServletRequest=RequestContext.getCurrentContext().getRequest();
if(请求!=null){
服务器=超级。选择(键);
字符串cookieName=getCookieName(服务器);
Cookie[]cookies=request.getCookies();
如果(cookies!=null){
返回数组.stream(cookies)
.filter(c->c.getName().equals(cookieName))
.findFirst();
}
}
返回可选的.empty();
}
私有字符串getCookieName(服务器){
返回server.getMetaInfo().getAppName()+COOKIE\u NAME\u后缀;
}
}

我认为您缺少一个预过滤器,如下所示:

import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

public class PreFilter extends com.netflix.zuul.ZuulFilter {

    @Override
    public Object run() {       
            RequestContext ctx = RequestContext.getCurrentContext();           
         RequestContext.getCurrentContext().set(FilterConstants.LOAD_BALANCER_KEY, ctx.getRequest());

        return null;
    }

    @Override
    public boolean shouldFilter() {     
        return true;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.SEND_RESPONSE_FILTER_ORDER;
    }

    @Override
    public String filterType() {
        return "pre";
    }

}
标记为豆子

@Bean
public PreFilter preFilter() {
        return new PreFilter();
}
并在你的规则中使用它

@Override
    public Server choose(Object key) {        
        javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest) key;

我认为您缺少一个预过滤器,如下所示:

import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

public class PreFilter extends com.netflix.zuul.ZuulFilter {

    @Override
    public Object run() {       
            RequestContext ctx = RequestContext.getCurrentContext();           
         RequestContext.getCurrentContext().set(FilterConstants.LOAD_BALANCER_KEY, ctx.getRequest());

        return null;
    }

    @Override
    public boolean shouldFilter() {     
        return true;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.SEND_RESPONSE_FILTER_ORDER;
    }

    @Override
    public String filterType() {
        return "pre";
    }

}
标记为豆子

@Bean
public PreFilter preFilter() {
        return new PreFilter();
}
并在你的规则中使用它

@Override
    public Server choose(Object key) {        
        javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest) key;

你也可以粘贴你的粘性会话规则实现吗?另外,你调用应用程序的url是什么?它应该是localhost:port/appname/something,以便zuul过滤request@TurbutAlin我将粘贴代码,但它将是确切的代码链接到后。另外,我点击了正确的URL,因为Zuul正确地路由了我的请求,我可以通过Zuul使用该应用程序,只是粘性会话规则不起作用。你也可以粘贴你的粘性会话规则实现吗?另外,你调用该应用程序的URL是什么?它应该是localhost:port/appname/something,以便zuul过滤request@TurbutAlin我将粘贴代码,但它将是确切的代码链接到后。此外,我点击了正确的URL,因为Zuul正确地路由了我的请求,我可以通过Zuul使用应用程序,只是粘性会话规则不起作用。