gateway
网关是什么,网关是一切外部访问程序的入口,他控制这这个服务架构的出入,鉴权,代理,流控,监控等.
一.简介
1.官网
2.是什么?
Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架
3.作用
网关在微服务架构中的位置
作用:
- 反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
- 等等
4.gateway于zuul的区别和特性
gateway的特性:
- 动态路由
- 路由断言(Predicate)和过滤(filter)
- 继承Hystrix的断路器功能
- 继承springcloud的服务注册与发现功能
- 请求限流
- 支持路劲重写
gateway和zuul的区别
- gateway是基于NIO的,非阻塞式架构模型
- zuul是基于阻塞IO模型的.
- gateway还支持webSocket,并且与spring紧密集成.
二.gateway的原理分析
1.gateway的核心组件
- Route(路由)
#路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由 - Predicate(断言)
#参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由 - Filter(过滤)
#指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
2.gateway的工作流程
步骤:
- 请求发送到handler Mapping上,handler mapping对比predicate(断言)匹配路劲.
- 在发送到web handler上,handler在经过一系列的过滤链.
- 经过过滤链之后才是发送到具体的微服务上请求服务.
- 再请求之后还会经过一系列的过滤链,回到web handler.
- web handler再返回给handler mapping.
总结:路由转发,断言匹配,过滤,执行业务
三.gateway搭建
1.基本使用
(1) 建module
略
(2) 改pom
<!--新增gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
(3) 写yml
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
#路由地址1
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
#路由地址2
- id: payment_routh2
uri: http://localhost:8001
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
#eureka,本服务也需要注册到eureka上
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
(4) 主启动
没有特定的启动类
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run( GateWayMain9527.class,args);
}
}
(5) 测试
- 1)第一步,Eureka
- 2)第二步,启动8001的服务
- 3)第三步,启动gateway网关服务
#查看两个服务是否已经注册到eureka上了
- 4)验证浏览器是否能够通过网关访问到8001上的服务.
8001项目上/payment/lb接口的代码
//自己手写轮询算法访问测试的请求路劲
@GetMapping(value = "/payment/lb")
public String getPaymentLB(){
return serverPort+"";
}
测试结果
2.路由
(1) 路由组成
- id
#当前路由地址的编号,或者名字 - uri
#当前路由地址,路由服务地址 - predicates
#当前路由地址的匹配断言规则 - filters
#当前路由地址的过滤规则.
(2) 路由的配置方法
1) yml配置(建议使用)
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启路由发现功能
routes:
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://cloud-payment-service #动态路由
predicates: #下面的断言条件,首字母必须大写
- Path=/payment/lb/** #断言,路径相匹配的进行路由
- After=2020-06-19T14:51:51.252+08:00[Asia/Shanghai] #断言 发送的时间要在这个时间之后
#- Cookie=username,gl #断言,携带cookie,username=gl
#- Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.atguigu.com #断言 主机
#- Method=GET #断言 请求方式为GET请求
#- Query=username, \d+ #要有参数名称并且是正整数才能路由
filters:
- AddRequestHeader=X-Request-red, blue
# 第二个路由地址
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #动态路由
predicates: #断言,路径相匹配的进行路由
- Path=/payment/**
- After=2020-06-19T14:51:51.252+08:00[Asia/Shanghai]
- Cookie=username,gl
2) 代码注入
通过代码注入RouteLocator bean的方式,配置路由
@Configuration
public class GateWayConfig {
/**
* 代码配置路由规则bean
*/
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
/**
* gl_baidu_01:路由名
* path:路由路劲
* uri:路由转发的服务或者服务地址
* ...
*/
routes.route("gl_baidu_01", r -> r.path("/tiyu").uri("http://news.baidu.com")).build();
return routes.build();
}
}
(3) 动态路由
-
默认情况,gateway从通过微服务名称,从注册中心获取服务地址,并且可以实现负载均衡算法.
-
uri: lb://cloud-payment-service
#lb:表示使用负载均衡算法,必须使用
#cloud-payment-service:表示调用的服务名称
(4) Predicate(断言)
1) 是什么?
这是用于匹配路由路劲的规则,只有满足predicate(断言)定义的规则才可能被转发到下一级步骤.
2) 常用的predicate属性如下:
predicates: #下面的断言条件,条件的首字母必须大写
- Path=/payment/lb/** #断言,路径相匹配的进行路由
- After=2020-06-19T14:51:51.252+08:00[Asia/Shanghai] #断言 发送的时间要在这个时间之后
- Cookie=username,gl #断言,携带cookie,username=gl
- Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
- Host=**.atguigu.com #断言 主机
- Method=GET #断言 请求方式为GET请求
- Query=username, \d+ #要有参数名称并且是正整数才能路由
(5) Filter(过滤器)
1) 是什么?
filter(过滤器)这是过滤请求,将请求过滤,可以实现权限,日志,熔断等规则.
2) filter的种类
[1]GatewayFilter
#单一的过滤器
作用:这种方式配置的是针对单一路由路劲的过滤器规则.
配置方式:
filters: #过滤器规则
- AddRequestHeader=X-Request-red, blue #将所有的请求头中添加, X-Request-red:blue
- AddRequestParameter=red, blue #将所有的请求中添加参数,red,blue
- name: Hystrix #添加hystrix熔断
args:
name: fallbackcmd
fallbackUri: forward:/incaseoffailureusethis #熔断方法
[2] GlobalFilter
#全局的过滤器,
作用:全局日志记录/统一网关鉴权
配置方式:
/**
*GlobalFilter:全局filter顶级接口.
*Ordered :过滤器级别顶级接口
*/
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered {
/**
* 定义filter(过滤器)
* @param exchange request相关对象
* @param chain 过滤链
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("==================come in MyLogGateWayFilter:" + new Date());
String username = exchange.getRequest().getQueryParams().getFirst("username");
if(username == null){
log.error("===============你没有登陆参数,无权访问");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
/**
* 过滤器的级别
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
3) filter的作用时机
- pre
#请求之前,在业务逻辑之前 - post
#请求之后,在业务逻辑之后