SpringCloud之网关服务(gateway)

叁歲伎倆 2022-10-26 15:26 345阅读 0赞

前言

62e3a5346b5d244f3c9a080ba8f6ce6d.png

网关服务在SpringCloud中有很重要的作用。

可以将服务跟外网进行隔离起到一定的保护作用,同时服务间局域网通信更加快捷。而且在网关中可以做限流、权限校验,使得服务更加专注自身业务。比如说下订单需要登录权限,限流,我们在本篇将介绍如何使用。

搭建网关项目
ae004131f578df5c9a3605bd8793f5f8.png

注意:需要添加Eureka Discovery,Zuul路由组件。

1.入口添加@EnableZuulProxy注解
f0b4c492e9a8da7d123147a00b52b0e8.png

2.配置文件

server:
port: 9000

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

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

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

我们启动EurekaServer、productService、OrderService、apigateway,通过访问:

fbbd501713cf14a5693171426b65b36c.png

6c51b6da38d30728880e4f7201fbc69d.png

统一对外只允许apigateway/product/,apigateway/order/形式访问接口,这样就对外做了一次屏蔽,隐藏了真实的服务api。

网关上做权限校验

权限校验需要通过实现ZuulFilter进行拦截。

package com.ckmike.api_gateway.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;

/**

  • LoginFilter 简要描述
  • TODO:描述该类职责
  • @author ckmike
  • @version 1.0
  • @date 18-11-24 下午3:53
  • @copyright ckmike
    **/
    @Component
    public class LoginFilter extends ZuulFilter {

    public static final String PRE_TYPE = “pre”;

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

    // 过滤顺序
    @Override
    public int filterOrder() {
    return 4;
    }

    @Override
    public boolean shouldFilter() {

    1. RequestContext requestContext = RequestContext.getCurrentContext();
    2. HttpServletRequest request = requestContext.getRequest();
    3. System.out.println("address:" + request.getRemoteAddr());
    4. System.out.println("uri:" + request.getRequestURI());
    5. System.out.println("url:" + request.getRequestURL());
    6. // 这里可以结合ACL进行本地化或者放入到redis
    7. if ("/apigateway/order/api/v1/order/saveforribbon".equalsIgnoreCase(request.getRequestURI())) {
    8. return true;
    9. }
    10. return false;

    }

    @Override
    public Object run() throws ZuulException {
    RequestContext requestContext = RequestContext.getCurrentContext();
    HttpServletRequest request = requestContext.getRequest();
    String token = request.getHeader(“token”);
    if (StringUtils.isBlank(token)) {
    token = request.getParameter(“token”);
    }
    if (StringUtils.isBlank(token)) {
    requestContext.setSendZuulResponse(false);
    requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
    }
    return null;
    }
    }

启动之后访问对应的接口
a0cf650e18dc0484f3e0e1529d74013f.png

到此说明我们以及做好网关的权限校验,通常我们都会结合redis+ACL方式进行,但这里因为简单我直接通过字符串进行校验,有兴趣可自行扩展redis+ACl做。

网关限流

通常系统都有一个承受极限,我们通常可以nginx做一限流,我们也可以通过网关进行限流,网关限流是通过每秒生成令牌作为访问通行标识,这里使用了guava做令牌生成。代码如下:

package com.ckmike.api_gateway.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;

/**

  • OrderRateLimiteFilter 简要描述
  • TODO:描述该类职责
  • @author ckmike
  • @version 1.0
  • @date 18-11-24 下午5:33
  • @copyright ckmike
    **/
    @Component
    public class OrderRateLimiteFilter extends ZuulFilter {

    public static final String PRE_TYPE = “pre”;
    //每秒钟产生1000个令牌,guava
    private static final RateLimiter rateLimiter = RateLimiter.create(1000);

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

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

    @Override
    public boolean shouldFilter() {

    1. RequestContext requestContext = RequestContext.getCurrentContext();
    2. HttpServletRequest request = requestContext.getRequest();
    3. if ("/apigateway/order/api/v1/order/saveforribbon".equalsIgnoreCase(request.getRequestURI())) {
    4. return true;
    5. }
    6. return false;

    }

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

我们可以通过jmeter进行压力测试,对/apigateway/order/api/v1/order/saveforribbon接口进行压力测试,这样我们就可以很好的测试上面的内容。

需要springloud的视频及源码评论区留言哦

5554b46519afcec59adeecd018a1c85c.png

发表评论

表情:
评论列表 (有 0 条评论,345人围观)

还没有评论,来说两句吧...

相关阅读

    相关 GateWay 服务

    GateWay简介 ⽹关(翻译过来就叫做GateWay):微服务架构中的重要组成部分。局域⽹中就有⽹关这个概念,局域⽹接收或者发送数据出去通过这个⽹关,⽐如⽤ Vmwar