企业管理系统定制开发微服务之服务网关Gateway

P65~P73

企业管理系统定制开发以上次博客的eureka企业管理系统定制开发集群作为注册中心来演示。
企业管理系统定制开发由于已经称为过去式且Zuul2前景未知,企业管理系统定制开发因此使用新一代服务网关GateWay企业管理系统定制开发已经成为主流。

1. GateWay

1.1 概述

Gateway是在Spring企业管理系统定制开发生态系统之上构建的网关服务,基于Spring5,SpringBoot2和Project Reactor等技术。
Gateway企业管理系统定制开发旨在提供一种简单而有企业管理系统定制开发效的方式来对API进行路由,目标是代替Zuul。为了提升的性能,Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能Reactor模式通信框架Netty。
Gateway的目标提供统一路由方式且基于Filter链的方式提供了网关基本的功能,安全、监控/指标、限流等。
Gateway是基于异步非阻塞模型上开发的,性能比较高。

  • 功能:

    1. 反向代理;
    2. 鉴权;
    3. 流量控制;
    4. 熔断;
    5. 日志监控。
  • 处于项目位置

  • 特性:

    1. 动态路由:能够匹配任何请求属性;
    2. 可以对路由指定Predicate(断言)和Filter(过滤器);
    3. 集成Hystrix的断路器功能;
    4. 集成Spring Cloud的服务发现功能;
    5. 易于编写PredicateFilter
    6. 请求限流功能;
    7. 支持路径重写。
  • zuul模型:Zuul是基于servlet之上的一个阻塞式处理模型,当请求进入Servlet Container时,会为当前请求绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发,线程数就会上升,而线程资源的代价是昂贵的,严重影响请求的处理时间,在一些简单的业务场景下,不希望为每个请求分配一个线程,只需要一个或者几个线程就能应对极大的并发请求,这种业务场景下servlet模型没有优势。

  • gateway模型:在servlet3.1之后有了异步非阻塞的支持,而WebFlux是一个典型的非阻塞异步的,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如netty,undertow及支持servlet3.1的容器上。非阻塞式+函数式编程。

1.2 核心概念

  • Router(路由):是构建网关的基本模块,由ID和目标URI和一系列的断言和过滤器组成,如果断言为true则匹配该路由。
  • Predicate(断言):可以匹配Http请求中的所有内容,如果请求与断言相匹配则进行路由。
  • Filter(过滤):使用过滤器,可以在路由被请求前或者请求后对请求进行修改。

根据web请求和匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。即根据predicate的匹配条件,通过过滤器,再加上uri来实现具体的路由。

1.3 工作流程

  1. 客户端向Spring Cloud Gateway发出请求;
  2. 然后再Gateway Handler Mapping中找到与请求相匹配的路由;
  3. 将其发送到Gateway Web Handler;
  4. Handler再通过指定的过滤器链来将请求发送到实际业务执行逻辑中,返回。
  • 请求前过滤器(pre):参数校验、权限校验、流量监控、日志输出、协议转换。
  • 请求后过滤器(post):响应内容和响应头修改,日志输出,流量监控等。

1.4 项目搭建

  • 新建moudle:cloud-gateway-gateway9527

  • 依赖:

        <dependencies>        <dependency>            <groupId>org.example</groupId>            <artifactId>cloud-api-commons</artifactId>            <version>1.0-SNAPSHOT</version>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-gateway</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-devtools</artifactId>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>            </dependencies>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 配置文件:

    server:  port: 9527spring:  application:    name: cloud-gatewayeureka:  instance:    hostname: cloud-gateway-service  client:    service-url:      register-with-eureka: true      fetch-registry: true      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 主启动类:

    @EnableEurekaClient@SpringBootApplicationpublic class GatewayMain9527 {    public static void main(String[] args) {        SpringApplication.run(GatewayMain9527.class,args);    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

1.5 路由配置详情

1.5.1 yml配置文件

  • 配置路由,避免暴露8001端口,将8001端口路由到当前网关微服务:
spring:  application:    name: cloud-gateway  cloud:    gateway:      discovery:        locator:          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由      routes: #  配置路由        - id: payment_routh  #路由的ID,没有固定规则但要求唯一,建议配合服务名          uri: http://localhost:8001  #匹配后提供服务的路由地址          predicates:            - Path=/payment/**   # 断言,路径相匹配的进行路由        - id: payment_routh2             uri: http://localhost:8001                  predicates:            - Path=/payment/lb/**         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 访问9527测试:

1.5.2 代码中注入RouteLocator的Bean

  • 模拟案例:使用网关9527访问外网:

  • 新建配置类:

    @Configurationpublic class GatewayConfig {    @Bean    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){        // 路由集合:类似于配置文件的 routes:        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();        // 指定路由唯一id 和  映射地址path  和 实际地址uri        routes.route("path_route_bli",                r -> r.path("/weixin_44289860")                        .uri("http://blog.csdn.net/")).build();        return routes.build();    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 访问测试:输入http://localhost:9527/weixin_44289860,直接跳转到我的个人主页。

1.6 动态路由

按照先前针对路由的配置,无法实现负载均衡,仅仅只能访问一个端口。

这样就需要针对网关再来实现负载均衡的功能,比较繁琐;
可以通过微服务名来实现动态路由

  • 修改配置文件:

    server:  port: 9527spring:  application:    name: cloud-gateway  cloud:    gateway:      discovery:        locator:          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由      routes:   #         配置路由        - id: payment_routh   #路由的ID,没有固定规则但要求唯一,建议配合服务名#          uri: http://localhost:8001          #匹配后提供服务的路由地址          uri: lb://cloud-payment-service   #匹配后根据微服务名称提供服务的路由地址          predicates:            - Path=/payment/**         # 断言,路径相匹配的进行路由eureka:  instance:    hostname: cloud-gateway-service  client:    service-url:      register-with-eureka: true      fetch-registry: true      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 请求测试:可以看到实现了负载均衡。

1.7 Predicate(断言)

  • 断言分类:
  1. After:在某时间之后才能访问;
  2. Before:在某时间之前才能访问;
  3. Between:在某时间之间才能访问;
  4. Cookie:验证Cookie中保存的信息
  5. Header:检查Header中是否包含了响应的属性
  6. Method:请求类型;
  7. Path:即指定当前网关的路径与实际路径的映射。
  8. Query:判断QueryPrameters列表是否存在指定值;
spring:  application:    name: cloud-gateway  cloud:    gateway:      discovery:        locator:          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由      routes:   #         配置路由        - id: payment_routh   #路由的ID,没有固定规则但要求唯一,建议配合服务名#          uri: http://localhost:8001          #匹配后提供服务的路由地址          uri: lb://cloud-payment-service   #匹配后根据微服务名称提供服务的路由地址          predicates:            - Path=/payment/**         # 断言,路径相匹配的进行路由            - After=2022-06-12T20:59:34.102+08:00[Asia/Shanghai]            - Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]            - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] ,  2020-03-08T10:59:34.102+08:00[Asia/Shanghai]            - Cookie=username,zzyy   # 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

1.8 Filter(过滤器)

允许进入Http请求和返回Http响应之间来进行一系列操作(修改)。

  • 生命周期

    1. pre:请求前过滤;
    2. post:请求后过滤。
  • 种类:

    1. GatewayFilter:针对某个请求的过滤器;
    2. GlobalFitler:全局过滤器。
  • 配置单一过滤器:

spring:  application:    name: cloud-gateway  cloud:    gateway:      discovery:        locator:          enabled: true   #开启从注册中心动态创建路由的功能,利用微服务名进行路由      routes:   #         配置路由        - id: payment_routh   #路由的ID,没有固定规则但要求唯一,建议配合服务名#          uri: http://localhost:8001          #匹配后提供服务的路由地址          uri: lb://cloud-payment-service   #匹配后根据微服务名称提供服务的路由地址          predicates: # 配置断言            - Path=/payment/**         # 断言,路径相匹配的进行路由            - After=2022-06-12T20:59:34.102+08:00[Asia/Shanghai]            - Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]            - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] ,  2020-03-08T10:59:34.102+08:00[Asia/Shanghai]            - Cookie=username,zzyy   #          filters: # 配置过滤器            - AddRequestHeader=test,aa #在请求头上添加:key:test,value:aa
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 自定义全局过滤器:继承implements GlobalFilter, Ordered接口。

    @Slf4j@Componentpublic class MyLogGatewayFilter implements GlobalFilter, Ordered {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        log.info("进入自定义全局过滤器:MyLogGatewayFilter");        // 获取请求参数        String uname = exchange.getRequest().getQueryParams().getFirst("uname");        if (Objects.isNull(uname)){            log.error("非法用户");            // 返回响应信息            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);            // 退出            return exchange.getResponse().setComplete();        }        // 携带exchange放行去下一个过滤器        return chain.filter(exchange);    }    /**     * 指定加载过滤器的顺序,数字越小,优先级越高。     * @return     */    @Override    public int getOrder() {        return 0;    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发