woshikid / blog

Apache License 2.0
8 stars 1 forks source link

Zuul学习笔记 #177

Open woshikid opened 2 years ago

woshikid commented 2 years ago

POM

<!-- 需要降级Spring Cloud -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    <version>2.2.10.RELEASE</version>
</dependency>

<!-- 对应Spring Boot为2.3.12.RELEASE -->
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>

启用Zuul

@EnableZuulProxy

自动配置 根据注册中心自动配置路由 注意:不包括Zuul本身的serviceId

zuul:
  routes:
    <serviceId>: /<serviceId>/**
    #<serviceId>:
      #path: /<serviceId>/**
      #serviceId: <serviceId>

自定义配置

zuul:
  servlet-path: /zuul # ZuulServlet地址(绕过DispatcherServlet,如文件上传时),默认为/zuul
  prefix: "" # 路由地址前缀,默认为空
  #ignored-services: test,test2 # 可使用"*"忽略所有自动配置
  #ignored-patterns: /**/test/** # 忽略的路由地址
  sensitive-headers: "" # 过滤请求头,默认为Cookie, Set-Cookie, Authorization
  add-host-header: true # 传递Host请求头,默认为false
  retryable: true # 使用Ribbon重试(依赖Spring Retry),默认为false
  routes: # 自定义路由配置
    test: # serviceId
      path: /test/** # 与自动配置的地址不同时将新增路由而不是覆盖
      #strip-prefix: true # 转发时去掉前缀,默认为true(重定向时会造成地址错误)
      #service-id: test # 可转发到其他serviceId
      #url: http://localhost:8080 # 指定服务地址,不使用注册中心与Ribbon/Hystrix(不跟随重定向)
      #url: forward:/test # 转发到Zuul本身的Controller
  host:
    max-total-connections: 200 # 最大并发请求数,默认为200
    max-per-route-connections: 20 # 每个路由的最大并发请求数,默认为20

自定义路由映射

@Bean
public PatternServiceRouteMapper serviceRouteMapper() {
    // 自动配置路由时serviceId: test-v1会被映射到path: /v1/test/**
    return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)", "${version}/${name}");
    // serviceId不匹配时,使用默认规则:<serviceId>会被映射到/<serviceId>/**
}

过滤器

@Component
public class TestFilter extends ZuulFilter {

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();

        if (request.getHeader("token") == null) {
            context.setSendZuulResponse(false); // 停止路由转发
            context.setResponseStatusCode(403); // 设置状态码,默认为200
        }

        return null;
    }

}

禁用过滤器

zuul.TestFilter.pre.disable: true

Hystrix降级

@Component
public class TestFallbackProvider implements FallbackProvider {

    @Override
    public String getRoute() {
        return "test"; // 需要降级的serviceId,"*"或null代表所有路由
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {

            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("fallback".getBytes());
            }

            @Override
            public void close() {
            }

        };
    }

}

AOP优先级

Hystrix(Ribbon())

限流

POM

<dependency>
    <groupId>com.marcosbarbero.cloud</groupId>
    <artifactId>spring-cloud-zuul-ratelimit</artifactId>
    <version>2.4.3.RELEASE</version>
</dependency>

<!-- BUCKET4J_JCACHE -->
<dependency>
    <groupId>com.github.vladimir-bukhtoyarov</groupId>
    <artifactId>bucket4j-core</artifactId>
    <version>6.4.1</version>
</dependency>
<dependency>
    <groupId>com.github.vladimir-bukhtoyarov</groupId>
    <artifactId>bucket4j-jcache</artifactId>
    <version>6.4.1</version>
</dependency>
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
</dependency>

JCache(依赖JCache实现)

@Bean
@Qualifier("RateLimit")
public Cache<String, GridBucketState> rateLimitCache() {
    CacheManager cacheManager = Caching.getCachingProvider().getCacheManager();
    return cacheManager.createCache("cacheName", new MutableConfiguration<>());
}

自定义配置

zuul:
  ratelimit:
    enabled: true # 默认为false
    repository: BUCKET4J_JCACHE
    #key-prefix: zuul # 默认为${spring.application.name:rate-limit-application}
    behind-proxy: true # Zuul位于代理之后,需解析X-Forwarded-For,默认为false
    response-headers: VERBOSE # 添加ratelimit相关header,默认为VERBOSE
    deny-request: # 黑名单
      response-status-code: 403 # 默认403
      origins: [192.168.0.1]
    default-policy-list: # 全局配置
      - limit: 100 # 限流请求数
        #quota: 100s # 限流总请求时间,有bug
        refresh-interval: 60 # 限流周期,默认为60秒
        type: # 限流粒度,可选
          - user # remoteUser
          - origin # remoteAddr
          - url # path
    policy-list: # 指定配置
      test:
        - limit: 10
          type:
            - user=anonymous
            - url=/api # prefix
            - http_method=get
            - http_header=customHeader
            - url_pattern=/api/*/payment