使用 Spring Cloud Gateway 隐藏服务和运行时发现

工程 | Ben Wilcock | 2019 年 7 月 01 日 | ...

Ben Wilcock – Spring 营销,Pivotal。Brian McClain – 技术营销,Pivotal。

公司很少希望所有 API 都可以公开访问。大多数公司默认倾向于隐藏其服务,仅在绝对必要时才将 API 公开。

Spring Cloud Gateway 可以提供帮助。Spring Cloud Gateway 允许您使用简单的 Java™ 指令(我们在上一篇文章中已介绍)或 YAML 配置文件(我们将在此文章中演示)来路由流向您 API 的流量。为了隐藏您的服务,您可以将网络设置为只有网关可以从外部访问。网关随即成为守门人,控制外部的进出。这是一种非常流行的模式。

基于云的服务也习惯于在没有太多警告的情况下更改位置和粒度。为了更好地应对这种情况,您可以将网关与服务注册中心结合使用,以使网络上的应用程序能够在运行时动态地找到彼此。如果您这样做,您的应用程序将更能适应变化。Spring Cloud Netflix Eureka Server 就是这样一种服务注册中心。

在本文中,我们将介绍 Spring Cloud 的网关和注册中心组件,并说明如何将它们结合使用,以使您的应用程序更安全、更可靠。

由于此设置需要特定的配置,我们提供了可以下载和运行的现成代码。我们将使用 Docker 来编排我们的服务并模拟私有网络。然后,我们将使用 HTTPie 与我们正在运行的服务进行通信。

所需物品

  • Java(假定使用版本 8),加上您喜欢的网络浏览器和终端应用程序。

  • 源代码 – 这次无需编写任何代码,只需从 GitHub git clone(或下载并 unzip此项目的源代码仓库

  • Docker Desktop – Docker 将提供我们的伪生产环境。我们将用它在私有网络中隐藏我们的服务。

  • Cloud Native Buildpacks – 我们将使用 Cloud Native Buildpacks 为我们构建 Docker 容器镜像。Buildpacks 体现了几种 DevOps 最佳实践,包括强化的开源操作系统和免费的 OpenJDK 发行版。

  • 大约 10-15 分钟,具体取决于您的互联网速度等。

开始吧...

步骤 1

从上面的列表中下载并安装所有“所需物品”。然后将目录切换到源代码中的 runtime-discovery 文件夹,如下所示

cd runtime-discovery

步骤 2

使用 Maven 构建 & 打包网关、注册中心和服务为 JAR,然后为它们分别创建 Docker 容器。我们提供了一个方便的 pack-images 脚本来完成这项工作

 ./pack-images.sh

步骤 3

在后台启动 Docker 测试环境。我们在这里使用 docker-compose 是因为它能够启动多个容器并创建一个私有网络供它们通信

docker-compose up

步骤 4

请稍候。Docker 将启动所有容器(使用 docker-compose.yml 文件中提供的配置)。建议在这里多等几分钟。这给 Docker 时间启动所有东西,也让应用程序有机会通信并稳定下来。如果您稍等片刻,您应该会看到 Gateway 和 Greeting Service 在 Registry 中注册自己。日志会很多,但在其中您会看到来自注册中心的类似这些行

registry    | 2019-06-28 12:19:01.780  INFO 1 --- [nio-8761-exec-2] c.n.e.registry.AbstractInstanceRegistry  : Registered instance REGISTRY/db1d80613789:registry:8761 with status UP (replication=false)
registry    | 2019-06-28 12:19:02.380  INFO 1 --- [nio-8761-exec-6] c.n.e.registry.AbstractInstanceRegistry  : Registered instance GATEWAY/9c0c0c9ba027:gateway:8760 with status UP (replication=true)
registry    | 2019-06-28 12:19:02.382  INFO 1 --- [nio-8761-exec-6] c.n.e.registry.AbstractInstanceRegistry  : Registered instance SERVICE/fe7e38b21cac:service:8762 with status UP (replication=true)

让我们来试试...

首先,检查 Greeting Service 是否被隐藏

Greeting Service 运行在端口 8762 上,并隐藏在 Docker 网络内部。让我们尝试使用您喜欢的浏览器访问 http://localhost:8762/greeting。您的浏览器应该会显示“无法访问此网站”。这是因为 Greeting Service 隐藏在 Docker 网络内部(就像在公司防火墙后面一样)。我们无法直接访问 Greeting Service。相反,您会看到一个类似于下面的错误页面。

Screenshot from the browser window showing that the service is unreachable

接下来,通过 Gateway 访问 Greeting Service

现在,在浏览器中导航到 http://localhost:8080/service/greeting。您现在应该会收到一个有效的响应,其内容类似于下面显示的“Hello, World”JSON

{ "id": 1, "content": "Hello, World!"}

当您从浏览器发出此新的 HTTP 请求时,它被发送到 Gateway 并由其处理。Gateway 服务可公开访问的(它被映射到端口 8080)。您的请求由 Gateway 代表您转发到 Greeting Service,然后响应由 Gateway 路由回给您。

现在,查看服务注册中心

Docker 网络上的微服务都在向 Registry server 注册(这可能需要几分钟,请耐心等待)。Registry server 充当服务的地址簿。如果服务移动或创建新实例,它们将把自己添加到注册中心。

要查看当前注册的服务列表,请在浏览器中打开 http://localhost:8080/registry。您应该会看到一个类似于下面的屏幕。

Screenshot from the Registry console, listing several services

最后,关闭

完成后,在终端中使用 ctrl-C 来关闭 Docker 服务。如果由于某种原因此方法无效,您也可以从 runtime-discovery 文件夹中使用 docker-compose down 命令。使用任何一种方法,您都应该看到类似于这样的输出

Stopping gateway  ... done
Stopping service  ... done
Stopping registry ... done

使用 docker-compose rm -f 可以进一步清理。

工作原理

在此演示中,我们有 3 个服务器。这些服务器都运行在由 Docker Compose 提供的“隐藏”网络内部。只有Gateway 服务器暴露给外部世界,因此所有 HTTP 流量都必须通过此 Gateway。

以下是这 3 个服务器的说明及其各自的功能...

  1. Gateway – 充当所有 HTTP 流量的守门人。所有入站和出站流量都通过此门户流动 – 它充当外部世界(您的浏览器)与内部 Docker 网络上的服务之间的桥梁。Gateway 有一个配置,指定可用于与网络内部服务通信的路由。这些路由使用目标服务的“逻辑”名称。这些逻辑名称由 Registry server 转换为实际地址。

  2. Registry – 充当隐藏网络上所有服务的电话簿。它允许 Gateway 仅使用其逻辑名称来查找 Greeting Service。

  3. Greeting Service – 是一个简单的 REST 服务,基于流行的 Spring.io 指南 "构建 RESTful Web 服务"。

正如您在 docker-compose.yml 中所见,Docker 被配置为只允许外部调用到达 Gateway – 在端口 80 上。其他服务器(Registry 和 Greeting Service)不能直接从外部访问。

Gateway 配置的 URL 直通路径可以在 Gateway 的 application.yml 文件中看到。此配置使用了这些服务器的“逻辑”名称和 lb:(负载均衡器)协议,如下面的摘录所示

spring:
  application:
    name: gateway  
  cloud:
    gateway:
      routes:
      - id: service
        uri: lb://service
        predicates:
        - Path=/service/**
        filters:
        - StripPrefix=1
...

通过使用这些“逻辑”服务器名称,Gateway 可以在运行时使用 Registry 来发现这些服务的真实位置。

总结

借助触手可及的整个 Spring 工具包,您很快就会发现 Spring Cloud Gateway 是多么灵活和强大。如果您深入研究源代码,您会注意到只需几行 Java 代码和一些依赖项,我们就可以轻松地将 Spring Boot 微服务与 Eureka 集成,并控制对我们服务 API 的访问。

在结束之前,何不注册参加 SpringOne Platform 2019 – 这是构建可扩展应用程序以取悦用户的顶级会议。加入数千名志同道合的 Spring 开发者,于 10 月 7 日至 10 日在德克萨斯州奥斯汀学习、分享并享受乐趣。注册时使用折扣代码 S1P_Save200,即可节省票价。如果您需要帮助说服您的经理,请使用此页面。期待在那里见到您。

订阅 Spring 资讯

订阅 Spring 资讯,保持联系

订阅

抢先一步

VMware 提供培训和认证,助您飞速进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

近期活动

查看 Spring 社区的所有近期活动。

查看全部