spring cloud 2. x 버 전 Gateway 사용자 정의 필터 튜 토리 얼

16016 단어 spring
머리말
    Spring cloud   2.1.8RELEASE,version=Greenwich.SR3

본 고 는 앞의 두 편의 문장 인 eureka - server, eureka - client, eureka - ribbon, eureka - fegn 과 spring - gataway 의 실현 을 바탕 으로 한다.레 퍼 런 스
  • eureka-server
  • eureka-client
  • eureka-ribbon
  • eureka-feign
  • spring-gateway

  • 개략
    Spring Cloud Gateway 내부 에는 이미 매우 많은 필터 필터 필터, Hystrix Gateway Filter, Prefix PathGateway Filter 등 이 제공 되 고 있다.관심 있 는 파트너 는 Spring Cloud Gateway 홈 페이지 관련 문 서 를 직접 읽 거나 소스 코드 를 직접 읽 을 수 있다.그러나 자체 필터 가 우리 의 요 구 를 만족 시 키 지 못 하 는 경우 가 많 기 때문에 사용자 정의 필 터 는 매우 중요 하 다.본 고 는 주로 전역 필터 (Global Filter) 와 국부 필터 (Gateway Filter) 를 소개 한다.
    Gateway Filter
    사용자 정의 필 터 는 Gateway Filter 와 Ordered 를 실현 해 야 합 니 다.그 중에서 Gateway Filter 는 사용자 정의 의 구체 적 인 논 리 를 실현 하 는 데 사 용 됩 니 다. Ordered 의 getOrder () 방법 은 필터 에 우선 순 위 를 설정 하 는 것 입 니 다. 값 이 클 수록 우선 순위 가 낮 습 니 다.
    1.1 필터 생 성
    package spring.cloud.demo.spring.gateway.filter;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.core.Ordered;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    public class MyGatewayFilter implements GatewayFilter, Ordered {
    
        private static final Log log = LogFactory.getLog(MyGatewayFilter.class);
    
        private static final String TIME = "Time";
    
        @Override
        public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            exchange.getAttributes().put(TIME, System.currentTimeMillis());
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {
                        Long start = exchange.getAttribute(TIME);
                        if (start != null) {
                            log.info("exchange request uri:" + exchange.getRequest().getURI() + ", Time:" + (System.currentTimeMillis() - start) + "ms");
                        }
                    })
            );
        }
    
        @Override
        public int getOrder() {
            return Ordered.LOWEST_PRECEDENCE;
        }
    }

    저희 가 도착 을 요청 할 때 ServerWebExchange 에 속성 TIME 를 넣 었 습 니 다. 속성의 값 은 현재 시간의 밀리초 입 니 다. 그리고 요청 이 끝 난 후에 요청 한 시간 수 를 꺼 내 서 현재 시간 수 와 차이 가 나 고 시간 이 걸 립 니 다.
    어떻게 "pre" 와 "post" 를 구분 합 니까?
  • pre 는 chain. filter (exchange) 부분 입 니 다.
  • post 는 then () 부분 입 니 다.
  • 1.2 Filter 를 Chain 에 추가
    package spring.cloud.demo.spring.gateway.config;
    
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import spring.cloud.demo.spring.gateway.filter.MyGatewayFilter;
    
    @Configuration
    public class RoutesConfig {
    
        @Bean
        public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
            return routeLocatorBuilder.routes().route(r -> r.path("/ribbon/**")
                    .filters(f -> f.stripPrefix(1)
                            .filter(new MyGatewayFilter()) //     filter
                            .addRequestHeader("X-Response-Default-Foo", "Default-Bar"))
                    .uri("lb://EUREKA-RIBBON")
                    .order(0)
                    .id("ribbon-route")
            ).build();
        }
    }

    1.2 관련 서비스 시작
    eureka - server, eureka - client, eureka - ribbon, spring - gateway 관련 서 비 스 를 시작 하여 방문 합 니 다.http://localhost:8100/ribbon/sayHello주소, 페이지 표시 결 과 는 다음 과 같 습 니 다.
    이 때 콘 솔 을 열 면 로그 출력 을 볼 수 있 습 니 다:
    2.1 글로벌 필터 만 들 기
    package spring.cloud.demo.spring.gateway.filter;
    
    import org.apache.commons.lang.StringUtils;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    
    /**
     *      
     *   token
     */
    public class MyGlobalFilter implements GlobalFilter, Ordered {
    
        private static final String TOKEN = "token";
    
        @Override
        public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            String parm = exchange.getRequest().getQueryParams().getFirst(TOKEN);
            if (StringUtils.isBlank(parm)) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        }
    
        @Override
        public int getOrder() {
            return 1;
        }
    }

    2.2 빈 추가
    MyGlobalFilter 를 Bean 에 추가 하기
    package spring.cloud.demo.spring.gateway.filter;
    
    import org.apache.commons.lang.StringUtils;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    
    /**
     *      
     *   token
     */
    public class MyGlobalFilter implements GlobalFilter, Ordered {
    
        private static final String TOKEN = "token";
    
        @Override
        public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            String parm = exchange.getRequest().getQueryParams().getFirst(TOKEN);
            if (StringUtils.isBlank(parm)) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        }
    
        @Override
        public int getOrder() {
            return 1;
        }
    }

    여 기 는 간단 한 시 뮬 레이 션 일 뿐 관심 이 있 는 파트너 가 모든 매개 변 수 를 꺼 내 분석 하려 고 시도 할 수 있 습 니 다 (반 사 를 이용 하여 실현 할 수 있 습 니 다).
    2.3 서비스 시작
    서비스 재 시작, 접근http://localhost:8100/ribbon/sayHello다음 과 같이 표 시 됩 니 다. 저 는 디 스 플레이 접근 이 유효 하지 않 음 을 볼 수 있 습 니 다. 저 희 는 요청 에 token = xxx 를 추가 하여 다음 과 같이 표 시 됩 니 다. 이것 은 정상 적 인 귀환 을 볼 수 있 습 니 다.로그 출력 입력:
    2019-10-21 16:20:00.478  INFO 15322 --- [ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
    2019-10-21 16:20:00.480  INFO 15322 --- [ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client EUREKA-RIBBON initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=EUREKA-RIBBON,current list of Servers=[eureka1.server.com:8901],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;    Instance count:1;    Active connections count: 0;    Circuit breaker tripped count: 0;    Active connections per server: 0.0;]
    },Server stats: [[Server:eureka1.server.com:8901;    Zone:defaultZone;    Total Requests:0;    Successive connection failure:0;    Total blackout seconds:0;    Last connection made:Thu Jan 01 08:00:00 CST 1970;    First connection made: Thu Jan 01 08:00:00 CST 1970;    Active Connections:0;    total failure count in last (1000) msecs:0;    average resp time:0.0;    90 percentile resp time:0.0;    95 percentile resp time:0.0;    min resp time:0.0;    max resp time:0.0;    stddev resp time:0.0]
    ]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@40585976
    2019-10-21 16:20:01.293  INFO 15322 --- [ctor-http-nio-8] s.c.d.s.gateway.filter.MyGatewayFilter   : exchange request uri:http://localhost:8100/sayHello?token=xxx, Time:23ms
    2019-10-21 16:20:01.467  INFO 15322 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

    홈 페이지 원문 참조: The GlobalFilter interface has the same signature as Gateway Filter. These are special filter that are conditionally applied to all routes.
    총결산
    이로써 사용자 정의 filter 의 두 가지 방식 이 간단하게 이 루어 졌 다.같은 방식 으로 feign 에서 테스트 할 수 있 습 니 다.
    달걀
    이전 글 에서 설정 파일 에 다음 설정 이 있 습 니 다.
    filters:
      - StripPrefix=1
      - AddResponseHeader=X-Response-Default-Foo, Default-Bar

    Strip Prefix 와 AddResponse Header 두 설정 은 사실상 두 필터 공장 (Gateway Filter Factory) 으로 필터 공장 의 사용 을 소개 합 니 다. 상대 적 으로 이런 방식 이 더욱 유연 합 니 다.
    1.1 사용자 정의 필터 공장 만 들 기
    package spring.cloud.demo.spring.gateway.factory;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
    import reactor.core.publisher.Mono;
    
    import java.util.Arrays;
    import java.util.List;
    
    /**
     *         
     */
    public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory {
    
        private static final Log log = LogFactory.getLog(MyGatewayFilterFactory.class);
    
        private static final String PARAMS = "myParams";
    
        private static final String START_TIME = "startTime";
    
        public MyGatewayFilterFactory() {
            super(Config.class);
        }
    
        @Override
        public List shortcutFieldOrder() {
            return Arrays.asList(PARAMS);
        }
    
        @Override
        public GatewayFilter apply(Config config) {
            return ((exchange, chain) -> {
                exchange.getAttributes().put(START_TIME, System.currentTimeMillis());
                return chain.filter(exchange).then(
                        Mono.fromRunnable(() -> {
                            Long startTime = exchange.getAttribute(START_TIME);
                            if (startTime == null) {
                                return;
                            }
                            StringBuilder sb = new StringBuilder();
                            sb.append("exchange request uri:" + exchange.getRequest().getURI() + ",");
                            sb.append("Time:" + (System.currentTimeMillis() - startTime) + "ms.");
                            if (config.isMyParams()) {
                                sb.append("params:" + exchange.getRequest().getQueryParams());
                            }
                            log.info(sb.toString());
                        })
                );
            });
        }
    
        /**
         *      
         */
        public static class Config {
    
            private boolean myParams;
    
            public boolean isMyParams() {
                return myParams;
            }
    
            public void setMyParams(boolean myParams) {
                this.myParams = myParams;
            }
        }
    }

    메모: AbstractGateway FilterFactory 를 계승 할 때 사용자 정의 Config 클래스 를 부모 클래스 에 전달 해 야 합 니 다. 그렇지 않 으 면 잘못 보고 할 수 있 습 니 다.
    1.2 사용자 정의 공장 빈 추가
    package spring.cloud.demo.spring.gateway.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import spring.cloud.demo.spring.gateway.factory.MyGatewayFilterFactory;
    
    @Configuration
    public class FilterFactory {
    
        @Bean
        public MyGatewayFilterFactory myGatewayFilterFactory() {
            return new MyGatewayFilterFactory();
        }
    }

    1.3 application. yml 수정
    server:
      port: 8100
    spring:
      application:
        name: spring-gateway
      cloud:
          gateway:
            discovery:
              locator:
                enabled: true #               serviceId        
            default-filters:
              - My=true
            routes:
              - id: ribbon-route
                uri: lb://EUREKA-RIBBON
                order: 0
                predicates:
                  - Path=/ribbon/**
                filters:
                  - StripPrefix=1 #    ,      StripPrefixGatewayFilterFactory
                  - AddResponseHeader=X-Response-Default-Foo, Default-Bar
              - id: feign-route
                uri: lb://EUREKA-FEIGN
                order: 0
                predicates:
                  - Path=/feign/**
                filters:
                  - StripPrefix=1
                  - AddResponseHeader=X-Response-Default-Foo, Default-Bar
    
    
    eureka:
      instance:
        hostname: eureka1.server.com
        lease-renewal-interval-in-seconds: 5
        lease-expiration-duration-in-seconds: 10
      client:
        service-url:
          defaultZone: http://eureka1.server.com:8701/eureka/,http://eureka2.server.com:8702/eureka/,http://eureka3.server.com:8703/eureka/

    default - filers: - My = true 는 주로 이 설정 을 추 가 했 습 니 다.
    1.4 서비스 시작
    방문 하 다.http://localhost:8100/ribbon/sayHello?token=xxx다음: 로그 출력 결과 보이 기:
    2019-10-21 17:40:20.191  INFO 18059 --- [ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
    2019-10-21 17:40:20.192  INFO 18059 --- [ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client EUREKA-RIBBON initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=EUREKA-RIBBON,current list of Servers=[eureka1.server.com:8901],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;    Instance count:1;    Active connections count: 0;    Circuit breaker tripped count: 0;    Active connections per server: 0.0;]
    },Server stats: [[Server:eureka1.server.com:8901;    Zone:defaultZone;    Total Requests:0;    Successive connection failure:0;    Total blackout seconds:0;    Last connection made:Thu Jan 01 08:00:00 CST 1970;    First connection made: Thu Jan 01 08:00:00 CST 1970;    Active Connections:0;    total failure count in last (1000) msecs:0;    average resp time:0.0;    90 percentile resp time:0.0;    95 percentile resp time:0.0;    min resp time:0.0;    max resp time:0.0;    stddev resp time:0.0]
    ]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@46c172ce
    2019-10-21 17:40:20.583  INFO 18059 --- [ctor-http-nio-7] s.c.d.s.g.f.MyGatewayFilterFactory       : exchange request uri:http://localhost:8100/ribbon/sayHello?token=xxx,Time:582ms.params:{token=[xxx]}
    2019-10-21 17:40:21.181  INFO 18059 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

    총결산
    필터 공장 의 최고급 인 터 페 이 스 는 Gateway FilterFactory 입 니 다. 추상 적 인 두 가지 추상 적 인 추상 적 인 추상 적 인 AbstractGateway FilterFactory 와 AbstractNameValueGateway FilterFactory 를 직접 계승 하여 개발 을 간소화 할 수 있 습 니 다.차이 점 은 AbstractGateway FilterFactory 는 하나의 인 자 를 받 아들 이 는 것 이 고, AbstractNameValueGateway FilterFactory 는 두 개의 인 자 를 받 는 것 이다. 예 를 들 어 - AddResponseHeader = X - Response - Default - Foo, Default - Bar
    결어
    본 고 는 Gateway Filter, GlobalFilter, Gateway Filter Factory 의 간단 한 사용 방식 을 소개 하 였 으 며, 어린이 들 이 Spring Cloud Gateway 에 대해 간단 한 이 해 를 가지 게 되 었 다 고 믿는다.
    코드 주소
    gitHub 주소
    디 렉 터 리
  • spring cloud 2. x 버 전 Eureka 서버 서비스 등록 센터 튜 토리 얼
  • spring cloud 2. x 버 전 Eureka 클 라 이언 트 서비스 제공 자 튜 토리 얼
  • spring cloud 2. x 버 전 Ribbon 서비스 발견 튜 토리 얼 (통합 Hystrix 퓨즈 메커니즘 포함)
  • spring cloud 2. x 버 전 Feign 서비스 발견 튜 토리 얼 (통합 Hystrix 퓨즈 메커니즘 포함)
  • spring cloud 2. x 버 전 Zuul 경로 게 이 트 웨 이 튜 토리 얼
  • spring cloud 2. x 버 전 config 분포 식 설정 센터 튜 토리 얼
  • spring cloud 2. x 버 전 Hystrix Dashboard 차단기 튜 토리 얼
  • spring cloud 2. x 버 전 Gateway 경로 게 이 트 웨 이 튜 토리 얼
  • spring cloud 2. x 버 전 Gateway 사용자 정의 필터 튜 토리 얼
  • 글 쓰기 가 쉽 지 않 습 니 다. 전재 할 때 출처 를 밝 혀 주 십시오. 좋아 하 는 파트너 는 대중 번호 에 관심 을 가지 고 더 좋아 하 는 글 을 볼 수 있 습 니 다.
  • 연락처:[email protected]

  • 본 고 는 블 로그 한 글 다발 플랫폼 OpenWrite 에서 발표 합 니 다!

    좋은 웹페이지 즐겨찾기