【问题标题】:Sticky session Ribbon rule in Zuul always has null requestZuul 中的粘性会话功能区规则始终具有空请求
【发布时间】:2019-10-21 04:16:39
【问题描述】:

我正在尝试在 Zuul 代理服务中实现粘性会话负载均衡器规则。我正在使用此示例中的代码:https://github.com/alejandro-du/vaadin-microservices-demo/blob/master/proxy-server/src/main/java/com/example/StickySessionRule.java

我似乎已经正确配置了所有内容,并且在我的调试器中触发了规则,但是对 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;
    }

}

【问题讨论】:

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

标签: spring-boot spring-cloud netflix-zuul spring-cloud-netflix netflix-ribbon


【解决方案1】:

RequestContext 不起作用导致“hystrix.command.APP_NAME.execution.isolation.strategy=THREAD”

【讨论】:

    【解决方案2】:

    我认为您缺少一个 PreFilter,如下所示:

    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

    @Bean
    public PreFilter preFilter() {
            return new PreFilter();
    }
    

    并在你的规则中使用它

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

    【讨论】:

      猜你喜欢
      • 2015-05-26
      • 2016-07-06
      • 1970-01-01
      • 1970-01-01
      • 2017-02-05
      • 2016-04-08
      • 2017-11-16
      • 2021-08-24
      • 2019-07-14
      相关资源
      最近更新 更多