Правило ленты Sticky Session в Zuul всегда имеет нулевой запрос

Я пытаюсь реализовать правило балансировки нагрузки фиксированного сеанса в прокси-службе 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;
    }

}

comment
Можете ли вы также вставить свою реализацию правила липкого сеанса?   -  person Turbut Alin    schedule 05.06.2019
comment
также, какой URL-адрес вы вызываете приложение? это должно быть localhost:port/appname/something, чтобы zuul мог фильтровать запрос   -  person Turbut Alin    schedule 05.06.2019
comment
@TurbutAlin Я вставлю код, но это будет точный код, ссылка на который есть в посте. Кроме того, я нажимаю правильный URL-адрес, потому что Zuul правильно маршрутизирует мои запросы, я могу использовать приложение через Zuul, просто правило закрепления сеанса не работает.   -  person JCN    schedule 05.06.2019


Ответы (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
public PreFilter preFilter() {
        return new PreFilter();
}

И используйте его в своем правиле

@Override
    public Server choose(Object key) {        
        javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest) key;
person Hugo Alberto Casiano Vidal    schedule 02.08.2019

RequestContext не работает, потому что hystrix.command.APP_NAME.execution.isolation.strategy=THREAD

person fengshu    schedule 21.06.2021