Gateway使用入门

一、什么是Gateway

如果没有网关,我们在开发和治理微服务架构的系统时,为了完成一个业务逻辑的功能,不得不自己调用多个服务的主机和端口,会显得繁杂,容易出错。因此微服务网关项目应运而生。

网关为微服务架构的系统提供简单、有效且统一的API路由管理,主要功能包含协议适配、协议转发、安全策略、防刷、流量控制、监控日志等。

二、入门案例

start.sprinig.io上一键下载包含了Gateway组件的项目即可。

一键生成gateway项目

然后在启动类上配置路由信息:

@SpringBootApplication
public class GatewayDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayDemoApplication.class, args);
    }

    // 配置路由信息
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
        return builder.routes()
                .route("blog_route",r -> r.path("/zhangxun")
                        .uri("https://blog.csdn.net"))
                .route("search_route", r -> r.path("/jansen")
                        .uri("https://www.zhihu.com/"))
                .build();
    }
}

以上配置路由信息主要定义了如下三个要素:

  • 路由ID,此处就是blog_route,可以自定义;
  • 路由断言,此处就是/zhangxun,凡是符合这个路由断言的访问路径都会被通过;
  • 路由目标,此时就是https://blog.csdn.net

当我们访问Gateway项目时,如果访问路径上包含"/zhangxun",网关就会将请求转发到"https://blog.csdn.net"上,我们启动如上的项目,然后访问“http://localhost:8080/zhangxun”就会看到,最终访问到的是CSDN的网址。

在实际开发中,一般都会采用配置文件的方式,而不是如上代码配置的方式。因为配置文件内容可以托管到统一配置中心,给与服务治理更大的灵活性。如下是等价的配置文件形式:

spring:
  application:
    name: gateway-demo-service
  cloud:
    gateway:
      routes:
        - id: blog_route
          # uri: lb://注册中心的服务名称
          uri: https://blog.csdn.net
          predicates:
            - Path=/zhangxun
        - id: search_route
          # uri: lb://注册中心的服务名称
          uri: https://www.zhihu.com/
          predicates:
            - Path=/jansen

三、路由断言

Gateway包含了很多的路由断言工厂,当请求达到Gateway的时候,配置好的的路由断言工厂就会根据配置的路由规则,对请求进行断言匹配,只有匹配成功才会进入到下一步的处理中,否则断言失败就会直接返回错误信息。

如下是Gateway支持的一些断言工厂,分别在不同的场景下可以配置使用:

gateway路由断言工厂

3.1 Datetime

假设我们设定一个标准时间,这个标准时间是某热销产品的开卖时间,只有当达到这个开卖时间时,用户购买请求才可以被转发到购买的服务上。此时我们就需要用到Datetime分类中的AfterRoutePredicateFactory。

    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder){
        // 设置一小时前的时间为标准时间
        ZonedDateTime standardTime = LocalDateTime.now().minusHours(1).atZone(ZoneId.systemDefault());
        return builder.routes()
                .route("after_route", r -> r.after(standardTime)
                        .uri("https://www.zhihu.com/"))
                .build();
    }

假设我们的热销产品有一个截止买卖时间,超过这个时间就不能再购买,那么可以使用Datetime分类的BeforeRoutePredicateFactory。

    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder){
        // 设置一小时后的时间为标准时间
        ZonedDateTime standardTime = LocalDateTime.now().plusHours(1).atZone(ZoneId.systemDefault());
        return builder.routes()
                .route("after_route", r -> r.before(standardTime)
                        .uri("https://www.zhihu.com/"))
                .build();
    }

同样的,我们还可以设置一个时间段,在这个时间段内的请求才是合法的,使用Datetime分类的BetweenRoutePredicateFactory。

    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder){
        // 设置一小时前的时间为开始时间
        ZonedDateTime startTime = LocalDateTime.now().minusHours(1).atZone(ZoneId.systemDefault());
        // 设置一小时后的时间为截止时间
        ZonedDateTime endTime = LocalDateTime.now().plusHours(1).atZone(ZoneId.systemDefault());
        return builder.routes()
                .route("after_route", r -> r.between(startTime, endTime)
                        .uri("https://www.zhihu.com/"))
                .build();
    }

3.2 Cookie

我们还可以设定对请求的cookie内容进行断言:

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("cookie_route", r -> r.cookie("name", "zhangsan")
                        .uri("https://www.zhihu.com/"))
                .build();
    }

在测试的时候,我们使用postman进行,首先输入期望的cookie内容进行测试:

CookiePredicate

然后输入非期望的cookie内容进行测试:

CookiePredicate2

3.3 Weight

基于路由权重的断言,指定路由分组和权重值即可使用:

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("weight_route_1", r -> r.weight("w1", 5)
                        .uri("https://www.zhihu.com/"))
                .route("weight_route_2", r -> r.weight("w1", 95)
                        .uri("https://blog.csdn.net"))
                .build();
    }

这里配置了两个路由,它们属于同一个路由分组w1,但是知乎网站的转发权重为5%,csdn网站的转发权重为95%,那么我们的请求将有95%概率会被转发到csdn去。

3.4 Header

Header中的某个属性值必须符合预期才会通过;

3.5 Host

请求来源域名必须是预期的才会通过;

3.6 Method

请求的方法必须是预期的才会通过;

3.7 Path

已经在第二节入门案例中演示过,符合预期路径才会通过;

3.8 Query

对请求路径中的参数内容进行断言;

3.9 RemoteAddr

基本同Host,只不过此时应该写IP地址或者网段;

四、内置Filter

过滤器的作用就是可以按照应用场景修改请求和返回的内容,总的来说,Filter可以分为如下七类,但是不限于以下这些Filter:

gateway过滤器工厂

4.1 Header

对于匹配上的请求加上header内容:

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("add_request_header_route", r -> r.path("/zhangxun")
                        .filters(f -> f.addRequestHeader("name", "zhangsan"))
                        .uri("https://www.zhihu.com/"))
                .build();
    }

4.2 Parameter

会在请求地址后面增加上请求参数:

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("add_request_parameter_route", r -> r.path("/zhangxun")
                        .filters(f -> f.addRequestParameter("name", "zhangsan"))
                        .uri("https://www.zhihu.com/"))
                .build();
    }

4.3 Path

StripPrefixGatewayFitlerFactory是用于去除请求前缀,而PrefixPathGatewayFilterFactory是用于增加请求前缀。

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("/zhangxun/jansen")
                        .filters(f -> f.stripPrefix(2))
                        .uri("https://www.zhihu.com/"))
                .build();
    }

如上前缀过滤器在我们访问http://localhost:8080/zhangxun/jansen的时候,会把路径前缀的前两个去掉再进行转发https://www.zhihu.com/

4.4 Status

4.5 Redirect

4.6 Hystrix

4.7 RateLimeter

部分实例暂未涉及,后续再补充。

你可能感兴趣的:(Gateway使用入门)