95-java-springcloud(08)-网关-gateway

    技术2022-07-20  78

    gateway

    网关是什么,网关是一切外部访问程序的入口,他控制这这个服务架构的出入,鉴权,代理,流控,监控等.

    一.简介

    1.官网

    官网地址: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#gateway-starter

    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)第一步,Eureka2)第二步,启动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(断言)

    参考官网: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#gateway-request-predicates-factories

    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(过滤器)

    参考官网: https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#gateway-request-predicates-factories

    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 #请求之后,在业务逻辑之后
    Processed: 0.008, SQL: 9