spring cloud zuul使用总结

一、spring cloud zuul的介绍
(1)spring cloud zuul是服务网管,是所有外部请求的统一入口。理论上服务网管是处理非业务逻辑的绝佳场所。如果服务网管出现问题,系统就会全部瘫痪,所以必须具备的要素有:稳定性、高可用、高并发、安全性以及可扩展性。
(2)spring cloud zuul最核心的组件就是一系列的过滤器,所有的请求经过zuul,都需要经过过滤器的过滤,再返回请求给客户端。zuul的过滤器分为:前置过滤器(pre)、路由过滤器(route)、后置过滤器(post)、处理异常的过滤器(error)以及自定义过滤器。
spring cloud zuul使用总结_第1张图片
这是zuul的组件架构图,可以看到每个过滤器之间是没有通信的,都是通过requestContext这个静态类进行数据的传递的。
(3)在zuul中一次http请求的生命周期
spring cloud zuul使用总结_第2张图片
由上图可以看出一次http请求首先经过前置过滤器(pre),可以在这里进行请求参数的加工,比如参数校验等。接下来到达路由过滤器(route),该类型的过滤器是将外部的请求转发到服务提供方,假如服务提供方有多个实例,就会用到负载均衡组件。接下来到达后置过滤器(post),在这里可以对返回的结果进行加工和处理。当前面说的这三种类型的过滤器出现异常的时候,会被error filter过滤器捕获到,因此可以在这里面进行统一的异常处理。
二、spring cloud zuul的使用
1.zuul的路由:首先要将zuul注册进eureka中,当调用一个服务的时候,zuul会拿着这个服务的服务名去eureka中寻找该服务的实例,如果只有一个服务实例就直接调用,如果有多个服务实例,就会根据负载均衡策略选择一个服务实例进行调用。
(1)添加依赖

		
            org.springframework.cloud
            spring-cloud-starter-netflix-zuul
        

(2)启动类上添加注解

@EnableZuulProxy

这样就可以实现最基本的路由功能了。

(3)如果要自定义路由的映射地址需要修改配置文件

zuul:
  routes:
    product: /myProduct/**  #product指的是需要调用服务的服务名。/myProduct/**是你自定义的映射地址
  ignored-patterns:  #改配置指的是你要排除的某些地址,也就是不对外暴露的地址
    - /**/product/getProductInfo
  ignored-services: /product   #改配置指的是将默认的映射地址关闭,不对外暴露。因为zuul默认的映射地址就是调用服务的服务名。如果要全部禁用可以写个"*"
  prefix: /wangbin   #改配置指的是,指定统一的访问路径的前缀
  #设置全局的敏感头
  sensitive-headers:   #改配置指的是将敏感头设置为空,因为默认的敏感头设置有"Cookie", "Set-Cookie", "Authorization",如果不设置此项像cookie等这三个值通过路由传递不过去

(4)实现动态路由
(1)将配置文件中zuul的配置参考配置中心放到git上。
(2)添加一个配置类

//因为zuulPropertis中所有关于zuul的属性都有,所以直接new zuulProperties()即可。
@Component
public class ZuulConfig {

    @ConfigurationProperties("zuul")
    @RefreshScope
    public ZuulProperties properties(){
        return new ZuulProperties();
    }
}

这样就可以实现在动态修改路由配置的时候,不用重启项目就可以自动刷新过来,即动态路由。

(5)路由的高可用
服务网管是所有请求的统一入口,一旦服务网管出现故障,系统就会全部瘫痪。所以在生产环境上都会部署多态zuul,可以把zuul看成普通的微服务,将多个zuul注册到eureka server上,这样就可以避免单个zuul服务出现故障,导致整个系统不可用的情况。
因为zuul的性能没有Nginx的性能高,所以在使用的时候可以继续让nginx继续实现负载均衡和反向代理的作用,从nginx将请求转发到各个zuul节点,继续让zuul发挥自身的优势。

2.zuul的过滤
(1)因为所有的请求都会先经过前置(pre)类型的过滤器,所以在这可以限流、鉴权、参数校验等。而后置(post)类型的过滤器,所以在这可以进行数据的统计、记录日志等。error filter类型的过滤器是在这些过滤器发生异常的时候会被拦截到,多以可以在这里进行异常的统一处理。
(2)前置过滤器的使用

/**
 * 自定义pre类型的filter进行鉴权操作
 * PRE_TYPE、PRE_DECORATION_FILTER_ORDER属性可以在zuul中的FilterConstants类中找到
 * */
@Component
public class TokenFilter extends ZuulFilter {

    /**
     * filterType指定过滤器的类型
     * */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * filterOrder指定过滤器的执行顺序,返回的值越小,说明越先执行
     * */
    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER -1;
    }

    /**
     * shouldFilter指定是否开启该过滤器
     * */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * run是拦截到请求后具体要实现的逻辑。
     * 这里为了举例只是简单的判断请求中有没有携带cookie,若携带cookie则表明有权限,若没有携带cookie则说明没有权限
     * */
    @Override
    public Object run() throws ZuulException {
        //RequestContext是zuul组件中请求上下文,各个过滤器之间没有通信,是通过该静态类进行数据的交互
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String token = request.getParameter("token");
        if(StringUtils.isEmpty(token)){
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }

(2)后置过滤器的使用

/**
 * 自定义post类型的过滤器可以对请求响应参数处理加工
 * POST_TYPE、SEND_RESPONSE_FILTER_ORDER属性可以在zuul中的FilterConstants类中找到
 * */
@Component
public class AddResponseHeadsFilter extends ZuulFilter {
    /**
     * filterType指定过滤器的类型
     */
    @Override
    public String filterType() {
        return POST_TYPE;
    }

    /**
     * filterOrder指定过滤器的执行顺序,返回的值越小,说明越先执行
     */
    @Override
    public int filterOrder() {
        return SEND_RESPONSE_FILTER_ORDER - 1;
    }

    /**
     * shouldFilter指定是否开启该过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * run是拦截到请求后具体要实现的逻辑。
     * 这里为了举例只是简单在响应头中设置了一个值
     */
    @Override
    public Object run() throws ZuulException {
        //RequestContext是zuul组件中请求上下文,各个过滤器之间没有通信,是通过该静态类进行数据的交互
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletResponse response = currentContext.getResponse();
        response.setHeader("RES", "123456");
        return null;
    }
 }

(3)在前置过滤器中实现限流(服务器的承载能力是有限的,当请求量非常大时可以做限流保护,防止网络攻击)

spring cloud zuul使用总结_第3张图片
限流的算法有很多种,这里介绍的是比较常用的令牌桶算法。令牌桶算法的基本原理就是:以固定的速率往令牌桶中放入令牌,当令牌桶存满时新生成的令牌就会直接抛弃掉。所有的请求都先要从令牌桶中获取令牌,若获取到令牌直接放行,若获取不到令牌则被拦截。

/**
 * 限流保护过滤器---使用令牌桶算法来实现,guawa提供了开源的组件ratelimit
 * */
@Component
public class RateLimitFilter extends ZuulFilter {

    //参数指的是每秒钟放多少个令牌
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(10);

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    //限流保护过滤器的执行顺序应该放到最前面
    @Override
    public int filterOrder() {
        return SERVLET_DETECTION_FILTER_ORDER -1;
    }

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

    //具体的处理逻辑
    @Override
    public Object run() throws ZuulException {
        //判断是否可以获取到令牌,若可以获取到请求可以继续往下走,若获取不到就被继续拦截
        if(!RATE_LIMITER.tryAcquire()){
            throw new RateLimitException();
        }
        return null;
    }
}

你可能感兴趣的:(spring cloud zuul使用总结)