gateway

Cloud 全家桶中有一个非常重要得组件就是网关。 在1.x 版本 我们都采用得zuul网关。

 gateway 是 zuul1.x 替代。

 Spring cloud Gateway 使用得webflux 中得reactor-netty 响应编程组件。 底层使用得netty框架。

作用:反向代理       鉴权       流量控制       熔断      日志监控

 zuul 1.x 基于servlet 2.5 阻塞架构。 不支持任何长连接 (websocket) zuul设计和nginx 有点像。每次i/o操作都是从工作线程中选择一个执行。 请求线程被阻塞工作线程完成。zuul2. 理念先进。 netty非阻塞和支持长连接。 zuul2. 比 zuul1 快了1.6倍。。

gateway是异步非阻塞,支持长连接websocket,(长链接就是服务端主动给客户端推送消息)。

 

zuul1.x模型采用tomcat容器,使用servlet io处理器,每个请求会绑定一个线程,一旦高并发线程数太多卡。在传统的web框架中 spring mvc struts2 都是基于servlet容器基础之上运行。

gateway用webflux,servlet 3.1 版本之后 才用异步非阻塞(AIO)的支持。 而webflux 是一个经典的非阻塞异步的框架。

一。路由配置

1.新建子项目,引pom.xml

<dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.etc.cloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
        </dependency>
        <!--一般基础配置类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>

 

2.新建application.yml

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
#          uri: lb://cloud-payment-service #匹配后提供服务的路由地址,lb是@loadbanlence负载均衡意思,可以负载均衡这个服务
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由


        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
             - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

这是在yml文件中配置相关路由信息

 

 3.还一种方法在类中配置路由

@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator constom(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("path_route", r -> r.path("/guoji").uri("https://news.baidu.com/guoji"));
        return routes.build();

    }

    @Bean
    public RouteLocator constom2(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("path_route", r -> r.path("/guonei").uri("https://news.baidu.com/guonei"));
        return routes.build();

    }

    @Bean
    public RouteLocator constom3(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("path_route", r -> r.path("/mil").uri("https://news.baidu.com/mil"));
        return routes.build();
    }
}

这里配了三个路由,访问http://localhost:9527/guoji  就可以去配好的地址

 

4.新建main方法

@EnableEurekaClient
@SpringBootApplication
@Slf4j
public class GatewayMain9527 {
    public static void main(String[] args) {
        SpringApplication.run( GatewayMain9527.class,args);
        log.info("****************GatewayMain9527 启动 ************ ");
    }

}

 二。过滤器

spring cloud gateway 内置了多种过滤器。 他们都由 gatewayfilter工程类产生

GlobalFilter 全局过滤器             GatewayFileter 将应用到单个路由或者一个分组的路由上

 

自定义一个GlobalFilter:

@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("come in global filter:{}" , new Date());
        ServerHttpRequest request = exchange.getRequest();
        String uname = request.getQueryParams().getFirst("uname");
        if (StringUtils.isEmpty(uname)){
            log.error("用户为null 非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
    /**Ordered 是顺序
     * 过滤器加载的顺序越小。 优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

加上这个类之后,任何请求都要携带uname才行,他是全局过滤

 

三。断言器

断言的类型分为 9 类型:

After - 在设置时间之后才能路由

Before - 在设置时间之前才能路由

Between - 在设置时间区间才能路由

Cookie - 路由断言工程会取2个参数 cookie 名称对应的key value

Header - 根据header配置 。 如果携带header 和断言工场一致就匹配成功否则就失败

Host - 对请求的host地址进行断言。

Method - 对请求的方法进行断言配置。 如果成功就路由 比如过 post get

Query - 对请求的参数进行断言 。 如果成功就路由 比如说 localhost:80/user/get?id=1

RemoteAddr - 对网段字符或者ip进行断言。 成功就路由

 

YML里配置断言:

predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由
            - After=2020-08-24T15:08:59.777+08:00[Asia/Shanghai]

时间可以用ZonedDateTime now = ZonedDateTime.now();获取

eq:

- Before=2020-08-26T15:08:59.777+08:00[Asia/Shanghai]
- Between=2020-08-24T15:08:59.777+08:00[Asia/Shanghai],2020-08-24T15:22:59.777+08:00[Asia/Shanghai]
- Method=GET
- Cookie=username, wgslcuky
- Host=**.somehost.org,**.anotherhost.org,{sub}.myhost.org
- RemoteAddr=192.168.1.1/24
#如果请求的客户端的ip地址是192.168.1.1 到192.168.1.24 之间的范围都是返回true

 

posted @ 2020-08-24 14:19  neona  阅读(537)  评论(0编辑  收藏  举报