SpringCloud之网关服务(gateway)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud之网关服务(gateway)相关的知识,希望对你有一定的参考价值。
前言
网关服务在SpringCloud中有很重要的作用。
可以将服务跟外网进行隔离起到一定的保护作用,同时服务间局域网通信更加快捷。而且在网关中可以做限流、权限校验,使得服务更加专注自身业务。比如说下订单需要登录权限,限流,我们在本篇将介绍如何使用。
搭建网关项目
注意:需要添加Eureka Discovery,Zuul路由组件。
1.入口添加@EnableZuulProxy注解
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,通过访问:
统一对外只允许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 简要描述
* <p> TODO:描述该类职责 </p>
*
* @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() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
System.out.println("address:" + request.getRemoteAddr());
System.out.println("uri:" + request.getRequestURI());
System.out.println("url:" + request.getRequestURL());
// 这里可以结合ACL进行本地化或者放入到redis
if ("/apigateway/order/api/v1/order/saveforribbon".equalsIgnoreCase(request.getRequestURI())) {
return true;
}
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;
}
}
启动之后访问对应的接口
到此说明我们以及做好网关的权限校验,通常我们都会结合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 简要描述
* <p> TODO:描述该类职责 </p>
*
* @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() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if ("/apigateway/order/api/v1/order/saveforribbon".equalsIgnoreCase(request.getRequestURI())) {
return true;
}
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接口进行压力测试,这样我们就可以很好的测试上面的内容。
以上是关于SpringCloud之网关服务(gateway)的主要内容,如果未能解决你的问题,请参考以下文章
Java之 Spring Cloud 微服务搭建网关SpringCloud Gateway微服务网关GateWay(第三个阶段)SpringBoot项目实现商品服务器端是调用
SpringCloud系列之网关gateway-4.路由功能详解
SpringCloud系列之网关gateway-14.网关层的其他妙用 - 限流
深入Java微服务之网关系列4: SpringCloud gateway详解(史上最全)