从程序员角度聊聊一码通

我是程序汪

共 3147字,需浏览 7分钟

 · 2022-01-09

最近西安疫情特别严重,前一阵子还出现了一码通崩溃的事件,网络上对此也有各种各样的评论和说法。对于各种言论和说法我们没有权力去评头论足,但是可以从技术的角度聊一聊,如果是我们接到了这样的需求,应该来如何设计这个系统。使得它可以在关键时刻经得住考验,为防疫工作提供方便做出贡献。


首先我们分析一码通大致有哪些基本需求需要实现,应该会有个人信息登记注册以及修改的需求。还会有个人健康信息查询需求,也就是健康码了。也有个人行程信息记录需求,也就是平时我们进出小区,商场,乘坐公共交通等等的时候扫码操作。应该还有后台修改个人数据的需求,例如更改个人的红绿黄码,个人核酸检测结果等。可以对上面需求做一个如下总结:

  • 个人信息登记注册以及修改:由用户端驱动,既有读操作也有写操作,实时性要求较高,写操作需要立即得到结果,但是并发量不大(毕竟大家同时修改个人信息的概率比较低)。

  • 个人健康信息查询由用户端驱动,只有读操作,实时性要求较高,并发量比较大(大家同时刷健康码的概率非常大,这次崩溃的就是这个服务)。

  • 个人行程信息记录:由用户端驱动,只有写操作,写操作不需要立即得到结果给用户,实时性要求较不高,并发量不大(毕竟疫情期间蜂拥而出情况不多)。

  • 后台修改个人数据:非用户驱动,应该是由后台的 job 或者相关工作人员来驱动的。只有操作发量不大(毕竟非用户驱动的操作还是可控的)。



数据中心

对于这种 mission critical 的系统还是建议从数据中心的角度建立多个 site,每个数据中心的接入点都申请不同的 FQDN 域名,从接入层就利用 DNS 的来分流到多个数据中心。当然这个可以不必那么复杂,不必引入 GTM 把流量基于地理位置分发到不同的地区的数据中心,毕竟大家都在一个地区。



接入层负载均衡以及 CDN

对于每个数据中心的服务来说一定是有负载均衡的,负载均衡基于不同的维度有很多种类。有三四层负载均衡,七层负载均衡,基于应用的负载均衡,基于操作系统内核的负载均衡,还有基于硬件的负载均衡。这个系统在接入层也不需有复杂的负载均衡策略,可以追求速度,所以可以选择更快的三四次负载均衡,或者硬件负载均衡。另外系统一定是有静态资源的,例如图片或者 html/css 等等,这些资源可以完全放在 CDN 来管理,以减轻系统负载,加速静态资源访问。



服务层拆分

根据上面的需求分析,可以根据基本需求的读写特性和并发量从业务上拆分不同的服务。

  • 个人信息登记注册以及修改:读写实时性较高,但是并发量不大,所以这个服务可以直接访问我们的存储 storage。

  • 个人健康信息查询:并发量比较大,这个服务不可以直接访问我们的存储,需要引入缓存来加速访问。

  • 个人行程信息记录:写操作不需要立即得到结果给用户,实时性要求较不高,并发量不大,所以可以引入消息队列 MQ 来加速并解耦这个服务和存储。

  • 后台修改个人数据:和上面的个人行程信息记录一样。

上面的服务层一定需要有快速的动态扩容和发布的能力,所以可以考虑基于当前比较流行的 kunbernetes 平台或者 service mesh 平台。另外对于服务的协议,如果追求速度可以考虑使用二进制的 RPC 协议(例如GRPC)来代替传统的 HTTPS + JSON 格式的协议。



缓存的引入

上面的分析指出,对于只读的,并且流量大的服务,例如个人健康信息查询,我们是一定需要引入分布式缓存的。对于分布式缓存我们可以考虑下面的几点:

  • 缓存容量:西安常住人口大约1200万人,一个人分配10KB的缓存估算,大约就需要120GB,在加上25%的 Buffer,所以需要大约总共150GB的缓存。当然这么大的缓存不可能是单机的,一定是分布式的的,需要利用一些基于缓存数据分片的 sharding 方式把他们均匀的缓存在不同的机器上。

  • 缓存预加载:我们不可以指望通过应用程先查询缓存,没有数据在去存储里取并放到缓存里,这样在并发大的时候依然会有问题。所以需要有缓存的预加载过程,当然我们可以基于数据 sharing 分片的方式去加载,例如可以基于人所属的区域,分不同的批次做,这样也提高效率。

  • 缓存击穿:如果查询一个不存在的对象,例如不存在的缓存 key,那么由于缓存里没有也依然会去访问存储的。所以对于缓存击穿的情况,我们可以给它设置一个短暂的缓存时间,以及一个空的值。

  • 缓存雪崩:当我们设置缓存的时候,如果不注意缓存过期时间,如果在同一时刻大批量的缓存失效,就会有大量的访问同时进入存储。所以我们可以基于数据 sharing 分片设置不同的缓存时间。另外我们还可以有一个缓存续约服务,对于那些没有数据更新的缓存,定期批量的延长缓存时间。当然这个服务也可以数据 sharing 分片提高效率。

  • 缓存同步:有缓存就有缓存同步的问题,我们可以引入缓存同步服务,来定期把有更改的数据批量同步到缓存里。当然这里的数据一定不是哪种实时性要求高的数据,比方说红绿码变更,近期核算检测结构等。对于实时性高的数据,例如个人信息登记和修改,一定是要同时更新存储和缓存的。



存储的引入

对于存储这个块,数据量一定是比较大的,而且根据不同时期的防御政策一定会有不同的动态数据加入,数据结构变化可能比较频繁,所以可以引入 NoSql 来做数据存储。另外不仅仅是存储的问题,一定会有大数据的分析需求,有基于实时性要求比较高的流处理和可以有等待的批处理,以及将数据汇报给国家防疫平台的处理等,这里我们做不展开讨论。



监控和预警的引入

对于这种 mission critical 的系统一定需要有完善的监控和预警的引入,需要从不同维度上来对整个系统来监控和预警,如:

  • 基础设施和操作系统维度:也就是我们经常会提到的计算维度的 CPU, 存储维度的 Memory/Disk,网络维度的吞吐量等等。

  • 中间件维度对各种中间件的监控,例如缓存,线程池,连接池,数据库,消息队列,应用服务器,负载均衡器等等。

  • 应用程序维度:应用程序本身的监控,也就是我们常常所说的 APM 这个概念,可以更细节的了解应用本身的运行。


总体架构设计

综合上面分析,high level 的设计可以如下:


另外从一码通的小程序详细信息上也看到一些不是很专业的地方,例如:
  • 莫名其妙的9443端口

  • 莫名其妙的消息

  • 可以看到前端调试信息按钮等

  • 友情提示一下证书还有半年多就要过期了,可以尽快换证书。



当然上面的设计和思路也只是笔者的家之言和浅浅的见解,不一定是最好最合适的方法,也许还有什么纰漏和漏洞,也欢迎大家多多交流,多提意见,一起学习。另外虽然一码通也经历了崩溃事件以及有不专业的地方,但是它毕竟也为这座城市的防疫数字化做出了贡献,也方便了防疫工作和大家,还是这座城市防疫工作中不可缺少的必要工具。希望大家都可以在疫情期间保持身心健康,注意安全,学习到多的东西,也希望疫情早日过去。

程序汪资料链接

程序汪接的7个私活都在这里,经验整理

Java项目分享 最新整理全集,找项目不累啦 06版

堪称神级的Spring Boot手册,从基础入门到实战进阶

卧槽!字节跳动《算法中文手册》火了,完整版 PDF 开放下载!

卧槽!阿里大佬总结的《图解Java》火了,完整版PDF开放下载!

字节跳动总结的设计模式 PDF 火了,完整版开放下载!

尚硅谷Java学科全套教程(总207.77GB)


欢迎添加程序汪个人微信 itwang005  进粉丝群或围观朋友圈

浏览 23
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报