-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
| 文件 | 放什么 | 进版本库? |
|---|---|---|
ipclick.toml |
行为配置:超时、重试、限流、引擎、集群拓扑 | ✅ 应该进 |
.env |
机密:令牌、密码、集群密钥、代理凭据 | ❌ 绝不能进 |
规则一句话:.env 只放机密,ipclick.toml 只放行为。
.env 里认的键(ipclick -e env 会输出这份模板):
IPCLICK_AUTH_TOKEN gRPC 鉴权令牌
IPCLICK_WEB_USER Web 管理端用户名
IPCLICK_WEB_PASSWORD Web 管理端密码
IPCLICK_PROXY_AUTH_KEY 代理账号
IPCLICK_PROXY_AUTH_PASSWORD 代理密码
IPCLICK_CLUSTER_SECRET 集群共享密钥(所有节点一致;每台的令牌由它派生)
机密写进 ipclick.toml 仍然生效——受信环境里图省事是合理的。只是启动时会点名提醒
(ipclick.toml 通常要进版本库,机密会跟着进 git、备份、CI 日志)。确实想这么放就设
[SECURITY].allow_secrets_in_config = true 关掉提醒。两边都写时环境变量优先。
ipclick config-info 会逐项显示每个机密来自哪里:
机密来源:
gRPC 鉴权令牌 环境变量 / .env
Web 管理端密码 配置文件 ⚠️ 建议改用环境变量
集群共享密钥 未配置
-
命令行参数 / 构造函数参数 ——
ipclick run -p 9527、Downloader(port=9527) - 真实环境变量
-
当前工作目录的
.env—— 只填补尚未设置的变量,不覆盖已有的 -
配置文件 ——
-c指定的,或当前目录的ipclick.toml/.ipclick.toml ~/.ipclick/config.toml- 包内默认配置
.env 排在真实环境变量之后是有意的:容器编排、CI、systemd 注入的变量必须能压过
仓库里那个用于本地开发的 .env。
配置文件的查找不向上递归——只看当前工作目录。这样"我在哪个目录起的服务"和 "用了哪份配置"是一一对应的,不会莫名其妙捡到上层目录的配置。
除了机密,这几个部署参数也能用环境变量给(给容器编排注入用):
| 环境变量 | 覆盖 |
|---|---|
IPCLICK_HOST / IPCLICK_PORT
|
[SERVER].host / port
|
IPCLICK_MAX_WORKERS |
[SERVER].max_workers |
IPCLICK_MODE |
[GENERAL].mode |
IPCLICK_LOG_LEVEL |
[LOG].level |
IPCLICK_CLUSTER_SELF_ID |
[CLUSTER].self_id —— 多台机器共用一份配置时靠它区分身份 |
这张表集中定义在 config_loader/loader.py 的 ENV_OVERRIDES 里。散着写 os.getenv
的话,"到底哪些环境变量有用"只能靠翻代码,文档也必然和实现失步。
| 节 | 管什么 | 详见 |
|---|---|---|
[GENERAL] |
运行模式(单机 / 集群 / auto)、调试开关 | 本页 |
[SERVER] |
监听地址、端口、worker 线程数 | 本页 |
[CLIENT] |
客户端到服务端这一跳的重试、请求压缩 | 性能 |
[PROXY] |
出站代理 | 本页 |
[CLUSTER] |
集群形态、节点列表、负载均衡、探活 | 集群 |
[SECURITY] |
鉴权令牌、TLS/mTLS、SSRF 防护 | 安全 |
[DOWNLOADER] |
超时、重试、连接池、按 host 限流 | 性能 |
[BROWSER] |
浏览器引擎与渲染行为 | 浏览器渲染 |
[TRACE] |
链路记录与落盘 | 链路记录 |
[WEB] |
Web 管理端 | Web 管理端 |
[MONITOR] |
健康检查开关 | 本页 |
[LOG] |
日志级别、输出、轮转 | 本页 |
每一项的完整注释就在 ipclick.toml 里(ipclick -e toml 可以随时看)——
那份模板是配置项的唯一权威来源,每一项都写了默认值的理由和配错的症状。
[GENERAL]
mode = "standalone" # standalone / cluster / auto
debug = false # 强制 DEBUG 级别日志,覆盖 [LOG].levelmode 决定 create_client() 返回单机还是集群客户端:
-
standalone—— 单节点Downloader -
cluster——ClusterDownloader。没配任何节点时直接报错,不会静默退回单机。 静默退回会让你以为集群生效了,实际所有流量都打在一个节点上、也没有故障转移。 -
auto—— 配了节点就走集群,没配就单机
[SERVER]
host = "[::]" # 监听地址。"[::]" = 所有网卡(IPv4 + IPv6)
port = 9527
max_workers = 100 # gRPC 线程池大小max_workers 有三重含义,调之前要知道:
- 同时能处理多少个请求 —— 服务端是一请求一线程做阻塞 IO
-
SendBatch的并发度上限(批量不会再开一个自己的池,否则总并发变成max_workers × 批量数,把下游打爆) - gRPC 的
maximum_concurrent_rpcs设为它的两倍,超出的请求排队而不是无限堆积
按 host 限流的等待也占着线程,所以 per_host_max_concurrent 设得很小时,
max_workers 要留够余量。见性能。
端口撞了会直接起不来(IPClick 显式关掉了
SO_REUSEPORT)。 gRPC 默认开着它,后果是两个进程都在监听、请求被内核随机分给其中一个—— 症状是"改了配置只有一半生效",极难定位。
[PROXY]
scheme = 'http'
host = ''
port = 0
# 账号密码走 .env:IPCLICK_PROXY_AUTH_KEY / IPCLICK_PROXY_AUTH_PASSWORD
# 三方隧道代理
channel_name = ''
session_ttl = ''
country_code = ''
tunnel_server = ''默认留空表示未配置代理,此时 proxy=True 会打一条警告并直连。
这里刻意不预置
127.0.0.1:7890之类的本地代理地址——否则所有用户的proxy=True都会指向他们自己机器上的某个端口(可能是别的服务)。
请求级用法:
d.get(url, proxy=True) # 用 [PROXY] 配置
d.get(url, proxy="http://user:pw@host:8080") # 直接给串
d.get(url, proxy=False) # 强制直连[MONITOR]
health_check = true # 注册 grpc.health.v1(免鉴权,供 K8s 探针用)
[LOG]
level = "info" # debug / info / warning / error
format = "" # 留空用内置格式
output = "stdout" # 三种写法见下
[LOG.rotation]
max_size = 100 # 单文件最大 MB(output 为文件时生效)
max_backups = 5output = "stdout" # 只打控制台(默认);"stderr" 同理
output = "logs/app.log" # 写这个文件;没有扩展名时自动补 .log
output = "logs/" # 以斜杠结尾 = 写进这个**目录**,文件名用 ipclick.log0.3 的第三种写法是坏的。
output = "logs/"会被当成"缺扩展名的文件名",logs被改写成同级的logs.log,而logs/目录里空空如也——且不报任何错。 用户以为配好了,真出问题时找不到日志在哪。0.4 修了:以/结尾、或指向一个已存在 的目录,都视为目录。填明确文件名的行为不变。
[LOG].format 的坑:底层是 loguru,占位符是 {time} / {level} / {message}
这种花括号写法,不是标准库 logging 的 %(asctime)s。写成后者的话 loguru 会把它当
普通文本原样打出来,每行日志变成一串字面量。所以 IPClick 会识别出这种写法、告警并忽略,
而不是照用。
例:format = "[{time:YYYY-MM-DD HH:mm:ss}] {level: <8} | {message}"
用 --port 就能把 gRPC 端口岔开,但有两项会静默撞车:
| 配置项 | 撞车表现 |
|---|---|
[TRACE].sqlite_path |
多实例写同一个库,链路记录混在一起,界面上完全看不出来 |
[LOG].output |
多进程抢写同一个日志文件 |
[WEB].port |
第二个实例的 Web 端起不来(这个有明确报错) |
前两项不报错、不提示,比"起不来"糟得多——用户以为在看单个实例的数据,实际是多进程 合并的结果。
两项路径值都支持 {port} 占位符,替换成运行时实际生效的监听端口
(--port 覆盖之后的那个,不是配置文件里的原始值):
[TRACE]
sqlite_path = "ipclick-trace.{port}.db" # -> ipclick-trace.9528.db
[LOG]
output = "logs/{port}/app.log" # 占位符在路径中间也行[WEB].port 则补了命令行覆盖(gRPC 端口一直有 --port,Web 端此前没有):
ipclick run --port 9528 --web-port 9531 -w为什么用占位符,而不是在代码里自动加端口后缀。 自动加后缀会改掉已有部署里用户
自己写死的路径——旧日志和 trace 数据看起来就像丢了。占位符则是:新用户从
ipclick init / ipclick -e 拿到的模板默认就带 {port},天然按端口分离;已有部署
一个字符都不变。而且这条规则写在 toml 里是看得见的,不是藏在代码里的隐式行为。
已有配置想要这个行为,手动把路径改成带 {port} 即可。
即便如此,真撞上了还是会打一条明确告警——检测到目标库正被另一个进程写入时提醒一句, 而不是静默合并。
范围:主要影响"单机模拟多节点"的测试 / 开发场景。生产环境每台机器独立文件系统, 不受影响。
Web 管理端的「配置」页可以改白名单内的行为配置,
写回 ipclick.toml:定点文本替换,保留注释与格式,改动前留 .bak,
写入用临时文件 + os.replace(断电不会留下半个配置文件)。
不可从网页修改:[SECURITY] 全部、Web 自己的登录凭据、集群共享密钥与各节点 token、
[BROWSER].allow_scripts。理由见 Web 管理端。
0.4 起配置页还能生成鉴权令牌 / Web 密码 / 集群共享密钥——只显示一次、服务端不保存,
给出可以直接粘进 .env 的那一行。生成而不是写入,是因为机密的正规位置始终是 .env;
集群共享密钥尤其不能自动写,每台各自生成一个就全对不上了。
ipclick config-info这个命令回答的是「什么真生效了」,而不是「配置文件里写了什么」——两者不一样: 环境变量会覆盖、有些项有默认值、有些项写错了会被忽略。输出里包括绑定地址、 TLS 与鉴权状态、每个机密的来源、限流设置、浏览器引擎与本体就绪状态、链路记录状态。