線上debug&gateway自定義路由規則

竹根七發表於2024-10-22
  1. 如何進行線上debug。
  2. 如何在gateway自定義路由規則去進行請求分發,讓請求打到叢集模式下我們想要的節點。
drawing

1.配置remote debug

1.在啟動引數配置引數:

-Xdebug
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6364
drawing

2.新建remote
drawing

3.啟動remote

2.gateway改造

我個人的需求是把某個使用者的請求,打到我想要的節點(開啟了debug模式的節點),避免因為叢集節點的負載導致請求打到其他節點,也避免影響其他使用者的正常請求流程。

我的做法是攔截請求投中的Authorization=xxx進行判斷,因此參考了gateway的路由策略:
gateway 路由匹配策略

而gateway自帶的路由策略是透過regix(正則匹配)來實現的,因此我做了以下改造:

1.新增HeaderValueRoutePredicateFactory

public class HeaderValueRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderValueRoutePredicateFactory.Config> {

    private static final String KEY_1 = "headerName";
    private static final String KEY_2 = "headerValue";

    public HeaderValueRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(KEY_1, KEY_2);
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange exchange) {
                List<String> values = exchange.getRequest().getHeaders().getOrDefault(config.getHeaderName(),
                        Collections.emptyList());
                if (values.isEmpty()) {
                    return false;
                }

                boolean match = values.stream().allMatch(item -> item.equals(config.getHeaderValue()));
                if (match) {
                    log.info("debug模式route策略已觸發");
                }

                return match;
            }

            @Override
            public Object getConfig() {
                return config;
            }

            @Override
            public String toString() {
                return String.format("HeaderName: %s headerValue=%s", config.getHeaderName(), config.getHeaderValue());
            }
        };
    }

    public static class Config {

        private String headerName;

        private String headerValue;

        public String getHeaderName() {
            return headerName;
        }

        public Config setHeaderName(String headerName) {
            this.headerName = headerName;
            return this;
        }

        public String getHeaderValue() {
            return headerValue;
        }

        public Config setHeaderValue(String headerValue) {
            this.headerValue = headerValue;
            return this;
        }
    }

}

程式碼筆記:

  • 獲取系統快取路由策略(可以看閘道器中配置的全部策略)
    org.springframework.cloud.gateway.route.CachingRouteLocator#getRoutes
  • 獲取路由策略(根據請求條件匹配)
    org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping#getHandlerInternal
  • 獲取路由策略(根據請求條件匹配)
    org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping#lookupRoute

2.配置類

@Configuration
public class Config {

    @Bean
    public HeaderValueRoutePredicateFactory headerValueRoutePredicateFactory() {
        return new HeaderValueRoutePredicateFactory();
    }

}

3.修改gateway配置

spring:
  cloud:
    gateway:
      routes:
        # 當請求頭中帶有Authorization=ff4a4ce5-5276-4263-b817-34d1ce553421切路徑為/ims/**會被該規則路由
        - id: ims
          uri: lb://ims
          predicates:
            - Path=/ims/**
          filters:
            - StripPrefix=1
        # 當請求頭中帶有Authorization=ff4a4ce5-5276-4263-b817-34d1ce553421切路徑為/ims/**會被該規則路由
        - id: ims-debug
          uri: lb://ims-debug
          # 配置-1是為了讓該路由策略在id: ims 前面進行判斷,否則會觸發id=ims的路由策略,不會觸發id=ims-debug的路由策略
          order: -1
          predicates:
            - Path=/ims/**
            - HeaderValue=Authorization,ff4a4ce5-5276-4263-b817-34d1ce553421
          filters:
            - StripPrefix=1

3.nacos配置

1.正常的節點配置

-Dspring.application.name=ims

2.debug的節點配置

-Dspring.application.name=ims-debug

本質上ims和ims-debug是同一服務,只是服務名不同,區分開是為了方便路由

4.其他問題

  1. 正常情況下,如果是生產環境,ims-debug服務即使開啟了debug模式,但會因為網路問題導致辦公網的本地無法進行連線。這種情況我們可以讓運維申請跳板機、VPN來對接專用網路,另外debug的對外埠也要申請好。
  2. 我在網上還看到其他的線上debug方式 點選跳轉他人連結,因此我這種方式未必適合所有人(但是都沒有考慮叢集下請求如果不進入當前節點的問題),本人只是折中。
  3. 即使你學會了也沒什麼用,正常情況下不會讓開發者進行線上debug。作者本人也只是心血來潮。

相關文章