使用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。每个服务将:
添加依赖:
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。