一、前言

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. 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第6章编程练习4

    #include <iostream> using namespace std; const int strsize=30; const int BOPSIZE=5; void showm ...

  2. Mem系列函数介绍及案例实现

      昨天导师甩给我们一个项目案例,让我们自己去看一看熟悉一下项目内容,我看到了这个项目里面大量使用memset(sBuf,0,sizeof(sBuf));这一块内存填充的代码,于是回想起以前查过Mem ...

  3. 在Github上为项目添加多个用户

    点击项目目录中的Settings 点击Collaborators 添加后,合作者会受到确认邮件,等待合作者确认后,合作者就可以提交了 添加组织 在Settings中找到Organizations 点击 ...

  4. Go语言基础之接口

    Go语言基础之接口 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节. 接口 接口介绍 在Go语言中接口(interface)是一种类型,一种抽象的类 ...

  5. ElasticSearch(6.2.2)的java API官方文档的总结 (三)

    一 : SearchRequest用于任何与搜索文档,聚合和建议有关的操作,并且还提供了对生成的文档进行高亮显示的方法. 在最基本的形式中,我们可以向请求添加一个查询:    1:添加一个Search ...

  6. microk8s

    https://microk8s.io/ video guide: sudo snap install microk8s --classic #snap install microk8s --clas ...

  7. JS跨域两三事

    今日,前端开发要求新的Web服务需要支持跨域,因为要发起 Ajax 到后端web 服务域名请求数据: 前端application域名是 other.abc.com (举个栗子)  api接口域名是 a ...

  8. Live2D插件--漂浮的二次元小姐姐

    这个插件找了很久,都没找到,今天偶然翻到一个小哥的博客发现了这个,果断偷走. 教程转自简书:https://www.jianshu.com/p/1cedcf183633 还有这些,你可能有用 修改位置 ...

  9. 对matplotlib库的运用

    1.matplotlib库的运用效果图 绘制基本的三角函数                                                                        ...

  10. python语法_函数

    ---恢复内容开始--- 函数: 1 减少重复代码 2 定义一个功能,需要直接调用 3 保持代码一致性 def  funcation_name(参数s): 功能代码块0 参数可以为多个,传入时按照前后 ...