上文讲到了Zuul的基本使用:

https://www.cnblogs.com/xuyiqing/p/10884860.html

自定义Zuul过滤器:

package org.dreamtech.apigateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
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 String
*/
@Override
public String filterType() {
//设置为前置过滤器
return PRE_TYPE;
} /**
* 过滤器顺序:值越小,越先执行
*
* @return int
*/
@Override
public int filterOrder() {
//不能是最先执行的
return 4;
} /**
* 过滤是否生效
*
* @return boolean
*/
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
return "/order/api/order/save".equalsIgnoreCase(request.getRequestURI());
} /**
* shouldFilter返回True则执行此方法,用于写业务逻辑
*
* @return Object
* @throws ZuulException 异常
*/
@Override
public Object run() throws ZuulException {
System.out.println("拦截成功");
return null;
}
}

启动项目:Eureka Server->Product-Service->Order-Service->Api Gateway

这里对模拟的下单接口进行了过滤

访问:http://localhost:9000/order/api/order/save?user_id=1&product_id=1

就会打印:拦截成功

进一步编码:

package org.dreamtech.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 String
*/
@Override
public String filterType() {
//设置为前置过滤器
return PRE_TYPE;
} /**
* 过滤器顺序:值越小,越先执行
*
* @return int
*/
@Override
public int filterOrder() {
//不能是最先执行的
return 4;
} /**
* 过滤是否生效
*
* @return boolean
*/
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
return "/order/api/order/save".equalsIgnoreCase(request.getRequestURI());
} /**
* 写业务逻辑
*
* @return Object
* @throws ZuulException 异常
*/
@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;
}
}

实际中,可以使用一种技术:JWT来做安全校验

这时候直接访问:http://localhost:9000/order/api/order/save?user_id=1&product_id=1

显示:401状态码(未授权)

访问:http://localhost:9000/order/api/order/save?user_id=1&product_id=1&token=12345

显示:

{"code":0,"data":{"id":0,"productName":"\"iPhone1 data from port=8771\"","tradeNo":"29d834be-f375-4112-b0a1-ed10b8e8679d","price":1111,"createTime":"2019-05-19T04:26:19.008+0000","userId":1,"userName":null}}

成功

为了方便,我直接把token放在参数里面了,根据编码也可以把token放在HttpHeader里面

进一步的编码可以这样尝试:

    @Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//TODO 从Resdis缓存中拿到List<[URL]>代替"/order/api/order/save"
if ("/order/api/order/save".equalsIgnoreCase(request.getRequestURI())) {
return true;
}
if ("/order/api/order/delete".equalsIgnoreCase(request.getRequestURI())) {
return true;
}
// ......
return false;
}

高并发的情况下,接口限流是很有必要的:

类似地铁:上地铁需要排队,才可以有效地运输;如果一群人拥挤,反而效率不高

实际应用:比如某电商网站搞活动,某一时刻同时访问上万人,而MySQL最大连接数3000,这时候就要进行限制:最高只能由2500人同时参与活动

限流的方式:Nginx进行限流、网关限流等。这里进行网关限流

使用Google Guava框架:令牌桶原理

Demo:对订单服务进行限流

package org.dreamtech.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 OrderLimiterFilter 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();
//对订单接口进行限流
return "/order/api/order/save".equalsIgnoreCase(request.getRequestURI());
} @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;
}
}

实际开发中,不只是要保证数据库和服务的高可用,也要保证网关不会挂掉:

Nginx可以和LVS组合实现高可用,不过这是运维要做的事情,我们Java程序员需要关心的是Zuul的高可用

于是想到部署Zuul集群:Zuul的集群搭建很简单,启动多个Zuul项目即可

可能有人会关心,如果Zuul是集群的方式,那么Guava的令牌桶如何实现共用?

后面会介绍Spring Cloud统一配置Config进行处理

Spring Cloud(7):Zuul自定义过滤器和接口限流的更多相关文章

  1. spring cloud 2.x版本 Gateway熔断、限流教程

    前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...

  2. SpringCloud(8)---zuul权限校验、接口限流

    zuul权限校验.接口限流 一.权限校验搭建 正常项目开发时,权限校验可以考虑JWT和springSecurity结合进行权限校验,这个后期会总结,这里做个基于ZuulFilter过滤器进行一个简单的 ...

  3. Spring Cloud Alibaba:Sentinel实现熔断与限流

    一.什么是Sentinel Sentinel,中文翻译为哨兵,是为微服务提供流量控制.熔断降级的功能,它和Hystrix提供的功能一样,可以有效的解决微服务调用产生的“雪崩效应”,为微服务系统提供了稳 ...

  4. Spring Cloud gateway 三 自定义过滤器GatewayFilter

    之前zuul 网关介绍.他有过滤器周期是四种,也是四种类型的过滤器.而gateway 只有俩种过滤器:"pre" 和 "post". PRE: 这种过滤器在请求 ...

  5. Spring Cloud Alibaba基础教程:使用Sentinel实现接口限流

    最近管点闲事浪费了不少时间,感谢网友libinwalan的留言提醒.及时纠正路线,继续跟大家一起学习Spring Cloud Alibaba. Nacos作为注册中心和配置中心的基础教程,到这里先告一 ...

  6. spring cloud(二) zuul

    spring cloud 网关 zuul 搭建过程 1. 新建boot工程 pom引入依赖 <dependency> <groupId>org.springframework. ...

  7. Spring Cloud Netflix Zuul 重试会自动跳过经常超时的服务实例的简单说明和分析

    在使用E版本的Spring Cloud Netflix Zuul内置的Ribbon重试功能时,发现Ribbon有一个非常有用的特性: 如果某个服务的某个实例经常需要重试,Ribbon则会在自己维护的一 ...

  8. Spring Cloud Alibaba 使用Sentinel实现接口限流

    Sentinel是什么 Sentinel的官方标题是:分布式系统的流量防卫兵.从名字上来看,很容易就能猜到它是用来作服务稳定性保障的.对于服务稳定性保障组件,如果熟悉Spring Cloud的用户,第 ...

  9. spring cloud 通过zuul网关去请求的时候报404的几个原因。

    spring cloud 中 zuul 网关的那些坑: 1.检查你的服务是否正常启动. 2.检查你的服务是否正常注册到注册中心. 3.zuul网关的路由规则是会把你注册在注册中心的serviceId ...

随机推荐

  1. Jauery 中Ajax的几种异步请求

       以下介绍Jquery中  Post   Get   Ajax几种异步请求的使用方法  <%@ Page Language="C#" AutoEventWireup=&q ...

  2. git---安装及配置

    git官网:https://git-scm.com 安装: 官网下载->一路Next->安装完成 配置git: 1.win+r进入windows命令行 2.注册: git config - ...

  3. 黑马程序员----java基础:异常

    dff ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 经常写程序的人对try...catch...finally语句肯定是不陌生的了.但是好多 ...

  4. 【译】x86程序员手册41-10.6 TLB(快表)测试

    译注:本章基本未做翻译 10.6 TLB Testing TLB测试 The 80386 provides a mechanism for testing the Translation Lookas ...

  5. redis 可视化管理工具

    Redis Desktop Manager 下载地址:http://redisdesktop.com/download 支持: Windows 7+, Mac OS X 10.10+, Ubuntu ...

  6. 4K屏选购秘诀

    最近我买了一台三星4K 27.7吋显示器,经试用,虽然达到4K标准,但感觉像素精细度不够.明显达不到我的苹果笔记本视网膜屏的精细程度,事后总结一下原因:因为4K屏总的像素是3840×2160,屏越大像 ...

  7. swift不同地方 命名空间module iOS

    Objective-C没有命名空间,为了避免冲突,Objective-C的类型一般都会加上两到三个字母的前缀,比如Apple保留的NS和UI前缀,各个系统框架的前缀,各个系统框架的前缀SK(Store ...

  8. 如何优雅地从CSDN转载文章

    复制粘贴应该是最显而易见的方法,但是不仅会有丢失内容,而且格式也会丢失.要想达到更好的效果,可以从html源码入手. 1.在chrome浏览器中打开要转载的文章,右键选择检查 2.在chrome的右方 ...

  9. 入门迅速、应用广泛、月薪两万,马哥Python前景为什么这么好?

    随着Python的技术的流行,Python在为人们带来工作与生活上带来了很多的便捷,因为Python简单,学起来快,也是不少新手程序员入门的首选语言.新手们比较关心的就是Python的发展前景与方向. ...

  10. 对散列进行sort排序,只是会产生一个顺序,但这顺序和初始化时的顺序不一致

    109 my $slice_layouts;    110 my $vertical_assignment;    111 my %map_function_indices = (    112    ...