news 2026/6/9 15:32:06

【架构实战】网关架构设计:微服务的统一入口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【架构实战】网关架构设计:微服务的统一入口

一、没有网关的日子我们是怎么过的

2018年,我们的微服务直接暴露给前端。前端要记10个不同的域名和端口。

更痛苦的是,每个服务各自实现鉴权、限流、日志,代码重复度超过60%。

有一次安全审计,发现3个服务没有做鉴权,2个服务没有做限流。

后来我们上了网关,统一入口、统一鉴权、统一限流,世界瞬间清净了。


二、网关核心功能

2.1 功能清单

┌─────────────────────────────────────────────────────────────────┐ │ 网关核心功能 │ │ │ │ 1. 路由转发 │ │ - 根据路径/域名/Header转发到后端服务 │ │ │ │ 2. 鉴权认证 │ │ - JWT验证、OAuth2认证 │ │ - 统一登录、单点登录 │ │ │ │ 3. 限流熔断 │ │ - 全局限流、按用户限流 │ │ - 服务熔断、降级 │ │ │ │ 4. 协议转换 │ │ - HTTP → gRPC │ │ - HTTP → WebSocket │ │ │ │ 5. 日志监控 │ │ - 请求日志、响应日志 │ │ - 链路追踪 │ │ │ │ 6. 灰度发布 │ │ - 按比例/按用户灰度路由 │ │ │ └──────────────────────────────────────────────────────────────────┘

三、Spring Cloud Gateway实现

3.1 路由配置

# application.ymlspring:cloud:gateway:routes:# 订单服务-id:order-serviceuri:lb://order-servicepredicates:-Path=/api/orders/**filters:-StripPrefix=1-name:RequestRateLimiterargs:redis-rate-limiter.replenishRate:100redis-rate-limiter.burstCapacity:200key-resolver:"#{@userKeyResolver}"# 商品服务-id:product-serviceuri:lb://product-servicepredicates:-Path=/api/products/**filters:-StripPrefix=1-name:CircuitBreakerargs:name:productCircuitBreakerfallbackUri:forward:/fallback/product# 支付服务(灰度)-id:payment-service-v2uri:lb://payment-service-v2predicates:-Path=/api/payments/**-Header=X-Gray,v2filters:-StripPrefix=1

3.2 鉴权过滤器

/** * JWT鉴权过滤器 */@Component@Slf4jpublicclassJwtAuthFilterimplementsGlobalFilter,Ordered{@AutowiredprivateJwtTokenProvidertokenProvider;/** 白名单路径 */privatestaticfinalSet<String>WHITE_LIST=Set.of("/api/auth/login","/api/auth/register","/api/auth/refresh","/api/public/**");@OverridepublicMono<Void>filter(ServerWebExchangeexchange,GatewayFilterChainchain){Stringpath=exchange.getRequest().getPath().value();// 白名单放行if(isWhiteListed(path)){returnchain.filter(exchange);}// 获取TokenStringtoken=extractToken(exchange.getRequest());if(token==null){returnunauthorized(exchange,"缺少认证Token");}try{// 验证TokenJwtClaimsclaims=tokenProvider.validateToken(token);// 将用户信息传递给下游服务ServerHttpRequestrequest=exchange.getRequest().mutate().header("X-User-Id",claims.getUserId()).header("X-User-Role",claims.getRole()).header("X-Trace-Id",generateTraceId()).build();returnchain.filter(exchange.mutate().request(request).build());}catch(JwtTokenExpiredExceptione){returnunauthorized(exchange,"Token已过期");}catch(JwtTokenInvalidExceptione){returnunauthorized(exchange,"Token无效");}}privateMono<Void>unauthorized(ServerWebExchangeexchange,Stringmessage){exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);Stringbody=JSON.toJSONString(Result.fail(401,message));DataBufferbuffer=exchange.getResponse().bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));returnexchange.getResponse().writeWith(Mono.just(buffer));}@OverridepublicintgetOrder(){return-100;// 高优先级}}

3.3 限流过滤器

/** * 自定义限流Key解析器 */@ComponentpublicclassUserKeyResolverimplementsKeyResolver{@OverridepublicMono<String>resolve(ServerWebExchangeexchange){StringuserId=exchange.getRequest().getHeaders().getFirst("X-User-Id");Stringpath=exchange.getRequest().getPath().value();if(userId!=null){returnMono.just("rate_limit:"+userId+":"+path);}// 未登录用户按IP限流Stringip=exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();returnMono.just("rate_limit:ip:"+ip+":"+path);}}

3.4 灰度路由

/** * 灰度路由过滤器 */@Component@Slf4jpublicclassGrayRouteFilterimplementsGlobalFilter,Ordered{@AutowiredprivateGrayConfigServicegrayConfigService;@OverridepublicMono<Void>filter(ServerWebExchangeexchange,GatewayFilterChainchain){StringuserId=exchange.getRequest().getHeaders().getFirst("X-User-Id");StringserviceId=getServiceId(exchange);// 检查灰度规则GrayRulerule=grayConfigService.getGrayRule(serviceId);if(rule!=null&&rule.isEnabled()){booleanisGrayUser=isGrayUser(userId,rule);if(isGrayUser){// 灰度用户路由到V2版本StringnewUri=rewriteUri(exchange.getRequest().getURI(),rule.getGrayVersion());ServerHttpRequestrequest=exchange.getRequest().mutate().uri(URI.create(newUri)).header("X-Gray","true").build();log.info("灰度路由: userId={}, service={}, version={}",userId,serviceId,rule.getGrayVersion());returnchain.filter(exchange.mutate().request(request).build());}}returnchain.filter(exchange);}privatebooleanisGrayUser(StringuserId,GrayRulerule){// 按用户ID范围灰度if(rule.getUserIdRange()!=null){returnrule.getUserIdRange().contains(Long.parseLong(userId));}// 按百分比灰度if(rule.getPercentage()>0){inthash=Math.abs(userId.hashCode());returnhash%100<rule.getPercentage();}returnfalse;}@OverridepublicintgetOrder(){return0;}}

四、踩坑实录

坑1:网关成为单点

网关挂了,所有服务都不可用。

解决:网关多实例部署 + 健康检查 + 自动扩容。

坑2:网关性能瓶颈

所有请求经过网关,QPS高时网关响应慢。

解决:网关只做轻量操作(路由、鉴权),重逻辑放在业务服务。

坑3:网关超时设置不合理

网关超时30秒,但有些导出接口需要60秒。

解决:不同路由设置不同超时,长连接接口特殊处理。

坑4:跨域配置遗漏

前端请求被CORS策略拦截。

解决:在网关统一配置CORS。

坑5:请求体大小限制

文件上传请求被网关拒绝,因为超过了默认请求体大小限制。

解决:调整spring.codec.max-in-memory-size配置。


五、总结

网关设计要点:

功能方案
路由Spring Cloud Gateway
鉴权JWT + GlobalFilter
限流Redis + RequestRateLimiter
熔断Resilience4J
灰度自定义路由规则
监控Actuator + Prometheus

最佳实践:

  1. 网关多实例部署
  2. 只做轻量操作
  3. 统一鉴权和限流
  4. 合理的超时配置
  5. 完善的监控告警

血的教训:

网关是微服务的大门。门没守好,再多的内部安全措施也白搭。

思考题:你的系统用了什么网关方案?有没有踩过坑?


个人观点,仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 15:28:58

GEO执行框架:从诊断到落地的完整实施方案

GEO执行框架&#xff1a;从诊断到落地的完整实施方案 适用时间&#xff1a; 2026年6月 适用对象&#xff1a; 已有一定内容基础、希望在AI搜索引擎中获得可见度的网站 做GEO&#xff08;生成式引擎优化&#xff09;一年多&#xff0c;我观察到一个普遍现象&#xff1a;很多人读…

作者头像 李华
网站建设 2026/6/9 15:27:03

MPC5500与MFR4310 FlexRay控制器EBI接口设计与调试实战

1. 项目概述与核心价值在汽车电子和工业控制领域&#xff0c;构建一个高可靠、实时的通信节点&#xff0c;其核心挑战往往不在于协议栈本身有多复杂&#xff0c;而在于主控微控制器&#xff08;MCU&#xff09;与专用通信控制器&#xff08;CC&#xff09;之间那“最后一公里”…

作者头像 李华
网站建设 2026/6/9 15:25:54

如何高效使用开源KMS激活工具:新手快速入门完整指南

如何高效使用开源KMS激活工具&#xff1a;新手快速入门完整指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 你是否曾为Windows系统或Office办公软件的激活问题而烦恼&#xff1f;当系统提示…

作者头像 李华
网站建设 2026/6/9 15:25:54

ARM7外部总线接口EIM实战:连接SRAM/Flash的配置与调试指南

1. 项目概述在嵌入式系统开发中&#xff0c;尤其是基于ARM7这类经典内核的微控制器&#xff0c;我们常常会遇到片上资源&#xff08;如RAM、Flash&#xff09;不够用的情况。这时&#xff0c;扩展外部存储器就成了刚需。但连接外部芯片&#xff0c;远不止是把地址线和数据线连起…

作者头像 李华
网站建设 2026/6/9 15:25:52

S12XD架构升级:XGATE协处理器与增强指令集实战解析

1. 项目概述&#xff1a;从S12到S12XD的架构跃迁在嵌入式开发领域&#xff0c;尤其是汽车电子和工业控制这类对实时性、可靠性要求严苛的场合&#xff0c;微控制器的每一次架构升级都牵动着开发者的神经。飞思卡尔&#xff08;现为NXP的一部分&#xff09;的HCS12系列曾以其出色…

作者头像 李华