zoukankan      html  css  js  c++  java
  • Spring Cloud系列(五):服务网关Zuul

    在前面的篇章都是一个服务消费者去调用一个服务提供者,但事实上我们的系统基本不会那么简单,如果真的是那么简单的业务架构我们也没必要用Spring Cloud,直接部署一个Spring Boot应用就够了。所以当我们的服务消费者有很多个,比如说在一个电商系统里,会员中心是一个微服务,商品详情又是一个微服务,订单又是一个微服务,支付又是一个等等,在这么多的微服务中,每个系统都需要自己的url,这种情况我们需要一个组件来集中管理和分发这些请求,把不同url转发给不同的微服务去处理。Zuul就可以很好地完成这件事,但是Zuul可以做的远不止是路由功能。先看一下官方对Zuul的简介:

    Routing is an integral part of a microservice architecture. For example, / may be mapped to your web application, /api/users is mapped to the user service and /api/shop is mapped to the shop service. Zuul is a JVM-based router and server-side load balancer from Netflix.

    Netflix uses Zuul for the following:

    • Authentication
    • Insights
    • Stress Testing
    • Canary Testing
    • Dynamic Routing
    • Service Migration
    • Load Shedding
    • Security
    • Static Response handling
    • Active/Active traffic management

    Zuul’s rule engine lets rules and filters be written in essentially any JVM language, with built-in support for Java and Groovy.

    内容来源:https://cloud.spring.io/spring-cloud-netflix/reference/html/#router-and-filter-zuul

    Zuul提供的功能有很多,这里限于篇幅先介绍路由和过滤功能。

    一、路由

    1.1、创建新的module

    新建一个新的module,名称为zuul,选择Eureka Discovery Client和Zuul两个依赖,如下:

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

    1.2、修改配置文件

    在application.properties中添加以下配置

    server.port=8033
    spring.application.name=server-zuul
    
    eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
    
    zuul.routes.api-ribbon.service-id=consumer-ribbon
    zuul.routes.api-ribbon.path=/api-ribbon/*
    
    zuul.routes.api-feign.service-id=consumer-feign
    zuul.routes.api-feign.path=/api-feign/*
    

    另外在启动类加上@EnableEurekaClient和@EnableZuulProxy注解

    解释一下上面的zuul的配置,zuul配置路由时zuul.routes.XXX.service-id指定的是XXX服务的服务名,这里指定的是消费者的应用名,比如我们的两个服务消费者的应用名分别是consumer-ribbon和consumer-feign,而zuul.routes.XXX.path指定是映射路径,配置之后的请求地址就可以直接是zuul的地址+端口+url。举个例子,比如zuul的主机是localhost,端口是8033,那么当我们所有url为localhost:8033/api-ribbon/的请求就会被映射到consumer-ribbon服务,所有url为localhost:8033/api-feign/的请求就会被映射到consumer-feign。

    1.3、启动&测试

    依次启动注册中心、服务提供者、ribbon消费者、feign消费者和zuul,访问http://localhost:8033/api-ribbon/index?uid=ribbon,可以看到返回了

    服务8770的消息:用户ribbon调用了此服务
    

    访问http://localhost:8033/api-feign/index?uid=ribbon也能看到同样的信息,这说明我们的路由功能已经生效了。

    二、过滤

    我们可以对某些请求进行一些过滤的工作,比如对分发给ribbon这个服务的请求都进行参数校验,要求所有这个服务的请求都要带上token。

    在zuul的module新建一个CustomFilter继承ZuulFilter

    @Component
    public class CustomFilter extends ZuulFilter {
    
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        @Override
        public String filterType() {
            return "pre";
        }
    
        @Override
        public int filterOrder() {
            return 0;
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public Object run() throws ZuulException {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            logger.info("request uri:" + request.getRequestURI());
            String uri = request.getRequestURI();
            String token = request.getParameter("token");
            if (uri.startsWith("/api-ribbon") && StringUtils.isEmpty(token)) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                ctx.setResponseBody("Token must not be empty.");
            }
            return null;
        }
    }
    

    需要重写的这四个方法:

    • filterType:返回过滤的类型,允许的有四个值:

      1. pre:路由前
      2. routing:路由时
      3. post:路由后
      4. error:发送错误调用
    • filterOrder:过滤顺序。这个方法返回一个整型数值,其实表示的是过滤的优先级,当有多个过滤器存在时,数字越大,优先级越高。

    • shouldFilter:返回一个布尔类型的值,它和run方法一起使用,返回true时会执行run方法,否则不执行。可以把这个方法理解问某种过滤规则的开关。

    • run:该方法是核心方法,过滤的具体规则在这个方法实现。虽然该方法要求返回一个对象,但是现在的实现往往会忽略,直接返回null就可以了。

    上面的代码就是先获取路由前的请求uri和请求参数token的值,如果请求的是ribbon服务,就需要token参数,否则不需要。

    依次启动注册中心、服务提供者、ribbon消费者、feign消费者和zuul,然后当访问http://localhost:8033/api-ribbon/index?uid=ribbon时会返回

    Token must not be empty.
    

    再访问http://localhost:8033/api-feign/index?uid=ribbon即会返回

    服务8770的消息:用户ribbon调用了此服务
    

    这说明我们的过滤器已经生效了

    三、总结

    以上就是Zuul的简单介绍,更多功能可以自行探索。下一篇介绍配置中心。

    源码已经上传到github:https://github.com/spareyaya/spring-cloud-demo/tree/master/chapter5

  • 相关阅读:
    项目总结_写代码
    项目总结_el表达式
    项目总结plc_过滤器规则(filter)_忽略过滤的js和css文件
    tomcat 启动错误
    每天学点java_Eclipse修改author名
    每天学点java_FileOutputSteam类
    每天学点java_File类
    11.28日日记
    《深入理解计算机系统》学习中期
    开始《深入理解计算机系统》
  • 原文地址:https://www.cnblogs.com/spareyaya/p/12805290.html
Copyright © 2011-2022 走看看