
👋 大家好,欢迎来到我的技术博客! 💻 作为一名热爱 Java 与软件开发的程序员,我始终相信:清晰的逻辑 + 持续的积累 = 稳健的成长。 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Gateway这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
- Gateway – 无服务器(Serverless)场景下的适用性分析 🚀
Gateway – 无服务器(Serverless)场景下的适用性分析 🚀
引言
在当今快速发展的软件开发领域,无服务器(Serverless)计算已经成为一种备受瞩目的架构模式。它允许开发者专注于业务逻辑的编写,而无需关心底层基础设施的维护和管理。这种模式极大地简化了部署流程,提高了资源利用率,并为按需扩展提供了极大的灵活性。
然而,当我们将目光投向微服务架构和 API 网关时,一个问题自然而然地浮现出来:Spring Gateway 这样一个传统意义上的 API 网关,是否也适用于无服务器场景呢?它能否在无服务器环境中发挥其核心价值——流量路由、请求过滤、安全控制、负载均衡等——并克服其固有的限制?
本文将深入探讨 Spring Gateway 在无服务器场景下的适用性,分析其优势、挑战和潜在的解决方案。我们将通过丰富的 Java 代码示例,结合实际应用场景,来全面剖析这个问题。
什么是无服务器(Serverless)?
无服务器计算(Serverless Computing)是一种构建和运行应用程序和服务的方法,它让开发者无需管理服务器即可部署代码。这里的“无服务器”并非指真的没有服务器,而是指开发者不需要显式地去配置、管理或扩展服务器实例。
主要特点包括:
常见的无服务器平台有 AWS Lambda、Google Cloud Functions、Azure Functions、阿里云函数计算(FC)等。
Spring Gateway 的核心能力
在讨论其在无服务器场景下的适用性之前,我们需要先明确 Spring Gateway 的核心能力:
无服务器场景下 Gateway 的优势
尽管无服务器计算强调“无服务器”,但在复杂的微服务架构中,API 网关仍然是不可或缺的一环。Spring Gateway 在无服务器场景下仍然具备显著优势:
示例:Spring Gateway 作为统一入口
想象一个基于无服务器的电商应用,前端需要调用用户服务、商品服务、订单服务等多个无服务器函数。
// Gateway 配置示例:定义路由规则
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 路由到用户服务相关的无服务器函数
.route("user-service", r -> r.path("/api/users/**")
.uri("http://user-service-lambda-url"))
// 路由到商品服务相关的无服务器函数
.route("product-service", r -> r.path("/api/products/**")
.uri("http://product-service-lambda-url"))
// 路由到订单服务相关的无服务器函数
.route("order-service", r -> r.path("/api/orders/**")
.uri("http://order-service-lambda-url"))
.build();
}
}
// 示例:用户服务的无服务器函数 (伪代码,具体实现依赖于平台)
// 例如,AWS Lambda 函数
/*
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
public class UserServiceLambda implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
// 处理用户相关逻辑
String userId = input.getPathParameters().get("userId");
// … 获取用户信息 …
return new APIGatewayProxyResponseEvent()
.withStatusCode(200)
.withBody("{\\"userId\\": \\"" + userId + "\\", \\"name\\": \\"John Doe\\"}");
}
}
*/
// Gateway 可以统一处理所有 /api/users/** 的请求,然后转发给相应的 Lambda 函数
在这个例子中,无论后端是运行在 Lambda 上的函数还是传统服务器上的服务,前端只需要知道 Gateway 的地址,从而实现了服务的解耦和抽象。
无服务器场景下 Gateway 的挑战
尽管有诸多优势,但 Spring Gateway 在无服务器环境下也面临着不少挑战:
示例:冷启动问题与优化
// Gateway 本身部署为无服务器函数时,可能会面临冷启动问题
// 例如,使用 AWS Lambda 部署 Gateway (伪代码)
// 伪代码:Gateway Lambda 函数
/*
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2ProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2ProxyResponseEvent;
public class GatewayLambda implements RequestHandler<APIGatewayV2ProxyRequestEvent, APIGatewayV2ProxyResponseEvent> {
// 初始化 Gateway 实例
private static final GatewayServer server = new GatewayServer();
@Override
public APIGatewayV2ProxyResponseEvent handleRequest(APIGatewayV2ProxyRequestEvent input, Context context) {
// 这里需要处理请求并返回响应
// 如果 Gateway 实例尚未初始化,或者由于冷启动导致初始化缓慢,会影响性能
try {
// 调用 Gateway 内部逻辑处理请求
// …
return response;
} catch (Exception e) {
// 处理异常
return new APIGatewayV2ProxyResponseEvent().withStatusCode(500);
}
}
}
*/
// 解决方案:预热和缓存
// 在 Gateway 部署时,可以设置定时任务(如 CloudWatch Event Rule)定期调用 Gateway,使其保持活跃
// 或者在函数初始化时进行必要的预加载操作
Spring Gateway 在无服务器平台上的部署模式
针对上述挑战,Spring Gateway 在无服务器环境中的部署和使用模式有几种不同的思路:
部署为无服务器函数(函数即服务):
- 优点: 与无服务器架构完全一致,易于与平台集成,按需伸缩。
- 缺点: 可能受到平台资源限制(内存、执行时间),冷启动问题,状态管理困难。
- 适用场景: 轻量级的网关功能,或者作为边缘网关,处理简单的路由和过滤。
部署为容器化服务(Kubernetes Pod / Docker Container):
- 优点: 保持了 Gateway 的完整功能和性能,可以更好地管理状态和资源,更适合复杂的业务逻辑。
- 缺点: 需要管理容器和集群,增加了复杂性和运维成本。
- 适用场景: 功能复杂、需要高性能和状态管理的场景。
混合部署模式:
- 优点: 结合两种模式的优点,例如,将核心的路由和安全逻辑放在容器化的 Gateway 中,而将轻量级的处理逻辑放在无服务器函数中。
- 缺点: 增加了架构的复杂性,需要更精细的设计和管理。
示例:混合部署模式
// 伪代码:混合部署 – 一部分功能在容器化 Gateway 中处理,另一部分在无服务器函数中处理
// 容器化 Gateway 配置
@Configuration
public class HybridGatewayConfig {
@Bean
public RouteLocator hybridRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 路由到需要复杂处理的内部服务
.route("complex-service", r -> r.path("/api/complex/**")
.uri("lb://internal-complex-service")) // 容器化服务
// 路由到轻量级无服务器函数
.route("simple-function", r -> r.path("/api/simple/**")
.uri("http://simple-lambda-function-url")) // 无服务器函数
.build();
}
}
// 示例:在容器化 Gateway 中处理认证和日志
@Component
public class AuthAndLoggingFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 执行认证逻辑
// 日志记录
System.out.println("Request: " + request.getURI());
return chain.filter(exchange); // 继续处理
}
}
// 示例:无服务器函数处理特定业务逻辑
/*
// 例如,一个处理图像上传的 Lambda 函数
public class ImageProcessingLambda implements RequestHandler<S3Event, String> {
@Override
public String handleRequest(S3Event input, Context context) {
// 处理 S3 事件触发的图像上传
// 调用外部 API 或执行其他逻辑
return "Processed image";
}
}
*/
微服务架构与无服务器的结合
在微服务架构中,许多服务可能已经采用无服务器形式部署。在这种情况下,Spring Gateway 作为网关层,需要与这些无服务器服务进行无缝协作。
- 服务发现: 无服务器服务通常不提供传统意义上的服务注册与发现。Gateway 可能需要通过配置、API 或平台提供的服务目录来获取服务地址。
- 事件驱动通信: 无服务器函数通常通过事件驱动的方式工作。Gateway 可能需要适配这些事件,或者通过 HTTP API 与它们交互。
- 数据一致性: 在无服务器环境中,数据一致性管理变得更加复杂。Gateway 可能在事务协调或状态同步方面扮演重要角色。
示例:与无服务器服务的集成
// Gateway 配置:处理与无服务器函数的集成
@Configuration
public class ServerlessIntegrationConfig {
@Bean
public RouteLocator serverlessRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 路由到无服务器函数,通过 HTTP API
.route("serverless-api", r -> r.path("/api/serverless/**")
.uri("http://your-serverless-api-gateway-url")) // 无服务器 API 网关
// 路由到无服务器函数,通过平台特定的 URI
.route("aws-lambda", r -> r.path("/api/aws-lambda/**")
.uri("arn:aws:lambda:us-east-1:123456789012:function:MyFunction")) // AWS Lambda ARN (示例)
.build();
}
}
// 示例:在 Gateway 中添加一个过滤器,用于处理特定的无服务器上下文
@Component
public class ServerlessContextFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
// 添加无服务器特定的 Header 或修改请求
// 例如,添加 Trace ID 用于追踪
String traceId = MDC.get("traceId"); // 假设使用 MDC
if (traceId != null) {
exchange.getRequest().mutate()
.header("X-Trace-ID", traceId)
.build();
}
// 可以在这里添加对无服务器函数的特定处理逻辑
// 例如,处理特定的错误码或响应格式
return chain.filter(exchange);
}
}
性能与成本优化策略
在无服务器场景下,性能和成本是两个关键考量因素。针对 Spring Gateway,可以采取以下优化策略:
优化 Gateway 本身的性能:
- 使用 WebFlux: 如前文所述,Spring Gateway 本身就是基于 WebFlux 构建的。充分利用其响应式特性,可以提高处理效率。
- 减少不必要的过滤器: 只保留必要的过滤器,避免在每个请求上执行过多的逻辑。
- 缓存策略: 合理利用缓存,减少对后端服务的调用次数。
- 连接池优化: 配置合适的 HTTP 连接池,提高与后端服务的通信效率。
与无服务器平台协同优化:
- 选择合适的内存和超时设置: 根据 Gateway 的实际需求,为其分配足够的内存和合理的执行超时时间。
- 使用预热机制: 通过定时任务或平台提供的预热功能,减少冷启动的影响。
- 利用平台特性: 例如,AWS API Gateway 与 Lambda 的集成优化,或者 Google Cloud Run 与 Cloud Functions 的配合。
成本控制:
- 合理规划路由: 避免不必要的请求转发,减少后端函数的调用次数。
- 实施限流策略: 防止突发流量导致的资源过度消耗和成本激增。
- 监控与告警: 实时监控 Gateway 和后端服务的性能和成本,及时发现异常。
示例:成本与性能优化
// 示例:配置限流过滤器
@Configuration
public class RateLimitingConfig {
@Bean
public RouteLocator rateLimitingRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("rate-limited-service", r -> r.path("/api/rate-limited/**")
.filters(f -> f.rewritePath("/api/rate-limited/(?<segment>.*)", "/${segment}")
.filter(new RequestRateLimiterGatewayFilterFactory())) // 限流过滤器
.uri("http://backend-service"))
.build();
}
}
// 示例:使用缓存过滤器
@Component
public class CacheFilter implements GlobalFilter {
private final CacheManager cacheManager; // 假设使用 Spring Cache
public CacheFilter(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String key = request.getURI().toString(); // 简单的 key 生成方式
// 尝试从缓存获取响应
ValueWrapper cachedValue = cacheManager.getCache("gatewayCache").get(key);
if (cachedValue != null) {
// 如果缓存命中,直接返回缓存结果
// 注意:这里简化处理,实际需要设置响应体
exchange.getResponse().setStatusCode(HttpStatus.OK);
// 设置响应头等
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap("Cached Response".getBytes())));
}
// 缓存未命中,继续处理请求
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 请求处理完成后,将结果放入缓存
// 这里简化处理,实际需要获取响应内容
// cacheManager.getCache("gatewayCache").put(key, responseContent);
}));
}
}
安全与合规性
在无服务器环境中,安全是重中之重。Spring Gateway 可以在保障安全方面发挥重要作用,但也需要适应无服务器环境的特点。
示例:安全过滤器
// 示例:实现一个简单的 JWT 认证过滤器
@Component
public class JwtAuthenticationFilter implements GlobalFilter {
private final JwtDecoder jwtDecoder;
public JwtAuthenticationFilter(JwtDecoder jwtDecoder) {
this.jwtDecoder = jwtDecoder;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String token = extractToken(request);
if (token == null || token.isEmpty()) {
// 拒绝请求
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
try {
Jwt jwt = jwtDecoder.decode(token);
// 验证 token 并设置认证信息
Authentication authentication = new JwtAuthenticationToken(jwt);
exchange.getAttributes().put("authentication", authentication);
} catch (JwtException e) {
// token 无效
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
private String extractToken(ServerHttpRequest request) {
String bearerToken = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7); // 移除 "Bearer "
}
return null;
}
}
监控与可观测性
在无服务器环境中,由于服务的短暂性和分布式特性,监控和可观测性变得更加重要。Spring Gateway 可以集成多种监控工具,提供全面的可观测性。
示例:集成 Prometheus 和 Grafana
// 示例:启用 Actuator 指标
// 在 application.properties 中添加
management.endpoints.web.exposure.include=*
management.endpoint.metrics.enabled=true
management.endpoint.prometheus.enabled=true
management.metrics.export.prometheus.enabled=true
// 配置 Gateway 路由以暴露指标
@Configuration
public class MetricsConfig {
@Bean
public RouteLocator metricsRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("metrics-endpoint", r -> r.path("/actuator/prometheus")
.uri("lb://gateway-service")) // 假设 Gateway 自身也暴露指标
.build();
}
}
// 示例:添加自定义指标
@Component
public class CustomMetricsCollector {
private final MeterRegistry meterRegistry;
public CustomMetricsCollector(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
public void recordRequest(String routeId, long duration) {
Timer.Sample sample = Timer.start(meterRegistry);
// 记录请求耗时
Timer timer = Timer.builder("gateway.requests.duration")
.tag("route", routeId)
.register(meterRegistry);
timer.record(duration, TimeUnit.MILLISECONDS);
}
}
案例研究:实际应用中的 Gateway 与无服务器
让我们来看一个实际的案例。假设一个电商平台需要处理大量的用户请求,后端服务采用无服务器架构部署。
- products 服务:一个 AWS Lambda 函数,负责处理商品查询。
- orders 服务:另一个 Lambda 函数,处理订单创建。
- users 服务:处理用户信息。
- 认证: 检查 JWT token。
- 路由: 将 /api/products 请求转发到 products Lambda。
- 限流: 限制每个用户的请求频率。
- 缓存: 对热门商品信息进行缓存。
- 日志: 记录所有请求的详细信息。
- 安全: 过滤掉恶意请求。
示例:完整的 Gateway 应用场景配置
// 完整的 Gateway 配置示例
@Configuration
public class CompleteGatewayConfig {
@Bean
public RouteLocator completeRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 商品服务
.route("product-service", r -> r.path("/api/products/**")
.filters(f -> f.stripPrefix(2)) // 去掉 /api/products 前缀
.uri("http://product-lambda-url"))
// 订单服务
.route("order-service", r -> r.path("/api/orders/**")
.filters(f -> f.stripPrefix(2))
.uri("http://order-lambda-url"))
// 用户服务
.route("user-service", r -> r.path("/api/users/**")
.filters(f -> f.stripPrefix(2))
.uri("http://user-lambda-url"))
.build();
}
// 全局过滤器:认证
@Bean
public GlobalFilter authenticationFilter() {
return new JwtAuthenticationFilter(jwtDecoder()); // 假设有 JWT 解码器
}
// 全局过滤器:限流
@Bean
public GlobalFilter rateLimitingFilter() {
return new RequestRateLimiterGatewayFilterFactory(); // Spring Cloud Gateway 内置
}
// 全局过滤器:日志
@Bean
public GlobalFilter loggingFilter() {
return new LoggingFilter();
}
// 全局过滤器:缓存
@Bean
public GlobalFilter cachingFilter() {
return new CacheFilter(cacheManager());
}
// 其他 Bean 配置…
}
结论与展望
Spring Gateway 在无服务器场景下具有显著的适用性,它能够有效地扮演 API 网关的角色,提供路由、过滤、安全、监控等核心功能。然而,要充分发挥其潜力,需要仔细考虑其在无服务器环境中的部署模式、性能优化、成本控制以及安全合规等方面的问题。
未来,随着无服务器技术的不断发展和成熟,Spring Gateway 也将不断演进,以更好地适应这种新型的计算模式。我们可以期待看到:
- 更紧密的平台集成: Gateway 将与主流无服务器平台(如 AWS、Azure、Google Cloud)更深度地集成,提供更便捷的配置和管理方式。
- 增强的无服务器感知: Gateway 会更智能地识别和适配无服务器函数的特性,例如自动处理冷启动、优化网络调用等。
- 更丰富的内置功能: 针对无服务器场景,可能会推出更多专门的过滤器、适配器和集成模块。
- 更好的可观测性支持: 与现代监控和追踪工具的集成将更加完善,提供更全面的洞察力。
对于开发者来说,理解 Spring Gateway 在无服务器环境中的优势和挑战,选择合适的部署模式和优化策略,是成功构建现代微服务应用的关键一步。无论是采用容器化部署还是无服务器函数部署,Gateway 都将在未来的软件架构中继续扮演着不可或缺的角色。
参考资料
- AWS Lambda 官方文档 📚
- Google Cloud Functions 官方文档 📚
- Azure Functions 官方文档 📚
- Spring Cloud Gateway 官方文档 📘
- Spring WebFlux 官方文档 📗
- OpenTelemetry 官方网站 🌐
- Prometheus 官方网站 🌐
结语
无服务器计算的兴起为软件架构带来了新的机遇和挑战。Spring Gateway 作为成熟的 API 网关,正积极适应这一趋势。通过深入分析其在无服务器环境中的适用性,我们可以看到它不仅能够胜任,而且能够为无服务器应用提供强有力的支撑。未来的开发者和架构师,应该充分认识到这种结合的价值,并将其应用于实际项目中,共同推动技术的进步和发展。
Mermaid 图表:Spring Gateway 与无服务器的交互模式
#mermaid-svg-1r4C3DpHMNLiZFUa{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1r4C3DpHMNLiZFUa .error-icon{fill:#552222;}#mermaid-svg-1r4C3DpHMNLiZFUa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1r4C3DpHMNLiZFUa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1r4C3DpHMNLiZFUa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1r4C3DpHMNLiZFUa .marker.cross{stroke:#333333;}#mermaid-svg-1r4C3DpHMNLiZFUa svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1r4C3DpHMNLiZFUa p{margin:0;}#mermaid-svg-1r4C3DpHMNLiZFUa .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-1r4C3DpHMNLiZFUa .cluster-label text{fill:#333;}#mermaid-svg-1r4C3DpHMNLiZFUa .cluster-label span{color:#333;}#mermaid-svg-1r4C3DpHMNLiZFUa .cluster-label span p{background-color:transparent;}#mermaid-svg-1r4C3DpHMNLiZFUa .label text,#mermaid-svg-1r4C3DpHMNLiZFUa span{fill:#333;color:#333;}#mermaid-svg-1r4C3DpHMNLiZFUa .node rect,#mermaid-svg-1r4C3DpHMNLiZFUa .node circle,#mermaid-svg-1r4C3DpHMNLiZFUa .node ellipse,#mermaid-svg-1r4C3DpHMNLiZFUa .node polygon,#mermaid-svg-1r4C3DpHMNLiZFUa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1r4C3DpHMNLiZFUa .rough-node .label text,#mermaid-svg-1r4C3DpHMNLiZFUa .node .label text,#mermaid-svg-1r4C3DpHMNLiZFUa .image-shape .label,#mermaid-svg-1r4C3DpHMNLiZFUa .icon-shape .label{text-anchor:middle;}#mermaid-svg-1r4C3DpHMNLiZFUa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1r4C3DpHMNLiZFUa .rough-node .label,#mermaid-svg-1r4C3DpHMNLiZFUa .node .label,#mermaid-svg-1r4C3DpHMNLiZFUa .image-shape .label,#mermaid-svg-1r4C3DpHMNLiZFUa .icon-shape .label{text-align:center;}#mermaid-svg-1r4C3DpHMNLiZFUa .node.clickable{cursor:pointer;}#mermaid-svg-1r4C3DpHMNLiZFUa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1r4C3DpHMNLiZFUa .arrowheadPath{fill:#333333;}#mermaid-svg-1r4C3DpHMNLiZFUa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1r4C3DpHMNLiZFUa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1r4C3DpHMNLiZFUa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1r4C3DpHMNLiZFUa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1r4C3DpHMNLiZFUa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1r4C3DpHMNLiZFUa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1r4C3DpHMNLiZFUa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1r4C3DpHMNLiZFUa .cluster text{fill:#333;}#mermaid-svg-1r4C3DpHMNLiZFUa .cluster span{color:#333;}#mermaid-svg-1r4C3DpHMNLiZFUa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1r4C3DpHMNLiZFUa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1r4C3DpHMNLiZFUa rect.text{fill:none;stroke-width:0;}#mermaid-svg-1r4C3DpHMNLiZFUa .icon-shape,#mermaid-svg-1r4C3DpHMNLiZFUa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1r4C3DpHMNLiZFUa .icon-shape p,#mermaid-svg-1r4C3DpHMNLiZFUa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1r4C3DpHMNLiZFUa .icon-shape rect,#mermaid-svg-1r4C3DpHMNLiZFUa .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1r4C3DpHMNLiZFUa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1r4C3DpHMNLiZFUa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1r4C3DpHMNLiZFUa :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
后端存储
网关层
无服务器平台
前端应用
Spring Gateway
无服务器函数 – 商品服务
无服务器函数 – 订单服务
无服务器函数 – 用户服务
商品数据库
订单数据库
用户数据库
注意: 本文中的代码示例仅供参考,实际开发中请根据具体需求和项目结构进行调整。部分示例可能需要额外的依赖或配置才能运行。
🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨

