SpringCloud之网关zuul

1、微服务网关介绍和使用场景

 1)什么是网关
  API Gateway,是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能

  统一接入
    智能路由
    AB测试、灰度测试
    负载均衡、容灾处理
    日志埋点(类似Nignx日志)

  流量监控
    限流处理
    服务降级

  安全防护
    鉴权处理
    监控
    机器网络隔离


 2)主流的网关
  zuul:是Netflix开源的微服务网关,和Eureka,Ribbon,Hystrix等组件配合使用,Zuul 2.0比1.0的性能提高很多
  kong: 由Mashape公司开源的,基于Nginx的API gateway
  nginx+lua:是一个高性能的HTTP和反向代理服务器,lua是脚本语言,让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求

 

2、SpringCloud的网关组件zuul基本使用

  1、加入依赖

<dependencies>
        <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>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

  2、启动类加入注解 @EnableZuulProxy
    默认集成断路器 @EnableCircuitBreaker   

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

@SpringBootApplication
@EnableZuulProxy
public class ApiGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class, args);
    }
}

    默认访问规则
    http://gateway:port/service-id/**

    例子:默认 /order-service/api/v1/order/save?user_id=2&product_id=1
              自定义 /xdclass_order/api/v1/order/save?user_id=2&product_id=1

             自定义路由转发:
           zuul:
          routes:
        order-service: /apigateway/**

    环境隔离配置:
             需求 :不想让默认的服务对外暴露接口
          /order-service/api/v1/order/save

      配置:
      zuul:
        ignored-patterns:  /*-service/api/v1/order/save

    yml 配置:

server:
  port: 9000

#服务的名称
spring:
  application:
    name: api-gateway

#指定注册中心地址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#/order-service/api/v1/order/save?user_id=2&product_id=1
#自定义路由映射(注意有路由覆盖的地方,所以一般会加个模块/apigateway/order, order模块)
zuul:
  routes:
    order-service: /apigateway/order/**
    product-service: /apigateway/product/**
  #统一入口为上面的配置,其他入口忽略(即不能通过 /order-service/api/v1/order/save 来访问)
  ignored-patterns: /*-service/**
  #处理http请求头为空的问题(默认的过滤集合包含 "cookie" ,所以后端拿不到 “cookie”, 将集合过滤设为空)
  sensitive-headers:
 

 

3、Zuul常用问题分析和网关过滤器原理分析

  Zuul网关原理和过滤器生命周期,

    1、路由名称定义问题
      路由映射重复覆盖问题

    2、Http请求头过滤问题(如cookie)

    3、过滤器执行顺序问题 ,过滤器的order值越小,越先执行

    4、共享RequestContext,上下文对象

 

4、自定义Zuul过滤器实现登录鉴权

  简介:自定义Zuul过滤器实现登录鉴权

  1、新建一个filter包

  2、新建一个类,实现ZuulFilter,重写里面的方法

  3、在类顶部加注解,@Component,让Spring扫描

  

package net.xdclass.apigateway.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 org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * 登录过滤器
 */
@Component
public class LoginFilter extends ZuulFilter {

    /**
     * 过滤器类型,前置过滤器
     *
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 过滤器顺序,越小越先执行
     *
     * @return
     */
    @Override
    public int filterOrder() {

        return 4;
    }


    /**
     * 过滤器是否生效
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {

        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //System.out.println(request.getRequestURI()); ///apigateway/product/api/v1/product/list
        //System.out.println(request.getRequestURL()); //http://localhost:9000/apigateway/product/api/v1/product/list

        //ACL

        if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        } else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())) {
            return false;
        } else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }
        return false;
    }

    /**
     * 业务逻辑
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {

        //JWT
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //token对象
        String token = request.getHeader("token");

        if (StringUtils.isBlank((token))) {
            token = request.getParameter("token");
        }
        //登录校验逻辑  根据公司情况自定义 JWT
        if (StringUtils.isBlank(token)) {
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }
}

    访问“/apigateway/order/api/v1/order/save”时需要鉴权  

 5、高并发情况下接口限流特技

  简介:谷歌guava框架介绍,网关限流使用

  对订单接口限流:

  

package net.xdclass.apigateway.filter;

import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * 订单限流
 */
@Component
public class OrderRateLimiterFilter extends ZuulFilter {


    //每秒产生1000个令牌
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);

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

    @Override
    public int filterOrder() {
        return -4;
    }



    @Override
    public boolean shouldFilter() {


        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //只对订单接口限流
        if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){
            return true;
        }

        return false;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        if(!RATE_LIMITER.tryAcquire()){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
        }
        return null;
    }
}

每秒1000个请求,超出则丢弃

 

6、Zuul微服务网关集群搭建
  简介:微服务网关Zull集群搭建

  1、nginx+lvs+keepalive 避免Nginx挂掉
  https://www.cnblogs.com/liuyisai/p/5990645.html

  启动另一个api-gateway,将1000读取从配置中心读取,2台api则为500

  private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);

posted on 2020-06-21 16:01  卖肾割阑尾  阅读(230)  评论(0编辑  收藏  举报

导航