正在开发一个 app ,用户在使用 app 访问服务时,需要根据对应的服务从后端获取对应的配置文件( json 格式)。
一共有上千个独立的配置项。
目前是当 app 第一次启动时,会首先通过接口查询配置项清单,然后再依次对各配置项进行请求获取。
这样的问题是,一个 app 就会向后端发起上千个请求。而且可能需要十来分钟甚至更长时间才能把全部配置拉下来。
这样一方面对后端服务器造成压力,另一方面影响用户体验。
如果把配置全部打包在一起的话,大概40-50MB左右。
有些配置项还会更新,这就需要app 在后续的运行过程中对有更新的配置项进行更新。
1
yyyyyyh 73 天前
一个客户端就是上千请求。。。 100 个客户用 ,对后端来说岂不是 10W 的并发了。
如果还有更新的话, 建议用实时通讯的方式会好一点。 MQTT 或者 websocket 就当你在做一个 IM 。 |
2
GotKiCry 73 天前
一个 app 向后端发起上千个请求?你确定该优化的不是后端逻辑吗
|
3
onichandame 73 天前
渐进式不行吗?这上千个配置项既然是独立的,那应该是各自影响各自的页面,为啥要一次性全拉下来?进首页就只拉首页的配置,进登录页就只拉登录页的配置。我感觉现在的梭哈式设计是前端的锅。。
|
4
shadowyue 73 天前
上千个配置马上就要用吗?按需加载吧
|
5
cweijan 73 天前 6
先把程序员优化了吧
|
6
wxw752 73 天前
大佬们的脑子已经宕机了😰
|
7
horizon 73 天前
@onichandame #3
明显是后端配置项设计的问题 |
8
flytsuki 73 天前
这。。。人都麻了
|
9
liuyx7894 73 天前
比较好奇什么 APP 会需要这么多配置项
|
10
liuidetmks 73 天前 4
既然已经这样了,
把配置当做静态文件,放在 oss 上吧,让 app 去刷吧 业务能稳定运行最重要 |
11
nice2cu 73 天前 1
按需请求
合并请求 后端配置存储走缓存 |
12
bootvue 73 天前
json 放到 oss 上 后端更新
|
13
onichandame 73 天前
@horizon 后端可以怎么优化
|
14
RightHand 73 天前 via Android
按需加合并呗,这就是后台偷懒,不是什么都要原子化的
|
15
Hilong 73 天前
这接口设计有毒吧。搞个 bff 层聚合一下啊
|
16
Puteulanus 73 天前
把默认的全量配置都内置在 App 里,然后你们服务器那边每次改的时候打个版本,App 拉更新的时候根据版本号只增量拉修改了的配置项( patch )
|
17
ala2008 73 天前
说实话,业务是不是不合理
|
18
cinlen 73 天前 4
能否分享一下,什么情况下 app 一启动就需要 40~50MB 的配置量?
|
19
horizon 73 天前
@onichandame #13
首先把配置项分分类,不是所有的配置项都要实时从数据库里查吧 一些通用的可以提取出来,像上面说的放到 OSS 里 每次启动的时候从 oss 里获取咯 另外一些实时获取的,接口优化聚合一下,也分分类,首页只获取必要的 |
20
lasuar 73 天前
按 描述,判断 OP 几乎是个后端新手水平。
|
21
tool2dx 73 天前
采用类似游戏客户端的差异化更新,第一次向打包一部分预配置到 app 内,每次启动,有新变动再申请下载。
|
22
onichandame 73 天前
@horizon #19 静态的移到 oss 没问题,动态的配置项分类获取不就是我说的渐进式获取吗。。。要优化的是前端的调用逻辑,后端接口根据题主说的明显已经分成了不同的接口
|
23
LieEar 73 天前
我觉得也可以采用 OSS 方案,打包后上传,让 APP 直接去 oss 拿
|
24
janus77 73 天前
啥系统啊这么多配置,感觉大厂的 APP 都没你们多
|
25
spicy777 73 天前
高并发就是这么玩出来的是吧
|
26
zgsi 73 天前
不改变现状的话,就 oss+cdn 吧
|
27
horizon 73 天前
|
29
horizon 73 天前
|
30
adoal 73 天前
如果是 to B 的项目,别优化了,to B 哪有不纵容屎山的。如果是 to C 的项目,首先重构业务逻辑。
|
31
mb4555 73 天前
不变的直接打包到 app 里面
|
32
potatowish 73 天前 via iPhone
把配置按使用场景分类,加个聚合层
|
33
mooyo 73 天前
app 层抽一个 proxy configuration manager ,服务端定期聚合部分 config ,如果是用户无关的,聚合成 CDN 文件,如果用户相关的,走接口一次性拉下来
|
34
learnshare 73 天前
是一次把数据库全吐出来吗
还是所谓的原子化、微服务 进入 App 的时候,第一个页面要用到所有数据? |
35
mymail6811 73 天前
在服务器加一层, app 给服务器发一个请求, 服务器再去获取那上千个配置项并返回. 之后再慢慢改后端
|
36
li746224 73 天前
好想见识一下这个 app
|
37
aboutboy OP @onichandame 也想过这个方式,感觉可能最合适的方案。
|
38
aboutboy OP @Puteulanus 现在是一次全部拉取,如果有更新的话,可以通过接口获取更新列表,再按照列表去拉取。
|
39
aboutboy OP @learnshare 其实只有在访问某个页面的时候才会用到那个对应的配置。可能是为了让用户不等待,所以在 app 首次启动的时候去把几千个配置都拉下来。感觉产品上用户访问某个页面时是可以接受等待加载配置的。
|
40
aduangduang 73 天前
配置项清单带上每个配置的 md5 结果
前端第一次请求全部内容后本地存储 后续只请求配置项清单,和本地配置项清单做对比后 增量同步有变动的内容 |
41
qbmiller 73 天前
是游戏吗? 40-50m.
长连接 ( mqtt 那种也行)|| oss |
42
superedlimited 73 天前 via iPhone
hoge ?
|
43
onichandame 73 天前
@horizon #29 没访问到的页面的配置项就不需要拉了呀。不过我倒是先入为主地觉得独立的配置项来自不同的独立接口,如果真是一个通用接口调一千次那确实后端有问题
|
44
aduangduang 73 天前
@aduangduang 每次 APP 新版本打包的时候可以把当前的配置项一起打包,这样首次启动也不需要大量请求了
可以统一使用增量同步的逻辑 |
45
ShuWei 73 天前
你确定这些东西能叫配置项?
|
46
fov6363 73 天前 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 ,对后端的压力比较小 |
47
wxf666 73 天前
|
48
henix 73 天前
展示加载进度条
|
49
wOuv7i4e7XxsSOR1 73 天前
什么样的配置会有 40-50M? 你知道 40M 存文本可以存多少吗?
|
50
xmumiffy 73 天前 via Android
就算 5000 个吧,50m 每个配置 10k ?
如果有压缩的话,每个配置原始有上百 k 了?那不能说后端没努力了,你们这一个配置就比别人整个配置大了 |
51
Tink 73 天前
重构
|
52
hwb 73 天前
好想见识一下这个 app
|
53
ruobingm 73 天前
我比较想看 到底这上千个配置 都配置了啥?需要在首页获取?
很想知道。。 |
54
fffq 73 天前
能跑吗
|
55
GooMS 73 天前
这配置不得有几千万字了
|
56
MozzieW 73 天前
最简单的,加上一个缓存,时间戳没变就不要更新了,1000 个配置频繁变的也没有几个。
还是正在开发的,这个 App 没有人用,放弃吧 |
57
joyoyao 73 天前
这玩意交给后端处理不就行了,app 只需要请求后端接口,那些需要展示,接口就返回,不需要展示接口就不返回。垃圾后端,自己不想搞,就恶心前端,交给前端搞。
|
58
burymme11 73 天前
oss+cnd 指标不治本、
好好整理下这些配置吧,几千个配置竟然要 40.50M ?? 你们不会把用户个人数据全部塞在配置里了吧? |
59
Mephisto233 73 天前
看这需求怎么感觉有点像是马甲包?先用正常 app 过审核,上线后通过配置项直接改界面?
|
60
vipfts 73 天前
@Mephisto233 哈哈, 变身🥵
|
61
Chad0000 73 天前 via iPhone
低代码?
|
62
k9982874 73 天前
建议废除后端,app 直读数据库
|
64
unco020511 73 天前
可以参考 firebase 的 remoteConfig 产品
https://firebase.google.com/docs/remote-config 几个关键点: 1. 有本地默认配置文件,用于各种情况下的兜底配置 2. 配置有分组,支持分组更新/获取 3. 有版本号机制,支持增量更新,绝大部分情况都应该是增量差异更新 4. 可选长链接,实现 real-time 更新机制 5. 扩展可与各种其他产品结合,比如与你的业务 api 网关结合,在 header 中携带客户端配置的版本号,网关中去拦截,如果线上有版本号更新,则触发配置更新,配置更新在客户端可以独立进程,做到业务无感 |
65
unco020511 73 天前
最关键的,就是动态配置是需要定期去固化清理的,比如一段时间去做一些 abtest,或者一些功能的临时开关,过了几个版本业务验证完之后一般是需要有明确数据结论去支撑,然后固化配置的.你现在配置数据有上千个,讲道理不太合理
|
66
icyalala 73 天前
哈哈,FGO 游戏逻辑就是这样,一启动就要下载几十 MB 的 JSON 配置数据,后来嫌大就改成 pb/msgpack 了。
|
67
lingalonely 73 天前
游戏更新的时候不是有个加载过程吗,把这些配置传过来就行,没有必要请求上千次
|
68
broken123 73 天前
app 有个东西叫做启动器
https://blog.csdn.net/jdsjlzx/article/details/129019317 道理都是通用的 每个端都可用 哦 |
69
FreshOldMan 73 天前
app 一进来是首页什么情况下需要上千个配置,这些配置不能在后端配置好再下发吗?
|
70
yufeng0681 73 天前
@Mephisto233 #59 如果是这种需求,是不是资源包在本地,网上只要弄个配置,就能启用第 N 套资源当界面更好? 资源压缩后扩展名改成不可预知的,规避审核人员打开即可。
|
71
gaobh 73 天前 via iPhone
不是应该进啥模块加载啥配置吗……
|
72
winglight2016 73 天前
这既是产品设计的缺陷,也是后端架构设计的缺陷,哪个 APP 需要一次性下载 1000 个配置项?再说了,有什么配置项非要在客户端才能起作用的?
退一万步说吧,即使真的就要启动前加载好 1000 个配置项,也只需要 app 内建一套默认配置,等到用户修改了某项配置再做 diff-merge 操作就够了,我不信哪个用户上来就把 1000 个配置项全部自定义一遍。 |
73
lambdaq 73 天前
不要盲目优化啊。先说加多少钱。
越屎的代码越值钱。 |
74
wu00 73 天前
某几个配置占了 50M ,剩下 99x 个配置占了几百 K ?
|
75
yufeng0681 73 天前
所有配置项梳理分类
1 、按加载重要性排序, 启动必需的,首页必需的,二级页面必需的 2 、按更新频率分类:不更新的(放 app 里),不经常更新的(初始数据放 app 里),频繁更新的(只存网络, 这类配置要精简到极少个) 3 、按功能分类:模块级数据同步,模块级配置接口,系统级配置接口,系统级数据同步 。 不要把所有数据用配置接口获得,可以换成数据同步,这样接口不涉及业务,只是数据同步。 服务端数据文件由各个模块自己负责生成,客户端也是由模块代码负责去获取数据文件。 |
76
juzisang 73 天前
40-50M ,是把图片转 base64 放配置里了吗...要不然纯配置怎么可能这么大,还请求上千次...
|
77
lefer 73 天前
@onichandame #3 我觉得你的方案是可取的。
|
78
cBlank 73 天前
参考游戏的启动流程
|
79
xuanbg 73 天前
这上千个达到 4-50M 之巨的所谓配置数据,不知道有几个是配置项,几个是模版数据,估计 99%其实都是模版数据吧,要不然怎么可能有几十 M 。。。。。
办法很简单,配置项启动一次加载,模版数据完全可以按需加载。 |
80
realJamespond 73 天前
拼成一个 json 一次发过来
|
81
icyalala 73 天前
给你们看看现实中几十 MB 配置项的例子:
这是 FGO 手游每次启动下载的 JSON 配置数据,80M+,现在更大了所以不用 JSON 了 https://github.com/UnderFGO/MasterDataDumper/releases |
82
28Sv0ngQfIE7Yloe 73 天前
@icyalala #81 这种一般是放在 OSS 获取吧
|
83
FireKey 73 天前
应用的话配置 copy 一份存本地,配置版本变化时再更新对应项.如果运行中需要及时更新,考虑将配置版本加入 headers 中,版本更新了接口走更新流程
|
84
panlatent 73 天前 1
纯色背景配上点大字:
”嗨,别来无恙“ ”一切即将准备就绪“ ”这可能需要几分钟“ ”马上就好“ |
85
ysw 73 天前
json 放 cdn ,然后按需加载,应该就差不多了
|
86
icyalala 73 天前
@Morii 这个配置数据变动还没那么频繁可以放静态,但用户数据游戏进度就不行了,那个同样也不小。
如果不换架构的话,最简单的办法就是换格式,用 protobuf/msgpack 再压缩一下,客户端选个高性能的解析库,这个量级基本还是够用的。 |
87
2owe 73 天前
按需缓存吧,首先获取一下当前需要更新的配置,只获取有更新的部分
|
88
veightz 73 天前
问题还挺多, 不是单方面的。整体方案就挺奇怪的,感觉没有沟通好设计。。
客户端的问题: 1. 用户体验问题肯定要客户端解决。不可能同步等这份配置吧,这个数据量的下载,反序列化,都是不小的开销。一般来说是同步读客户端缓存,异步刷新数据。 2. 配置同步做下版本管理, 记录下版本的上一次同步时间。 做好缓存时间控制。 服务端问题: 1. 上千个配置下是同构的吧? 一个读结构不同的配置项 key 吧? 要支持批量的接口。 2. 服务端都做热缓存吧, 有内存缓存的话, 我觉得性能本身倒是还好。 但是目前方案我觉得你们的第一个瓶颈是带宽。 3. 我觉得可以的方式是读 cdn , 配置大概率也不是高频更新的,可以结合 etag 等手段, 确定有数据变更了再回拉。 |
89
xiangyuecn 73 天前
能用上你们的 app 的客户也是倒了八辈子霉🐶
|
90
Ritr 73 天前
什么 APP ,说出来我避雷
|
91
shunia 73 天前
游戏不就是这样的吗?
一万个配置文件也可以做一个更新列表,有更新的才拉,没更新的用缓存。 基本只有冷启动会全量下载,热启动基本很难遇到大量更新的情况。 |
92
simo 73 天前
如果你说的 50M 的配置必须所有人都加载,那就分析下,拆分请求,按需,数据压缩,缓存,cdn 。
|
93
murmurkerman 73 天前 via iPhone
这个明显要用增量更新,可以看看有没有类似于 remote config 的国内替代。没有的话只能自己撸一个。也可以借助 s3 ,oss 实现,s3 文件下载都会返回一个文件内容的 hash 值,可以用 head 请求判断是否更新了。然后就是拉配置的时候需要有一个请求队列,安卓 okhttp 自带,不用担心网络并发。
配置下载也可以加一个分页接口,一次下载 n 项。 最好还是用 protobuff 缩小配置文件传输大小。 |
95
prosgtsr 72 天前 via iPhone
放在一个接口全部请求回来。
还可以带上版本号,每次通过版本号获取更新的数据。 我们公司的 app 就是这么干的,没什么问题。 |
96
jzphx 72 天前
启动一次 app 40-50M ,用户流量不要钱的吗
|
97
duanxianze 72 天前
不明白,什么样的应用会有这种需求?
|
98
ArianX 72 天前
上千个配置为什么会有 40M
|
99
Huelse 72 天前
区分启动配置和分页配置,另外很多配置都是应该存本地的,更改时发送一份到服务端记录就行了,不需要再次下载。
|
100
p1gd0g 72 天前
配置不放 cdn 上?不做缓存?没有增量更新?
|