一、前言

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. MYSQL必知必会学习笔记

    8.1.1 百分号( %)通配符最常使用的通配符是百分号( %).在搜索串中, %表示任何字符出现任意次数.例如,为了找出所有以词jet起头的产品,可使用以下SELECT语句:SELECT prod_ ...

  2. 使用Axis2创建一个简单的WebService服务

    使用过Java进行过WebService开发都会听过或者接触过Apache Axis2,Axis2框架是应用最广泛的WebService框架之一了. 这里使用Axis2来开发和部署一个最简单的WebS ...

  3. 团队项目:Recycle

    一.团队名字 地球保卫队(EPT) 二.团队阵容 1.项目部分 小组成员思维活跃,仅仅在一节课的时间里提出了n个颠覆软件开发界的思维的idea,最后在层层pk最后留下了八个惊世骇俗的想法.其中包括了要 ...

  4. PHP环境在7以上的项目报错A non-numeric value encountered

    报错如下图: 解决办法: 在相对应的报错控制器层加入一行代码,需加载控制器上方,代码如下:   ini_set("error_reporting","E_ALL & ...

  5. 1、了解计算机与操作系统发展阶段 2、选择一个具体的操作系统,结合计算机与操作系统的发展阶段,详细了解其渊源、发展过程、趋势,整理成简洁美观的图文博客发布。 Windows Mac os x Unix Linux Android 等。

    1.了解计算机与操作系统发展阶段 操作系统并不是与计算机硬件一起诞生的,它是在人们使用计算机的过程中,为了满足两大需求:提高资源利用率.增强计算机系统性能,伴随着计算机技术本身及其应用的日益发展,而逐 ...

  6. 如何安装并且使用jmeter进行简单的性能测试

    Jmeter  介绍 Jmeter  是一款使用Java开发的,开源免费的,测试工具, 主要用来做功能测试和性能测试(压力测试/负载测试). 而且用Jmeter 来测试 Restful API, 非常 ...

  7. 解决idea导入项目后依赖报错问题

    1.在idea首页 Confige-->setting-->build,execution,deployment-->buildTool-->maven-->work o ...

  8. Hadoop 数据去重

    数据去重这个实例主要是为了读者掌握并利用并行化思想对数据进行有意义的筛选.统计大数据集上的数据种类个数.从网站日志中计算访问等这些看似庞杂的任务都会涉及数据去重.下面就进入这个实例的MapReduce ...

  9. [Swift]LeetCode375. 猜数字大小 II | Guess Number Higher or Lower II

    We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...

  10. linux入门--Linux的应用领域

    Linux 似乎在我们平时的生活中很少看到,那么它应用在哪些领域呢?其实,在生活中随时随地都有 Linux 为我们服务着. 网站服务器 用事实说话!访问国际知名的 Netcraft 网站 http:/ ...