一、前言

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的更多相关文章

  1. 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.----------- ...

  2. 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. ---------- ...

  3. Atitit opencv版本新特性attilax总结

    Atitit opencv版本新特性attilax总结 1.1. :OpenCV 3.0 发布,史上功能最全,速度最快的版1 1.2. 应用领域2 1.3. OPENCV2.4.3改进 2.4.2就有 ...

  4. 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. ...

  5. IOS第三天-新浪微博 - 版本新特性,OAuth授权认证

    *********版本新特性 #import "HWNewfeatureViewController.h" #import "HWTabBarViewController ...

  6. 【开源】OSharp3.3框架解说系列:重新开源及3.3版本新特性

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  7. Atitit 发帖机系列(8)  词法分析器v5 版本新特性说明)

    Atitit 发帖机系列(8)  词法分析器v5 版本新特性说明) v5  增加对sql单引号的内部支持.可以作为string 结构调整,使用递归法重构循环发..放弃循环发. V4 java dsl词 ...

  8. [iOS微博项目 - 1.7] - 版本新特性

    A.版本新特性 1.需求 第一次使用新版本的时候,不直接进入app,而是展示新特性界面 github: https://github.com/hellovoidworld/HVWWeibo       ...

  9. framework各版本新特性(为面试准备)

    菜鸟D估计描述这些新特性的文章都是烂大街的货色,之所以拿出来分(e)享(xin)一下,有两个原因:1.当年面试的时候有人问到,我不知道该怎么回答:2.项目需要发布了,但是考虑到framework的版本 ...

随机推荐

  1. 华为ssh远程登录,配置

  2. 记录一次DataTable排序的问题

    //dt.DefaultView.Sort = "字段名 方式"; 最开始用的上面的没好用,改成底下转换了一下就好用了0.0 DataView dv = new DataView( ...

  3. 用OleDb导入Excel时提示驱动错误问题解决办法

    导入格式为xls的excel文件,发生了错误 未处理System.Data.OleDb.OleDbException HResult=-2147467259 Message=外部数据库驱动程序 (1) ...

  4. python学习:字典

    字典 1.查询内存地址 a = 10 print(id(a)) b = a print(id(b)) b = 15 print(id(b)) 2. 数据类型 不可变类型:整型.字符串.元组 可变类型: ...

  5. java对文件的基本操作

    package cn.edu.fhj.day009.FileDemo; import java.io.File; import java.io.IOException; public class Fi ...

  6. over(partition by..) 的运用(转)

    oracle的分析函数over 及开窗函数一:分析函数overOracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每 ...

  7. 关于外网无法访问阿里云主机CentOs

    前两天阿里云ECS搞活动,所有买了个三年的Ecs,然后照着之前在虚拟机同样的搭建服务器,一切都很正常,可是 当我配置好防火墙和nginx之后,发现个问题,外网无法访问. 思考: 1.我的nginx没配 ...

  8. linux学习历程-不熟悉的linux命令

    一:man(执行查看帮助命令) 二:常用的系统工作命令 1:echo echo命令用于显示在终端输出字符串或变量提取后的值,格式“echo [字符串]|[$变量]” 2:date 用于显示系统的时间和 ...

  9. ipset和iptables配合来自动封闭和解封有问题的IP

    iptables封掉少量ip处理是没什么问题的,但是当有大量ip攻击的时候性能就跟不上了,iptables是O(N)的性能.而ipset就像一个集合,把需要封闭的ip地址放入这个集合中,ipset 是 ...

  10. 东软实习<3>

    今天学习过程和小节 主要对多线程,单例模式以及jdbc进行了一些深入着重的学习, 还有就是学习了如何使用java操作HDFS 主要是对于一些继承调用的使用等 1.封装JDBC,自定义范型 2.反射,自 ...