使用Spring Cloud Gateway与Eureka构建真实API网关

本文详细介绍了如何使用Spring Cloud Gateway和Eureka构建一个动态、可扩展的API网关,涵盖服务注册、发现和路由配置,适合微服务架构初学者和实践者。

使用Spring Cloud Gateway与Eureka构建真实API网关

API网关在微服务架构中至关重要。但构建一个真实可用、安全、可扩展且服务感知的网关,需要的不仅仅是几个注解的配置。让我们面对现实:微服务听起来很激动人心,但一旦开始构建,事情很快就会变得复杂。

你是否曾想过大型系统如何在数十个微服务之间路由流量?前端如何知道调用哪个服务?服务如何相互发现?如何避免直接暴露每个内部服务?我们真的希望向外部世界暴露每个内部服务的URL吗?如何集中处理安全、日志和限流等问题?

所有这些问题的答案都是一个API网关 + 服务发现。本教程将引导你使用Spring Cloud Gateway和Eureka构建一个完全可用的API网关。我们不仅会介绍代码,还会解释每个部分的原因,你将获得一个清晰、可扩展的基础,可以在此基础上构建真实的应用。

为什么需要API网关

关键在于:当你的应用增长时,前端不应该担心内部服务做什么或在哪里托管。API网关通过以下方式帮助:

  • 隐藏内部微服务URL
  • 进行服务发现(以便服务可以自由扩展和移动)
  • 将请求路由到正确的服务
  • 集中处理安全、日志、限流等

它就像你微服务办公室的接待员。一切流量都通过它,它知道每个调用应该指向哪里。

使用的技术

部分 技术
API网关 Spring Cloud Gateway
服务发现 Netflix Eureka
后端服务 Spring Boot(微服务)
构建工具 Maven

工作原理

每个服务向Eureka注册,网关动态获取路由信息。这意味着零硬编码URL。

构建内容

  • Eureka:我们的服务注册中心(类似于服务的黄页)
  • API网关:知道流量发送位置的中央入口点
  • 微服务A和B:两个返回"hello"的虚拟服务

步骤

步骤1:构建Eureka服务器

首先,创建一个名为eureka-server的Spring Boot项目。这是所有微服务的目录。服务将在这里注册并相互发现。

添加依赖:

1
2
3
4
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

添加注解:

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableEurekaServer
public class ServerApplication {

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

}

@EnableEurekaServer – 将你的应用转换为Eureka注册中心

配置:

1
2
3
4
spring.application.name=server
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

现在运行应用并打开http://localhost:8761,你的注册中心就启动了。恭喜!

步骤2:创建两个微服务

让我们创建服务1和服务2。每个服务将:

  • 向Eureka注册
  • 暴露一个端点

添加依赖:

1
2
3
4
5
6
7
8
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

服务1的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@SpringBootApplication
public class Service1Application {

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

}

@RestController
class Service1Controller {
 @GetMapping("/app1/hello")
 public String hello() {
  return "Hello From Service 1";
 }
}

配置:

1
2
3
spring.application.name=service1
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:8761/eureka

为服务2重复此过程(将端口更改为8082,名称更改为service2)。确保每个服务都暴露一个简单的端点,如/hello,以便我们测试。

现在启动它们两个——你应该在Eureka仪表板上看到两个服务都已注册。

步骤3:创建API网关

创建另一个名为api-gateway的Spring Boot应用。这是你系统的前门。

添加依赖:

1
2
3
4
5
6
7
8
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

主类:

1
2
3
4
5
6
7
8
@SpringBootApplication
public class GatewayApplication {

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

}

配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
server.port=8080

spring.application.name=api-gateway

spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true

spring.cloud.gateway.routes[0].id=service1
spring.cloud.gateway.routes[0].uri=lb://SERVICE1
spring.cloud.gateway.routes[0].predicates[0]=Path=/app1/**

spring.cloud.gateway.routes[1].id=service2
spring.cloud.gateway.routes[1].uri=lb://SERVICE2
spring.cloud.gateway.routes[1].predicates[0]=Path=/app2/**

eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

这里发生的事情:

  • 你告诉网关通过Eureka使用服务发现
  • lb://service1意味着它将使用Ribbon风格的负载均衡
  • 所有命中/service1/**的流量都被路由到真实服务

启动网关并测试:

  • http://localhost:8080/app1/hello
  • http://localhost:8080/app2/hello

你已经通过实际网关实现了路由,由服务发现支持。

就是这样——你已经使用Spring Cloud Gateway和Eureka构建了一个发现感知、动态的API网关。

大多数教程向你展示静态路由设置。但这个版本是:

  • 发现感知
  • 负载均衡(通过服务ID)
  • 可扩展——部署更多实例,Eureka处理它
  • 动态——添加/删除服务无需代码更改

这种设置非常适合真实世界的项目,其中服务频繁演变,基础设施必须跟上步伐,而不需要不断重新部署或硬编码链接。

需要注意的常见错误

问题 修复方法
服务未找到 检查是否以正确的名称注册
路径模式错误 使用/service-name/**,而不是/service-name/*
服务ID大小写不匹配 在网关中使用lower-case-service-id: true
无限重试或500错误 确保你的服务实际上在本地运行

可能的下一步

你现在有一个工作的网关,它知道你的服务并智能地路由请求。在接下来的文章中,我将扩展本教程,添加以下要点,使其成为生产级应用:

  • 添加Spring Security + JWT认证
  • 使用Resilience4j添加断路器
  • 使用Docker和Docker Compose进行简单设置
  • 添加配置服务器以集中管理属性

如果你正在认真构建微服务,拥有一个智能、灵活的API网关不是可有可无的,而是必须的。

奖励:想要完整代码和可下载的入门项目?

这里是GitHub链接:VivekRajyaguru/spring-api-gateway-eureka-demo。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计