Skip to content

[Feature] Optimize the icon synchronization logic in the App Store #11697

@HynoR

Description

@HynoR

1Panel Version

2.0.17

Please describe your needs or suggestions for improvements

应用商店经过加日志测试,在 2c2g 美西小鸡(nvme磁盘)上测试结果如下

download_zip:≈ 1.06s 下载1panel.json.zip
decompress:≈ 0.024s 解压
json_decode:≈ 0.097s 序列化解码
sync_detail:03:40:21.361 → 03:42:35.716 ≈ 134.36s(> 99%) 从oss上同步资源信息
db: 0.24s

可见其实 1panel应用商店同步逻辑中,时间卡在了sync_detail上,对于其他数据入库其实几乎在一秒内完成
然而 sync_detail 这个并非是机器性能导致的问题,134s 全部在扫描目前 226 个 app,对于每个 app 检查和下载一次图标,有的会下载版本的 compose 文件。

sync_detail 具体问题:

  1. req_helper 里对包装函数的滥用
Image

handle request函数里,每次请求调用都会新建一个 http client, 这个操作消耗是巨大的,对于 226 个 app 的同步,会创建 226 个 http client, 创建的时候至少有一倍的开销,并且每个 client 独立链接、无法复用链接.

#11691 进行了优化,把同步速度从 132s 优化到了 90s 左右,并且少创建了数百个 client,对性能的浪费更小

  1. icon 存储问题
    这是一个灾难性问题

首先图标下载的端点,1panel oss 用的阿里云是有 etag 的支持,可以你传已有文件的 etag,让对面回 304,这样可以知道 oss 里数据没有更新,减少流量开支,同时 1panel 面板传图标给用户时也可以采用这个逻辑。由于存库导致了无法正常使用 etag,而如果需要强行支持 etag 则每次都得重算,不能复用。这也是为什么我当时关闭pr
#11136 的问题,治标不治本。

第二个icon 是 b64后存在 sqlite 里的,把数据库当做 s3 来用。数据库本身就不应该存这种东西,sqlite时结构化数据库,一个图标至少4-50kb,对db查询实际上会有拖累
并且db 阶段,在磁盘性能差的服务器上 batch 写入 200 个 icon 的 b64(大概 4MB+) 的数据,对数据库是灾难性,直接冲完了 sqlite 的 cache、并且由于数据库的写放大问题,实际读写开支可能远比 4mb要多,很大程度上锁死 busy 都是这个问题导致。

Image Image
  1. 同步逻辑问题

1panel 最开始部署时和后期同步,全量同步可以做的更优雅。sync_detail 卡了 db 入库太久。
1panel.json里有个recommend值用于标注程序的优先级,实际上可以先同步优先级高的detail,比如小于 1000的 app(总共 31 个)
在不修改下载文件逻辑情况下,让 go 程序把 2m 的 json 中根据推荐值过滤,让同步优先更新完常用的(recommend<1000)。再起一个子任务更新不常用的(recommend>1000). 分成两个任务来执行
很多非高优先的 app 实际上用户平均只会用 1-2 个,其余根本一辈子都碰不到,然而这些需要用户付出性能去同步。

一个 demo 参考 https://github.com/HynoR/1Panel/tree/play/sy

后期如果可以改 oss 的文件格式,可以把1panel json分片,把优先级高的做一个json,其余按照类型(ai、云存储等)来分 json。按需更新才是最好的解决方案

19 03:40:20] [INFO] [AppStoreTiming] step=download_zip_start time=2026-01-19T03:40:20.079247308Z url=https://apps-assets.fit2cloud.com/dev/1panel.json.zip  
[2026-01-19 03:40:20] [INFO] [AppStore] download file from https://apps-assets.fit2cloud.com/dev/1panel.json.zip  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=download_zip_done time=2026-01-19T03:40:21.137686422Z path=/opt/1panel/resource/1panel.json.zip  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=decompress_start time=2026-01-19T03:40:21.137747965Z zip=/opt/1panel/resource/1panel.json.zip  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=decompress_done time=2026-01-19T03:40:21.161343309Z dest=/opt/1panel/resource  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=json_decode_start time=2026-01-19T03:40:21.161488017Z path=/opt/1panel/resource/1panel.json  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=json_decode_done time=2026-01-19T03:40:21.258366801Z apps=226  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=sync_list_ready time=2026-01-19T03:40:21.258481174Z apps=226  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=sync_tags_done time=2026-01-19T03:40:21.265241295Z  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=sync_delete_custom_done time=2026-01-19T03:40:21.333696179Z  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=sync_load_old_apps_done time=2026-01-19T03:40:21.359801071Z old_apps=223  
[2026-01-19 03:40:21] [INFO] [AppStoreTiming] step=sync_detail_start time=2026-01-19T03:40:21.361003865Z apps=226  
[2026-01-19 03:42:35] [INFO] [AppStoreTiming] step=sync_detail_done time=2026-01-19T03:42:35.716323775Z  
[2026-01-19 03:42:35] [INFO] [AppStoreTiming] step=sync_db_start time=2026-01-19T03:42:35.717148921Z  
[2026-01-19 03:42:35] [DEBUG] [tx_1768794155786339776] tx start 
github.com/1Panel-dev/1Panel/agent/utils/common.initializeTxWatch.func1/sqlite_tx_logs.go:22
github.com/1Panel-dev/1Panel/agent/app/repo.AppDetailRepo.BatchCreate/app_detail.go:61
github.com/1Panel-dev/1Panel/agent/app/service.AppService.SyncAppListFromRemote.func1/app.go:1152
github.com/1Panel-dev/1Panel/agent/app/task.(*SubTask).Execute.func1/task.go:238  
[2026-01-19 03:42:35] [DEBUG] [tx_1768794155786339776] tx commit! time: 1.887128ms  
[2026-01-19 03:42:35] [INFO] [AppStoreTiming] step=sync_db_commit_done time=2026-01-19T03:42:35.960385109Z  
[2026-01-19 03:42:35] [INFO] [AppStoreTiming] step=sync_complete time=2026-01-19T03:42:35.963766422Z

Please describe the solution you suggest

  1. 已修复 refactor: improve code logic and format in app remote sync task #11691
  2. 最好是后期把图标放在 resource 文件夹下,后续新版逐步淘汰这个方案并清理,sqlite 记录路径和 etag,如果没有图标用默认图标占位。然后利用 etag 来进行增量更新。无需修改 oss 里任何数据格式。这个需要商讨迁移过程 (希望能在下个版本或者 2.0.19 解决)
  3. 在不改上游 oss数据格式或者分片的情况下,按照 recommend 拆分两个任务是可行并且几乎无损的。 分片可以等v3.
    上述修改都是可以最小影响的情况下来改进 app sync 这个定时炸弹。

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions