西安一码通分析! 2022-01-10

哈喽,大家好!我是指北君!

西安一码通最近出现了两次事故,大家都在分析原因,想找到一些优化的方向。指北君也看过了网上的各种猜测等等。但是无端的猜测还不如自己分析一番,那么我们先来分析西安一码通的工作原理,然后猜想后面的架构等。

1.一码通访问抓包解析

通过西安一码通访问网址可以先看看返回的数据内容。(https://data.xa.gov.cn/ptrace/view/qrcode.html)

这个已经是1月4日优化过后的系统了,我们也可以继续分析一下麽!

1.1 返回的静态资源数据

首先需要登陆一码通,登陆之后返回静态资源如下:

image-20220107005121583

这些文件有多大呢

image-20220107010756379

优化后的传输内容一共是325kb,解压之后一共是624kb。资源使用应该是不大的。

并且很多静态数据都放到Cookies里面了,过期时间大多都是在100年或者10年

个人二维码相关的数据也放到了Cookies里面,数据过期时间应该是设置了1小时。这一块应该是1月4号一码通崩溃之后一个紧急修复结果。如果Cookies不清理,一个小时内刷新二维码都不会重新获取二维码数据,也就不会把压力打到服务器上,这也是4号之后,一码通感觉快了很多的原因。

下图个就是Cookies数据

image-20220107070909779

1.2 个人一码通重要数据

其实到最后不停地刷新获取的数据是QRCode接口返回的json数据了,然后我们单独看获取QRCode的接口,

https://data.xa.gov.cn/person/app/refreshQRCode

返回值如下,

image-20220107010213434

摘取出返回的json串数据后,并对返回的JS数据分析,得出各节点数据内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
	"msg": "操作成功",
	"code": "0",  // 可能是代表返回的数据状态 从JS文件中看到有01001301205这些值,
    			 //0应该是正常返回值 
	"data": {
		"personName": "X**",
		"code": "8ed******************************************3", // 个人token,很重要!
		"logoFlag": "0", //是否为入境人员
		"showTreeReason": null,
		"healthStatus": "1", //健康状态,决定你是绿马还是黄码或者红码!1234分别代表了不同的防疫措施
		"idCard": "6****************4",
		"iconFlag": "0",
		"codeReason": null
	}
}


下面几个值是比较重要的数据。

  • code应该是代表返回数据状态,是否正常返回

  • data.code是一个重要的数据,算是个人的一码通token信息,这个是生成二维码的关键信息,我们后面会讲到。
  • 还有一个重要的数据就是data.healthStatus,1234 分别表示绿黄红、深红,也代表了不同的防疫措施。

其他都是一些个人数据

2. 一码通二维码是如何生成的

其实在前面的分析中也可以看到加载的静态资源文件,从命名可以猜测,其中大部分文件都是2021年12月9号17:55分提交的文件,一些css和js文件后缀可以看出来。

其中只有qrcode.js的文件是2022年1月4日12点20左右提交更改的。命名也是比较清晰的,一目了然。

image-20220106230331619

其中刷新,生成二维码的js代码就在qrcode.js中,将js文件全部导出,用VS-Code打开,并且格式化这些JS文件。

  1. 可以看到refreshQRCode()方法。

其中有一行 getCookie(“personCodeInfo”),猜测这一判断逻辑是1月4号修复时加的。起码1小时内可以不用把流量打到服务器,服务器压力立马就下来了。

客户端缓存了个人token,而且有1小时的过期时间,对于当天所核酸的人群来说,完全足够了。

image-20220107011712060

如果Cookies中没有缓存的数据那么才会去请求接口获取最新的二维码信息。 而且也会在请求完成后,更新cookies中的数据,

image-20220107080955280

  1. 从Cookies中或者直接请求接口获取到的数据之后,会调用personCodeShow()

这个方法用于显示二维码

由于参数传递只用了一个字母,很难判断其代表的意思,故将接口返回的json数据也列出来,方便查看对比。

image-20220107075340157

到这里就很容易看出其调用如下方法来生成二维码

1
qrcodeColour("#output", n, "#000000", p)

其中n就是之前提到的个人token,p为二维码中间的图标。

  1. 下面再来看看qrcodeColour这个方法。

image-20220107075855811

直接拼接出 https://data.xa.gov.cn/ptrace/view/login.html?code=xxxxxxx 这样一个登陆地址,

然后再使用jquery.qrcode 生成二维码数据。

至此二维码生成,可以去扫码做核酸了。

核酸扫码的时候,扫码的机器会识别二维码然后去到了防疫人员登陆系统,此时就录入核酸检测记录系统了。

image-20220107080519413

这里小结一下:

  1. 一码通二维码生成并不是网友们调侃的传输图片数据,而是通过前端框架jquery.qrcode生成的。内容就包含了一个登陆链接再加上个人token码。
  2. 也有网友说崩溃的一个原因是因为静态资源加载问题,这个也可以排除了,客户端都有这些静态资源的缓存,所以这些静态资源在第一次加载之后,不会重新加载了。西安的用户每天都在展示二维码,所以肯定不会每次都去加载这些静态数据。
  3. 一码通生成的绿黄红码等是通过接口数据控制,主要通过背景色来显示,此时猜测一般情况下个人token在一段时间内应该是不变的,所以二维码本身也不会变话。所以收集保存二维码截图,做核酸的时候,防疫终端也可以识别此二维码。
  4. 其实这样看来,服务器的重点内容是要通过大数据计算出此人的二维码应该是绿黄红、深红等。
  5. 1月4日的客户端修复措施主要是将个人token数据缓存到客户端,一小时内不会访问服务器,这一措施还是比较管用的,同一时间段不会有大量请求打到服务器上。

3. 一码通崩溃的个人分析

从1月4日上线的修复记录来看,服务端崩溃就是获取qrcode的个人数据的时候服务器崩溃,至于服务端是怎么崩溃的众说纷纭。没有具体的代码可以看,我们也不妄加揣测。

工信部的领导过来之后,提出了给服务其扩容,那么此时可以看出服务器优化的事情在短时间内肯定是做不了的。

2021年12月 一码通崩溃应该也是同样的原因,但是当时可能没有在客户端想办法削减流量,只是简单重启了服务,而且当时服务停止的时间超过12个小时了,而且很多核酸数据都丢失。据此看,上一次的修复可能只是重启,数据库会滚到某一个时间点,而且对服务端进行了扩容,至此在此后核酸检测的时候,一段时间内都没有出现问题。然而到了1月4号的时候服务器又崩溃,此时又是服务端处理能力已经到头了。

2022年1月4日采取的修复措施,改变了思路。在客户端缓存数据直接削减大部分流量,服务器压力立马少了很多。而且当天服务恢复用了几个小时,应该是回滚到某一个备份的版本。12月崩溃之后,应该是每天都有了备份数据,恢复也比之前容易了很多。所以我们看都之前某一天的核酸数据没有了,但是上前天的数据还在。

另外一个注意的点是,1月4日一码通恢复当天,有的人不能刷新数据。有一个原因就是需要把小程序删除重新加载一次获取当天更新的qrcode.js文件。另外一个原因可能是移动网络和电信网络之间的刷新问题,域名后面的IP地址刷新到移动网络需要一点时间,而电信网络就快一点。

下图可以看到一码个人qrcode码数据请求ip时在电信云数据中心的网关。

image-20220107084448987

4. 后续可能的优化

后续应该会针对服务端加redis,redis集群,或者mq,读写分离等等一系列操作,还会加强压力测试等。这些都是网友们群策群力想出的服务端优化方案。如果有机会看到服务端的一些信息,我们还可以在分析一波。

Java Geek Tech wechat
欢迎订阅 Java 技术指北,这里分享关于 Java 的一切。