新 Spring Cloud (五) 之 Zuul 网关

一、前言

0. 之前写过两篇Spring Cloud,但是感觉不够具体,所以重新写了一份。

新 Spring Cloud (一) 之 Eureka 服务注册中心
新 SpringCloud (二) 之 Ribbon 负载均衡
新 Spring Cloud (三) 之 Hystrix熔断保护
新 Spring Cloud (四) 之 Fegin远程调用
新 Spring Cloud (五) 之 Zuul 网关

1. 正文

Zuul是Netflix开源的微服务网关,它可以和Eureka、Ribbon、 Hystrix 等组件配合使用。
Zuul的核心是–系列的过滤器,这些过滤器可以完成以下功能。

  • 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求。
  • 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。
  • 动态路由:动态地将请求路由到不同的后端集群。
  • 压力测试:逐渐增加指向集群的流量,以了解性能。
  • 负载分配:为每- -种负载类型分配对应容量,并弃用超出限定值的请求。
  • 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群。
  • 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB ( Elastic Load Balancing )
    使用的多样化,以及让系统的边缘更贴近系统的使用者。

Spring Cloud对Zuul进行了整合与增强。目前, Zuul使用的默认HTTP客户端是Apache
HTTP Client,也可以使用RestClient或者okhttp3.0kHttpClient。如果想要使用RestClient,
可以设置ribbon.restclient ,enabled=true ;想要使用okhttp3.0kHttpClient ,可以设置rib-
bon. okhttp . enabled=true。

Zuul网关的架构图:
在这里插入图片描述

二、Zuul基本使用

  1. 创建新模块 EurekaZuul 作为zuul网关。选中引入Zuul依赖和Eureka客户端依赖。Zuul依赖自不必说,引入Eureka客户端的依赖是为了从Eureka注册中心拉取注册已注册的服务。
    在这里插入图片描述


  2. 在启动类上加上注解 @EnableZuulProxy 开启zuul网关代理,@EnableDiscoveryClient 注册为Eureka客户端

    @SpringBootApplication
    @EnableZuulProxy            // 开启网关代理功能
    @EnableDiscoveryClient      // 注册人Eureka客户端
    public class SpringcloudApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudApplication.class, args);
        }
    
    }
    

  3. yml进行如下配置

    spring:
      application:
        name: zuul-gateway  #  指定服务名
    server:
      port: 9999  #端口号
    zuul:
      routes:
        eureka-server-provider: /provider/**  #  /provider/** 路径的请求都映射到的 eureka-server-provider 服务上
        eureka-server-consumer: /consumer/**  #  /provider/** 路径的请求都映射到的 eureka-server-provider 服务上
      prefix: /api    # 添加路由前缀。用来分辨哪个接口通过了Zuul网关。
    eureka:
      client:
        service-url: # EurekaServer的地址
          defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
    

    注: Zuul 网关的常用的路由方式有以下三种
    1. 使用 path 指定映射路径,serviceId指定服务名

    zuul:
      routes:
        eureka-server-provider:         # 路由id,可以随意写
          path: /provider/** 			# 服务将要映射的路径
          serviceId: eureka-server-provider   # 指定需要路由的服务名
    

    2. 是第一种的简化形式,格式是 ----> 服务名:映射路径

    	zuul:
    	  routes:	# 上面简化形式: 服务名:映射路径
    	    eureka-server-provider: /provider/**  #  /provider/** 路径的请求都映射到的 eureka-server-provider 服务上
    

    3. 不进行配置: 不配置默认将服务名作为映射路径。Zuul默认格式是 ----> 服务名: /服务名/**


  4. 启动服务,访问服务,如下:
    在这里插入图片描述

三、Zuul过滤器

1. 简介

Zuul作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现的。
Zuul提供了一个最顶层的抽象过滤器ZuulFilter。我们通过继承这个抽象类来实现过滤器功能。

public abstract ZuulFilter implements IZuulFilter{

    abstract public String filterType();

    abstract public int filterOrder();
    
    boolean shouldFilter();// 来自IZuulFilter 

    Object run() throws ZuulException;// IZuulFilter
}
  • shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
  • run:过滤器的具体业务逻辑。
  • filterType:返回字符串,代表过滤器的类型。包含以下4种:
    • pre:请求在被路由之前执行
    • route:在路由请求时调用
    • post:在route和errror过滤器之后调用
    • error:处理请求时发生错误调用
  • filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。

2. 使用场景

  • 请求鉴权:一般放在pre类型,如果发现没有访问权限,直接就拦截了
  • 异常处理:一般会在error类型和post类型过滤器中结合来处理。
  • 服务调用时长统计:pre和post结合使用。

3. 过滤器的生命周期

正常流程:

  • 请求到达首先会经过pre类型过滤器,而后到达route类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器。而后返回响应。

异常流程:

  • 整个过程中,pre或者route过滤器出现异常,都会直接进入error过滤器,在error处理完毕后,会将请求交给POST过滤器,最后返回给用户。
  • 如果是error过滤器自己出现异常,最终也会进入POST过滤器,将最终结果返回给请求客户端。
  • 如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和route不同的是,请求不会再到达POST过滤器了。

4. 自定义过滤器实现

创建一个类继承 ZuulFilter 类,并实现其中的方法,最后将其注入到Spring容器中即可。

package com.kingfish.springcloud.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @Des: 自定义过滤器
 */
@Component
public class CallFilter extends ZuulFilter {
    /**
     * 过滤类型
     *
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 过滤器顺序,数字越小优先级越高
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 10;
    }

    /**
     * 是否执行拦截
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        // 获取zuul提供的上下文对象
        RequestContext context = RequestContext.getCurrentContext();
        // 从上下文对象中获取请求对象
        HttpServletRequest request = context.getRequest();
        // 设置编码格式
        context.getResponse().setContentType("text/html;charset=UTF-8");
        // 获取token信息
        String msg = request.getParameter("msg");
        // 判断
        if (StringUtils.isBlank(msg)) {
            // 过滤该请求,不对其进行路由
            context.setSendZuulResponse(false);
            // 设置响应状态码,401
            context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            // 设置响应信息
            context.setResponseBody("{\"status\":\"401\", \"text\":\"来者何人,报上姓名!\"}");
        } else if ("张三".equals(msg)) {
            // 过滤该请求,不对其进行路由
            context.setSendZuulResponse(false);
            // 设置响应状态码,401
            context.setResponseStatusCode(HttpStatus.SC_FORBIDDEN);
            // 设置响应信息
            context.setResponseBody("{\"status\":\"403\", \"text\":\"张三不能打车!\"}");
        }
        // 校验通过,把登陆信息放入上下文信息,继续向后执行
        context.set("msg", msg);
        return null;
    }
}

调用如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、Ribbon负载均衡和Hystrix熔断

Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制。其使用方式和配置和单独使用并无差别。故此不再叙述。

以上:内容部分参考网络
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫吻鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值