API调用位置抉择:网关过滤器VS微服务内部?
API调用位置选型分析
背景
每个请求都会经过API网关,且请求携带包含自定义声明"x-token"的JWT。这个"x-token"是用于从数据库获取对应数据的ID,3个微服务中有2个会用到它。
问题
获取xTokenObject的API调用应该放在哪里执行?
现有方案分析
1. API网关过滤器方案
在Spring Cloud Gateway中添加API过滤器,对所有GET/POST请求做修改:
- 创建过滤器,在过滤器里调用API获取与"x-token"关联的
xTokenObject,然后修改请求,把xTokenObject加入请求体,让微服务的Controller可以直接使用。
优点
- 权限集中管控:只有API网关拥有访问该数据API的权限
- 微服务使用便捷:控制器可以直接拿到
xTokenObject,无需额外处理
微服务控制器使用示例代码:
@PostMapping() public ResponseEntity<SomeObject> someMethod(@RequestBody @Valid XTokenObject xTokenObject){ return ResponseEntity.ok(this.someService.someFunction(xTokenObject)); }
缺点
- 存在请求体冲突问题:如果请求本身已有请求体,无法直接将
xTokenObject合并进去,微服务控制器也难以同时获取原请求体和新增对象。
2. 微服务内部调用方案
在网关过滤器里给请求添加携带"x-token"的请求头,然后在微服务的@Service层中用这个值调用API获取xTokenObject。
优点
- 实现成本低:网关添加请求头比修改请求体简单得多
微服务Service层示例代码:
@Service public class SomeService { public SomeObject someFunction(String xTokenId) { // 在这里用xTokenId调用API获取数据 return someObject; } }
缺点
- 重复配置多:需要用到该数据的2个微服务都得单独配置与数据API的连接,冗余工作多。
补充疑问与考量
哪种方案性能更快?有没有更优的方案?另外,Token Data微服务的数据包含敏感信息,是加密存储在认证服务器的同库不同表中的,我还考虑用Redis缓存这些数据。
方案对比与最优建议
性能对比
- 网关过滤器方案:所有请求仅在网关层调用一次数据API,配合Redis缓存的话,还能直接从缓存取结果,避免重复调用,高并发场景下性能优势明显。
- 微服务内部调用方案:每个微服务都要单独发起API请求,即使是同一个
x-token的请求,不同微服务可能重复调用,性能损耗大,缓存也需要每个微服务单独维护,成本高。
网关方案的请求体问题解决
如果请求已有请求体,不建议修改原请求体,推荐用以下方式传递xTokenObject:
自定义请求头传递
在网关过滤器中将xTokenObject序列化为JSON字符串,放到自定义请求头(如X-Token-Object)中,微服务控制器通过@RequestHeader获取后反序列化即可。
示例代码:
// 网关过滤器中 ObjectMapper objectMapper = new ObjectMapper(); String xTokenObjectJson = objectMapper.writeValueAsString(xTokenObject); exchange.getRequest().mutate().header("X-Token-Object", xTokenObjectJson).build(); // 微服务控制器中 @PostMapping() public ResponseEntity<SomeObject> someMethod(@RequestBody @Valid OriginalRequestBody originalBody, @RequestHeader("X-Token-Object") String xTokenObjectStr) throws JsonProcessingException { XTokenObject xTokenObject = new ObjectMapper().readValue(xTokenObjectStr, XTokenObject.class); return ResponseEntity.ok(this.someService.someFunction(originalBody, xTokenObject)); }
最优方案推荐
推荐网关过滤器+Redis缓存的组合:
- 网关层统一处理:只有网关调用数据API,优先从Redis缓存读取,缓存失效时再请求后端,减少数据库压力。
- 请求头传递数据:避免修改原请求体的冲突问题,实现简单。
- 权限与复杂度管控:微服务无需直接连接数据API,权限集中在网关,降低微服务配置复杂度。
敏感数据处理建议
因为数据是加密存储的,网关获取后:
- 优先传递微服务所需的非敏感字段,减少敏感数据传输范围;
- 如果必须传递敏感信息,保持加密状态传输,微服务按需解密(需确保微服务有解密权限),降低传输泄露风险。
内容的提问来源于stack exchange,提问作者dvbngln
相关产品推荐
相关产品推荐

