V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
aboutboy
V2EX  ›  程序员

app 初始化时需要通过接口获取上千个独立的配置项,如何优化?

  •  
  •   aboutboy · 2024-09-02 10:33:02 +08:00 · 11787 次点击
    这是一个创建于 365 天前的主题,其中的信息可能已经有所发展或是发生改变。

    正在开发一个 app ,用户在使用 app 访问服务时,需要根据对应的服务从后端获取对应的配置文件( json 格式)。

    一共有上千个独立的配置项。

    目前是当 app 第一次启动时,会首先通过接口查询配置项清单,然后再依次对各配置项进行请求获取。

    这样的问题是,一个 app 就会向后端发起上千个请求。而且可能需要十来分钟甚至更长时间才能把全部配置拉下来。

    这样一方面对后端服务器造成压力,另一方面影响用户体验。

    如果把配置全部打包在一起的话,大概40-50MB左右。

    有些配置项还会更新,这就需要app 在后续的运行过程中对有更新的配置项进行更新

    请问大佬们有什么好的思路?

    106 条回复    2024-09-04 08:00:06 +08:00
    1  2  
    yyyyyyh
        1
    yyyyyyh  
       2024-09-02 10:49:29 +08:00
    一个客户端就是上千请求。。。 100 个客户用 ,对后端来说岂不是 10W 的并发了。

    如果还有更新的话, 建议用实时通讯的方式会好一点。

    MQTT 或者 websocket 就当你在做一个 IM 。
    GotKiCry
        2
    GotKiCry  
       2024-09-02 11:03:23 +08:00
    一个 app 向后端发起上千个请求?你确定该优化的不是后端逻辑吗
    onichandame
        3
    onichandame  
       2024-09-02 11:10:04 +08:00
    渐进式不行吗?这上千个配置项既然是独立的,那应该是各自影响各自的页面,为啥要一次性全拉下来?进首页就只拉首页的配置,进登录页就只拉登录页的配置。我感觉现在的梭哈式设计是前端的锅。。
    shadowyue
        4
    shadowyue  
       2024-09-02 11:10:20 +08:00
    上千个配置马上就要用吗?按需加载吧
    cweijan
        5
    cweijan  
       2024-09-02 11:12:38 +08:00   ❤️ 6
    先把程序员优化了吧
    wxw752
        6
    wxw752  
       2024-09-02 11:14:27 +08:00
    大佬们的脑子已经宕机了😰
    horizon
        7
    horizon  
       2024-09-02 11:14:49 +08:00
    @onichandame #3
    明显是后端配置项设计的问题
    flytsuki
        8
    flytsuki  
       2024-09-02 11:18:58 +08:00
    这。。。人都麻了
    liuyx7894
        9
    liuyx7894  
       2024-09-02 11:20:29 +08:00
    比较好奇什么 APP 会需要这么多配置项
    liuidetmks
        10
    liuidetmks  
       2024-09-02 11:22:47 +08:00   ❤️ 4
    既然已经这样了,
    把配置当做静态文件,放在 oss 上吧,让 app 去刷吧
    业务能稳定运行最重要
    nice2cu
        11
    nice2cu  
       2024-09-02 11:22:59 +08:00   ❤️ 1
    按需请求
    合并请求
    后端配置存储走缓存
    bootvue
        12
    bootvue  
       2024-09-02 11:23:37 +08:00
    json 放到 oss 上 后端更新
    onichandame
        13
    onichandame  
       2024-09-02 11:24:48 +08:00
    @horizon 后端可以怎么优化
    RightHand
        14
    RightHand  
       2024-09-02 11:28:47 +08:00 via Android
    按需加合并呗,这就是后台偷懒,不是什么都要原子化的
    Hilong
        15
    Hilong  
       2024-09-02 11:32:29 +08:00
    这接口设计有毒吧。搞个 bff 层聚合一下啊
    Puteulanus
        16
    Puteulanus  
       2024-09-02 11:34:47 +08:00
    把默认的全量配置都内置在 App 里,然后你们服务器那边每次改的时候打个版本,App 拉更新的时候根据版本号只增量拉修改了的配置项( patch )
    ala2008
        17
    ala2008  
       2024-09-02 11:35:25 +08:00
    说实话,业务是不是不合理
    cinlen
        18
    cinlen  
       2024-09-02 11:38:59 +08:00   ❤️ 4
    能否分享一下,什么情况下 app 一启动就需要 40~50MB 的配置量?
    horizon
        19
    horizon  
       2024-09-02 11:40:54 +08:00
    @onichandame #13
    首先把配置项分分类,不是所有的配置项都要实时从数据库里查吧
    一些通用的可以提取出来,像上面说的放到 OSS 里
    每次启动的时候从 oss 里获取咯
    另外一些实时获取的,接口优化聚合一下,也分分类,首页只获取必要的
    lasuar
        20
    lasuar  
       2024-09-02 11:43:11 +08:00
    按 描述,判断 OP 几乎是个后端新手水平。
    tool2dx
        21
    tool2dx  
       2024-09-02 11:44:40 +08:00
    采用类似游戏客户端的差异化更新,第一次向打包一部分预配置到 app 内,每次启动,有新变动再申请下载。
    onichandame
        22
    onichandame  
       2024-09-02 11:46:07 +08:00
    @horizon #19 静态的移到 oss 没问题,动态的配置项分类获取不就是我说的渐进式获取吗。。。要优化的是前端的调用逻辑,后端接口根据题主说的明显已经分成了不同的接口
    LieEar
        23
    LieEar  
       2024-09-02 11:48:11 +08:00
    我觉得也可以采用 OSS 方案,打包后上传,让 APP 直接去 oss 拿
    janus77
        24
    janus77  
       2024-09-02 11:48:48 +08:00
    啥系统啊这么多配置,感觉大厂的 APP 都没你们多
    spicy777
        25
    spicy777  
       2024-09-02 11:50:17 +08:00
    高并发就是这么玩出来的是吧
    zgsi
        26
    zgsi  
       2024-09-02 11:50:52 +08:00
    不改变现状的话,就 oss+cdn 吧
    horizon
        27
    horizon  
       2024-09-02 11:52:09 +08:00
    @onichandame #22
    「一个 app 就会向后端发起上千个请求」
    看上去是后端把配置项细分了啊
    不然哪需要这么多请求
    gorvey
        28
    gorvey  
       2024-09-02 11:52:32 +08:00
    @cinlen 盲猜是以前的中后台系统,迭代了很久产生了大量的字典数据,后端没做优化,然后 APP 用以前的接口问题就暴露了
    horizon
        29
    horizon  
       2024-09-02 11:54:44 +08:00
    @onichandame #22
    再渐进不还是要发上千个请求么
    关键要是聚合吧
    大概率是后端新手,创建了一个通用获取配置的接口而且不支持传多个 key 值
    adoal
        30
    adoal  
       2024-09-02 12:12:11 +08:00
    如果是 to B 的项目,别优化了,to B 哪有不纵容屎山的。如果是 to C 的项目,首先重构业务逻辑。
    mb4555
        31
    mb4555  
       2024-09-02 12:26:18 +08:00
    不变的直接打包到 app 里面
    potatowish
        32
    potatowish  
       2024-09-02 12:30:09 +08:00 via iPhone
    把配置按使用场景分类,加个聚合层
    mooyo
        33
    mooyo  
       2024-09-02 12:30:56 +08:00
    app 层抽一个 proxy configuration manager ,服务端定期聚合部分 config ,如果是用户无关的,聚合成 CDN 文件,如果用户相关的,走接口一次性拉下来
    learnshare
        34
    learnshare  
       2024-09-02 12:33:46 +08:00
    是一次把数据库全吐出来吗
    还是所谓的原子化、微服务

    进入 App 的时候,第一个页面要用到所有数据?
    mymail6811
        35
    mymail6811  
       2024-09-02 12:38:14 +08:00
    在服务器加一层, app 给服务器发一个请求, 服务器再去获取那上千个配置项并返回. 之后再慢慢改后端
    li746224
        36
    li746224  
       2024-09-02 12:53:26 +08:00
    好想见识一下这个 app
    aboutboy
        37
    aboutboy  
    OP
       2024-09-02 13:00:52 +08:00
    @onichandame 也想过这个方式,感觉可能最合适的方案。
    aboutboy
        38
    aboutboy  
    OP
       2024-09-02 13:02:43 +08:00
    @Puteulanus 现在是一次全部拉取,如果有更新的话,可以通过接口获取更新列表,再按照列表去拉取。
    aboutboy
        39
    aboutboy  
    OP
       2024-09-02 13:04:58 +08:00
    @learnshare 其实只有在访问某个页面的时候才会用到那个对应的配置。可能是为了让用户不等待,所以在 app 首次启动的时候去把几千个配置都拉下来。感觉产品上用户访问某个页面时是可以接受等待加载配置的。
    aduangduang
        40
    aduangduang  
       2024-09-02 13:36:48 +08:00
    配置项清单带上每个配置的 md5 结果
    前端第一次请求全部内容后本地存储
    后续只请求配置项清单,和本地配置项清单做对比后 增量同步有变动的内容
    qbmiller
        41
    qbmiller  
       2024-09-02 13:38:08 +08:00
    是游戏吗? 40-50m.
    长连接 ( mqtt 那种也行)|| oss
    superedlimited
        42
    superedlimited  
       2024-09-02 13:41:52 +08:00 via iPhone
    hoge ?
    onichandame
        43
    onichandame  
       2024-09-02 13:43:34 +08:00
    @horizon #29 没访问到的页面的配置项就不需要拉了呀。不过我倒是先入为主地觉得独立的配置项来自不同的独立接口,如果真是一个通用接口调一千次那确实后端有问题
    aduangduang
        44
    aduangduang  
       2024-09-02 13:44:57 +08:00
    @aduangduang 每次 APP 新版本打包的时候可以把当前的配置项一起打包,这样首次启动也不需要大量请求了
    可以统一使用增量同步的逻辑
    ShuWei
        45
    ShuWei  
       2024-09-02 13:47:28 +08:00
    你确定这些东西能叫配置项?
    fov6363
        46
    fov6363  
       2024-09-02 13:56:53 +08:00   ❤️ 1
    一个类似的解决办法,加一个 BFF 层,将所有接口汇总为两个接口:
    1 、/api/config/update
    2 、/api/config/list

    app 在打包时,自动从 /api/config/list 拉到最新的全量的配置,并返回一个 hashId 来标识这次结果,这样用户打开 app 所有功能都是可用的。

    然后 app 定期轮询 /api/config/update?id=$hashId ,如果有变更,就返回 true ,然后 app 端异步更新 diff 数据(复杂点就设计一套 add 、update 、delete 的语法,简单点就全量再拉一遍),如果无变更,就返回 false 。

    这样针对相同的 hashId 还可以做 cache ,对后端的压力比较小
    wxf666
        47
    wxf666  
       2024-09-02 13:59:15 +08:00
    能不能像聊天记录一样,只拉取有更新却没下载过的?

    简单做法:配置项放数据库里,标记创建/更新时间。

    客户端开启时,拉取 [上次开机时间,现在] 范围内的新配置项?

    henix
        48
    henix  
       2024-09-02 14:00:47 +08:00
    展示加载进度条
    wOuv7i4e7XxsSOR1
        49
    wOuv7i4e7XxsSOR1  
       2024-09-02 14:01:24 +08:00
    什么样的配置会有 40-50M? 你知道 40M 存文本可以存多少吗?
    xmumiffy
        50
    xmumiffy  
       2024-09-02 14:06:15 +08:00 via Android
    就算 5000 个吧,50m 每个配置 10k ?
    如果有压缩的话,每个配置原始有上百 k 了?那不能说后端没努力了,你们这一个配置就比别人整个配置大了
    Tink
        51
    Tink  
    PRO
       2024-09-02 14:07:25 +08:00
    重构
    hwb
        52
    hwb  
       2024-09-02 14:08:54 +08:00
    好想见识一下这个 app
    ruobingm
        53
    ruobingm  
       2024-09-02 14:11:13 +08:00
    我比较想看 到底这上千个配置 都配置了啥?需要在首页获取?
    很想知道。。
    fffq
        54
    fffq  
       2024-09-02 14:12:56 +08:00
    能跑吗
    3IOhG7M0knRu5UlC
        55
    3IOhG7M0knRu5UlC  
       2024-09-02 14:13:01 +08:00
    这配置不得有几千万字了
    MozzieW
        56
    MozzieW  
       2024-09-02 14:16:11 +08:00
    最简单的,加上一个缓存,时间戳没变就不要更新了,1000 个配置频繁变的也没有几个。

    还是正在开发的,这个 App 没有人用,放弃吧
    joyoyao
        57
    joyoyao  
       2024-09-02 14:19:50 +08:00
    这玩意交给后端处理不就行了,app 只需要请求后端接口,那些需要展示,接口就返回,不需要展示接口就不返回。垃圾后端,自己不想搞,就恶心前端,交给前端搞。
    burymme11
        58
    burymme11  
       2024-09-02 14:20:44 +08:00
    oss+cnd 指标不治本、
    好好整理下这些配置吧,几千个配置竟然要 40.50M ??
    你们不会把用户个人数据全部塞在配置里了吧?
    Mephisto233
        59
    Mephisto233  
       2024-09-02 14:22:41 +08:00
    看这需求怎么感觉有点像是马甲包?先用正常 app 过审核,上线后通过配置项直接改界面?
    vipfts
        60
    vipfts  
       2024-09-02 14:26:25 +08:00
    @Mephisto233 哈哈, 变身🥵
    ktqFDx9m2Bvfq3y4
        61
    ktqFDx9m2Bvfq3y4  
       2024-09-02 14:27:41 +08:00 via iPhone
    低代码?
    k9982874
        62
    k9982874  
       2024-09-02 14:29:50 +08:00
    建议废除后端,app 直读数据库
    zxc880301
        63
    zxc880301  
       2024-09-02 14:30:36 +08:00
    @fov6363 靠谱 我们就是这么做的
    unco020511
        64
    unco020511  
       2024-09-02 14:37:56 +08:00
    可以参考 firebase 的 remoteConfig 产品
    https://firebase.google.com/docs/remote-config

    几个关键点:
    1. 有本地默认配置文件,用于各种情况下的兜底配置
    2. 配置有分组,支持分组更新/获取
    3. 有版本号机制,支持增量更新,绝大部分情况都应该是增量差异更新
    4. 可选长链接,实现 real-time 更新机制
    5. 扩展可与各种其他产品结合,比如与你的业务 api 网关结合,在 header 中携带客户端配置的版本号,网关中去拦截,如果线上有版本号更新,则触发配置更新,配置更新在客户端可以独立进程,做到业务无感
    unco020511
        65
    unco020511  
       2024-09-02 14:41:35 +08:00
    最关键的,就是动态配置是需要定期去固化清理的,比如一段时间去做一些 abtest,或者一些功能的临时开关,过了几个版本业务验证完之后一般是需要有明确数据结论去支撑,然后固化配置的.你现在配置数据有上千个,讲道理不太合理
    icyalala
        66
    icyalala  
       2024-09-02 14:46:41 +08:00
    哈哈,FGO 游戏逻辑就是这样,一启动就要下载几十 MB 的 JSON 配置数据,后来嫌大就改成 pb/msgpack 了。
    lingalonely
        67
    lingalonely  
       2024-09-02 14:47:40 +08:00
    游戏更新的时候不是有个加载过程吗,把这些配置传过来就行,没有必要请求上千次
    broken123
        68
    broken123  
       2024-09-02 14:49:25 +08:00
    app 有个东西叫做启动器
    https://blog.csdn.net/jdsjlzx/article/details/129019317 道理都是通用的 每个端都可用 哦
    FreshOldMan
        69
    FreshOldMan  
       2024-09-02 14:58:17 +08:00
    app 一进来是首页什么情况下需要上千个配置,这些配置不能在后端配置好再下发吗?
    yufeng0681
        70
    yufeng0681  
       2024-09-02 15:01:31 +08:00
    @Mephisto233 #59 如果是这种需求,是不是资源包在本地,网上只要弄个配置,就能启用第 N 套资源当界面更好? 资源压缩后扩展名改成不可预知的,规避审核人员打开即可。
    gaobh
        71
    gaobh  
       2024-09-02 15:03:07 +08:00 via iPhone
    不是应该进啥模块加载啥配置吗……
    winglight2016
        72
    winglight2016  
       2024-09-02 15:05:10 +08:00
    这既是产品设计的缺陷,也是后端架构设计的缺陷,哪个 APP 需要一次性下载 1000 个配置项?再说了,有什么配置项非要在客户端才能起作用的?

    退一万步说吧,即使真的就要启动前加载好 1000 个配置项,也只需要 app 内建一套默认配置,等到用户修改了某项配置再做 diff-merge 操作就够了,我不信哪个用户上来就把 1000 个配置项全部自定义一遍。
    lambdaq
        73
    lambdaq  
       2024-09-02 15:06:38 +08:00
    不要盲目优化啊。先说加多少钱。

    越屎的代码越值钱。
    wu00
        74
    wu00  
       2024-09-02 15:10:44 +08:00
    某几个配置占了 50M ,剩下 99x 个配置占了几百 K ?
    yufeng0681
        75
    yufeng0681  
       2024-09-02 15:12:24 +08:00
    所有配置项梳理分类
    1 、按加载重要性排序, 启动必需的,首页必需的,二级页面必需的
    2 、按更新频率分类:不更新的(放 app 里),不经常更新的(初始数据放 app 里),频繁更新的(只存网络, 这类配置要精简到极少个)
    3 、按功能分类:模块级数据同步,模块级配置接口,系统级配置接口,系统级数据同步 。 不要把所有数据用配置接口获得,可以换成数据同步,这样接口不涉及业务,只是数据同步。 服务端数据文件由各个模块自己负责生成,客户端也是由模块代码负责去获取数据文件。
    juzisang
        76
    juzisang  
       2024-09-02 15:12:49 +08:00
    40-50M ,是把图片转 base64 放配置里了吗...要不然纯配置怎么可能这么大,还请求上千次...
    lefer
        77
    lefer  
       2024-09-02 15:13:55 +08:00
    @onichandame #3 我觉得你的方案是可取的。
    cBlank
        78
    cBlank  
       2024-09-02 15:14:17 +08:00
    参考游戏的启动流程
    xuanbg
        79
    xuanbg  
       2024-09-02 15:14:48 +08:00
    这上千个达到 4-50M 之巨的所谓配置数据,不知道有几个是配置项,几个是模版数据,估计 99%其实都是模版数据吧,要不然怎么可能有几十 M 。。。。。

    办法很简单,配置项启动一次加载,模版数据完全可以按需加载。
    realJamespond
        80
    realJamespond  
       2024-09-02 15:30:55 +08:00
    拼成一个 json 一次发过来
    icyalala
        81
    icyalala  
       2024-09-02 15:47:21 +08:00
    给你们看看现实中几十 MB 配置项的例子:
    这是 FGO 手游每次启动下载的 JSON 配置数据,80M+,现在更大了所以不用 JSON 了
    https://github.com/UnderFGO/MasterDataDumper/releases
    28Sv0ngQfIE7Yloe
        82
    28Sv0ngQfIE7Yloe  
       2024-09-02 15:58:17 +08:00
    @icyalala #81 这种一般是放在 OSS 获取吧
    FireKey
        83
    FireKey  
       2024-09-02 16:02:50 +08:00
    应用的话配置 copy 一份存本地,配置版本变化时再更新对应项.如果运行中需要及时更新,考虑将配置版本加入 headers 中,版本更新了接口走更新流程
    panlatent
        84
    panlatent  
       2024-09-02 16:06:13 +08:00   ❤️ 1
    纯色背景配上点大字:


    ”嗨,别来无恙“
    ”一切即将准备就绪“
    ”这可能需要几分钟“
    ”马上就好“
    ysw
        85
    ysw  
       2024-09-02 16:07:17 +08:00
    json 放 cdn ,然后按需加载,应该就差不多了
    icyalala
        86
    icyalala  
       2024-09-02 16:09:33 +08:00
    @Morii 这个配置数据变动还没那么频繁可以放静态,但用户数据游戏进度就不行了,那个同样也不小。
    如果不换架构的话,最简单的办法就是换格式,用 protobuf/msgpack 再压缩一下,客户端选个高性能的解析库,这个量级基本还是够用的。
    2owe
        87
    2owe  
       2024-09-02 18:02:42 +08:00
    按需缓存吧,首先获取一下当前需要更新的配置,只获取有更新的部分
    veightz
        88
    veightz  
       2024-09-02 18:49:48 +08:00
    问题还挺多, 不是单方面的。整体方案就挺奇怪的,感觉没有沟通好设计。。

    客户端的问题:
    1. 用户体验问题肯定要客户端解决。不可能同步等这份配置吧,这个数据量的下载,反序列化,都是不小的开销。一般来说是同步读客户端缓存,异步刷新数据。
    2. 配置同步做下版本管理, 记录下版本的上一次同步时间。 做好缓存时间控制。

    服务端问题:
    1. 上千个配置下是同构的吧? 一个读结构不同的配置项 key 吧? 要支持批量的接口。
    2. 服务端都做热缓存吧, 有内存缓存的话, 我觉得性能本身倒是还好。 但是目前方案我觉得你们的第一个瓶颈是带宽。
    3. 我觉得可以的方式是读 cdn , 配置大概率也不是高频更新的,可以结合 etag 等手段, 确定有数据变更了再回拉。
    xiangyuecn
        89
    xiangyuecn  
       2024-09-02 19:03:41 +08:00
    能用上你们的 app 的客户也是倒了八辈子霉🐶
    Ritr
        90
    Ritr  
       2024-09-02 20:38:59 +08:00
    什么 APP ,说出来我避雷
    shunia
        91
    shunia  
       2024-09-02 21:54:52 +08:00
    游戏不就是这样的吗?
    一万个配置文件也可以做一个更新列表,有更新的才拉,没更新的用缓存。
    基本只有冷启动会全量下载,热启动基本很难遇到大量更新的情况。
    simo
        92
    simo  
       2024-09-02 22:03:56 +08:00
    如果你说的 50M 的配置必须所有人都加载,那就分析下,拆分请求,按需,数据压缩,缓存,cdn 。
    murmurkerman
        93
    murmurkerman  
       2024-09-02 22:10:05 +08:00 via iPhone
    这个明显要用增量更新,可以看看有没有类似于 remote config 的国内替代。没有的话只能自己撸一个。也可以借助 s3 ,oss 实现,s3 文件下载都会返回一个文件内容的 hash 值,可以用 head 请求判断是否更新了。然后就是拉配置的时候需要有一个请求队列,安卓 okhttp 自带,不用担心网络并发。

    配置下载也可以加一个分页接口,一次下载 n 项。
    最好还是用 protobuff 缩小配置文件传输大小。
    caqiko
        94
    caqiko  
       364 天前
    @panlatent #84 请坐和放宽,海内存知己,天涯若比邻
    prosgtsr
        95
    prosgtsr  
       364 天前 via iPhone
    放在一个接口全部请求回来。
    还可以带上版本号,每次通过版本号获取更新的数据。
    我们公司的 app 就是这么干的,没什么问题。
    jzphx
        96
    jzphx  
       364 天前
    启动一次 app 40-50M ,用户流量不要钱的吗
    duanxianze
        97
    duanxianze  
       364 天前
    不明白,什么样的应用会有这种需求?
    ArianX
        98
    ArianX  
       364 天前
    上千个配置为什么会有 40M
    Huelse
        99
    Huelse  
       364 天前
    区分启动配置和分页配置,另外很多配置都是应该存本地的,更改时发送一份到服务端记录就行了,不需要再次下载。
    p1gd0g
        100
    p1gd0g  
       364 天前
    配置不放 cdn 上?不做缓存?没有增量更新?
    1  2  
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1027 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 22:57 · PVG 06:57 · LAX 15:57 · JFK 18:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.