`
wx1568905209
  • 浏览: 25156 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析

 
阅读更多

API 网关

API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:

  1. 客户端会多次请求不同的微服务,增加了客户端的复杂性。
  2. 存在跨域请求,在一定场景下处理相对复杂。
  3. 认证复杂,每个服务都需要独立认证。
  4. 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
  5. 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。

以上这些问题可以借助 API 网关解决。API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:

使用 API 网关后的优点如下:

  • 易于监控。可以在网关收集监控数据并将其推送到外部系统进行分析。
  • 易于认证。可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
  • 减少了客户端与各个微服务之间的交互次数。

API 网关选型

业界的情况:

我前面的文章<Netflix网关zuul(1.x和2.x)全解析>已经介绍了zuul1 和zuul2,现在就尝试从实例入手介绍一下spring cloud gateway

首先我们一步步实现一个最简单的网关例子

步骤1:在http://start.spring.io网站上创建一个spring-cloud-gateway-example项目,依赖spring-cloud-gateway,如下图所示

此时生产了一个spring-cloud-gateway-example的空项目包,pom.xml文件如下

复制代码

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-cloud-gateway-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-gateway-example</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

复制代码

2.创建一个Route实例的配置类GatewayRoutes

复制代码

package com.example.springcloudgatewayexample;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayRoutes {
    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(r ->
                        r.path("/java/**")
                                .filters(
                                        f -> f.stripPrefix(1)
                                )
                                .uri("http://localhost:8090/helloWorld")
                )
                .build();
    }
}

复制代码

当然,也可以不适用配置类,使用配置文件,如下图所示

复制代码

spring:
  cloud:
    gateway:
      routes: 
        - predicates:
            - Path=/java/**
          filters:
            - StripPrefix=1
          uri: "http://localhost:8090/helloWorld"

复制代码

不过,为了调试方便,我们使用配置类方式。

此时项目已经完成,足够简单吧。

3.启动此项目

  >>因api网关需要转发到一个服务上,本文为http://localhost:8090/helloWorld,那需要先启动我上文<spring boot整合spring5-webflux从0开始的实战及源码解析>,你也可以创建一个普通的web项目,启动端口设置为8090,然后启动。

复制代码

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)

2019-02-21 09:29:07.450 INFO 11704 --- [ main] c.e.demo.Spring5WebfluxApplication : Starting Spring5WebfluxApplication on DESKTOP-405G2C8 with PID 11704 (E:\workspaceForCloud\spring5-webflux\target\classes started by dell in E:\workspaceForCloud\spring5-webflux)
2019-02-21 09:29:07.455 INFO 11704 --- [ main] c.e.demo.Spring5WebfluxApplication : No active profile set, falling back to default profiles: default
2019-02-21 09:29:09.409 INFO 11704 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8090
2019-02-21 09:29:09.413 INFO 11704 --- [ main] c.e.demo.Spring5WebfluxApplication : Started Spring5WebfluxApplication in 2.304 seconds (JVM running for 7.311)

复制代码

 >>以spring boot方式启动spring-cloud-gateway-example项目,日志如下

复制代码

2019-02-21 10:34:33.435  INFO 8580 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1e059320] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.3.RELEASE)

2019-02-21 10:34:33.767  INFO 8580 --- [           main] e.s.SpringCloudGatewayExampleApplication : No active profile set, falling back to default profiles: default
2019-02-21 10:34:34.219  INFO 8580 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=d98183ec-3e46-38ba-ba4c-e976a1017dce
2019-02-21 10:34:34.243  INFO 8580 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1e059320] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-02-21 10:34:44.367  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [After]
2019-02-21 10:34:44.367  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Before]
2019-02-21 10:34:44.367  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Between]
2019-02-21 10:34:44.367  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Cookie]
2019-02-21 10:34:44.367  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Header]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Host]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Method]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Path]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Query]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [RemoteAddr]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Weight]
2019-02-21 10:34:44.368  INFO 8580 --- [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [CloudFoundryRouteService]
2019-02-21 10:34:44.920  INFO 8580 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2019-02-21 10:34:44.923  INFO 8580 --- [           main] e.s.SpringCloudGatewayExampleApplication : Started SpringCloudGatewayExampleApplication in 12.329 seconds (JVM running for 13.126)

复制代码

4.测试,浏览器访问http://localhost:8080/java/helloWorld

返回hello world !

5.从上面的代码和配置及实例中,我们可以看出spring cloud gateway处理request请求的流程如下所示:

即在最前端,启动一个netty server(默认端口为8080)接受请求,然后通过Routes(每个Route由Predicate(等同于HandlerMapping)和Filter(等同于HandlerAdapter))处理后通过Netty Client发给响应的微服务。

那么在gateway本身最重要的应该是Route(Netty Server和Client已经封装好了),它由RouteLocatorBuilder构建,内部包含Predicate和Filter,

复制代码

private Route(String id, URI uri, int order, AsyncPredicate<ServerWebExchange> predicate, List<GatewayFilter> gatewayFilters) {
        this.id = id;
        this.uri = uri;
        this.order = order;
        this.predicate = predicate;
        this.gatewayFilters = gatewayFilters;
    }

复制代码

那么我们就来探讨一下这两个组件吧

5.1.Predicate

Predicte由PredicateSpec来构建,主要实现有:

以path为例

复制代码

/**
     * A predicate that checks if the path of the request matches the given pattern
     * @param patterns the pattern to check the path against.
     *                The pattern is a {@link org.springframework.util.PathMatcher} pattern
     * @return a {@link BooleanSpec} to be used to add logical operators
     */
    public BooleanSpec path(String... patterns) {
        return asyncPredicate(getBean(PathRoutePredicateFactory.class)
                .applyAsync(c -> c.setPatterns(Arrays.asList(patterns))));
    }

复制代码

PathRoutePredicateFactory中执行

复制代码

@Override
    public Predicate<ServerWebExchange> apply(Config config) {
        final ArrayList<PathPattern> pathPatterns = new ArrayList<>();
        synchronized (this.pathPatternParser) {
            pathPatternParser.setMatchOptionalTrailingSeparator(
                    config.isMatchOptionalTrailingSeparator());
            config.getPatterns().forEach(pattern -> {
                PathPattern pathPattern = this.pathPatternParser.parse(pattern);
                pathPatterns.add(pathPattern);
            });
        }
        return exchange -> {
            PathContainer path = parsePath(exchange.getRequest().getURI().getPath());

            Optional<PathPattern> optionalPathPattern = pathPatterns.stream()
                    .filter(pattern -> pattern.matches(path)).findFirst();

            if (optionalPathPattern.isPresent()) {
                PathPattern pathPattern = optionalPathPattern.get();
                traceMatch("Pattern", pathPattern.getPatternString(), path, true);
                PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path);
                putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
                return true;
            }
            else {
                traceMatch("Pattern", config.getPatterns(), path, false);
                return false;
            }
        };
    }

复制代码

5.2.Filter

Filter分两种,一种GatewayFilter,一种GlobalFilter

5.2.1 GatewayFilter

GatewayFilter由GatewayFilterSpec构建,GatewayFilter的构建器

 

5.2.2 GlobalFilter

5.3 GlobalFilter和GatewayFilter的联系

FilteringWebHandler.GatewayFilterAdapter代理了GlobalFilter

6.总结

  本文从一个spring-cloud-gateway实例入手,深入浅出的介绍了spring-cloud-gateway的组件,并从源码角度给出了实现的原理。

   spring-cloud-gateway在最前端,启动一个netty server(默认端口为8080)接受请求,然后通过Routes(每个Route由Predicate(等同于HandlerMapping)和Filter(等同于HandlerAdapter))处理后通过Netty Client发给响应的微服务。

 Predicate和Filter的各个实现定义了spring-cloud-gateway拥有的功能。

参考资料:

【1】https://www.infoq.cn/article/comparing-api-gateway-performances

【2】https://dzone.com/articles/spring-cloud-gateway-configuring-a-simple-route

转载于:https://my.oschina.net/u/2277392/blog/3094715

分享到:
评论

相关推荐

    springcloud Gateway网关-压测用.zip

    这个名为"springcloud Gateway网关-压测用.zip"的压缩包包含了一个用于性能测试的配置,目的是评估和优化Gateway的处理能力。下面我们将深入探讨SpringCloud Gateway的相关知识点,以及如何使用性能测试工具进行压测...

    CVE-2022-22947-Spring-Cloud-Gateway 内存马POC

    Spring Cloud Gateway 是基于 Spring Framework 和 Spring Boot 构建的 API 网关,它旨在为微服务架构提供一种简单、有效、统一的 API 路由管理方式。 Spring官方博客发布了一篇关于Spring Cloud Gateway的CVE...

    最新Spring Cloud Gateway 官方参考指南-中文版-3.x

    Spring Cloud Gateway 是一款基于Spring生态系统构建的API网关,它主要设计用于提供一种简单而有效的方式来路由API,并为API提供核心关注点,如安全性、监控/度量和弹性。在3.1.3版本中,它利用了Spring Boot 2.x、...

    spring-cloud-gateway-demo.zip

    Spring Cloud Gateway 是一款基于 Spring Framework 5 和 Spring Boot 2 设计的现代化微服务路由网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。在本示例 "spring-cloud-gateway-demo.zip" 中...

    springcloud下通过gateway转发websocket

    在IT行业中,Spring Cloud Gateway作为Spring Cloud生态体系中的一个关键组件,被广泛用于构建微服务架构中的API网关。这个框架允许我们集中处理各种请求,包括路由、过滤、安全等,极大地简化了服务间的通信。而...

    详解SpringCloud Finchley Gateway 统一异常处理

    详解 SpringCloud Finchley Gateway 统一异常处理 SpringCloud Finchley Gateway 统一异常处理是指在使用 SpringCloud Finchley 版本的 Gateway 时,如何统一处理系统级异常的方法。默认情况下,SpringCloud ...

    spring cloud zookeeper gateway

    在这个名为"spring-cloud-zookeeper-master"的项目中,开发者可以深入研究如何在Spring Cloud环境中配置和使用Zookeeper作为注册中心,以及如何有效地利用Spring Cloud Gateway构建一个高效的服务网关。通过阅读源...

    SpringCloud.03.网关Gateway 配置文件

    在Spring Cloud生态体系中,Spring Cloud Gateway作为新一代的API网关,被广泛应用于微服务架构中,用于统一处理请求路由、过滤器链、限流、熔断等核心功能。本篇将详细介绍Spring Cloud Gateway的配置文件相关知识...

    Spring Cloud Gateway 整合 Spring Security 统一登录认证鉴权

    在构建分布式系统时,Spring Cloud Gateway 作为微服务架构中的边缘服务或 API 网关,扮演着至关重要的角色。它负责路由请求到相应的微服务,并可以提供过滤器功能,如限流、熔断等。而Spring Security 则是 Java ...

    Spring Cloud Gateway的全局异常处理

    Spring Cloud Gateway作为一款基于Spring Framework 5、Project Reactor和Spring Boot 2.0构建的云原生网关框架,它提供了强大的路由转发能力和灵活的过滤器模型,能够很好地满足微服务网关的各种需求。然而,在实际...

    spring cloud api gateway简介

    Spring Cloud API Gateway就是基于Spring生态系统,专为构建微服务架构而设计的API网关。 在Spring Cloud框架下,API Gateway扮演着核心角色,它允许开发者定义路由规则,将不同的微服务实例暴露的接口聚合在一起,...

    spring-cloud使用的各种示例

    - [springcloud(十六):服务网关 Spring Cloud GateWay 服务化和过滤器](http://www.ityouknow.com/springcloud/2019/01/19/spring-cloud-gateway-service.html) - [springcloud(十七):服务网关 Spring Cloud ...

    springcloud实现gate网关转发功能和整合websocket源码

    Spring Cloud Gateway作为Spring Cloud生态系统的组件,是新一代的API网关,它旨在提供一种简单有效的方式来对微服务进行路由,同时提供了过滤器功能,可以进行限流、熔断、鉴权等操作。它的主要优点包括性能高、...

    springcloud zuul gateway 服务网关

    SpringCloud Zuul Gateway 服务网关是Spring Cloud生态系统中的一个重要组件,它主要负责微服务架构中的路由转发和过滤器功能。Zuul是Netflix开源的一个边缘服务,而Gateway则是Spring Cloud针对Zuul进行的升级版,...

    Spring Cloud实战 _springcloud实战_springcloud_

    Spring Cloud Gateway是新一代的API网关,它替代了Zuul,提供了更强大的路由规则、过滤器等功能,能够更灵活地处理请求和响应。 此外,Spring Cloud OpenFeign是声明式服务调用的组件,简化了服务之间的调用,使得...

    ithuhui-hui-base-springcloud-master.zip

    《SpringCloud基础学习指南——ithuhui-hui-base-springcloud-master深度解析》 SpringCloud作为微服务架构的主流框架,深受开发者的喜爱。本文将深入解析名为"ithuhui-hui-base-springcloud-master"的压缩包项目,...

    基于Springcloud的基础框架,统一gateWay网关鉴权demo,附下载地址

    基于Springcloud的基础框架,统一gateWay网关鉴权demo,附下载地址 使用方法具体见:https://blog.csdn.net/a1139628523/article/details/132664763

    spring-cloud-gateway-example-master.zip

    《Spring Cloud Gateway实战详解》 在微服务架构中,API网关扮演着至关重要的角色,它作为客户端与各个微服务之间的桥梁,承担了路由转发、鉴权、限流、熔断等多种职责。Spring Cloud Gateway是Spring Cloud生态...

    springcloud gateway 全局过滤器统一签名判定.doc

    它是Spring Cloud生态中的一个API网关服务,提供路由、熔断、限流等能力,可以作为所有微服务的统一入口。为了添加自定义的全局过滤器,我们需要创建一个新的Java类并实现`GlobalFilter`接口。这个过滤器将在每个...

    SpringCloud系列之API Gateway开发手册(Hoxton版本).pdf

    SpringCloud Gateway是Spring Cloud生态体系中的一个核心组件,主要用于构建微服务架构中的API网关。API网关作为所有客户端请求的统一入口,扮演着至关重要的角色。它不仅可以简化客户端与后端服务之间的交互,还...

Global site tag (gtag.js) - Google Analytics