网关介绍
分布式架构存在的弊端
- 每个业务都会需要鉴权,限流、权限校验,跨域等逻辑。如果每个业务都各自为战,自己造轮子实现一遍,会很蛋疼,完全可以抽出来,放到一个统一的地方去做。
- 如果业务量比较简单的话,这种方式前端不会有什么问题。但随着业务量越来越复杂,比如淘宝等打开一个页面可能会涉及到数百个微服务协同工作,如果每一个微服务都分配一个域名的话,一方面客户端代码会很难维护,涉及到数百个域名,另一方面是连接数量的瓶颈。想象一下打开一个APP,通过抓包发现涉及到了数百个微服务远程调用,这在移动端下会显得非常低效
- 后期如果对微服务进行重构的话,也会变得非常麻烦,需要客户端配合你一起进行改造,比如商品服务,随着业务变得越来越复杂,后期需要进行拆分成多个微服务,这个时候对外部提供的服务也需要拆分成多个,同时前端也需要改变
所谓的API网关,就是指系统的统一入口,他分装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权,监控路由转发等。添加上API网关后,系统的架构图变成了如下所示:
Gateway介绍
网关作为流程的日寇,常用的功能包括路由转发,权限校验,限流等。
GateWay:是spring Cloud官方推出的第二代网关框架,提供更优秀的性能,具有更强大的功能。它是由WebFlux+Netty+Reactir实现的响应式API网关,它不能在传统的servlet容器中工作,也不能构建成war包。GateWay旨在为微服务架构提供一种简单并且有限的API路由管理方式,并基于Filter的方式提供网关的基本功能,例如说安全认证、监控、限流等。
核心概念
- 路由: 路由是网关中最基础的部分,路由的信息包括一个ID,一个目的URI,一个断言工厂,一组Filter组成。如果断言为真,则说明请求的路由和配置的路由匹配
- 断言: Java8中的断言函数,断言函数类型是spring5框架中的。断言函数允许开发者去定义匹配http/httpss中request的任何信息,比如请求头和参数等
- Filter: 可以对请求和响应进行处理
工作原理
初体验
添加依赖
<!--添加gateway的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
修改yaml文件
server:
port: 8886
spring:
application:
name: api-gateway
cloud:
# 配置相关的gateway配置
# 配置路由规则
gateway:
routes:
- id: order_route #路由的唯一标识,路由到order服务上
uri: http://localhost:8010 #需要转发的地址
#断言规则,用于路由规则匹配
predicates:
- Path=/order-serv/** #需要匹配的路径
filters:
- StripPrefix=1 # 转发之前,去掉第一层的内容
gateway整合nacos
引入nacos注册与发现的依赖
<!--nacos服务器的注册与发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置yaml文件
server:
port: 8886
spring:
application:
name: api-gateway
cloud:
nacos: # 配置nacos发现的相关信息
discovery:
server-addr: 111.229.181.158:8847
username: nacos
password: nacos
# 配置相关的gateway配置
# 配置路由规则
gateway:
routes:
- id: order_route #路由的唯一标识,路由到order服务上
uri: lb://order-service #改成对应服务的服务名。使用nacos中本地负载均衡策略
#断言规则,用于路由规则匹配
predicates:
- Path=/order-serv/** #需要匹配的路径
filters:
- StripPrefix=1 # 转发之前,去掉第一层的内容
使用简写的配置,自动寻找服务器
server:
port: 8886
spring:
application:
name: api-gateway
cloud:
nacos: # 配置nacos发现的相关信息
discovery:
server-addr: 111.229.181.158:8847
username: nacos
password: nacos
# 配置相关的gateway配置
# 配置路由规则
gateway:
discovery:
locator:
enabled: true #自动识别nacos的服务
#routes:
# - id: order_route #路由的唯一标识,路由到order服务上
# uri: lb://order-service #改成对应服务的服务名。使用nacos中本地负载均衡策略
#断言规则,用于路由规则匹配
# predicates:
# - Path=/order-serv/** #需要匹配的路径
# filters:
# - StripPrefix=1 # 转发之前,去掉第一层的内容
内置路由断言工厂
当请求gateway的时候,使用断言对请求进行匹配,如果匹配成功就路由转发,请求失败就返回404
基于DateTime类型的断言工厂
- AfterRoutePreducateFactory:接收一个日期参数,判断请求日期是否晚于指定日期
- BeforeRoutePreducateFactory:接收一个日期参数,判断请求日期是否早于指定日期
- BetweenRoutePreducateFactory:接收两个日期参数,判断请求日期是否在指定的时间段内
- After=
- 基于远程地址的断言工厂
RemoteAddrRoutePredicateFactory:接收一个IP地址端,判断请求主机地址是否在地址段中- RemoteAddr=192.168.1.1/24
- 基于cookie的断言工厂
CookieRiytePreducateFactory:接收两个参数,cookie名字和一个正则表达式,判断请求
-Cookie-chocloate, ch.
- 基于header的断言工厂
HeaderRiytePreducateFactory - 基于Host的断言工厂
- 基于Method请求方法的断言工厂
自定义路由断言工厂
自定义路由断言工厂需要继承AbstractRoutePredicateFactory
类,重写apply方法的逻辑。在apply方法中可以通过exchange.getRequest()
拿到ServeltHttpRequest
对象,从而可以获取到请求的参数,请求方式、请求头等信息
注意:命名需要以RoutePredicateFactory结尾,并且使用@Component
注解加入到组件中
局部(内置、自定义)过滤器
跟自定义的断言工厂形式差不多
全局过滤器
局部过滤器是针对某个路由的,全局过滤器是针对所有路由请求的。
局部过滤器需要在路由中配置,全局路由器一旦定义了就会投入使用
自定义全局过滤器
需要实现GlobalFilter
接口,并且注入到spring容器中
请求日志记录&跨域处理
React Netty访问日志需要设置:``
他必须通过Java系统属性,而不是Spring Boot配置的
GateWay的跨域请求
server:
port: 8886
spring:
application:
name: api-gateway
cloud:
nacos: # 配置nacos发现的相关信息
discovery:
server-addr: 111.229.181.158:8847
username: nacos
password: nacos
# 配置相关的gateway配置
# 配置路由规则
gateway:
globalcors:
# discovery:
# locator:
# enabled: true #自动识别nacos的服务
routes:
- id: order_route #路由的唯一标识,路由到order服务上
uri: lb://order-service #改成对应服务的服务名。使用nacos中本地负载均衡策略
#断言规则,用于路由规则匹配
predicates:
- Path=/order-serv/** #需要匹配的路径
filters:
- StripPrefix=1 # 转发之前,去掉第一层的内容
# 配置跨域的信息
cors-configurations:
'[/**]': # 允许跨域访问的资源
allowedOrigins: "*" # 允许跨域的来源
allowedMehtods:
- GET
- POST
- DELETE
- PUT
- OPTION
整合sentinel流控降级
添加依赖
<!--引入sentinel-gateway的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!--引入sentinel的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
添加配置
# 配置dashbaord的控制台
sentinel:
transport:
dashboard: 111.229.181.158:8847