SpringCloud学习笔记(六):使用Zuul实现路由和请求过滤

SpringCloud学习笔记(六):使用Zuul实现路由和请求过滤

Zuul的作用

没有使用Zuul时的情况

简单架构
通过先前的内容我们可以很容易实现如上图所示的架构。在常规的项目中,调用服务前基本都需要经过鉴权之类的操作。使用上面的架构,每个开放服务都需要实现鉴权,不仅提高了开发的复杂程度,而且使得代码变得冗余。因此我们需要一个组件来搭建开放服务和用户端之间的桥梁,在这一层面上实现代理、鉴权等操作。Netfilx Zuul就能达成这一目的。

使用了Zuul时的情况

Zuul架构
在原有架构中加入Zuul组件后,架构如上图所示,使用了Zuul之后,用户调用我们系统服务的请求将会先到达Zuul网关,再由网关对不同的请求进行路由转发。在执行转发操作之前,Zuul可以通过过滤器执行一系列代码,实现请求过滤,达到类似Spring MVC中拦截器的效果。此时各个微服务的开发人员不需要在关注诸如鉴权之类的问题,鉴权由Zuul统一处理,只有鉴权通过的请求才会被路由,否则Zuul直接过滤掉该请求。

实现

路由实现

我们在项目中新建一个Maven模块,我这里给模块命名为zuulgateway,在模块下pom.xml中新增如下的依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <!-- 导入Spring Cloud的依赖管理 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>

        <!--整合eureka客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.0.2.RELEASE</version>
        </dependency>

        <!--整合zuul网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.0.3.RELEASE</version>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

然后在resource目录下新建application.yml,配置一下Zuul的路由转发规则。application.yml内容如下

server:
  port: 8070 #端口号
spring:
  application:
    name: app-zuul-gateway #应用名

##配置eureka,从注册中心获取服务地址
eureka:
  client:
    service-url:
           defaultZone: http://localhost:9090/eureka/
###因为该应用为服务提供者,是eureka的一个客户端,需要注册到注册中心
    register-with-eureka: true
###是否需要从eureka上检索服务
    fetch-registry: true
  instance:
        prefer-ip-address: true #将自己的ip地址注册到Eureka服务中
        ip-address: 127.0.0.1
        instance-id: ${spring.application.name}###${server.port} #指定实例ID



##zuul路由规则
zuul:
  host:
    connect-timeout-millis: 15000 #HTTP连接超时大于Hystrix的超时时间
    socket-timeout-millis: 60000   #socket超时
  routes:
    cargo-service: #这是个随便取的名字,用于识别不同的路由,从原地址到目的地址
      path: /cargo-service/** #访问的地址
      serviceid: app-cargo #转发到哪个微服务

    cargolist-service:
      path: /cargolist-service/**
      serviceid: app-cargolist

ribbon:        #设置ribbon的超时时间小于zuul的超时时间
  ReadTimeout: 10000
  ConnectTimeout: 10000

这里注意一下,一定要让Zuul的超时时间大于Ribbon的超时时间,否则Zuul无法正常工作,请求会失败。

然后在src/main/java下新建一个runner包,在包下新建启动类,类上添加@EnableZuulProxy注解,表示启动Zuul,启动微服务即可测试查看效果。启动类完整代码如下

package runner;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy//启用Zuul
public class ZuulGatewayApp {
    public static void main(String[] args) {
        SpringApplication.run(ZuulGatewayApp.class, args);
    }
}

微服务启动完成后,访问http://localhost:8070/cargolist-service/cargoList/123,通过Zuul微服务来调用app-cargo-list微服务,页面正常返回结果,Zuul在此时已经起到了路由代理的作用,Zuul的基本配置就完成了。

过滤器实现

Zuul的过滤器实现同样非常简单,只需要新建一个过滤器类,并且让SpringBoot框架扫描到它就可以实现了,我们在模块下再新建一个filter包用来存放过滤器类,新建一个TokenZuulFilter类,并继承ZuulFilter。ZuulFilter是一个抽象方法,里面定义了一系列拦截器执行过程。TokenZuulFilter类完整代码如下。

package filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.HttpServletRequest;

@Component
public class TokenZuulFilter extends ZuulFilter {
    @Override
    public String filterType() {
        //pre:请求被路由前执行
        //routing:路由请求调用时执行
        //post:路由完成或路由提交后出错后返回前执行
        //error:处理请求时发生错误执行
        return "pre";
    }

    @Override
    public int filterOrder() {
        //数字越小优先级越高
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        //true执行,false不执行
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String token = request.getParameter("token");
        if(StringUtils.isEmpty(token)||!"123".equals(token)){//检查token
            requestContext.setSendZuulResponse(false); // 过滤该请求,不对其进行路由
            requestContext.setResponseStatusCode(401); // 设置响应状态码
            requestContext.setResponseBody("TOKEN ERROR"); // 设置响应状态码
            return null;
        }
        return null;
    }
}

在启动类@SpringBootApplication注解加入包扫描的参数,添加filter包,重启微服务即可测试查看结果。

@SpringBootApplication(scanBasePackages = "filter")

访问http://localhost:8070/cargolist-service/cargoList/123,发现页面返回TOKEN ERROR,F12查看请求状态码为401。我们在URL上加入参数再访问http://localhost:8070/cargolist-service/cargoList/123?token=123,此时发现页面可以正常返回,至此Zuul过滤器实现就完成了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值