SpringCloud笔记五:微服务网关zuul
文章目录
什么是网关
- API Gateway,是系统的唯一对外入口,介于客户端和服务端之间的中间层,处理非业务功能,提供路由请求,鉴权,监控,缓存,限流等功能。
统一接入
智能路由,
AB测试,灰度测试
负载均衡,容灾处理
日志埋点。
流量监控
限流处理
服务降级
安全防护
鉴权处理
监控
机器网络隔离
- 网关的架构位置
- 主流网关
1、zuul:是Netflix开源的微服务项目,和Eureka,Ribbon,Hystrix等组件配合使用,zuul2.0比1.0的性能提高了很多。
2、Kong:由Mashape公司开源,基于Nginx的ApI gateway
3、Nginx+Lua:是一个高性能的Http和反向代理服务器,lua是脚本语言,让Nginx执行Lua脚本,并且高并发,非阻塞的处理各种请求。
SpringCloud的网关组件zuul基本使用
- 加入依赖,可以在创建应用的时候选择zuul和hystrix,引入依赖,比较慢,可以指定镜像
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>Nexus aliyun</name>
<layout>default</layout>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
- 进行eureka服务注册
server:
port: 9000
#服务名称
spring:
application:
name: api-gateway
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
- zuul网关路由映射配置
#自定义路由映射
zuul:
routes:
order-service: /apigatewaytwo/**
product-service: /apigateway/**
ignored-patterns: /*-service/**
#忽略整个服务,对外提供接口
#ignored-services: product-service
- zuul配置作用图
Zuul常见问题分析和网关过滤器原理分析
- 路由名称定义问题
路由映射重复覆盖问题。后面的会覆盖前面的。
#自定义路由映射
zuul:
routes:
#下面两个必须唯一
order-service: /apigateway/order/**
product-service: /apigateway/product/**
ignored-patterns: /*-service/**
#忽略整个服务,对外提供接口
#ignored-services: product-service
- http请求头过滤问题
zuul网关有个问题,默认会屏蔽调请求的cookie内容,这样后端就会接收不到cookie信息,需要在配置中处理一下。sensitive-headers:
#自定义路由映射
zuul:
routes:
#下面两个必须唯一
order-service: /apigateway/order/**
product-service: /apigateway/product/**
ignored-patterns: /*-service/**
#处理http请求头为空
sensitive-headers:
#忽略整个服务,对外提供接口
#ignored-services: product-service
- 过滤器执行顺序问题,过滤器的order值越小,越先执行。
在ZuulFilter类里面
- 共享requestContext,上下文对象。
自定义Zuul过滤器实现登录鉴权功能
- 在网关项目中新建一个包filter,然后新建一个类并集成ZuulFilter
- 重写ZuulFilter里面的方法。
- 添加@Component,让spring扫描
- 过滤器代码
/**
* @program: api-gateway
* @description: 登录过滤器
* @author: kaifan·Zhang
* @create: 2020-03-19 16:
*/
@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());
System.out.println(request.getRequestURL());
/*
* /apigateway/order/api/v1/order/save
http://localhost:9000/apigateway/order/api/v1/order/save
**/
//ACL,将访问接口列表存储在redis里面,定期进行拉取
if("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){
return true;
}
return false;
}
/**
* 业务逻辑,这段代码就是如果拦截,就会执行,如果不拦截,就不会执行。
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
//jwt操作
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String token = request.getHeader("token");
if(StringUtils.isBlank(token)){
token=request.getParameter("token");
}
if(StringUtils.isEmpty(token)){
currentContext.setSendZuulResponse(false);
currentContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());//401未授权
}
return null;
}
}
高并发情况下接口限流的特技
- 采用谷歌guava框架,网关限流
原理:当用户请求时,服务端设置一个令牌,只有拿到令牌的请求,才允许访问,否则就抛弃掉。也就是这个网关设置最多访问量为1000,当超过1000的并发量时,就限制访问。
使用RateLimiter设置令牌。这个令牌是每秒产生的。限制每秒最多1000的访问量。
- 限流种类
1、nginx限流
2、网关限流
- 网关限流代码
@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();
HttpServletRequest request = requestContext.getRequest();
if(!RATE_LIMITER.tryAcquire()){
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());//429请求过多
}
return null;
}
}
Zuul微服务网关集群搭建
-
网关架构模型
-
nginx+lvs+keepalive
- 开启多个网关服务
换个服务端口,
或者在Idea的启动vm中
-Dserver.port=xxxx(端口)