Zuul——微服务网关

1 Zuul 简介

在微服务架构中,如果让客户端直接和各个微服务直接通信的话,会产生很多问题,比如:客户端需要多次请求不同的微服务;对每个服务都要设立认证;难以重构,如果微服务需要重新划分,客户端也要作出相应的修改...要解决这些问题,我们可以在客户端和微服务之间设立一个中间层——微服务网关,网关对微服务接口进行了封装,微服务只跟网关进行交互,使得客户端和微服务的耦合度降低。
Zuul是Netflix开源的微服务网关,其核心是一系列的过滤器,通过这些过滤其,我们可以实现身份认证、动态路由等功能。

2 如何使用Zuul

  1. 引入相应的依赖:
        
            org.springframework.cloud
            spring-cloud-starter-eureka
        
        
            org.springframework.cloud
            spring-cloud-starter-zuul
        
  1. 在启动类中添加@EnableZuulProxy注解
@EnableZuulProxy
@SpringBootApplication
public class GatewayZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayZuulApplication.class, args);
    }
}
  1. 编写配置文件,将Zuul服务注册到Eureka Server
server:
  port: 8007
spring:
  application:
    name: gateway-zuul
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8001/eureka/
  instance:
    prefer-ip-address: true

3 路由配置

  1. 默认配置
    如果没有在配置文件中对路由进行配置,那么默认将对 http://ZUUL_HOST:ZULL_PORT/CONTEXT-PATH/serviceId/**的请求转发到serviceId对应的微服务

  2. 为指定微服务设置访问路径:
    使用zuul.routes.指定微服务的serviceId=访问路径进行设置,比如:

zuul:
  routes: 
    ribbon-demo: /ribbon/**
  1. 还可以为每一个serviceId-path对设置别名,如:
zuul:
  routes:
    ribbon-route:
      sevice-id: ribbon-demo
      path: /ribbon/**

该设置与2中效果一致。

  1. 如果要禁止默认的路由配置,使用zuul.ignored-services进行设置,比如禁用所有的默认路由:
zuul:
  ignored-services: '*'
  1. 指定URL和path:
zuul:
  routes:
    ribbon-route:
      url: http://localhost:8003/
      path: /ribbon/**

使用该方法指定的路由不会具有Hystrix和Ribbon的特性,如果要具有Hystrix和Ribbon的特性,要为Ribbon禁用Eureka,用listOfServers来指定url:

zuul:
  routes:
    ribbon-route:
      serviceId: ribbon-demo
      path: /ribbon/**
ribbon:
  eureka:
    enabled: false
ribbon-demo:
  ribbon:
    listOfServers: localhost:8003
  1. 路由转发可以带上前缀,有两种方式:
    方式1:
zuul:
  routes:
    ribbon-route:
      serviceId: ribbon-demo
      path: /ribbon/**
      strip-prefix: false

方式2:

zuul:
  prefix: /ribbon
  strip-prefix: false  
  routes:
    ribbon-route:
      serviceId: ribbon-demo
      path: /ribbon/**

以上两种方法都是将请求转发到ribbon-demo的/ribbon/**

4 过滤器

4.1 过滤器分类

Zuul的核心是一系列的过滤器,过滤器主要分为四种:

  • PRE,在请求被转发出去之前执行。
  • ROUTING,将请求转发到微服务。
  • POST,在请求转发之后执行。
  • ERROR,在发生错误的时候执行。

4.2 自定义过滤器

  1. 编写一个类继承 ZuulFilter并实现其中的抽象方法。
public class AccessFilter extends ZuulFilter {

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

    @Override
    public int filterOrder() {
        return 0;
    }

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

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

        Object accessToken = request.getParameter("accessToken");
        if (accessToken == null) {
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(401);
            return null;
        }

        return null;
    }
}
  • filterType(): 返回过滤器的类型,过滤器的类型有pre、 route、 post、 error等等,可以使用org.springframework.cloud.netflix.zuul.filters.support.FilterConstants中的常量进行指定,该类提供了关于ZuulFilter的各种常量。
  • filterOrder(): 返回过滤器执行的顺序。
  • shouldFilter(): 判断过滤器是否需要执行。
  • run(): 过滤器的具体逻辑。
  1. 在启动类中为过滤器创建具体的Bean。
    @Bean
    public AccessFilter accessFilter() {
        return new AccessFilter();
    }

4.3 禁用过滤器

禁用过滤器的话使用zuul...disable=true,比如要禁用上面编写的自定义过滤器,可使用如下配置:

zuul:
  AccessFilter:
    pre:
      disable: true

5 回退

在Spring Cloud中,Zuul默认集成了Hystrix, 如果要为其编写回退方法,可按如下方法,实现ZuulFallbackProvider接口,指定要为哪个微服务提供回退,并提供一个ClientHttpResponse作为响应。

@Component
public class RibbonDemoFallbackProvider implements ZuulFallbackProvider {

    @Override
    public String getRoute() {
        return "eureka-client-demo";
    }

    @Override
    public ClientHttpResponse fallbackResponse() {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.SERVICE_UNAVAILABLE;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return this.getStatusCode().value();
            }

            @Override
            public String getStatusText() throws IOException {
                return this.getStatusCode().getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("服务不可用!".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));
                httpHeaders.setContentType(mt);
                return httpHeaders;
            }
        };
    }
}

6 端点

Zuul提供了两个端点来查看路由和过滤器信息:/routes/filters,不过要先设置management.security.enabled=false

7 安全和Header

7.1 敏感Header

在进行路由时,有一些敏感Header不能外泄,可以使用下面配置进行设置:

 zuul:
  routes:
    users:
      path: /myusers/**
      sensitiveHeaders: Cookie,Set-Cookie,Authorization
      url: https://downstream

或者可以进行全局的配置:

 zuul:
  sensitiveHeaders: Cookie,Set-Cookie,Authorization
  routes:
    users:
      path: /myusers/**
      url: https://downstream

前者的配置会覆盖后者的全局配置。另外sensitiveHeaders: Cookie,Set-Cookie,Authorization是默认的Header设置,如果不希望使用该配置,可以让该项的值为空,如 sensitiveHeaders:

7.2 忽略Header

可以在请求转发的时候丢弃一些Header:

 zuul:
  ignored-headers: Header1,Header2

默认情况下ignored-headers为空值,但是如果Spring Security在项目的classpath中,默认值将会变化,如果需要将这些Headers传递下去,则要将zuul.ignoredSecurity-Headers设置为false

你可能感兴趣的:(Zuul——微服务网关)