- 后端
- Web框架
【免费下载链接】sanic
Accelerate your web app development | Build fast. Run fast.
Sanic Inspector 是 Sanic Server 内置 Worker Manager 体系中的一项管理能力,它以独立进程、独立应用、独立 socket的方式运行在你的 Sanic 实例后台,让开发者通过 CLI 或 HTTP API 与运行中的应用程序交互:查看实例状态、触发 worker 重载、优雅关闭全部进程、动态伸缩 worker 数量,甚至注册任意自定义命令。读完本文,你将掌握 Inspector 的启用方式、内置命令、自定义命令扩展、TLS 与 API Key 生产加固,以及它背后与WorkerManager、multiplexer协同工作的底层原理。
注意:Inspector 从 v22.9 开始以有限能力引入,本文内容以 v22.12 及以上版本为准。
Inspector 是什么
Inspector 是 Sanic 的一个可选组件,只有在使用内置 Worker Manager 运行时才可用(即默认的多进程运行模式)。它是一个 HTTP 应用,可以在你的应用程序后台"可选地"运行,用于与运行中的实例交互。
从源码结构看,Inspector 的本质是一个独立的 Sanic 应用。在 sanic/worker/inspector.py 中,Inspector类被设计为一个可调用对象:当它被调用时,会创建一个名为"Inspector"的 Sanic 应用,并以single_process=True的方式运行在一个独立的 socket 上:
# sanic/worker/inspector.py 中的核心逻辑(节选) self.app = Sanic("Inspector") self._setup() if run: self.app.run( host=self.host, port=self.port, single_process=True, ssl={"key": self.tls_key, "cert": self.tls_cert} if not isinstance(self.tls_key, Default) and not isinstance(self.tls_cert, Default) else None, )它在你的 Sanic 应用之外单独存在,因此:
- 它不是跑在 Sanic 应用内部的中间件或路由,而是一个分离的进程、一个分离的应用、暴露在一个分离的 socket 上;
- 默认绑定在
localhost:6457; - 只有当
app.config.INSPECTOR为True时,主进程(Main process)才会把它作为一个非 server 进程注册到 Worker Manager 中。
在 sanic/mixins/startup.py 中可以看到它的注册逻辑:
inspector = None if primary.config.INSPECTOR: ... inspector = primary.inspector_class( monitor_pub, app_info, worker_state, primary.config.INSPECTOR_HOST, primary.config.INSPECTOR_PORT, primary.config.INSPECTOR_API_KEY, primary.config.INSPECTOR_TLS_KEY, primary.config.INSPECTOR_TLS_CERT, ) manager.manage("Inspector", inspector, {}, transient=False)这里manager.manage(...)将其注册为transient=False的 durable(持久)进程,意味着它不会被 auto-reloader 随文件变更重启。
启用 Inspector
Inspector 默认是关闭的。启用它有两种等价方式:
方式一:创建应用实例时传入标志
app = Sanic("TestApp", inspector=True)方式二:设置配置值
app = Sanic("TestApp") app.config.INSPECTOR = True⚠️ 警告:如果使用配置值的方式,必须在主 worker 进程启动之前尽早设置。这意味着它要么是环境变量,要么像上面这样在创建应用实例后立刻设置。
在源码 sanic/app.py 中可以看到,inspector=True本质上也是写入配置:
if inspector: self.config.INSPECTOR = inspector而 sanic/config.py 中给出了所有 Inspector 相关配置的默认值:
"INSPECTOR": False, # 是否启用 Inspector "INSPECTOR_HOST": "localhost", # 绑定主机 "INSPECTOR_PORT": 6457, # 绑定端口 "INSPECTOR_TLS_KEY": _default, # TLS 私钥路径 "INSPECTOR_TLS_CERT": _default,# TLS 证书路径 "INSPECTOR_API_KEY": "", # API 认证密钥(空表示不启用认证)使用 Inspector
一旦 Inspector 运行起来,你可以通过两种方式访问它:CLI 或直接 HTTP 访问其 Web API。
通过 CLI
sanic inspect通过 HTTP
curl http://localhost:6457CLI 底层就是一个 HTTP 客户端。在 sanic/cli/inspector_client.py 中,InspectorClient使用 Python 标准库urllib发起请求,并根据secure参数决定使用https还是http协议;在 sanic/cli/app.py 中,_inspector()方法负责解析sanic inspect后面的参数,将 host、port、secure、raw、api_key 剥离出来,剩余参数作为 action 及自定义命令参数交给InspectorClient.do(action, **kwargs)。
CLI 与 HTTP 的对照关系如下:
| CLI 命令 | HTTP 动作 | 说明 |
|---|---|---|
sanic inspect | GET / | 显示运行中应用的基本信息 |
sanic inspect reload | POST /reload | 触发所有 server worker 的重载 |
sanic inspect shutdown | POST /shutdown | 触发所有进程的关闭 |
sanic inspect scale N | POST /scale,body{"replicas": N} | 将 worker 数量伸缩到 N |
CLI 的完整参数(定义于 sanic/cli/inspector.py):
--host, -H:Inspector 主机地址,默认localhost--port, -p:Inspector 端口,默认6457--secure, -s:通过 TLS 加密访问 Inspector--api-key, -k:Inspector 认证密钥--raw:输出原始响应信息(不经过 MOTD 格式化)- 子命令:
reload(支持--zero-downtime)、shutdown、scale <replicas>、<custom>(自定义命令)
内置命令的底层实现
内置命令并不是"魔法",而是Inspector类上的真实方法(见 sanic/worker/inspector.py),每个方法通过_publisher(一条multiprocessing.connection.Connection)向主进程的 monitor 管道发送指令消息:
- reload:发送
"__ALL_PROCESSES__:";若带zero_downtime=True,则发送"__ALL_PROCESSES__::STARTUP_FIRST",即先启动新进程、等它 ack 后再拆除旧进程,实现零停机重载; - scale:发送
"__SCALE__:{num_workers}",由 sanic/worker/manager.py 的_handle_message解析后调用self.scale(int(...))执行真正的伸缩; - shutdown:发送
"__TERMINATE__",主进程收到后触发整体关闭。
这些行为在 tests/worker/test_inspector.py 中有对应的测试验证,例如:
def test_run_inspector_reload_zero_downtime(publisher, http_client): _, response = http_client.post("/reload", json={"zero_downtime": True}) assert response.status == 200 publisher.send.assert_called_once_with("__ALL_PROCESSES__::STARTUP_FIRST") def test_run_inspector_scale(publisher, http_client): _, response = http_client.post("/scale", json={"replicas": 4}) assert response.status == 200 publisher.send.assert_called_once_with("__SCALE__:4")注意scale的语义是伸缩到 N 个 worker(WorkerManager.scale内部通过create_server()扩容、shutdown_server()缩容),而不是"增加 N 个"。
自定义命令
Inspector 可以非常容易地扩展出自定义命令(以及对应的 HTTP endpoint)。
编写自定义方法
子类化Inspector类,并创建任意方法。只要方法名不以_(下划线)开头,该方法名就会成为 Inspector 上的一个新子命令:
from sanic import json from sanic.worker.inspector import Inspector class MyInspector(Inspector): async def something(self, *args, **kwargs): print(args) print(kwargs) app = Sanic("TestApp", inspector_class=MyInspector, inspector=True)这样会按以下通用模式暴露自定义方法:
- CLI:
sanic inspect <method_name> - HTTP:
POST /<method_name>
从源码看,HTTP 路由在_setup()中统一注册为self.app.post("/<action:str>")(self._action),_action通过getattr(self, action, None)查找对应方法并调用(sanic/worker/inspector.py)。因此任何不带下划线前缀的方法天然成为一个 endpoint。
参数传递规则
新方法接受什么参数,取决于你打算如何使用该命令。例如上面的something方法接受所有位置参数和关键字参数。
在 CLI 中,位置参数和关键字参数会作为位置参数或关键字参数传递给方法。所有值都是str,但有如下例外:
- 一个没有赋值的关键字参数,其值为
True; - 如果参数以
no-为前缀,则其值为False。
sanic inspect something one two three --four --no-five --six=6在你的应用日志控制台,你会看到:
('one', 'two', 'three') {'four': True, 'five': False, 'six': '6'}这个解析逻辑位于 sanic/cli/app.py 的_inspector()方法中:--开头的参数若含=则拆分为 key/value,否则--no-前缀解析为False、普通标志解析为True。
直接调用 API也能达到同样的效果:把参数放到 JSON payload 中传给方法。唯一需要注意的是,位置参数应放在{"args": [...]}中:
curl http://localhost:6457/something \ --json '{"args":["one", "two", "three"], "four":true, "five":false, "six":6}'在你的应用日志控制台,你会看到:
('one', 'two', 'three') {'four': True, 'five': False, 'six': 6}注意 HTTP 方式下 JSON 中的类型会被保留(如six是整数6),而 CLI 方式下所有值都是字符串(如'6')。
在生产环境使用
⚠️ 危险:在把 Inspector 暴露到生产环境之前,请仔细考虑本节的所有选项。Inspector 是一个能触发 worker 重载、关闭、伸缩的管理接口,一旦暴露在公网且未做防护,任何人都可能关闭你的服务。
在远程生产实例上运行 Inspector 时,你可以通过以下两种方式保护 endpoint:要求 TLS 加密,以及要求 API Key 认证。
TLS 加密
为 Inspector 的 HTTP 实例启用 TLS,需要传入证书和密钥的路径:
app.config.INSPECTOR_TLS_CERT = "/path/to/cert.pem" app.config.INSPECTOR_TLS_KEY = "/path/to/key.pem"配置后,访问时必须使用--secure标志,或使用https://协议:
sanic inspect --secure --host=<somewhere>curl https://<somewhere>:6457对应地,sanic/worker/inspector.py 中只有同时配置了tls_key和tls_cert时才向app.run()传入ssl参数;而InspectorClient会根据secure选择httpsscheme 发起请求。
API Key 认证
你可以使用 Bearer Token 认证来保护 API:
app.config.INSPECTOR_API_KEY = "Super-Secret-200"配置后,访问时需要--api-key参数,或携带 Bearer Token 授权头:
sanic inspect --api-key=Super-Secret-200curl http://localhost:6457 -H "Authorization: Bearer Super-Secret-200"其认证实现见 sanic/worker/inspector.py:
def _authentication(self, request: Request) -> None: if request.token != self.api_key: raise Unauthorized("Bad API key")当api_key非空时,_setup()会为 Inspector 应用注册on_request钩子,比较请求中的 token(即Authorization: Bearer头中的值)与配置的密钥,不一致则抛出Unauthorized。CLI 侧则在 sanic/cli/inspector_client.py 中自动附加authorization: Bearer {api_key}头。
配置项总览
所有 Inspector 相关配置项、默认值与说明如下(默认值来源 sanic/config.py,表格来源 configuration 文档):
| 配置项 | 默认值 | 说明 |
|---|---|---|
INSPECTOR | False | 是否启用 Inspector |
INSPECTOR_HOST | localhost | Inspector 绑定主机 |
INSPECTOR_PORT | 6457 | Inspector 绑定端口 |
INSPECTOR_TLS_KEY | - | Inspector 的 TLS 私钥路径 |
INSPECTOR_TLS_CERT | - | Inspector 的 TLS 证书路径 |
INSPECTOR_API_KEY | - | Inspector 的 API 认证密钥 |
版本演进方面:
- v22.9 新增了
INSPECTOR; - v22.12 新增了
INSPECTOR_HOST、INSPECTOR_PORT、INSPECTOR_TLS_KEY、INSPECTOR_TLS_CERT、INSPECTOR_API_KEY。
更完整的配置说明可参考 Running - Configuration。
与 Worker Manager 的关系
Inspector 是 Worker Manager 体系中的一个内置非 server 进程(与 auto-reloader 并列)。Worker Manager 负责管理所有进程,而 Inspector 则把 Manager 的部分能力(重载、关闭、伸缩)以及所有进程的运行状态,通过 HTTP/CLI 暴露出来。
从 manager 文档 可以看到,一旦启用了 Inspector(app.config.INSPECTOR = True),你就可以执行这些 CLI 命令:
sanic inspect reload Trigger a reload of the server workers sanic inspect shutdown Shutdown the application and all processes sanic inspect scale N Scale the number of workers to N sanic inspect <custom> Run a custom command要理解 Inspector 的完整能力边界,需要先了解 Worker Manager 的进程模型、multiplexer(app.m)、worker 状态机(NONE/IDLE/STARTING/STARTED/ACKED/JOINED/TERMINATED/RESTARTING/FAILED/COMPLETED)以及自定义进程的注册方式,这些内容可继续阅读 Worker Manager。
小结
Sanic Inspector 为运行中的多进程实例提供了一条轻量的管理通道:一条 CLI 命令sanic inspect或一个curl调用,就能完成状态查看、worker 重载、进程关闭与数量伸缩;通过子类化Inspector,还能把任意业务方法暴露为自定义管理命令。在生产环境中,务必组合使用 TLS 与 API Key 双保险,将管理能力牢牢锁在可信网络内。
- 后端
- Web框架
【免费下载链接】sanic
Accelerate your web app development | Build fast. Run fast.
相关推荐
JupyterHub项目实战:如何独立运行中转服务与Hub服务
JupyterHub项目实战:如何独立运行中转服务与Hub服务 前言 在JupyterHub的架构设计中,中转服务 Proxy 扮演着至关重要的角色。它作为用户
后端微服务webpack Web Worker 实战解析:`new Worker()`/`new SharedWorker()` 的分包、命名与独立运行时
webpack Web Worker 实战解析: new Worker / new SharedWorker 的分包、命名与独立运行时 本技术指南以仓库中的官方
前端构建开发工具用 EasyOCR 搭建 LiteParse 独立 OCR 服务:部署、HTTP API 与接入实战
用 EasyOCR 搭建 LiteParse 独立 OCR 服务:部署、HTTP API 与接入实战 LiteParse 除了内置的 Tesseract OCR
OCR文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考