• 邋遢的流浪剑客
    2026-08-27 来自上海
    思考题使用dsh写代码验证结果如下: 第一种情况:删除 consumer 的 inject: ['greeter'],但 apply 里仍然写 ctx.greeter.greet('world')。 运行结果是: [greeter:v1] 已上线 Error: cannot get property "greeter" without inject 结论:会直接报错。 原因是 Cordis 对 ctx.greeter 这种服务属性访问有依赖声明校验。consumer 没有声明 inject: ['greeter'],就不能直接通过 ctx.greeter 读取 greeter 服务。即使 root 上已经提供了 greeter,也会报 cannot get property "greeter" without inject。 所以 inject 不只是表示“等 greeter 服务就绪后再启动 consumer”,它也表示“consumer 允许通过 ctx.greeter 直接访问这个服务”。 第二种情况:把 consumer 里的访问方式改成软探测: const g = ctx.get('greeter') if (g) console.log(g.greet('world')) 运行时先挂载 consumer,此时 greeter 还不存在。 运行结果是: --- 先挂载 consumer,此时 greeter 缺失 --- [consumer] greeter missing, skipped [greeter:v1] 已上线 --- 撤销 greeter --- [greeter:v1] 已下线 --- 新 greeter 上线 --- --- 撤销 greeter v2 --- [greeter:v2] 已下线 结论:ctx.get('greeter') 在 greeter 缺失时不会报错,会返回空值,所以可以静默跳过。 但这里有个关键点:如果 consumer 没有 inject,那么 greeter 后续上线、下线,都不会触发 consumer 自动重启。consumer 只在自己挂载时执行一次。后面 greeter:v1 上线、下线、greeter:v2 上线、下线,consumer 都不会再次执行。 最终区别可以这样理解: 硬依赖写法: inject: ['greeter'] apply(ctx) { console.log(ctx.greeter.greet('world')) } 行为是:greeter 缺失时 consumer 不启动;greeter 上线后 consumer 自动启动;greeter 下线后 consumer 自动停止;新的 greeter 上线后 consumer 自动重启。 软依赖写法: apply(ctx) { const g = ctx.get('greeter') if (g) console.log(g.greet('world')) } 行为是:greeter 缺失时不报错,可以静默跳过;但 greeter 上线或下线不会自动触发 consumer 重启。 总结: inject 是硬依赖,参与 Cordis 的生命周期调度;ctx.get 是软依赖,只是当前时刻查一下有没有这个服务,不参与自动启停。
    展开

    作者回复: 你好,赞👍

    
    1