Flower v1.14.0 版本解读:flwr stop 命令、CLI JSON 输出与 OIDC 认证基础设施
【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower
Flower v1.14.0(发布于 2024-12-20)围绕flwr命令行工具的运行管理能力展开:新增flwr stop命令用于停止已提交的 run,并为flwr run、flwr ls、flwr stop三个命令提供--format json输出,便于接入自动化工具;同时首次引入基于 OIDC 的用户认证扩展点。读完本文,你可以正确停止一个正在运行的 Flower App,掌握 JSON 输出中各字段的含义,理解 StopRun 在 SuperLink 侧的完整调用链,并知道如何把依赖已移除Client.context属性的旧代码迁移到client_fn(context: Context)签名。
一、v1.14.0 变更概览
本版本的完整变更清单见 v1.14.0 更新日志。主要特性可归为四类:
| 类别 | 要点 |
|---|---|
| 新特性 | flwr stop命令;run/ls/stop命令支持--format json;OIDC 用户认证扩展点 |
| 生态 | FedRep baseline 迁移到flwr run启动方式;模拟教程系列改版为 Flower Apps 流程 |
| 健壮性 | ServerApp↔SuperLink、ClientApp↔SuperNode、SuperLink↔Simulation 三类连接的网络可靠性提升;flwr new在 Windows 上的 UTF-8 修复 |
| 不兼容变更 | 移除Client与NumPyClient的context属性 |
此外还包含文档改进(新增 Microsoft Azure 虚拟机部署指南)、CI/CD 基础设施更新、缺陷修复与通用维护,下文逐项结合源码展开。
二、flwr stop命令:停止已提交的 Run
2.1 用法
根据 changelog 的说明,该命令支持两种写法:
flwr stop <run-id> flwr stop <run-id> [<app>] [<federation>]第二种形式是遗留兼容写法。命令的语义是指令 SuperLink 终止指定 run。需要特别注意:ServerApp与ClientApp进程不会因此被瞬间中断,它们会在下一次与 SuperLink 通信时获知 run 已停止,然后优雅地自行退出。这种"软停止"设计避免了强杀进程可能遗留的任务队列脏状态。
2.2 CLI 侧实现
实现入口在 stop.py。stop函数(L41-L91)的核心步骤:
- 进入
cli_output_handler上下文管理器,确定是否以 JSON 模式输出; - 调用
migrate对遗留参数(旧式位置参数<app>/<federation>)做兼容迁移; - 通过
read_superlink_connection读取 SuperLink 连接配置(可选位置参数superlink指定连接名); - 用
init_http_client_from_connection构建ControlHttpClient,经 Control API 发送StopRunRequest(run_id=run_id); - 成功时打印 "Run {run_id} successfully stopped.";若使用
--format json,额外向 stdout 输出{"success": true, "run-id": "<id>"};失败则抛出ClickException(见 stop.py L94-L118)。
--format选项定义为Literal["default", "json"],默认值CliOutputFormat.DEFAULT(stop.py L59-L66)。该常量定义于 constant.py:CliOutputFormat仅有default与json两个取值,且禁止实例化,保证只作为常量使用。
2.3 SuperLink 侧的 StopRun 调用链
SuperLink 端的处理分三层:
1. 请求路由。Control API 提供两个等价入口:gRPC 服务的 ControlServicer.StopRun 与 HTTP 路由 router.py 中的 stop_run(挂载在/v1/control前缀下),二者最终都收敛到 control_handlers.py 的stop_run处理函数。
2. 处理器校验。control_handlers.stop_run依次执行:
- 从 LinkState 查询 run 记录,不存在则抛出
RUN_ID_NOT_FOUND错误; - 通过
_validate_federation_membership_in_request校验当前账号是否为该 run 所属联邦的成员,未授权则拒绝; - 若 run 状态已是
FINISHED,抛出RUN_ALREADY_FINISHED错误; - 最后调用
state.stop_run(run_id),将其布尔返回值封装为StopRunResponse(success=...)。
3. 状态迁移与清理。抽象方法 LinkState.stop_run 约定"停止 run 并清理 run 级消息与对象",当至少一个未完成任务迁移为 stopped 时返回True。内存实现 InMemoryLinkState.stop_run 给出了具体步骤:找到 run 的主任务(primary task),对其执行finish_task(primary_task_id, SubStatus.STOPPED, ""),主任务的停止会级联停止其全部任务,随后cleanup_run(run_id)清理该 run 的消息与对象。基于 SQL 的 SqlLinkState.stop_run 逻辑一致,只是持久化到 SQLite 后端。
测试佐证。control_servicer_test.py 断言:调用StopRun后,run 状态变为RunStatus(Status.FINISHED, SubStatus.STOPPED, ""),且delete_objects_in_run被调用一次以清理 run 级对象。另有权限测试(L1979-L1995):非联邦成员发起的StopRun会被FEDERATION_NOT_FOUND错误拒绝,联邦成员则成功并得到相同的 FINISHED/STOPPED 状态。
三、CLI JSON 输出:--format json
v1.14.0 为flwr run、flwr ls、flwr stop三个命令统一增加了--format json标志,目的是让 CLI 输出可被解析,方便与其他工具集成(如 CI 脚本、日志收集)。
3.1 统一的输出机制
三个命令都复用 utils.py 中的两个工具:
- cli_output_handler:上下文管理器。请求 JSON 格式时,将 stdout/stderr 重定向到内存缓冲区,吞掉面向人的进度日志,保证输出流只含 JSON;异常也会统一处理,在 JSON 模式下将错误序列化为 JSON 结构输出;
- print_json_to_stdout:通过
sys.__stdout__把 JSON 直接打印到系统真实 stdout,绕过上面的重定向,确保 JSON 负载即使在输出被捕获的场景下也能到达终端或管道。
3.2flwr ls的 JSON 字段结构
ls.py 是 JSON 输出最完整的示例。ls支持--run-id(查看单个 run,垂直详情表)与--limit(限制列表条数)两个选项,--limit最小值为 1,且与--run-id互斥(L109-L113 直接抛ValueError)。人类可读视图展示 Run ID、Federation、App、Status、Elapsed、Status Changed @ 等列;启用--format json时,数据由_to_json(L279-L324)序列化为如下结构:
{ "success": true, "runs": [ { "run-id": "123", "federation-id": "...", "fab-id": "account/app", "fab-name": "app", "fab-version": "v1.0.0", "fab-hash": "...", "status": "running", "status-details": "", "elapsed": "...", "pending-at": "YYYY-MM-DD HH:MM:SSZ", "starting-at": "...", "running-at": "...", "finished-at": "...", "network-traffic": { "inbound-bytes": 0, "outbound-bytes": 0, "total-bytes": 0 }, "compute-time": { "serverapp-seconds": 0, "clientapp-seconds": 0, "total-seconds": 0 } } ] }按ls的 docstring 约定,所有时间戳遵循 ISO 8601 UTC,格式为YYYY-MM-DD HH:MM:SSZ。状态文本形如finished:stopped,_get_status_style(L139-L163)会解析其中的子状态用于着色:completed 绿色、failed 红色、stopped 黄色,starting/running 蓝色,pending 灰色——从源码结构看,finished:stopped正是flwr stop停止 run 后在列表中呈现的状态。
3.3 选项定义的一致性
在 run.py 与 stop.py 的参数定义中,--format选项统一为case_sensitive=False,帮助文本 "Format output using 'default' view or 'json'",取值大小写不敏感,三个命令默认值均为default。
四、OIDC 用户认证基础设施
Flower 自 v1.9 起支持 SuperNode 认证(SuperNode 与 SuperLink 之间的互相认证),v1.14.0 则增加了基于 OpenID Connect(OIDC)的用户认证初始扩展点,为后续的账号登录、联邦与权限功能打底。从源码结构看,该功能落在三层:
- 常量层。constant.py 新增
AuthnType,取值为NOOP与OIDC,用于声明认证类型; - 认证插件层。auth_plugin.py 定义了 SuperLink 侧认证插件契约:
get_login_details()返回 OIDC 设备授权流程所需的登录详情(authn_type、device_code、verification_uri_complete、expires_in、interval,组装逻辑见 control_handlers.py 的 get_login_details),get_auth_tokens(device_code)则用设备码换取账号凭证(get_auth_tokens处理见 L1420 附近);默认实现 noop_auth_plugin.py 返回空的 device_code,未启用 OIDC 的部署不受影响; - 协议层。
GetLoginDetailsRequest/Response、GetAuthTokensRequest消息对贯穿 Control API,gRPC 拦截器与 HTTP 路由层均覆盖这两个调用,可在 control_account_auth_interceptor_test.py 与 router_test.py 中看到以authn_type="oidc"和 device-code 请求验证完整登录链路的测试用例。
changelog 明确称其为 "initial extension points",即本版本只开放接口与流程骨架,具体 IdP 接入是后续版本的事。
五、本版本其他改进
5.1 FedRep baseline 迁移到flwr run
本版本启动将 baselines 从旧式start_simulation迁移到通过flwr run启动的工作,FedRep 因其效果突出成为首个迁移对象,对应代码位于 baselines/fedrep。新建 baseline 可以从flwr new模板起步,采用flwr run兼容格式,贡献指引见 how-to-contribute-baselines.rst。
5.2 模拟教程系列改版
examples/flower-simulation-step-by-step-pytorch 已更新,新版演示如何通过flwr run创建并运行 Flower App,覆盖自定义策略、ClientApp 与 ServerApp 之间的 metrics 传递、全局模型 checkpoint 创建、将 metrics 记录到 Weights & Biases 等环节。
5.3 连接可靠性与 Windows 修复
- ServerApp↔SuperLink、ClientApp↔SuperNode、SuperLink↔Simulation 三类连接对网络问题的抗扰性提升。从源码结构看,重试与心跳基础设施位于 grpc_retry.py、heartbeat.py 等 supercore 模块,本版本沿上述三类连接做了加固;
flwr new通过设置 UTF-8 编码在 Windows 上正确创建与传输文件,解决了跨平台编码兼容问题。
5.4 其他维护工作
- 示例与
flwr new模板更新:移除不必要的numpy依赖、升级mlx版本、增强认证示例; - 文档改进:docstring 更新、拼写修正、新增贡献指引,并引入自动同步机制保证翻译源文本常新;本版本还新增了 Microsoft Azure 虚拟机上部署 Flower 的入门指南;
- 基础设施与 CI/CD 更新、缺陷修复、通用改进:涉及 PR 众多,清单以 changelog 原文为准。
六、不兼容变更:移除context属性
由于Context已可以作为参数传入client_fn与server_fn,v1.14.0 正式移除了Client和NumPyClient上的context属性——该特性已废弃数个版本,现在是移除时点。
当前代码库中的正确用法:
client_fn签名为def client_fn(context: Context)并返回 Client 实例,调用处为client = client_fn(context)(见 message_handler.py L95-L98);ClientApp源码中对client_fn的同样签名约束与提示见 client_app.py;NumPyClient定义位于 compat/client/numpy_client.py。
如果从 v1.13.x 升级:凡是依赖client.context的代码,需要改为在client_fn内部直接使用作为参数传入的context,同时确保 Flower 框架版本升级到 v1.14.0 及以上。
七、小结
Flower v1.14.0 的主题是运行期的"运维工程化":flwr stop补齐了 run 生命周期管理的最后一块(启动、列表、停止),--format json为run/ls/stop提供了机器可读接口,使 Flower CLI 可以被 CI 流水线与自动化脚本直接包装;OIDC 扩展点则启动了用户认证能力。对使用者而言,升级时的唯一硬性动作是处理Client.context属性移除带来的签名调整。以上行为均基于当前仓库的实际代码,文中给出了对应的源码文件路径与行号,可直接查证。
【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考