Spring Cloud学习笔记(五)——Zuul服务网关

本文介绍了如何使用Spring Cloud Zuul快速搭建微服务网关,包括引入依赖、配置Zuul服务、路由规则、优先级、前缀、本地跳转、头部过滤与重定向等功能,并提供了自定义过滤器的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

在微服务的架构中,服务网关就是一个介于客户端与服务端之间的中间层。在这种情况下,客户端只需要跟服务网关交互,无需调用具体的微服务接口。这样的好处在于,客户端可以降低复杂性;对于需要认证的服务,只需要在服务网关配置即可;同样也方便后期微服务的变更和重构,即微服务接口变更只需在服务网关调整配置即可,无需更改客户端代码。

Spring Cloud Zuul入门

zuul使用

新建Springboot应用,编辑pom文件,引入依赖:

	<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

因为spring-cloud-starter-zuul依赖已经包含了Hystrix和Ribbon,所以zuul支持前面介绍的Hystrix和Ribbon相关配置。

接着在Spring Boot的入口类上标注@EnableZuulProxy注解,开启Zuul服务网关的功能:

@EnableZuulProxy
@SpringBootApplication
public class ZuuldemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuuldemoApplication.class, args);
    }

}

最后简单配置下application.yml:

server.port=8091
spring.application.name=Zuul-Gateway

至此一个简单的Zuul微服务网关就搭建好了,下面开始对路由规则进行配置。

路由配置
  1. 传统配置
    传统配置就是手动指定服务的转发地址,如在yml中配置:

    zuul:
      routes:
        api-a:
          path: /api-a/**
          url: http://localhost:8082
    

    通过上面的配置,所有符合/api-a/**规则的访问都将被路由转发到http://localhost:8082/地址上,即当我们向服务网关访问http://localhost:12580/api-a/hello请求的时候,请求将被转发到http://localhost:8082/hello服务上。

  2. 基于服务名称配置

    传统的配置方式不便之处在于需要知道服务的具体地址和端口号等信息,我们可以借助Eureka来实现通过服务名称配置路由。在Zuul-Gateway项目中引入Eureka依赖:

    		<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    

    然后在入口类中加入@EnableDiscoveryClient注解,使其具有获取服务的能力。

    接着在yml中配置基于服务名称的路由:

    eureka:
    	client:
    		service-url:
    			defaultZone: http://localhost:8085/eureka, http://localhost:8087/eureka
    zuul:
    	routes:
    		api-a:
    			path: /api-a/**
    			service-id: Feign-Consumer
    

    基于服务名称的路由配置还可以进行简化,格式为zuul.routes.= ,所以我们可以将api-b和api-c的路由配置修改为:

    	zuul:
    		routes:
    			feign-consumer
    				path: /api-a/**
    
  3. 默认路由配置规则

    我们尝试访问http://localhost:8091/feign-consumer/user/1会发现可以正常访问,我们却没有配置相应的服务地址映射,这是由于feign存在默认的路由配置,当我们使用服务名称作为请求的前缀路径时,实际上就会匹配上类似下面的默认路由配置:

    zuul:
      routes:
        server-consumer:
          path: /feign-consumer/**
          serviceId: feign-consumer
    

    如果不想启动这个默认配置,我们可以使用zuul.ignored-services配置来关闭,如在yml中加入如下配置之后,再次访问http://localhost:8091/feign-consumer/user/1将返回404:

    zuul:
      ignored-services: feign-consumer
    

    设置为zuul.ignored-services=*的时候将关闭所有默认路由配置规则。

  4. 优先级

    在yml文件中,路由映射的优先匹配按照其声明顺序进行匹配

  5. 前缀配置

    zuul.prefix可以为网关的请求路径加个前缀,比如:

    zuul:
      	prefix: /gateway
    

    这样配置后,我们通过Zuul网关获取服务的时候,路径也得加上这个前缀,如http://localhost:12580/gateway/api-c/user/1。

  6. 本地跳转

    Zuul网关除了支持将服务转发到各个微服务上之外,还支持将服务跳转到网关本身的服务上,比如现在yml中有如下一段配置:

    zuul:
      routes:
        api-e:
          path: /api-e/**
          url: forward:/test
    

    当访问http://localhost:8091/gateway/api-e/hello时,Zuul会从本地/test/hello获取服务。

    我们在Zuul-Gateway入口类中加上该REST服务:

    @EnableZuulProxy
    @EnableDiscoveryClient
    @SpringBootApplication
    @RestController
    public class ZuuldemoApplication {
    
        @GetMapping("/test/hello")
        public String hello() {
            return "hello zuul";
        }
    
        public static void main(String[] args) {
            SpringApplication.run(ZuuldemoApplication.class, args);
        }
    }
    

头部过滤 & 重定向

在使用Zuul网关的时候你可能会遇到Cookie丢失的情况,这是因为默认情况下Zuul会过滤掉HTTP请求头中的一些敏感信息,这些敏感信息通过下面的配置设定:

zuul:
  sensitive-headers: Cookie,Set-Cookie,Authorization

如果想关闭这个默认配置,通过设置全局参数为空来覆盖默认值:

zuul:
  sensitive-headers:

如果只想关闭某个路由的HTTP请求头过滤,可以这样:

zuul:
 routes:
   api-a:
     sensitive-headers:

使用Zuul另一个常见问题是重定向的问题,可以通过下面的设置解决:

zuul:
  add-host-header: true

过滤器

Zuul另一个核心的功能就是请求过滤。Zuul中默认定义了4种不同生命周期的过滤器类型,在如下图所示
在这里插入图片描述
这4种过滤器处于不同的生命周期,所以其职责也各不相同:

  • PRE:PRE过滤器用于将请求路径与配置的路由规则进行匹配,以找到需要转发的目标地址,并做一些前置加工,比如请求的校验等;
  • ROUTING:ROUTING过滤器用于将外部请求转发到具体服务实例上去;
  • POST:POST过滤器用于将微服务的响应信息返回到客户端,这个过程种可以对返回数据进行加工处理;
  • ERROR:上述的过程发生异常后将调用ERROR过滤器。ERROR过滤器捕获到异常后需要将异常信息返回给客户端,所以最终还是会调用POST过滤器。

核心过滤器
Spring Cloud Zuul为各个生命周期阶段实现了一批过滤器,如下所示:
在这里插入图片描述
这些过滤器的优先级和作用如下表所示:

生命周期优先级过滤器功能描述
pre-3ServletDetectionFilter标记处理Servlet的类型
pre-2Servlet30WrapperFilter包装HttpServletRequest请求
pre-1FormBodyWrapperFilter包装请求体
route1DebugFilter标记调试标志
route5PreDecorationFilter处理请求上下文供后续使用
route10RibbonRoutingFilterserviceId请求转发
route100SimpleHostRoutingFilterurl请求转发
route500SendForwardFilterforward请求转发
post0SendErrorFilter处理有错误的请求响应
post1000SendResponseFilter处理正常的请求响应

其中优先级数字越小,优先级越高。

要关闭这些过滤器可以在application.yml中按照格式zuul...disable=true配置即可。比如关闭SendResponseFilter过滤器:

zuul:
  SendResponseFilter:
    post:
      disable:
        true

自定义Zuul过滤器
我们自定义一个PreSendForwardFilter用于获取请求转发前的一些信息:

@Component
public class PreSendForwardFilter extends ZuulFilter {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public String filterType() {
        return "pre";
    }

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

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

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String host = request.getRemoteHost();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        logger.info("请求URI:{},HTTP Method:{},请求IP:{}", uri, method, host);
        return null;
    }
}

可以看到自定义Zuul过滤器只需要继承ZuulFilter,然后实现以下四个抽象方法即可:

  • filterType:对应Zuul生命周期的四个阶段:pre、post、route和error;
  • filterOrder:过滤器的优先级,数字越小,优先级越高;
  • shouldFilter:方法返回boolean类型,true时表示是否执行该过滤器的run方法,false则表示不执行;
  • run:过滤器的过滤逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值