欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微服务网关

程序员文章站 2022-06-03 20:26:07
...

微服务网关

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

简介:讲解网关的作用和使用场景 (画图)

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脚本,并且高并发、非阻塞的处理各种请求

SpringCloud的网关组件zuul基本使用

1:配置网关服务器

新建springBoot项目导入相关依赖,启动类开启网关注解 @EnableZuulProxy 该注解默认集成了熔断器注解 @EnableCircuitBreaker

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- api 网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

配置appliction.yml文件

#网关服务访问端口
server:
  port: 9000
#网关服务名称
spring:
  application:
    name: api-gateway

#注册中心服务
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/

网关默认访问规则–> 网关服务IP地址:端口 / 访问服务的项目名称 / 相关访问方法路径

http://localhost:9000/order-server/order/save?id=1&productId=2

自定义访问规则:指定所有访问不能通过/*-server/** 访问,只能通过网关指定方式访问

#自定义服务访问名称路由映射
zuul:
  routes:#**因为routes底层使用的Map存储数据,所以设置网关名称时,同样的名称后面的设置会覆盖前面的设置,		   #所以在设置服务网关映射时名称不能一样
    #指定order-server服务可以通过 /apigateway/** 方式访问
    order-server: /apigateway/order/**
    product-server: /apigateway/product/**
  #指定那些服务不对外提供访问
  #ignored-services: product-server
  #指定所有访问不能通过   /*-server/** 访问只能通过网关指定的方式访问
  ignored-patterns: /*-server/**

2:登陆验证网关过滤器:建议使用jwt

新建一个filter包,新建一个类,继承 ZuulFilter,重写里面的方法

@Component
public class LoginFilter extends ZuulFilter {

    /**
     * 过滤器类型:前置过滤器
     * 可设置是前置过滤还是后置过滤
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

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

    /**
     * 过滤器是否生效
     * 所有通过网关的请求都会进这个方法,
     * 从而可以执行,字符编码,或者登陆验证,如果返回为true,则会进入业务逻辑方法
     * @return
     */
    @Override
    public boolean shouldFilter() {
        //获取 requestContext 上下文对象。
        RequestContext requestContext = RequestContext.getCurrentContext();
        //获取请求 request 对象
        HttpServletRequest request = requestContext.getRequest();
        //获取请求路径 url  apigateway/product/product/list
        String url = request.getRequestURI();
        //判断是否是需要拦截的url  .equalsIgnoreCase():不区分大小写
        if("/apigateway/order/order/save".equalsIgnoreCase(url)){

            //进入登陆验证业务逻辑处理
            return true;
        }
        return false;
    }

    /**
     *执行业务逻辑
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("进行了拦截");
        //获取 requestContext 上下文对象。
        RequestContext requestContext = RequestContext.getCurrentContext();
        //获取请求 request 对象
        HttpServletRequest request = requestContext.getRequest();
        /**
         * 此处做是否已经登陆验证,查看 request 请求参数中是否含有 token
         */
        //从请求参数中获取token
        String token = request.getHeader(("token"));
        //登陆验证
        if(StringUtils.isBlank(token)){
            //Zuul设置不往下执行
            requestContext.setSendZuulResponse(false);
            //设置返回状态码
            requestContext.setResponseStatusCode(HttpStatus.SC_GONE);
        }


        return null;
    }
}

3:高并发情况下网关限制接口限流:建议使用,谷歌guava框架

每个用户调用接口前要取令牌,又令牌放行,没有等待。

新建一个类,继承 ZuulFilter,重写里面的方法

/**
 * 服务接口限流
 */
@Component
public class OrderRateLimiterFilter extends ZuulFilter {

    //定义每秒产生多少个令牌,具体数值根据测试数据
    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 = RequestContext.getCurrentContext();
        //获取请求request对象
        HttpServletRequest request = requestContext.getRequest();
        //获取请求路径 url  apigateway/product/product/list
        String url = request.getRequestURI();
        //对指定接口进行限流
        if("/apigateway/order/order/save".equalsIgnoreCase(url)){
            return true;
        }
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        //获取 requestContext 上下文对象。
        RequestContext requestContext = RequestContext.getCurrentContext();
        //如果没有令牌
        if(!RATE_LIMITER.tryAcquire()){
            //Zuul设置不往下执行
            requestContext.setSendZuulResponse(false);
            //设置返回状态码
            requestContext.setResponseStatusCode(HttpStatus.SC_GONE);
        }

        return null;
    }
}