• Spring Cloud 核心组件——网关


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

    它主要有以下几个功能:

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

    2)流量监控:限流处理;服务降级

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

    主流的网关有以下这些:

    1)Zuul:是 Netflix 开源的微服务网关,和 Eureka,Ribbon,Hystrix 等组件配合使用,Zuul 2.0 比 1.0 的性能提高很多

    2)Kong: 由 Mashape 公司开源的,基于 Nginx 的 API gateway

    3)Nginx+Lua:是一个高性能的 HTTP 和反向代理服务器,Lua 是脚本语言,让 Nginx 执行 Lua 脚本,并且高并发、非阻塞的处理各种请求

    1. Zuul 网关基本使用

    第一步:加入依赖

    使用 IDEA 创建 Spring Boot 项目时,添加以下两个依赖

    第二步:启动类加入注解 @EnableZuulProxy,默认集成断路器 @EnableCircuitBreaker

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

    第三步:我们可以通过网关访问之前的项目

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

    例子:http://localhost:9000/product-service/api/v1/product/find?id=1

    这里需要注意:我们可以通过网关去访问服务,但服务基本的访问,我们还是可以访问的,网关只是多加了一层

    比如访问:http://localhost:8772/api/v1/product/find?id=1,还是可以的

    当然,我们可以自定义路由转发:

    zuul:
      routes:
        product-service: /apigateway/**

    这样就可以通过自定义的路径进行访问

    如果不想让默认的服务对外暴露接口,可以进行环境隔离配置:

    server:
      port: 9000
    
    #服务的名称
    spring:
      application:
        name: api-gateway
    
    #指定注册中心地址
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    
    #自定义路由映射 zuul: routes: product-service: /apigateway/** #统一入口为上面的配置,其他入口忽略(我们可以通过规则,屏蔽掉某些服务) ignored-patterns: /*-service/** #忽略整个服务,不对外提供接口(我们可以直接屏蔽掉某个服务) #ignored-services: product-service

    注意: 

    1)如果自定义多个服务的访问地址,地址不能重复,否则后定义的会覆盖之前定义的。如下所示,多个服务地址应该不一样

    zuul:
      routes:
        order-service: /apigateway/order/**
        product-service: /apigateway/product/**

    2)我们经过网关这一层到具体的服务里面,会发现请求头无法获取到,这是因为 Zuul 默认过滤掉了请求头,所以服务访问不到,我们需要去除掉这个默认设置

    #自定义路由映射
    zuul:
      routes:
        order-service: /apigateway/order/**
        product-service: /apigateway/product/**
      #统一入口为上面的配置,其他入口忽略
      ignored-patterns: /*-service/**
      #处理http请求头为空的问题
      sensitive-headers:

    2. 自定义 Zuul 过滤器实现登录鉴权

    新建一个 filter 包,在包里新建一个类,实现 ZuulFilter,重写里面的方法。在类顶部加注解 @Component,让 Spring Boot 扫描。

    package com.jwen.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 true;
            }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;
        }
    }

    3. 自定义 Zuul 过滤器实现限流

    使用谷歌 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;
        }
    }

    注意:网关也是可以启用多个节点的,达到集群的目的 

    4. Zuul微服务网关集群搭建

    使用 Nginx+Lvs+Keepalive 

    参考资料:https://www.cnblogs.com/liuyisai/p/5990645.html

    本文的示例承接上文:

    https://www.cnblogs.com/jwen1994/p/11408511.html

    https://www.cnblogs.com/jwen1994/p/11432842.html

  • 相关阅读:
    chrome被篡改 导航到搜狗 或者特殊页面
    安装tomcat jdk
    监控tomcat 启动
    关于如何关闭445端口
    python模拟大数据登陆
    搭建vsftpd服务
    kali syn洪水攻击实例
    HP880G3 安装RHEL6.5
    Python_列表
    Python第一个请求接口
  • 原文地址:https://www.cnblogs.com/jwen1994/p/11441947.html
Copyright © 2020-2023  润新知