本文正在参加 「金石计划 . 分割6万现金大奖」
共享一个印象深刻的线上问题,期望能够给 xdm 带来一点考虑
一个稀松往常的工作日,正准备下班的时分,不巧,突发线上紧迫问题,心中一万个不情愿,可仍是要硬着头皮去定位问题
简略的表象为微服务之间 gRPC通讯的通道默许是用了默许值,并没有依照实践事务去设置通道承受和发送的字节巨细
用过 golang grpc 通讯的 xdm 就知道,grpc 通道默许的发送和接纳的音讯巨细为 4M,因为传送的数据包大于了 4M,导致通道堵塞,一向报错 rpc 过错,
rpc error: code = ResourceExhausted desc = grpc: received message larger than max (6394324 vs. 4194304)
于是便有了一个定位并想办法解决或许规避问题的逐渐长夜
简述根本介绍通讯流程
整个事务架构比较复杂,咱们简略的提出出问题的服务链路来进行阐述
服务 A – 专门和第三方对接
有一个服务 A 是专门找第三方同步源读取第三方系统的用户安排结构,并转换成咱们渠道自己的数据结构,将数据发送给 服务 B
服务 B – 专门处理用户相关数据
服务 B 专门处理关于用户安排结构数据的,处理完毕之后落盘,并将数据给到服务 C
服务 C – 主要做数据转发
服务 C 主要是做数据的通道,会将数据转发给到节点中的运用 D,因为 运用 D 和 服务 A 和 服务 B 没有办法直接通讯
运用 D,处理处理实践的流量即管控
运用 D 接纳或许去找 服务 C 拉取数据后做相应的事务,做根本的流量管控和用户认证等
其中上述两者之间都是经过 gRPC 的方法通讯
问题 1 – rpc 通道发送和接纳音讯设置过小
万万没想到的是,在做第三方安排结构同步的时分,竟然是服务 A 从第三方同步源中获取一切的用户安排结构(包括一切的组,一切的用户),不管总量多少,一口气悉数弄过来,然后再一口气悉数推给 服务 B
可这一次线上问题,正是因为这么 low 的做法和处理方法,导致超出了 gRPC 的默许音讯巨细 4M,闪现就是服务 A 将数据发送给到服务 B 的时分,发送没有问题,可是服务 B 接纳的时分出了问题,日志中张狂打印上述的 rpc 过错
rpc error: code = ResourceExhausted desc = grpc: received message larger than max (6394324 vs. 4194304)
当然,这个时分不允许咱们停下来去考虑怎么优化的事项,必须第一时刻解决或许规避问题
立刻评估,将涉及到的服务,gRPC 的 send 和 receive 的当地悉数统一修改为 32 M(1024102432) ,这个问题暂时得以规避
能够检查到 grpc 源码中的说明
MaxRecvMsgSize 承受音讯 在 grpc 中默许巨细为 4M−−(1024∗1024∗4)=2224M –(1024*1024*4)= 2^{22}
MaxSendMsgSize 发送音讯在 grpc 中默许是MaxInt32=1<<31−1也就是4M∗29−1即2048M=2GMaxInt32 = 1<<31 – 1 也就是 4M * 2^9 -1 即 2048 M = 2G
则在 grpc.NewServer 的时分,将上述的 option 加上去就能够了,例如这样
// 例如设置接纳音讯巨细为 math.MaxInt32
var opts []grpc.ServerOption
opts = append(opts, grpc.MaxRecvMsgSize(math.MaxInt32))
newSvr := grpc.NewServer(opts...)
// grpc RegisterxxxxServer()
问题 2 – 安排结构同步的层级太小,不支撑 16 层
本认为问题就这么规避了,但是仍是太年青
当服务 A 将数据悉数打包发送到服务 B 的时分,才发现,本来问题才刚刚开始,因为数据量比之前测验过的数据量大了好几倍,导致各种问题接二连三的出来,这也体现了整个渠道的健壮性太差
当时遇到的问题是服务 B 处理的安排结构层数,最大只能有 8 层,超越 8 层的数据就直接不要了,看到这儿,what??? 之前是谁规划的
迅速阅读源码,检查相相关的逻辑,调整相关代码,火速将支撑的 8 层,调整为 16 层安排结构,还好代码不是太复杂,否则这么大半夜的,真的不敢大动,毕竟这个时分现已不是一个人了,仅仅半个人
此处的安排结构好在不是传递的一棵树,如果是一棵树的话,大概率是要栈空间超限的,咱们知道栈空间一般 2M,超越就要溢出了
好在是传递的是一个用户的 list,元素是关于用户的绝对路径,例如 /a/b/c/小花
问题 3 – 同步近 3 w 个用户竟然花了近 8 分钟,近 3w 用户放到一个音讯里
处理完问题 2 之后,测验同步一次安排结构,发现近 3 w 的用户,竟然同步花费了 8 分钟左右,其中 服务A 到服务B耗时近 2 分钟,然后服务 B 就处理了4 分钟,其余时刻花费在别的服务处理
这个时分,就看到页面上一向在转圈,如果是用户看到一幕,那或许直接就是退货的节奏了
不过好在是同步成功了,暂时先把同步的按钮先关了吧,毕竟数据都过来了,接下来的工作都是能够调整的
其实看到这儿,一个音讯放近 3 w 个用户,只能说这一块底子没有规划,需求是赶鸭子上架赶出来的吧?关于这一块的优化放到下一篇来共享
问题 4 – 操作界面一向转圈,前端处理数据极慢
但是,当上一个问题还没有完全解决的时分,发现又爆出另外一个问题,看来年青的不仅仅是一点点大,这个时分甲方爸爸要开始喊 细狗你行不行啊
翻开渠道,检查用户相关页面,卡的一匹,足以和上世纪翻开网页的程度比慢了,几乎没眼看,。处理 3 w 数据耗时 20 分钟,才看到正常的页面
本来处理方法是这样的:
前端找后台查询这个租户一切的用户,然后前端再进行树形展示,看到这儿是不是蒙圈了???
哪有这么去完成功用的?根本的懒加载不会吗?暂时后端供给相应的接口, 前端 调整逻辑得以规避
懒加载, 是一种共同而又强壮的数据获取方法,它能够在用户滚动页面的时分主动获取更多的数据,而新得到的数据不会影响原有数据的显现,同时最大程度上削减服务器端的资源耗用
然后,大部人的回答是,我也不知道会有那么多数据呀,诶,仍是吃亏在太年青,不行专业,乃至还有人提议,这个页面暂时让客户不要点
问题 5 – 大数据日志上报,因为数据量猛增,导致日志通道堵塞
真是福无双至,祸不单行啊
因为大数据日志上报模块也需求经过 grpc 根用户数据更新时刻来一次性查询用户,相同的问题,这一条链路也卡的要死,显现因为恳求超时,因为 rpc 超时时刻代码中默许就设置了 10 s , 后边将时刻改大了之后得以规避,最终因为大数据模块处理数据慢,花费了 2 个小时才把近 3w 的数据搞定
心中想,这也是大数据??,感觉这个产品要完蛋了
问题 6 – 系统本身仅支撑 1 w 用户,前哨静静的揽了一个 5w 用户的客户
处理到这儿,天也逐渐蒙蒙亮了,从功用测验的小伙伴报告中了解到,之前做的功用测验最多就支撑 1 个租户下有 1w 个用户,但是,出售吹牛皮招揽了远远大于这个数的客户,且还不奉告研发内部
其实出售也没想到,怎样咱们的渠道这么弱鸡?逐渐丧失决心。。
实践上呈现的问题远远不止上述几个,接下来就是无尽的优化和考虑,期望露出的问题能给 xdm 带来一些提示和考虑
不管之前架构怎么,关于第三方安排结构同步的时分,咱们需求考虑这些问题
- 产品的根本数据目标要同步给前哨等相关方,防止自己人坑自己人,火急火燎的,很难有用的解决好问题
- 从第三方获取安排结构的时分,根本的分页要有,不仅仅是分页从第三方同步源获取,还要分页的给出去
- 关于服务 A 将数据给到服务 B 的时分,先分页给组,再分页给用户
- 关于 rpc 中音讯巨细规划,需求在规划之初依据事务考虑到或许的音讯状况,去设置一个合理的数值
- 关于同步数据的时分,需求分步骤,分状态来进行处理,需求完成断点续传,需求能够应对各种异常场景
- 关于前端从后台获取用户树的时分,务必记住运用懒加载(简略来说就是能够先获取最外层的组,当点击到某个组的时分,再去查询这个组下面的用户信息和子组信息,而不是一口气将整个租户的安排结构加载出来,这也太心大了)
天然,实践落地的时分还需求考虑很多,咱们需求更多的往前看一步,不给他人留坑,也不给自己挖坑
天然咱们需求提高自己的才能,提高自己的思想,不断向大佬看齐,或许低级问题咱们都会犯,但要有进步,要有改变,做需求,做规划,需求考虑愈加全面,否则你永远不知道你带来的影响有多大
关于怎么去优化第三方安排结构同步这个功用,感兴趣的朋友能够考虑一下,谈论区讨论一下哦,下一篇会进行阐述对其优化的方法,以及落地的计划
文中说到的技能感兴趣的能够检查如下相关文章,或许自行扩展:
- 【功用优化上】第三方安排结构同步优化一,你 get 到了吗?
- 【功用优化下】安排结构同步优化二,全量同步/增量同步,断点续传
- gRPC介绍
- gRPC 客户端调用服务端需求连接池吗?
- gRPC-Gateway 快速实战
- 懒加载
- 分页,同步
感谢阅读,欢迎沟通,点个赞,重视一波 再走吧
欢迎点赞,重视,保藏
朋友们,你的支撑和鼓励,是我坚持共享,提高质量的动力
好了,本次就到这儿
技能是敞开的,咱们的心态,更应是敞开的。拥抱改变,向阳而生,尽力向前行。
我是阿兵云原生,欢迎点赞重视保藏,下次见~