Apollo Federation如何向不同微服务发送不同@key解决schema组合报错
Apollo Federation 实体键校验错误解决方案
问题根因
Apollo Federation v2 对跨服务实体的键校验规则比旧版本更严格:扩展实体声明的@key必须是源实体定义服务中显式声明过的合法键,不允许直接拆分源实体的复合键作为扩展用键。如果仅给源实体声明单字段键而忽略原有复合键,也会触发校验错误。
调整步骤
1. 统一依赖版本
所有微服务和网关必须使用@apollo/subgraph v2.x、@apollo/gateway v2.x及以上版本依赖,子服务构建Schema时默认启用Federation v2指令集即可。
2. 调整源服务(MS1)的Movie实体定义
在MS1的Movie实体上显式声明所有需要用到的键,包含原复合键和两个独立单字段键:
type Movie @key(fields: "id name") # 保留原有复合键,兼容历史逻辑 @key(fields: "id") # 声明独立id键,供MS2扩展使用 @key(fields: "name") # 声明独立name键,供MS3扩展使用 { id: String! name: String }
3. 补充MS1的__resolveReference兼容逻辑
MS1的Movie实体解析器需要支持三种键的查询场景:
const resolvers = { Movie: { __resolveReference(ref) { // 处理原复合键查询 if (ref.id && ref.name) { return movieDB.findOne({ id: ref.id, name: ref.name }) } // 处理仅id查询(供MS2调用) if (ref.id) { return movieDB.findOne({ id: ref.id }) } // 处理仅name查询(供MS3调用) if (ref.name) { return movieDB.findOne({ name: ref.name }) } return null } } }
4. 无需修改MS2、MS3的扩展定义
你当前MS2、MS3的Movie扩展定义已经和MS1声明的独立键完全匹配,不需要调整,网关会自动在解析对应扩展字段时传递指定的键参数。
功能验证
重启所有子服务和网关后,Schema组合错误会自动消失,可执行以下查询验证逻辑正确性:
query { movie(id: "test_id") { id name location { # 调用MS2扩展字段,自动传递id作为查询键 longitude latitude } award { # 调用MS3扩展字段,自动传递name作为查询键 count } } }
内容的提问来源于stack exchange,提问作者ashiaka
相关产品推荐
相关产品推荐

