目录
Zuul网关和gateway网关的区别:
Gateway路由配置
1、新建服务网关项目,并在项目pom文件中引入gateway网关依赖
2、在application.yml配置gateway
3、如果不用配置的方式配置gateway路由,还可以通过代码的形式配置
4、启动网关服务,访问localhost:8081/api/goods/goodsInfo
5、服务提供者server-goods
Gateway熔断降级
1、在网关服务项目中引入Hystrix依赖
2、在网关服务项目application.yml中配置以下内容
3、在网关服务项目resource下添加application-hystrix.yml文件配置hystrix信息
4、在网关服务项目中新增一个Controller,配置fallbackUri中的降级方法
5、启动网关服务,再次访问localhost:8081/api/goods/goodsInfo
6、服务提供者server-goods
Gateway限流
1、在网关服务项目中引入redis-reactive依赖
2、在服务网关项目中修改application.yml激活application-limit.yml的配置
3、在服务网关项目中添加application-limit.yml配置限流条件
4、在网关服务项目中添加名为userKeyResolver的Bean
5、本地启动redis服务,访问localhost:8081/api/goods/goodsInfo?user="张三"
Zuul网关和gateway网关的区别:
Zuul是netflix在2013年开源的网关组件,大规模应用在Netflix的生产环境中,经受了实践考验。它可以与Eureka、Ribbon、Hystrix等组件搭配使用,实现路由转发、负载均衡、熔断等功能。Zuul的核心是一系列过滤器,过滤器简单易于扩展。Zuul基于Servlet构建,使用的是阻塞的IO,引入了线程池来处理请求。每个请求都需要独立的线程来处理,从线程池中取出一个工作线程执行,下游微服务返回响应之前这个工作线程之前一直是阻塞的。
SpringCloud Gateway是SpringCloud的一个全新项目,该项目是基于Spring5.0,SpringBoot2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。
SpringCloud Gateway作为SpringCloud生态系统的网关,目标是代替Zuul,它是基于Webflux框架实现的,而Webflux框架底层则是使用了高性能的Reactor模式通信框架Netty。
SpringCloud Gateway目标不仅提供统一的路由方式,而且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,限流等。
Gateway路由配置
1、新建服务网关项目,并在项目pom文件中引入gateway网关依赖
<!-- 引入gateway网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2、在application.yml配置gateway
Gateway配置各字段含义:
id : 我们自定义的路由ID,保持唯一(“-”与id之间有空格)
uri: 目标服务地址,(lb://服务名)lb为load balance负载均衡的意思
predicates: 路由条件,Predicates接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将Predicates组合成其他复杂的逻辑(如:与、或、非)
server:
port: 8081
spring:
application:
name: server-gateway
#配置gateway路由规则
cloud:
gateway:
routes:
- id: route1 #route ID 自定义
uri: lb://server-goods #目标服务地址 lb://服务名称
# uri: http://localhost:8041 #直接指定服务地址
predicates: #路由条件
- Path=/api/goods/**
eureka:
instance:
# 使用ip地址作为host,而不是机器号/电脑名称
prefer-ip-address: true
# Eureka客户端向注册中心发送心跳的时间间隔是1s,默认是30s
lease-renewal-interval-in-seconds: 1
# Eureka服务端在收到一次心跳后等待时间上限是2s,默认是90s
# 超时将剔出该微服务,也可以在Eureka服务端进行设置
lease-expiration-duration-in-seconds: 2
client:
service-url:
defaultZone: http://localhost:8060/eureka/
3、如果不用配置的方式配置gateway路由,还可以通过代码的形式配置
代码方式项目中用得比较少
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
//使用分布的形式创建返回RouteLocator
RouteLocatorBuilder.Builder routes = builder.routes();
//指定具体的服务地址
routes.route("route2",r->{
return r.path("/api/goods/**").uri("http://localhost:8041");
});
//使用lb负载均衡配置服务地址
// routes.route("route3",r->{
// return r.path("/api/goods/**").uri("lb://server-goods");
// });
return routes.build();
//使用链式编程一步到位
// return builder.routes()
// .route("route2",r->r.path("/api/goods/**")
// .uri("lb://server-goods"))
// .build();
}
4、启动网关服务,访问localhost:8081/api/goods/goodsInfo
在访问网关服务时,由于/api/goods/goodsInfo匹配到了gateway里配置的路由规则/api/goods/**,所以gateway会将请求转发到server-goods服务上去处理,然后在server-goods服务中匹配/api/goods/goodsInfo接口,匹配成功后调用处理逻辑,完成后将结果返回。
如果我们配置路由规则时直接指定了具体的服务器,如上述http://localhost:8041,则不需要搭配注册中心使用gateway;相反,如果我们使用lb://server-goods来配置服务地址,则需要搭配注册中心来使用gateway,这样才能将请求负载均衡到server-goods集群的节点中,否则将会无法路由到对应的服务。
5、服务提供者server-goods
@RestController
@RequestMapping("/api/goods")
public class GoodsController {
@Value("${server.port}")
private String port;
@GetMapping("/goodsInfo")
public String goodsInfo(){
return "goodsInfo"+port;
}
}
Gateway熔断降级
1、在网关服务项目中引入Hystrix依赖
<!-- Hystrix服务保护 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、在网关服务项目application.yml中配置以下内容
使用spring.profiles.active激活application-hystrix.yml配置
server:
port: 8081
spring:
application:
name: server-gateway
profiles:
active: hystrix
eureka:
instance:
# 使用ip地址作为host,而不是机器号/电脑名称
prefer-ip-address: true
# Eureka客户端向注册中心发送心跳的时间间隔是1s,默认是30s
lease-renewal-interval-in-seconds: 1
# Eureka服务端在收到一次心跳后等待时间上限是2s,默认是90s
# 超时将剔出该微服务,也可以在Eureka服务端进行设置
lease-expiration-duration-in-seconds: 2
client:
service-url:
defaultZone: http://localhost:8060/eureka/
3、在网关服务项目resource下添加application-hystrix.yml文件配置hystrix信息
spring:
cloud:
gateway:
routes:
- id: route1 #route ID 自定义
uri: lb://server-goods #目标服务地址 lb://服务名称
predicates: #路由条件
- Path=/api/goods/**
filters:
-name: Hystrix
args:
#指定一个command命令名称
name: fallbackCmd
#指定一个降级方法
fallbackUri: forward:/fallbackMethod
#Hystrix配置
hystrix:
commond:
fallbackCmd:
execution:
isolation:
thread:
timeoutInMillseconds: 2000 #超时2000ms后进入降级服务
配置解释:
过滤器Hystrix,作用是通过Hystrix进行熔断降级。
当上游的请求进入了Hystrix熔断降级机制时,就会调用fallbackUri配置的降级地址,需要注意的是,还需要单独设置Hystrix的CommanKey的超时时间。
4、在网关服务项目中新增一个Controller,配置fallbackUri中的降级方法
@RestController
public class FallbackController {
@GetMapping("/fallbackMethod")
public Map<String,String> fallbackMethod(){
HashMap<String, String> response = new HashMap<>(2);
response.put("code","100");
response.put("msg","服务暂时不可用");
return response;
}
}
5、启动网关服务,再次访问localhost:8081/api/goods/goodsInfo
6、服务提供者server-goods
@RestController
@RequestMapping("/api/goods")
public class GoodsController {
@Value("${server.port}")
private String port;
@GetMapping("/goodsInfo")
public String goodsInfo() throws InterruptedException {
Thread.sleep(3000);
return "goodsInfo"+port;
}
}
修改服务提供者,是其线程休眠3秒,达到hystrix的超时条件,触发fallbackCmd的降级方法。
Gateway限流
限流是高并发场景下比较常用的手段之一,可以有效的保障服务的整体稳定性,Spring Cloud Gateway提供了基于Redis的限流方案
1、在网关服务项目中引入redis-reactive依赖
<!-- Reactive -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
2、在服务网关项目中修改application.yml激活application-limit.yml的配置
server:
port: 8081
spring:
application:
name: server-gateway
profiles:
active: limit
eureka:
instance:
# 使用ip地址作为host,而不是机器号/电脑名称
prefer-ip-address: true
# Eureka客户端向注册中心发送心跳的时间间隔是1s,默认是30s
lease-renewal-interval-in-seconds: 1
# Eureka服务端在收到一次心跳后等待时间上限是2s,默认是90s
# 超时将剔出该微服务,也可以在Eureka服务端进行设置
lease-expiration-duration-in-seconds: 2
client:
service-url:
defaultZone: http://localhost:8060/eureka/
3、在服务网关项目中添加application-limit.yml配置限流条件
spring:
redis:
host: 127.0.0.1
port: 6379
cloud:
gateway:
routes:
- id: test_limiter_route #route ID 自定义
uri: lb://server-goods #目标服务地址 lb://服务名称
predicates: #路由条件
- Path=/api/goods/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 2
key-resolver: "#{@userKeyResolver}"
Filter参数说明
name: 名称必须是RequestRateLimiter
redis-rate-limiter.replenishRate: 允许用户每秒处理多少个请求
redis-rate-limiter.burstCapacity: 令牌桶容量,允许在一秒钟内完成的最大请求数
key-resolver: 使用SpEL按名称引用bean
4、在网关服务项目中添加名为userKeyResolver的Bean
@Bean
KeyResolver userKeyResolver(){
//根据请求参数中的user字段来限流
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
5、本地启动redis服务,访问localhost:8081/api/goods/goodsInfo?user="张三"
快速点击刷新按钮,由于拿不到令牌,所以会导致进不去服务。
而如果访问速度不快的情况下是可以正常访问页面的