SpringCloud-Greenwich版本新特性探索(1)---SpringCloudGateway
一、前言
1、SpringCloudGateway是SpringCloud新推出的网关框架,比较于上一代Zuul,功能和性能有很大的提升。Zuul1.x采用的是阻塞多线程方式,也就是一个线程处理一个连接请求,高并发情况下性能较差,即使是Zuul2.x虽然做到了非阻塞,但是面对连续跳票,看起来Zuul要被抛弃了。取而代之的是SpringCloudGateway,SpringCloudGateway是基于Webflux,是一个非阻塞异步的框架,性能上有很大提升,而且包含了Zuul的所有功能,可以从Zuul无缝切换到SpringCloudGateway
2、SpringCloud环境版本:Greenwich.RELEASE
3、SpringBoot环境版本:2.1.3.RELEASE
二、环境搭建
1、在父工程下新建一个网关模块
2、引入SpringCloudGateway需要的POM,记得引入actuator组件,否则服务发现中心会认为服务不在线,导致网关无法路由到服务,并且加入熔断组件Hystrix
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 健康检查 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
3、主函数很简单,加入必要的注解,比如服务发现等
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayCarfacApplication
{
public static void main(String[] args)
{
SpringApplication.run(GatewayCarfacApplication.class, args);
}
}
4、进行SpringCloudGateway的配置,配置可以使用Java代码进行配置或者yml配置,这里使用yml进行配置
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 设置可以路由到其他服务
routes: # 可以配置多个路由
- id: service-media- # 路由id唯一
uri: lb://service-media # 可以直接跳转到具体的地址,如果要跳转到其他服务,则填写lb://<服务id>
predicates:
- Path=/media/** # 路由规则
filters:
- StripPrefix= # 不填则无法路由到其他服务
- AddRequestHeader=X-Request-Foo, Bar
- name: Hystrix # 添加熔断
args:
name: fallbackcmd
fallbackUri: forward:/test/fallback # 熔断跳转地址 # 熔断超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:
5、上面我们配置了熔断的配置,一旦发生熔断就会跳转到/test/fallback这个地址,下面我们实现一下这个接口,这里简单的返回了error,我们可以自定义处理熔断的逻辑
@Controller
@RequestMapping(value = "/test")
public class TestController
{
@RequestMapping(value = "/fallback", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<String> fallback()
{
return new ResponseEntity<>("error.", HttpStatus.OK);
}
}
6、网关配置好后,再启动一个其他的服务模块,记得添加引入actuator,否则无法被路由到
<!-- Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 健康检查 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
7、编写一个HTTP接口,来测试网关的调用,为了检测熔断的效果,这里通过参数来控制接口的响应时间
@Controller
@RequestMapping(value = "/test")
public class TestController
{
@Value("${server.port}")
private String port; @RequestMapping(value = "/get/{time}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<String> get(@PathVariable("time") long time)
{
try
{
Thread.sleep(time);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return new ResponseEntity<>(port + " get ok.", HttpStatus.OK);
}
}
8、在同一注册中心下启动网关和服务,根据我们配置的路由规则/media/**,我们可以这样调用http://127.0.0.1:8501/media/get/100,可以看到正确的路由到了服务
9、我们将响应时间改成5秒http://127.0.0.1:8501/media/get/5000,超高熔断的检测时间,可以发现接口熔断,并且跳转到了指定的链接
三、高级特性---断言
1、以上我们实现了SpringCloudGateway的基本使用办法,可以应付大部分应用场景了,我们同时可以细粒度的去改造路由,就使用到了断言Predict,如果不满足我们设置的断言条件,则无法被路由
2、设置断言,我们只需要在predicates下面加入配置即可,要注意如果设置了多个断言,则请求必须满足所有断言才可以被正确路由到
spring:
cloud:
gateway:
routes: # 可以配置多个路由
- id: service-media-1 # 路由id唯一
uri: lb://service-media # 可以直接跳转到具体的地址,如果要跳转到其他服务,则填写lb://<服务id>
predicates:
# 加入断言
3、常用的一些断言,还有很多其他断言就不一一列举了,当然最常用的可能是Path断言,我们需要通过路径来指定路由
(1)- Header=<key>, <value>(必须有指定的HTTP Header才能路由)
(2)- Cookie=<key>, <value>(必须有指定的Cookie才能路由)
(3)- Host=aaa.bbb.com(请求域名必须是aaa.bbb.com才能路由)
(4)- Method=GET(请求方式必须是Get请求才能路由)
四、高级特性---过滤器
1、通过设置网关的过滤器,我们可以在用户访问的入口增加一些处理,比如鉴权、接口监控等,下面介绍一些常用的过滤器
2、常用的过滤器
(1)- AddRequestHeader=<key>, <value>(增加自定义HTTP请求头)
(2)- SetStatus=401(设置响应的HTTP错误码)
(3)- RedirectTo=302, http://acme.org(重定向到指定链接)
3、自定义过滤器,可以通过代码定制更加灵活的过滤器,下面实现一个简单的接口耗时统计的过滤器,思路:设置两个过滤器,一个前置过滤器用来收集接口开始调用的时间,一个后置过滤器来将结束时间减去开始时间得到接口的耗时时间,并打印出来
(1)前置过滤器工厂,将开始时间写到attributes里面
public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> { public PreGatewayFilterFactory() {
super(Config.class);
} @Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
exchange.getAttributes().put("requestTime", System.currentTimeMillis());
return chain.filter(exchange);
};
} public static class Config { } }
(2)后置过滤器工厂,获取attribute里面的开始时间,并用当前时间减去,得到耗时时间,打印
public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config>
{
public PostGatewayFilterFactory() {
super(Config.class);
} @Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute("requestTime");
long time = System.currentTimeMillis() - startTime;
System.out.println("接口耗时时间(ms):"+time);
}));
};
} public static class Config { } }
(3)接下来将两个过滤器注入到Spring里面
@Configuration
public class FilterConfig
{
@Bean
public PreGatewayFilterFactory preGatewayFilterFactory() {
return new PreGatewayFilterFactory();
} @Bean
public PostGatewayFilterFactory postGatewayFilterFactory() {
return new PostGatewayFilterFactory();
}
}
(4)前往application.yml进行过滤器的配置,在filter属性下配置上我们的自定义过滤器,根据框架的约定引用过滤器:比如我们的过滤器名称是PreGatewayFilterFactory,那我们引用的名称就是去掉GatewayFilterFactory这个后缀,也就是Pre,具体配置如下
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 设置可以路由到其他服务
routes: # 可以配置多个路由
- id: service-media- # 路由id唯一
uri: lb://service-media # 可以直接跳转到具体的地址,如果要跳转到其他服务,则填写lb://<服务id>
predicates:
- Path=/media/** # 路由规则
filters:
- StripPrefix= # 不填则无法路由到其他服务
- Pre # 自定义过滤器
- Post # 自定义过滤器
(5)接下来我们调用接口,可以看到耗时时间打在公屏上
五、网关限流
1、我们可以在网关层面做限流的功能,防止高并发时把服务器搞崩,或者应对一些网络攻击等情况
2、SpringCloudGateway为我们提供了一个很方便使用的令牌桶限流,思路:我们设置一个固定大小的令牌桶,如果令牌桶不满,则根据一定的频率向桶里放入令牌,每当有客户端的请求发来,会先从令牌桶里面取令牌,取到了则继续执行,取不到请求则会被拒绝,这样就达到了限流的作用,我们可以灵活地调整令牌补充速率和令牌桶大小,来细粒度的控制限流,我们使用redis来存储令牌,下面是一个简单的demo
(1)引入redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
(2)接下来自定义限流的维度,我们可以从域名、uri等维度进行限流
public class HostAddrKeyResolver implements KeyResolver
{
@Override
public Mono<String> resolve(ServerWebExchange exchange)
{
// 域名维度限流
return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
// uri维度限流
// return Mono.just(exchange.getRequest().getURI().getPath());
}
}
(3)将解析器注入到Spring
@Configuration
public class TokenLimitConfig
{
@Bean
public HostAddrKeyResolver hostAddrKeyResolver() {
return new HostAddrKeyResolver();
}
}
(4)接下来配置限流器的配置,将我们编写的解析器引用,并且配置令牌桶的属性,这里我配置的是,每秒补充一个令牌,令牌桶的大小为3,最后配置redis的参数,用起来非常简单
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 设置可以路由到其他服务
routes: # 可以配置多个路由
- id: service-media- # 路由id唯一
uri: lb://service-media # 可以直接跳转到具体的地址,如果要跳转到其他服务,则填写lb://<服务id>
predicates:
- Path=/media/** # 路由规则
filters:
- StripPrefix= # 不填则无法路由到其他服务
- name: RequestRateLimiter # 配置限流器
args:
key-resolver: '#{@hostAddrKeyResolver}' # 自定义限流过滤器
redis-rate-limiter.replenishRate: # 令牌桶每秒填充平均速率
redis-rate-limiter.burstCapacity: # 令牌桶总容量
redis:
host: 127.0.0.1
port:
password:
(5)配置好后,使用JMeter来压测一下接口,可以发现某些请求返回429错误码,被限流
SpringCloud-Greenwich版本新特性探索(1)---SpringCloudGateway的更多相关文章
- Atitit.c# .net 3.5 4.0 4.5 5.0 6.0各个版本新特性战略规划总结
Atitit.c# .net 3.5 4.0 各个版本新特性战略规划总结 1. --------------.Net Framework版本同CLR版本的关系1 2. paip.----------- ...
- c# .net 3.5 4.0 4.5 5.0 6.0各个版本新特性战略规划总结【转载】
引用:http://blog.csdn.net/attilax/article/details/42014327 c# .net 3.5 4.0 各个版本新特性战略规划总结 1. ---------- ...
- Atitit opencv版本新特性attilax总结
Atitit opencv版本新特性attilax总结 1.1. :OpenCV 3.0 发布,史上功能最全,速度最快的版1 1.2. 应用领域2 1.3. OPENCV2.4.3改进 2.4.2就有 ...
- Atitit mac os 版本 新特性 attilax大总结
Atitit mac os 版本 新特性 attilax大总结 1. Macos概述1 2. 早期2 2.1. Macintosh OS (系统 1.0) 1984年2 2.2. Mac OS 7. ...
- IOS第三天-新浪微博 - 版本新特性,OAuth授权认证
*********版本新特性 #import "HWNewfeatureViewController.h" #import "HWTabBarViewController ...
- 【开源】OSharp3.3框架解说系列:重新开源及3.3版本新特性
OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...
- Atitit 发帖机系列(8) 词法分析器v5 版本新特性说明)
Atitit 发帖机系列(8) 词法分析器v5 版本新特性说明) v5 增加对sql单引号的内部支持.可以作为string 结构调整,使用递归法重构循环发..放弃循环发. V4 java dsl词 ...
- [iOS微博项目 - 1.7] - 版本新特性
A.版本新特性 1.需求 第一次使用新版本的时候,不直接进入app,而是展示新特性界面 github: https://github.com/hellovoidworld/HVWWeibo ...
- framework各版本新特性(为面试准备)
菜鸟D估计描述这些新特性的文章都是烂大街的货色,之所以拿出来分(e)享(xin)一下,有两个原因:1.当年面试的时候有人问到,我不知道该怎么回答:2.项目需要发布了,但是考虑到framework的版本 ...
随机推荐
- 华为ssh远程登录,配置
- 记录一次DataTable排序的问题
//dt.DefaultView.Sort = "字段名 方式"; 最开始用的上面的没好用,改成底下转换了一下就好用了0.0 DataView dv = new DataView( ...
- 用OleDb导入Excel时提示驱动错误问题解决办法
导入格式为xls的excel文件,发生了错误 未处理System.Data.OleDb.OleDbException HResult=-2147467259 Message=外部数据库驱动程序 (1) ...
- python学习:字典
字典 1.查询内存地址 a = 10 print(id(a)) b = a print(id(b)) b = 15 print(id(b)) 2. 数据类型 不可变类型:整型.字符串.元组 可变类型: ...
- java对文件的基本操作
package cn.edu.fhj.day009.FileDemo; import java.io.File; import java.io.IOException; public class Fi ...
- over(partition by..) 的运用(转)
oracle的分析函数over 及开窗函数一:分析函数overOracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每 ...
- 关于外网无法访问阿里云主机CentOs
前两天阿里云ECS搞活动,所有买了个三年的Ecs,然后照着之前在虚拟机同样的搭建服务器,一切都很正常,可是 当我配置好防火墙和nginx之后,发现个问题,外网无法访问. 思考: 1.我的nginx没配 ...
- linux学习历程-不熟悉的linux命令
一:man(执行查看帮助命令) 二:常用的系统工作命令 1:echo echo命令用于显示在终端输出字符串或变量提取后的值,格式“echo [字符串]|[$变量]” 2:date 用于显示系统的时间和 ...
- ipset和iptables配合来自动封闭和解封有问题的IP
iptables封掉少量ip处理是没什么问题的,但是当有大量ip攻击的时候性能就跟不上了,iptables是O(N)的性能.而ipset就像一个集合,把需要封闭的ip地址放入这个集合中,ipset 是 ...
- 东软实习<3>
今天学习过程和小节 主要对多线程,单例模式以及jdbc进行了一些深入着重的学习, 还有就是学习了如何使用java操作HDFS 主要是对于一些继承调用的使用等 1.封装JDBC,自定义范型 2.反射,自 ...