百科问答小站 logo
百科问答小站 font logo



一码通崩溃的技术原因是什么? 第1页

  

user avatar    网友的相关建议: 
      

以前我以为这只是个黑的段子,后来看到图片存服务器上真信了:


user avatar   ityouknow 网友的相关建议: 
      

推荐阅读:《西安健康一码通崩了!程序员抢修竟然被……》


1 又崩了


12月20号,算得上西安崩溃的一天。那么1月4号,就是上西安市民的又又一次崩溃。

在中央的领导下,西安正在打攻坚战的时候,西安一码通又又一次崩溃了。。。




第一次出现问题,修复了整整一天,那么这次呢?同样的问题过去了十几天仍然再次出现了!!!

今天小区8点,西安市通知开始又一轮全市核酸检测,于是各个小区开始让大家排队做核酸。

结果很多小区都没开始做的时候,大家突然发现一码通打不开了,大家可要知道西安市现在的温度是1度,大家排队在外面的感受。

刚开始还让等待,结果等了30分钟之后,发现仍然没有一点恢复的迹象,于是通知大家回家等待。

西安现在防疫压力有多大,我这里不需要再复述了,严重程度仅次于当年的武汉。

最讽刺的是,大家都还在排队的过程中,收到了市里面发过来的短信,而一码通仍然处于崩溃中。



关键是这个问题有那么难吗?

关键时刻、关系到国计民生的事情,如果负责的技术团队解决不了,能不能请求一下 BAT 的专家过来帮忙支援。

到现在这个程度,已经不是钱的问题了,严重影响整个西安防控的进展了。

吐槽归吐槽,估计一码通的程序员,现在压力巨大,希望他们可以沉下心来尽快将问题解决吧。

这个级别的问题和干活的程序员关系不大,主要的责任人都在负责的相关领导身上。

希望相关领导负起责任来,将类似的问题一次性解决好,西安真的以及经不起再次再次的折腾了。。。


下面这篇文章是我在20号,崩溃的时候写的,只能从局外人给出一些浅薄的见解。


2 产品分析


西安一码通其它业务我们暂且不分析,那并不是重点,并且当天也没有完全崩溃,崩溃的仅有扫码功能。

其实这是一个非常典型的大量查询、少数更新的业务,闭着眼睛分析一下,可以说, 90% 以上的流量都是查询。

我们先来看看第一版的产品形态,扫码之后展示个人部分姓名和身份证信息,同时下面展示绿、黄、红码。



这是西安一码通最开始的样子,业务流程仅仅只需要一个请求,甚至一个查询的 SQL 就可以搞定。

到了后来,这个界面做了2次比较大的改版。

第一次改版新增了疫苗接种信息,加了一个边框;第二次改版新增了核酸检测信息,在最下方展示核酸检测时间、结果。

整个页面增加了2个查询业务,如果系统背后使用的是关系数据库,可能会多增加至少2个查询SQL。

基本上就是这样的一个需求,据统计西安有1300万人口,按照最大10%的市民同时扫码(我怀疑不会有这么多),也就是百万的并发量。

这样一个并发量的业务,在互联网公司很常见,甚至比这个复杂的场景也多了去了。

那怎么就崩了呢?


3 技术分析


在当天晚上的官方回复中,我们看到有这样一句话:

12月20日早7:40分左右,西安“一码通”用户访问量激增,每秒访问量达到以往峰值的10倍以上,造成网络拥塞,致使包括“一码通”在内的部分应用系统无法正常使用。“

一码通”后台监控第一时间报警,各24小时驻场通信、网络、政务云、安全和运维团队立即开展排查,平台应用系统和数据库运行正常,判断问题出现在网络接口侧。

根据上面的信息,数据库和平台系统都正常,是网络出现了问题。

我之前在文章《一次dns缓存引发的惨案》画过一张访问示意图,用这个图来和大家分析一下,网络出现问题的情况。



一般用户的请求,会先从域名开始,经过DNS服务器解析后拿到外网IP地址,经过外网IP访问防火墙和负载之后打到服务器,最后服务器响应后将结果返回到浏览器。

如果真的是网络出现问题,一般最常见的问题就是 DNS 解析错误,或者外网的宽带被打满了。

DNS解析错误一定不是本次的问题,不然可能不只是这一个功能出错了;外网的宽带被打满,直接增加带宽就行,不至于一天都没搞定。

如果真的是网络侧出现问题,一般也不需要改动业务,但实际上系统恢复的时候,大家都发现界面回到文章开头提到了第一个版本了。



也就是说系统“回滚”了。

界面少了接种信息和核酸检测信息的内容,并且在一码通的首页位置,新增加了一个核酸查询的页面。



所以,仅仅是网络接口侧出现问题吗?我这里有一点点的疑问。



4 个人分析


根据我以往的经验,这是一个很典型的系统过载现象,也就是说短期内请求量超过服务器响应。

说人话就是,外部请求量超过了系统的最大处理能力。

当然了,系统最大处理能力和系统架构息息相关,同样的服务器不同的架构,系统负载量差异极大。

应对这样的问题,解决起来无非有两个方案,一个是限流,另外一个就是扩容了。

限流就是把用户挡在外面,先处理能处理的请求;扩容就是加服务器、增加数据库承载能力。

上面提到官方让大家没事别刷一码通,也算是人工限流的一种方式;不过在技术体系上基本上不会这样做。

技术上的限流方案有很多,但最简单的就是前面挂一个 Nginx 配置一下就能用;复杂一点就是接入层自己写算法。

当然了限流不能真正的解决问题,只是负责把一部分请求挡在外面;真正解决问题还是需要扩容,满足所有用户。

但实际上,根据解决问题的处理和产品回滚的情况来看,一码通并没有第一时间做扩容,而是选择了回滚。

这说明,在系统架构设计上,没有充分考虑扩容的情况,所以并不能支持第一时间选择这个方案。



5 理想的方案?


上面说那么多也仅仅是个人推测,实际上可能他们会面临更多现实问题,比如工期紧张、老板控制预算等等...

话说回来,如果你是负责一码通公司的架构师,你会怎么设计整个技术方案呢?欢迎大家留言,这里说说我的想法。

第一步,读写分离、缓存。

至少把系统分为2大块,满足日常使用的读业务单独抽取出来,用于承接外部的最大流量。

单独抽出一个子系统负责业务的更新,比如接种信息的更新、核酸信息的变化、或者根据业务定时变更码的颜色。

同时针对用户大量的单查询,上缓存系统,优先读取缓存系统的信息,防止压垮后面的数据库。

第二步,分库分表、服务拆分。

其实用户和用户之间的单个查询是没有关系的,完全可以根据用户的属性做分库分表。

比如就用用户ID取模分64个表,甚至可以分成64个子系统来查询,在接口最前端将流量分发掉,减轻单个表或者服务压力。

上面分析没有及时扩容,可能就是没有做服务拆分,如果都是单个的业务子服务的话,遇到过载的问题很容易做扩容。

当然,如果条件合适的话,上微服务架构就更好了,有一套解决方案来处理类似的问题。

第三步,大数据系统、容灾。

如果在一个页面中展示很多信息,还有一个技术方案,就是通过异步的数据清洗,整合到 nosql 的一张大表中。

用户扫描查询等相关业务,直接走 nosql 数据库即可。

这样处理的好处是,哪怕更新业务完全挂了,也不会影响用户扫码查询,因为两套系统、数据库都是完全分开的。

使用异地双机房等形式部署服务,同时做好整体的容灾、备灾方案,避免出现极端情况,比如机房光缆挖断等。

还有很多细节上的优化,这里就不一一说明了,这里也只是我的一些想法,欢迎大家留言补充。


6 最后


不管怎么分析,这肯定是人祸而不是天灾。

系统在没有经过严格测试之下,就直接投入到生产,在强度稍微大一点的环境中就崩溃了。

比西安大的城市很多,比西安现在疫情还要严重的情况,其它城市也遇到过,怎么没有出现类似的问题?

西安做为一个科技大城,出现这样的问题真的不应该,特别是我看了这个小程序背后使用的域名地址之后。



有一种无力吐槽的感觉,虽然说这和程序使用没有关系,但是从细节真的可以看出一个技术团队的实力。

希望这次能够吸取教训,避免再次出现类似的问题!

最后,这里再给大家推荐一个程序员学习网站,可以说涉及到程序员的方方面面的资源都有,使用了的朋友都说,只恨没有早点发现这个网站:


@纯洁的微笑

也可以关注我的知乎,一个有故事的程序员,如果对你有用,来个赞吧!


user avatar   lu-xing-min 网友的相关建议: 
      

回答一波

健康码连续挂了两次真的有点业余了,不过确实也没有low到服务器生成图片进行下发这么蠢。

看一波西安健康码的接口数据。

真正的二维码数据是 /person/app/refreshQRCode这个接口


看下这个接口返回,设计上也没有太大的问题。


主要问题集中在所有的js/css/img这些静态资源全都从从一个出口进行提供,没上CDN

粗略估算了一下,js/css/img数据总共约500kB

按照从某个群里得到的数据,暂且认为是准的,健康码的请求量峰值达到了3.3w qps

那按照这个量估计 33000 x 500 x 8 bps ≈ 125Gbps 这个出口量级很难用单机房承载,峰值一来,出口网卡打满,直接gg。


到写这个回答时,西安健康码还是没有将静态资源上CDN,之后看看访问量再起飞的时候,能不能扛得住吧。


user avatar   luo-wei-zi 网友的相关建议: 
      

根据这个报道,起码错了两三个地方。


ABC这个,高并发软件不能作主从备,主从备在切换的时候,是最危险的时候,高并发突发的必须双活或者多活备,主从备只能用在低可靠性软件上。这是架构师可以直接开除的软件架构错误。

前端主工程师也可以直接开除,因为他不懂如何处理图片。。。1MB直接到100KB就可以,为什么会走中间一步。而且我看出错,是加载失败和502,也就是说,这个前端是完全加载的,而不是优先加载重要部件,最后把proxy搞死了,我甚至于猜这个宕机根本不是流量的问题,说不定是proxy上的log把系统撑爆了都有可能。。。绿码最重要,什么东西都不显示都应该优先显示,其他logo之类的玩意,优先级应该放低。顺便说一下两个通宵把1MB图片变到100KB这个技术实力等同于什么呢?计算机系如果大一下不能在4个小时内找到解决方案,退学算了。拿大家都懂的比喻,大概是“我校数学教研组组长能在1小时内做出15道20以内四则运算呢!”

项目计划也有问题。如果一个项目,连着40天,每天白天开发,晚上发布测试。但凡做过1年以上项目管理工作的人都知道:这项目要完了,这是严重delay拼了命修bug呢。。。


真的,写技术软文稍微咨询下架构师,能少多少麻烦。


user avatar   zhang-hai-tao-82-58 网友的相关建议: 
      

表面是个技术问题,实际是一个经济问题!


我造了一条完美的船,那么这条船交付之后就没我啥事了,我造了一条到处漏水但勉强能开的船,现在船主每天都离不开我~

修船什么的,总得要经费吧?


user avatar   ZhXand618 网友的相关建议: 
      

服务端生成二维码图片?

昨天看到有人提到二维码服务端生成的梗

傻白(不甜)的我当真了……(开始用错词了,原来傻白甜不能形容男生 Orz...)


还跑去扒证据看热闹……结果发现自己被骗了[捂脸]

看热闹过程

1、想直接抓 HTTP 包

惦记通过 PC 微信打开「西安市民一码通」抓个包,结果发现「个人电子码」注册时需要以西安的地址注册

怕万一给我健康码搞红了,所以没敢继续……

简单的路走不通,只能换一条复杂点的

2、那就看看这个小程序咋写的吧

因为自己是苹果手机,于是找出之前用过的安卓模拟器(为啥不是虚拟机?因为我电脑里没有 Android Studio 之类…)

我真的不是拿这个(安卓模拟器)玩游戏,我发誓……


具体步骤

  • 在安卓模拟器登微信小号,打开大号转发来过来的「西安市民一码通」小程序
  • 然后找到此路径下的新增文件(*.wxapkg)
  • 把它们拷到电脑上,用一个叫「wxappUnpacker」的东西解包,拿到微信小程序源代码
  • 从源码的 pagesindexindex.wxml 中找到了个人电子码,及其点击事件绑定的函数名「onElectronCode」,进而从 pagesindexindex.js[1] 中跟踪到「onYmtLogin」->「toYmtLink」-> 「toElectronCode」

其中

       N = getApp(),      
  • 从源码的 app-service.js 中,找到 globalData.ymtUrl 的值
  • 拼接出完整 URL(就是参数不全),浏览器访问了一下
  • 然后发现了 qrcode.js,在里面找到了「personCodeShow」->「qrcodeColour」
       function qrcodeColour(e, t, a, o) {     var s = baseUrl + "/view/login.html?code=" + t       , i = 300       , r = 300       , n = i       , d = r       , p = 80       , l = 80       , c = (i - p) / 2       , u = (r - l) / 2       , m = $(e).qrcode({         render: "canvas",         text: s,         width: i,         height: r,         background: "transparent",         foreground: a     })       , g = m.find("canvas").get(0)       , C = new Image;     C.src = g.toDataURL("image/png"),     C.onload = function() {         g.width = n,         g.height = d;         var e = g.getContext("2d");         e.fillStyle = "#ffffff",         e.fillRect(0, 0, g.width, g.height),         e.drawImage(C, 0, 0);         var t = new Image(p,l);         t.src = o,         t.onload = function() {             e.drawImage(t, c, u, p, l)         }     } }      

到这终于发现自己被骗了,人家并没有服务端生成二维码图片。

花了这么长时间,没看到想看到的结果,我亏大了啊……



被系统误伤了 - -

昨天被系统误伤了,个人信息被重置,无法修改文章、点赞和回复,刚刚恢复正常 - -b


感谢大家的围观,我这一个看热闹翻车的经历,竟然占据了回答的前排,诚惶诚恐…

如果想看专业的分析,可以多看看其他高赞回答哈~

参考

  1. ^ 感谢 @rewriter1.0 提醒,已经补上 js 文件路径(函数定义在这里,wxml 里是结构)

user avatar   lejoys 网友的相关建议: 
      

算了,不说了 。


这就是答案。


user avatar   sun-yi-fu 网友的相关建议: 
      

算了,不说了 。


这就是答案。


user avatar   undersea 网友的相关建议: 
      

算了,不说了 。


这就是答案。


user avatar   kavience-xiaofan 网友的相关建议: 
      

算了,不说了 。


这就是答案。




  

相关话题

  Visual Studio Code 如何编写运行 C、C++ 程序? 
  CSS Grid 布局那么好,为什么至今没有人开发出基于 Grid 布局的前端框架呢? 
  如何看待每周更新文章等于个人能力一般加上工作不饱和的看法? 
  为什么所有计算机培训课程老师的宣传照都是一身西装双手交叉在胸前。这明明不符合程序猿应该有的气质啊? 
  为什么很多后端写接口都不按照restful规范? 
  后端人员转前端是不是真的很容易? 
  如何看待这份2018互联网校招高薪清单? 
  为什么 Java 只有值传递,但 C# 既有值传递,又有引用传递,这种语言设计有哪些好处? 
  朋友自杀前把名字改成了nullptr,是什么意思? 
  大文件传输主要技术瓶颈都有哪些?如何处理的? 

前一个讨论
你怎么看西安女子集中隔离哭着讨要卫生巾?
下一个讨论
如果你是乌克兰领导人,怎么带领这个国家走出困境,甚至实现崛起?





© 2024-12-22 - tinynew.org. All Rights Reserved.
© 2024-12-22 - tinynew.org. 保留所有权利