• 微服务架构整理-(十二、SpringCloud实战之Zuul网关)


    Zuul概念

    Zuul是Netflix旗下的又一重要成员,是一个基于 JVM 路由和服务端的网关和负载均衡器,是一个提供路由、监控、弹性、安全等方面的服务框架。其核心是过滤器,通过这些过滤器我们可以扩展出很多功能,例如:

    • 动态路由
      动态地将客户端的请求路由到后端不同的服务,做一些逻辑处理,比如聚合多个服务的数据返回。
    • 请求监控
      可以对整个系统的请求进行监控,记录详细的请求响应日志,可以实时统计出当前系统的访问量以及监控状态。
    • 认证鉴权
      对每一个访问的请求做认证,拒绝非法请求,保护好后端的服务,所有的请求通过Zuul进行认证鉴权,无需在每个微服务中进行。
    • 压力测试
      有些系统上线前,需要进行压力测试来验证系统的稳定性和可靠性,以便系统能更好的应对可种促销活动,尤其是现在的双11,双12等活动。当并发量达到一定量级时,这些请求能否有效的转发到对应的服务上,都可以在事先通过Zuu进行压力测试。
    • 灰度发布
      灰度发布可以保证系统的平稳过度,在初始灰度的时候就可以发现、调整问题,以降低新特性对整个系统的影响度。

    Zuul构建网关

    Zuul的网关功能非常强大,这里通过一个简单的例子,通过zuul网关路由到之前的微服务中。

    创建Spring Boot 工程

    springboot版本:2.2.6.RELEASE 。工程名:zuul。启动类为:ZuulApplication

    添加依赖

    需要添加2个依赖,分别为eureka,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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    添加注解

    启动类上添加@EnableZuulProxy注解

    @SpringBootApplication
    //开启
    @EnableZuulProxy
    public class ZuulApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(ZuulApplication.class, args);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    添加配置文件

    需要在配置文件中添加基础配置,eureka,路由规则等。

    基础配置

    配置端口号与服务名

    server:
      port: 9008 #端口
    spring:
      favicon:
        enabled: false
      application:
        name: service-zuul #服务名称
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注册Eureka

    由于serice-zuul也是一个微服务因此也需要注册到Eureka中

    #配置eureka server
    eureka:
      client:
        register-with-eureka: true
        fetch-registry: true
        service-url:
          #注册到两个eureka上
          defaultZone: http://localhost:9005/eureka/,http://localhost:9006/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    添加路由规则

    #配置路由规则
    zuul:
      routes:
        api-monkey:
          path: /api-monkey/**
          serviceId: service-openfeign
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    以上配置,路由规则就是匹配所有符合/api-monkey/**的请求,只要路径中带有/api-monkey/都将被转发到service-openfeign服务上,至于service-openfeign服务的地址到底是什么则由eureka-server注册中心去分析,我们只需要写上服务名即可。

    以当前搭建的项目为例,请求 http://localhost:9008/api-monkey/buy/1 接口则相当于请求 http://localhost:9007/buy/1 (service-openfeign服务的地址为 http://localhost:9007/buy/1), 路由规则中配置的api-monkey是路由的名字,可以任意定义,但是一组path和serviceId映射关系的路由名要相同。返回结果为:

    {
        "id": 1,
        "name": "apple1",
        "price": 8000.00
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    说明API网关服务已经构建成功。

    Zuul请求过滤

    Zuul 就像一个安检站 ,所有请求都会经过这个安检站,安检站中需要对所有的请求按照一定的规则进行过滤。例如:请求验证,当验证通过了才可以进行转发。这里模拟一个带token的过滤,如果请求中没有token,则返回无效请求,反之进行跳转

    定义过虑逻辑

    
    @Component
    //必须要继承ZuulFilter
    public class OAuth2Filter extends ZuulFilter {
    
        @Override
        public Object run() throws ZuulException {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            String token = request.getParameter("token");
            if (token == null) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                ctx.addZuulResponseHeader("content-type", "text/html;charset=utf-8");
                ctx.setResponseBody("无效请求");
            }
            return null;
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public int filterOrder() {
            return 0;
        }
    
        @Override
        public String filterType() {
            return "pre";
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • filterType方法的返回值为过滤器的类型,过滤器的类型决定了过滤器在哪个生命周期执行,pre 表示在路由之前执行过滤器,其他值还有 post 、error 、route和static,当然也可以自定义。
    • filterOrder方法表示过滤器的执行顺序,当过滤器很多时, 需要通过此方法的返回值来指定过滤器的执行顺序 。
    • shouldFilter方法用来判断过滤器是否执行,true表示执行,false 表示不执行。
    • run方法表示过滤的具体逻辑, 如果请求地址中携带了token参数的话,则认为是合法请求,否则为非法请求,如果是非法请求的话,首先设置ctx.setSendZuulResponse(false)表示不对该请求进行路由,然后设置响应码和响应值。这里只是个模拟,所以run方法的返回值目前暂时没有任何意义。

    请求结果

    • http://localhost:9008/api-monkey/buy/1?token=123
    {
        "id": 1,
        "name": "apple1",
        "price": 8000.00
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • http://localhost:9008/api-monkey/buy/1
      无效请求

    Zuul路由规则

    在上面的例子中,路由规则配的是:

    #配置路由规则
    zuul:
      routes:
        api-monkey:
          path: /api-monkey/**
          serviceId: service-openfeign
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当访问地址符合/api-monkey/**规则的时候,会被自动定位到service-openfeign服务上。如果路由规则什么都不写,则zuul默认会路由到注册中心中的所有服务。格式为:域名/服务名/api地址
    例如,本服务系统中可以向外提供服务的有service-openfeignservice-product,则对应的请求分别为:

    • http://localhost:9008/service-openfeign/buy/1?token=111
    • http://localhost:9008/service-product/product/1?token=111
      当然,也可以在配置文件中添加相应的路由规则
    • 忽略某个服务
    zuul:
      ignored-services: service-product
    
    • 1
    • 2
    • 忽略某带某个关键字的api
    zuul:
      ignored-patterns: /**/hello/**
    
    • 1
    • 2
    • 配置前缀
    zuul:
      prefix:/v1
    
    • 1
    • 2

    此时访问路径就变成:http://localhost:9008/v1/api-monkey/buy/1?token=123

    • 路由规则通配符
    通配符含义举例备注
    匹配任意单个字符/api-monkey/?可以匹配: /api-monkey/1
    *匹配单路径任意数量字符/api-monkey/*可以匹配:/api-monkey/1,/api-monkey/22,/api-monkey/333 不可以匹配:/api-monkey/1/2/3
    **匹配多路径任意单个字符/api-monkey/**可以匹配: /api-monkey/1,/api-monkey/1/22

    总结

    关于Zuul的基本知识点就介绍完了。最后,希望本文能帮助大家,祝大家在IT之路上少走弯路,一路绿灯不堵车,测试一性通过,bug秒解!
    源码下载

  • 相关阅读:
    Autoware.universe部署06:使用DBC文件进行UDP的CAN通信代码编写
    单链表(1)
    充分理解判别模型和生成模型、概率模型和非概率模型
    Compiling and Loading
    【力扣 - 爬楼梯】
    MQTT协议规范总结
    springboot事务的失效场景
    C++-Cmake指令:add_executable
    C++入门应该注意的问题(this指针和类对象)
    囊个搭建自己的图床
  • 原文地址:https://blog.csdn.net/hongyinanhai00/article/details/125138050