本文首要介绍微服务中网关的效果,并比较了几种干流网关的差异,要点介绍了网关gateway。

微服务网关的总结和实践

一、布景介绍

在微服务架构中,一个体系会被拆封成多个微服务,每个微服务能够单独对外提供服务,假如需求统一的对外服务进口则需求网关来完成,网关记载事务微服务的服务名和地址,每次调用能够正确的映射到正确的实在地址上。总的来说网关的效果有:

  1. 路由转发:外部接口对微服务的调用转发到对应的实在地址上。
  2. 鉴权认证:网关作为体系的进口,能够在进入体系前进行鉴权和认证。
  3. 流控:对于进入的流量进行控制,假如流量过大能够进行限流。
  4. 监控:针对进入的流量进行监控和告警,也能够设置黑白名单等。

常见的网关对比

  1. Zuul 1.0 : Netflix开源的网关,运用Java开发,依据Servlet架构构建,便于二次开发。因为依据Servlet内部推迟严峻,并发场景不友好,一个线程只能处理一次连接恳求。
  2. Zuul 2.0 : 选用Netty完成异步非堵塞编程模型,一个CPU一个线程,能够处理一切的恳求和呼应,恳求呼应的生命周期通过事情和回调进行处理,削减线程数量,开销较小。相比于zuul 1.0,zuul 2.0完成的异步非堵塞的特性,在功能上有较大提升。
  3. Gateway:是springcloud的全新API网关项目,旨在替换zuul的网关服务,依据spring framework5.0+springboot 2.0+webFlux开发,其也完成了异步非堵塞的特性,有较高的功能,其有丰厚的过滤器类型,能够依据自身需求来自界说过滤器。
  4. Nginx : 运用Nginx的反向署理和负载均衡完成对API服务器的负载均衡以及高可用,一般放在整个体系的前端,进行静态资源的负载均衡。
  5. Kong : 依据OpenResty(Nginx + Lua模块)编写的高可用、易扩展的,功能高效且稳定,支撑多个可用插件(限流、鉴权)等,开箱即可用,只支撑HTTP协议,且二次开发扩展难,缺少更易用的管理和装备方法

二、Gateway介绍

1.基本概念

  1. Route(路由) :路由是构建网关的基本模块,它是由ID,方针URI,一系列的断语和过滤器组成,假如断语为true则匹配该路由。
  2. Predicate(断语) :开发人员能够匹配HTTP恳求中的一切内容(例如恳求头或者恳求参数),假如恳求和断语相匹配则进行路由。
  3. Filter(过滤器) :指的是spring框架中GatewayFiletr实例,运用过滤器,能够在恳求被路由前或者后对恳求进行修正。

2.首要流程

微服务网关的总结和实践

流程说明:

  1. Gateway ClientSpring Cloud Gateway 发送恳求。
  2. 恳求首要会被 HttpWebHandlerAdapter 进行提取组装成网关上下文
  3. 然后网关的上下文会传递到 DispatcherHandler ,它负责将恳求分发给 RoutePredicateHandlerMapping
  4. RoutePredicateHandlerMapping 负责路由查找,并依据路由断语判断路由是否可用。
  5. 假如过断语成功,由FilteringWebHandler 创建过滤器链并调用。
  6. 通过特定于恳求的 Fliter 链运转恳求,Filter 被虚线分隔的原因是Filter能够在发送署理恳求之前(pre)和之后(post)运转逻辑。
  7. 执行一切pre过滤器逻辑。然后进行署理恳求。发出署理恳求后,将运转“post”过滤器逻辑。
  8. 处理完毕之后将 Response 返回到 Gateway 客户端。

3.过滤器

todo

4.核心思维

用户发送的恳求到达Gateway后,依据恳求的匹配条件来匹配真正地址,这个匹配条件能够是URL也能够是服务名,这个匹配条件便是断语(Predicate),匹配后的恳求会通过一系列的过滤,这个便是过滤器起效果的时分。

三、代码实践

利用Gateway作为微服务网关,需求注册中心进行服务注册,在本次实践中,我们选用nacos作为注册中心。

微服务网关的总结和实践

1.装备pom文件

<!--Gateway网关-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <!-- Maven整个生命周期内扫除内置容器,扫除内置容器导出成war包能够让外部容器运转spring-boot项目-->
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
    </exclusion>
  </exclusions>
</dependency><dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency><!--nacos服务发现依靠-->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

pom文件首要引进spring-cloud-starter-gateway网关和spring-cloud-starter-loadbalancer负债均衡,其间可能存在以下问题:

(1)由于spring-cloud-starter-gateway选用的是呼应式的WebFlux web容器,这和spring-boot-starter-web默认的web容器会冲突,所以需求扫除。一般的报错信息如下:

Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.

(2)引进负债均衡spring-cloud-starter-loadbalancer需求配扫除nacos中的spring-cloud-starter-netflix-ribbon,这两者会包冲突,到时无法运用服务名来进行路由转发。

2.装备文件

server:
  port: 9010
spring:
  application:
   name: test-gateway
  cloud:
   nacos:
    discovery:
     server-addr: x.x.x.x:8848
     enabled: true
   gateway:
    routes: # 网关路由装备
     - id: my-test # 路由id,自界说,只要仅有即可
      # uri: http://127.0.0.1:8081 # 路由的方针地址 http便是固定地址
      uri: lb://my-test # 路由的方针地址 lb便是负载均衡,后面跟服务名称
      predicates: # 路由断语,也便是判断恳求是否符合路由规则的条件
       - Path=/my-test/** # 这个是按照路径匹配,只要以/user/最初就符合要求

装备文件中首要在 spring.gateway.gateway中,其间{spring.gateway.gateway} 中,其间 {routes.uri} 表示需求转发到的URL或者服务名。

3.过滤器

@Slf4j
@Component
public class MyFilter implements Ordered, GlobalFilter {
  /**
   * @param exchange 能够拿到对应的request和response
   * @param chain 过滤器链
   * @return 是否放行
   */
  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    String name = exchange.getRequest().getQueryParams().get("name").get(0);
    log.info("用户:{} 开始进入体系", name);
    if (!StringUtils.isEmpty(name)) {
      if (name.equals("noName")) {
        log.info("用户没有访问权限");
        exchange.getResponse().setStatusCode(HttpStatus.PROXY_AUTHENTICATION_REQUIRED);
        return exchange.getResponse().setComplete();
       }
     }
    return chain.filter(exchange);
   }
​
  /**
   * 设定过滤器的优先级,值越小则优先级越高
   * @return
   */
  @Override
  public int getOrder() {
    return 0;
   }
}

假如需求在Gateway中完成过滤器,能够完成GlobalFilter接口,以上Filter是用来进行鉴权的,假如进入网关的恳求没有权限就会被拦截。


TODO

  • 把过滤器的类别和效果写的更详细。

参考资料

  1. 这篇SpringCloud GateWay 详解,你用的到:/post/710791…
  2. Spring Cloud Gateway:docs.spring.io/spring-clou… (官方文档)
  3. 14.服务网关Zuul和Gateway:www.cnblogs.com/wmd-l/p/163…
  4. Spring Cloud Gateway过滤器装备:/post/713874…