Статьи

Маршрутизация на основе соотношения с устаревшим и современным приложением — Netflix Zuul через Spring Cloud

При переходе от устаревшей версии приложения к модернизированной версии приложения очень распространенным требованием является возможность медленной миграции пользователей в новое приложение. В этом посте я расскажу об этом слое маршрутизации, написанном с использованием поддержки Netflix Zuul через Spring Cloud . Прежде чем я продолжу, я должен признать, что большая часть кода, продемонстрированного здесь, была написана в сотрудничестве с превосходным Shaozhen Ding

сценарий

У меня есть устаревшая служба, которая была переработана до более современной версии (предполагается, что в ходе этой миграции URI конечных точек не изменились). Я хочу медленно перенести пользователей из устаревшего приложения в современную версию.

Внедрение с использованием Spring Cloud Netflix — Поддержка Zuul

Это может быть легко реализовано с помощью поддержки Netflix Zuul в проекте Spring Cloud .

Zuul управляется набором фильтров, которые действуют на запрос до (предварительные фильтры), во время (маршрутные фильтры) и после (после фильтров) запроса к бэкэнду. Spring Cloud добавляет свой собственный набор фильтров к Zuul и управляет поведением этих фильтров конфигурацией, которая выглядит следующим образом:

1
2
3
4
5
zuul:
  routes:
    ratio-route:
      path: /routes/**
      strip-prefix: false

Это указывает, что Zuul будет обрабатывать запрос к Uri с префиксом «/ routs», и этот префикс не будет удален из последующего вызова. Эта логика закодирована в «PreDecorationFilter» . Моя цель — выполнить запрос ПОСЛЕ PreDecorationFilter и указать, что бэкэнд должен быть либо устаревшей, либо современной версией. Учитывая это, фильтр, который действует на запрос, выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
...
 
@Service
public class RatioBasedRoutingZuulFilter extends ZuulFilter {
 
    public static final String LEGACY_APP = "legacy";
    public static final String MODERN_APP = "modern";
     
    private Random random = new Random();
     
    @Autowired
    private RatioRoutingProperties ratioRoutingProperties;
 
    @Override
    public String filterType() {
        return "pre";
    }
 
    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }
 
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return ctx.containsKey(SERVICE_ID_KEY)
                && ctx.get(SERVICE_ID_KEY).equals("ratio-route");
    }
 
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
 
        if (isTargetedToLegacy()) {
            ctx.put(SERVICE_ID_KEY, LEGACY_APP);
        } else {
            ctx.put(SERVICE_ID_KEY, MODERN_APP);
        }
        return null;
    }
 
    boolean isTargetedToLegacy() {
        return random.nextInt(100) < ratioRoutingProperties.getOldPercent();
    }
}

Фильтр настроен на работу после «PreDecorationFilter» путем переопределения метода filterOrder (). Логика маршрутизации довольно наивна, но должна работать в большинстве случаев. Как только serviceId будет разрешен, Spring Cloud будет использовать Ribbon для маршрутизации запроса, и просто для варианта я использую настроенный URL для устаревшего вызова и Eureka для современного внутреннего вызова. Если вы заинтересованы в изучении всего приложения, оно доступно в моем репозитории github.

После установки всей системы небольшой тест с устаревшей обработкой 20% трафика подтверждает, что фильтр работает эффективно:

Вывод

Поддержка Spring Cloud для Netflix Zuul упрощает обработку таких сценариев маршрутизации и должна хорошо подходить для любой организации, имеющей такие сценарии маршрутизации, которые они могут захотеть реализовать.