原创

只因少传了一个参数导致线上OOM了...

温馨提示:
本文最后更新于 2024年10月19日,已超过 95 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

那是一个十分平常的工作日,在那个阳光明媚的下午,刚刚午睡醒来的码农们睡眼惺忪的睁开眼;突然接收到线上环境接口缓慢的反馈,点开日志平台打着哈欠排查着日志,问题具体原因还未分析出来,就收到系统崩了不幸消息。。。

一通捣鼓之下,问题点很快就排查出来了,从权限中台查出一堆重复数据,日志几个屏都放不下,然后直接OOM了。。。
OOM

问题点分析

对于查询问题点

  • 首先由于查询用户名下所有权限信息集合,且返回数据未去重,一年多累计重复数据已经非常大(已过万),远程接口返回缓慢,导致系统会请求超时;
  • 接收远程数据集过大,加上接口响应缓慢,用户大量点击导致系统内存短时间飙升;
  • 获取用户权限后数据后筛选ID集合使用了List而非Set,将未去重集合当作查询条本地数据库,当集合过大时同样影响查询性能;
  • 前端未限制按钮点击频率,并未对已点击按钮置灰;
  • 后端同样未对接口限流,当同一用户多次触发同一接口且前面请求还未完成时未进行拦截;
  • 当接口或SQL响应超时时,未及时告警反馈,导致超过系统承受临界点,最后导致系统崩溃;
  • 热点数据未作任何缓存,完全依赖数据库实时查询,短时间高并发请求给数据库带来较大压力;

ID集合共一百条
百条

ID集合共一万条
万条

可以看到结果集虽然相同,但查询时间明显变慢,这还仅仅是示例数据库一共才230条数据的情形下;虽然传入数据去重后仅10个数据,但重复数据传给MySql时会随着数据量增加而增加数据库解析成本;同时占用数据库内更大存会来处理查询条件;

对于新增数据问题点

当发现数据集合重复后,查找各自服务更新代码发现:

  • 新增/修改为同一接口,每次都是把当前所选权限集合全量请求到权限中台,并不是做增量更新;
  • 未配置请求服务ID,且权限中台对请求服务ID并未强制校验;
  • 中台对应数据类型未做好对应去重措施,且未清理历史权限数据而直接全量新增,导致每次更新或新增权限数据量都会翻倍;

小结

  • 1.作为中台(底层)服务,在系统设计上必须要综合考虑不同服务N多细节点,在兼容配合其它服务的同时,首要保证自身数据的稳定性、正确性,不能因为附和某些业务场景改变中台或者底层平台的通用性、可靠性

  • 2.作为中台(底层)服务,当考虑到为多方提供通用接口时,为每个服务分配一个唯一ID及强制验证是必须的,宁可抛出错误提示也不应存储未知来源数据;

  • 3.作为数据接收及存储方,数据幂等性及唯一性一定要保证,某些业务场景下必须要求请求方传参请求编码用以幂等性校验;而无法幂等性校验如本文中问题时,数据唯一性同样要验证,显然在当前业务背景下同一用户同一数据权限只应存在一条;

  • 4.作为存储及提供方,对热点数据应做好缓存,避免所有压力都给到数据库;当请求相同资源时,缓存能给系统带来非常大的性能提升;

  • 5.接口单次返回数据条数必须要有最大限制,即使是内部请求给一个较大限制值也好过没有任何限制;

  • 6.当数据集超过单次限制时,不能毫无节制的放大限制;此时应考虑业务的合理性,改变对应业务实现方案才是更合理的解决方案;

  • 7.对于使用数据库IN查询,应保证List集合已去重,但更推荐使用Set而不是List,因为List不能保证每个人都会做好去重工作,容易被忽略,需要更多的代码审核工作来保障;

  • 8.一个健壮的服务对于接口及SQL等查询应有一个完善的监控告警机制,当接口超过警戒值时应及时通过相关措施发送告警信息给相关负责人,便于及时排查处理,避免系统超负荷运行导致崩溃;

  • 9.前台应在用户点击后将按钮置灰直至接口正常响应或超时自动恢复,避免用户短时间内重复触发,在接口处理缓慢时大量重复请求无形中给系统增加了更大的压力;

  • 10.网关应建立一个限流、降级、熔断措施,当短时间内服务响应超时或异常,应及时熔断、降级,避免更多压力给到对应服务节点,给服务起到一层保障;

  • 11.服务自身在接口层应对相同请求做一些策略限制,当前一次请求还在处理中,后续请求进行排队拒绝

  • 12.后台服务自身对于热点数据如用户权限值可做一个短期随机时间缓存,避免完全依赖于底层服务;

正文到此结束
本文目录