关于微服务:微服务网关Gateway实践总结

9次阅读

共计 4460 个字符,预计需要花费 12 分钟才能阅读完成。

有多少申请,被网关截胡;

一、Gateway 简介

微服务架构中,网关服务通常提供动静路由,以及流量管制与申请辨认等外围能力,在之前的篇幅中有说过 Zuul 组件的应用流程,然而当下 Gateway 组件是更惯例的抉择,上面就围绕 Gateway 的实际做详细分析;

从架构模式上看,网关不论采纳什么技术组件,都是在客户端与业务服务两头提供一层拦挡与校验的能力,然而相比拟 Zuul 来说,Gateway 提供了更弱小的性能和卓越的性能;

基于实际的场景来看,在性能上网关更偏重申请方的非法校验,流量管控,以及 IP 级别的拦挡,从架构层面看,通常须要提供灵便的路由机制,比方灰度,负载平衡的策略等,并基于音讯机制,进行零碎级的平安告诉等;

上面围绕客户端、网关层、门面服务的三个节点,剖析 Gateway 的应用细节,即客户端向网关发出请求,通过网关路由到门面服务解决;

二、动静路由

1、根底概念

路由:作为网关中最外围的能力,从源码构造上看,包含 ID、申请 URI、断言汇合、过滤汇合等组成;

public class RouteDefinition {
    private String id;
    private URI uri;
    private List<PredicateDefinition> predicates = new ArrayList<>();
    private List<FilterDefinition> filters = new ArrayList<>();}

断言 + 过滤:通常在断言中定义申请的匹配规定,在过滤中定义申请的解决动作,构造上看都是名称加参数汇合,并且反对快捷的形式配置;

public class PredicateDefinition {
    private String name;
    private Map<String, String> args = new LinkedHashMap<>();}

public class FilterDefinition {
    private String name;
    private Map<String, String> args = new LinkedHashMap<>();}

2、配置路由

以配置的形式,增加 facade 服务路由,以门路匹配的形式,如果申请门路谬误则断言失败,StripPrefix 设置为 1,即在过滤中去掉第一个 /facade 参数;

spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        - id: facade
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/facade/**
          filters:
            - StripPrefix=1

执行原理如下:

这里是以配置文件的形式,设置 facade 服务的路由策略,其中指定了门路形式,在 Gateway 文档中提供了多种路由样例,比方:Header、Cookie、Method、Query、Host 等断言形式;

3、编码方式

基于编码的形式治理路由策略,在 Gateway 文档同样提供了多种参考样例,如果路由服务少并且固定,配置的形式能够解决,如果路由服务很多,并且须要动静增加,那基于库表形式更适宜;

@Configuration
public class GateConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes()
                .route("facade",r -> r.path("/facade/**").filters(f -> f.stripPrefix(1))
                .uri("http://127.0.0.1:8082")).build();}
}

4、库表加载

在惯例的利用中,从库表中读取路由策略是比拟常见的形式,定义路由工厂类并实现 RouteDefinitionRepository 接口,波及加载、增加、删除三个外围办法,而后基于服务类从库中读取数据转换为 RouteDefinition 对象即可;

@Component
public class DefRouteFactory implements RouteDefinitionRepository {
    @Resource
    private ConfigRouteService routeService ;
    // 加载
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {return Flux.fromIterable(routeService.getRouteDefinitions());
    }
    // 增加
    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {return route.flatMap(routeDefinition -> { routeService.saveRouter(routeDefinition);
            return Mono.empty();});
    }
    // 删除
    @Override
    public Mono<Void> delete(Mono<String> idMono) {return idMono.flatMap(routeId -> { routeService.removeRouter(routeId);
            return Mono.empty();});
    }
}

在源码仓库中采纳的就是库表治理的形式,代码逻辑的更多细节能够移步 Git 参考,此处不再过多粘贴;

三、自定义路由策略

  • 自定义断言 ,继承AbstractRoutePredicateFactory 类,留神命名以 RoutePredicateFactory 结尾,重写 apply 办法,即可执行特定的匹配规定;
@Component
public class DefCheckRoutePredicateFactory extends AbstractRoutePredicateFactory<DefCheckRoutePredicateFactory.Config> {public DefCheckRoutePredicateFactory() {super(Config.class);
    }
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {return new GatewayPredicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {log.info("DefCheckRoutePredicateFactory:" + config.getName());
                return StrUtil.equals("butte",config.getName());
            }
        };
    }
    @Data
    public static class Config {private String name;}
    @Override
    public List<String> shortcutFieldOrder() { return Collections.singletonList("name"); }
}
  • 自定义过滤 ,继承AbstractNameValueGatewayFilterFactory 类,留神命名以 GatewayFilterFactory 结尾,重写 apply 办法,即可执行特定的过滤规定;
@Component
public class DefHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    @Override
    public GatewayFilter apply(AbstractNameValueGatewayFilterFactory.NameValueConfig config) {return (exchange, chain) -> {log.info("DefHeaderGatewayFilterFactory:"+ config.getName() + "-" + config.getValue());
            return chain.filter(exchange);
        };
    }
}
  • 配置加载形式,此处断言与过滤即快捷的配置形式,所以在命名上要恪守 Gateway 的约定;
spring:
  cloud:
    gateway:
      routes:
        - id: facade
          uri: http://127.0.0.1:8082
          predicates:
            - Path=/facade/**
            - DefCheck=butte
          filters:
            - StripPrefix=1
            - DefHeader=cicada,smile

通常来说,在利用级的零碎中都须要进行断言和过滤的策略自定义,以提供业务或者架构层面的撑持,实现更加粗疏的规定校验,尤其在雷同服务多版本并行时,能够更好的治理路由策略,从而防止分支之间的影响;

四、全局过滤器

在路由中采纳的过滤是 GatewayFilter,理论 Gateway 中还提供了GlobalFilter 全局过滤器,尽管从构造上看十分相似,然而其职责是有本质区别的;

  • 全局过滤器 1:打印申请 ID
@Component
@Order(1)
public class DefOneGlobalFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("request-id:{}",exchange.getRequest().getId()) ;
        return chain.filter(exchange);
    }
}
  • 全局过滤器 2:打印申请 URI
@Component
@Order(2)
public class DefTwoGlobalFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("request-uri:{}",exchange.getRequest().getURI()) ;
        return chain.filter(exchange);
    }
}

Gateway 网关作为微服务架构零碎中最先接管申请的一层,能够定义许多策略来爱护零碎的平安,比方高并发接口的限流,第三方受权验证,受到歹意攻打时的 IP 拦挡等等,尽量将非法申请在网关中拦挡掉,从而保证系统的平安与稳固。

五、参考源码

利用仓库:https://gitee.com/cicadasmile/butte-flyer-parent

组件封装:https://gitee.com/cicadasmile/butte-frame-parent
正文完
 0