SpringCloudGateway网关 学习记录
微服务网关的概念:
微服务网关GateWay
ZUUL是一个基于阻塞IO的微服务网关。其内在原理也依赖Servlet。所以其整体的性能并不是很良好。
对于JAVA项目来说SpringCloudGateWay是主场作战。在Spring大家庭中融入的比较好。所以使用起来相对方便。
在SpringCloudGateWay中有三个比较核心的概念:
SpringCloud Gateway的使用:
(1)导入依赖
<!-- 网关依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
(2)配置启动类
package com.kerry.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class, args);
}
}
(3)编写application.yml配置文件
server:
port: 8001
spring:
application:
name: server-gateway #服务名称
cloud:
gateway:
routes:
- id: category-service #自定义的路由id,保持唯一
uri: http://127.0.0.1:9001 #目标服务地址
predicates: #路由条件 可于网上搜索更多
- Path=/category/**,/admin/category/**
- id: headline-service
uri: http://127.0.0.1:9002
predicates:
- Path=/headline/**,/admin/headline/**
到此简简单单的路由功能已经实现了,但是我们可以注意到在目标服务地址上我们填写的对应的ip端口,这样写死的话
明显是不够完善的。对此我们可以引入动态路由
动态路由
<!-- eureka网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)修改application.yml配置文件
server:
port: 8001
spring:
application:
name: server-gateway #服务名称
cloud:
gateway:
routes:
- id: category-service
uri: lb://service-category
predicates:
- Path=/category/**,/admin/category/**
- id: headline-service
uri: lb://service-headline
predicates:
- Path=/headline/**,/admin/headline/**
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8000/eureka #,http://127.0.0.1:8999/eureka/
registry-fetch-interval-seconds: 5 # 获取服务列表的周期:5s
instance:
prefer-ip-address: true #使用ip注册
ip-address: 127.0.0.1
重写转发路径
spring: application: name: api-gateway #指定服务名 cloud: gateway: routes: - id: product-service uri: lb://shop-service-product predicates: - Path=/product-service/** filters: - RewritePath=/product-service/(?<segment>.*), /$\{segment}
过滤器
我们可以通过GlobalFilter类来实现统一鉴权:
代码实现:
package com.kerry.gateway.filter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /* * 该类为用户登录权监过滤器 todo:后期将token参数改到session或者是redis中。 * 目前的代码效果为:当请求链接来到网关的时候会判断请求参数中是否有token参数,如果无的话则视为没有权限,如果有则视为有权限 * 例子: * http://localhost:8001/admin/category/demo.do/1 效果:访问失败 * http://localhost:8001/admin/category/demo.do/1?token=1 效果:访问成功 * */ @Slf4j @Component public class LoginFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("执行了自定义的登录权监全局过滤器"); //String url = exchange.getRequest().getURI().getPath(); // 忽略以下url请求 // if(url.indexOf("/login") >= 0){ // return chain.filter(exchange); // } String token = exchange.getRequest().getQueryParams().getFirst("token"); if (StringUtils.isBlank(token)) { log.info( "token is empty ..." ); exchange.getResponse().setStatusCode( HttpStatus.UNAUTHORIZED ); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
学习小记:
SpringCloud Gateway底层使用的web框架是webflux和SpringMVC不兼容引入的限流组件是hystrix。redis底层不再使用jedis,而是lettuce。
由于SpringCloud Gateway在SpringCloud上是主场作战,所以在进行网关上的使用上相对于ZUUL等其他技术上更为简单有效。它是基于Nttey的响应式开发模式
SpringCloud Gateway的核心概念有路由(route)断言(predicates)过滤器(filter)
Gateway的路由功能上很强大,支持各种各样的条件匹配同时也支持动态路由【动态路由需引入Eureka服务】。
Gateway在过滤器的功能上比不上ZUUL那么丰富,只要'pre'和'post'。一个是请求被路由之前调用,一个是路由到微服务之后调用。
过滤器的类型有GatewayFilter(局部)和 GlobalFilter(全局)。全局过滤器较为常用,可作用于用户信息认证校验token。
SpringCloud Gateway过滤器不止可以用作用户信息校验,还可以作为网关限流
限流算法:计数器、漏桶算法、令牌桶算法
计算器算法:规定时间内只能访问到最大阈值,到时间会重置累计数重新增加
漏桶算法:这个算法跟线程池隔离类似,规定一个容量池的大小,限制住访问量
令牌桶算法:是漏桶算法的一种改进更好的控制访问量的灵活度。
网关限流中
1.基于Filter的限流,是Gateway官方提供的基于令牌桶的限流法,需要引入
redis依赖,在配置中可以调整令牌桶的容量与数度还有对象来源
2.基于Sentinel的限流,也是需要引入依赖,编写配置类,网关配置。基于Sentinel
的Gateway限流底层也是依靠Filter功能,只需要在配置类中注入实例定义好限流方法
即可实习限流功能。
在分布式架构体系中,高可用是非常关键的存在。网关统一了服务的对外访问。那如
果说是单一的网关服务万一宕机,那对整个项目的影响是巨大的。所以我们应该
对网关也进行高可用的部署。然后将网关交给nginx进行统一管理,还能进行负载均衡
这样就可以大大的降低网关服务层的错误率。