技术视角看我的一码通-系列2

小伙伴们,大家好。上次那篇文章-“技术视角看我的一码通【系列】”简单的从扫描一码通后二维码中包含的网址信息分析了下,今天我们继续。

这篇文章主要是为下期深入讲解【缓存】做个铺垫,以及准备一下缓存所需的基本环境。

两个核心入口

笔者把“一码通”保存在了手机桌面,所以打开一码通非常方便。一般打开一码通的步骤是:

    支付宝: 支付宝首页 -> 一码通(已添加到了首页)或者:首页-》 搜索一码通-》 进入
    微信: 微信 -》 发现 -》 小程序 -》搜索一码通  
  以上说明:对于用户量非常庞大,几乎是人人都需要的程序,【使用要非常便捷】。从小孩到大人,都要能非常方便的找到自己的“一码通”,同时要借用已有的软件(用户基数庞大),可以做到“一夜”之间普及,这应该是非常基本的“产品”思维吧。
  所以:支付宝、微信都可以通过“小程序”进入一码通,对于开发人员而言,需要对接这两种小程序。

1) 小程序

“一码通”的入口本质是:小程序,即:支付宝的小程序(至于小程序,笔者就多介绍了,请自行百度)。微信只是提供了一个入口,最终跳转到的【我的一码通】还是支付宝的小程序界面。

其实,如果细心点,我们在这个“码”一上线的时候,就可以发现这些信息:

支付小程序入口
在这里插入图片描述

这表明这是个支付宝的小程序。其他信息大家通过新闻都基本很了解了。可以看到最近更新是1月8号,是周六,可以猜想同行们加班了。

微信小程序入口
在这里插入图片描述

此图是从微信小程序入口进去后可以查看到的信息,表明来源是:【微信小程序】。笔者访问了【服务由以下网址提供】罗列出的所有网址,发现了上一篇博客的介绍的:https://data.xa.gov.cn 这个网址,以及:腾讯地图等,其他是测试网址。用到地图可能是需要采集行动轨迹、是否时空交叉等,不过具体使用界面笔者暂未从小程序中找到。

总结:以上信息是我们自主自发获取到的,并非通过新闻“后知后觉”地知道,可以从中感受到一些设计思想:

产品采用什么形式开发?是开发一款App?还是做个Web端?还是小程序?基于支付宝还是基于微信?基于了其中一款,另外一款怎么办?
“一码通”是基于支付宝小程序开发的,微信小程序做了个入口直接“链”过去。开发小程序非常方便,开发APP太重,开发Web端不利于用户访问。

2)进入方式

点击小程序图标,拉起小程序主页之后,点击【我的电子码】,可以发现进入的是一个【H5页面】。我们知道,如果是原生的APP或者小程序里面的页面,页面加载是非常流畅的,基本感受不到这种“加载”的过程,从第二张长长的加载进度条可知,这个界面是H5。

在这里插入图片描述
在这里插入图片描述
当然,抓一下包看一下接口是最直白的方式了。笔者因为疫情,购买的Type-C USB转换头还在路途中,导致无法刷机、安装系统证书去抓包,不过也看到有网友抓了一下包并简短的分享了一下接口信息。
这个下面会继续讲。

核心接口

笔者虽然最近无法抓包,但是受益于公众号【C语言与CPP编程】的一篇文章,文章来源是:

卢兴民 知乎上一篇文章 连接就不粘贴了 作者发的是图片
文章提到获取二维码数据的接口是:

	   /person/app/refreshQRCode  
	   具体是GET、还是POST,文章没提,笔者后期可以抓包了在补充。

那篇文章是从加载的静态图片来分析的,笔者想对这个接口的一些参数背后的故事做一些猜想:

{
  "msg": "操作成功",
  "code": "0",
  "data": {
    "personName": "",
    "code": "",
    "logoFlag": "0",
    "showTreeReason": "",
    "healthStatus": "1",
    "idCard": "",
    "iconFlag": "",
    "codeReason": ""
  }
}

这就是后端返回的二维码包含的信息,这里面有一些我们比较“熟悉”的字段:

 healthStatus 
 这个字段自然是表达“一码通”颜色。假设 1-绿色,2-黄色 3-红色。
 这个字段“大有来头”,就是后端根据什么“规则”来判定这个码到底是什么颜色呢?
 从新闻中了解到:大体规则是:“根据人员的风险等级及管控措施进行标码:
 高风险人员及需集中隔离人员标红码,中风险人员及需居家隔离人员标黄码,低风险人员及无管控要求人员标绿码”

简单的说,两个主要因素:
1-人员的风险等级   
2-管控措施

人员的风险等级:举个例子,如果一个人核酸检测阳性,其“码”要能在检测结果出来之后自动变为红色;
如果一个人来自“高风险”地区,其码也要能自动变为红色;

管控措施: 如果A城区升级为高风险地区,或者B小区发现一例病例,整个小区需要集中隔离,那么该地区的人员或者说该小区的人员的所有的“码”要能够及时变成红色;
如果C区原本正常,后来调整管控力度升级为了“中风险”,那么C区的人员的“码”应该及时变黄。

从这个角度来看,“码”实在太重要了。一旦疫情发生,如果“码”能够精准、及时变色,对于阻断传播链非常重要。
所以,我们来设想一下“码变色”背后的逻辑:
【1 人员的风险等级】要和核酸检测结果相关。假设1000万人,每人核酸7次,至少产生7千万条核酸数据记录,
算上以往核酸的记录(虽然不展示,后台要保留数据),轻松就过亿了。假设数据库是MySQL,如果不分库不分表,最“差”的情况是单表存,
单表数据到“亿”级别查询就会非常吃力。这还只是核酸的数据,还不包括人员信息、行程信息、区域管控信息等;

假设一个人去上海旅游,中途去浙江,然后回到西安,最后回到某某村。去上海时那里一切正常;在浙江期间,所在地升级为“中风险”地区,
那么这个人的“码”要能变“黄”,这个要根据他的地理位置信息,所以后台要记录每个人的地理位置和移动轨迹,才能在这个人进入某个地方的时候,能够实时或者异步根据这些“赋码”规则来计算这个人的“码”应该展现什么颜色。我们经常听到“时空交叉”,指的是:时间、空间上和病例有交叉的人员。怎么判断“我”在时间上、空间上是否和别人有交叉呢?光靠自己脑袋回忆是万万不行的,个别人出于顾虑可能还会隐瞒,所以需要收集每个人的行程数据,这个数据可能来自“12306”,来自“携程”,来自各大购票网站,就是说会有一个整“行程网”记录了你的所有轨迹;然后时间、空间是否交叉,就需要把相关人员的数据全都关联在一起,就简单的理解为集合之间的交集、并集、合集之类的操作,最终“算”出你是否有可能和病毒携带者“密接”,然后:调用三大运营商的短信接口,给你发送提示短信;后台异步任务去刷新你的一码通,当你进村的时候,乡亲们让你展码,你发现在浙江的时候还是黄码,怎么现在就是红码了?所以,你需要隔离。
因此,这个“码”及时的阻断了你可能给一个村的传播的可能性。


上面说的还不算【2-管控措施】对“码”颜色的影响,一旦某个地区疫情有抬头的趋势,一个村、一个小区、或者一个省都在不停的调整管控措施,每次调整政策之后,后台都要能及时根据调控的政策来对对应区域的人的“码”的颜色进行计算,计算的时机和频率都要能快速响应政策的要求;这对于后台算法,计算的实时性、数据量要求是很高的,笔者真的希望可以非常具体的从代码层面来描述一个算法,这个留在后面有了灵感在细说吧。


想象一下,一个省的数据就非常多了,国家还需要宏观管控所有的数据,数据量真的是“海量”。


    code 
    这个字段很有可能就是https://data.xa.gov.cn/ptrace/view/login.html?code=634588JFDAJFAKFAJF  这个连接携带的code。至于这个code具体含义,就不在深究。
    codeReason
    showTreeReason
    这个codeReason可能就是:“码”颜色的解释。比如一个人的码是“红色”,那么这个字段可能会很简洁、清晰的说明这个人为什么“红码”。因为所有的计算都是后台完成,这个计算结果是否正确?计算用到了哪些数据?只有程序员说说得清楚,对于计算逻辑,根本无法在短时间内排查,因此,要在计算过程中记录每个“决定”的依据,然后在需要的时候返回缓存的计算过程数据。
    
   showTreeReason ,字面意思是一个“树状”的原因,推测可能是一个原因“链”。就是层层分析、层层推算的这样一个过程的展示数据。

以上可以表明:
1、该接口背后要做很多事,要用到大数据
2、数据量大得超乎想象
3、算法复杂,对实时性要求有高有低
4、这个查询接口调用频繁
调用频繁的场景举例:
1)上班高峰调用频繁。
每天上班8-9.30,所有上班人员都需要展示一码通,意味着在8点之前,后端的计算结果要出来,然后缓存计算结果,当人们到达公司给门卫叔叔展码的时候,才能很流畅。
2)集中核酸时调用频繁

使用缓存

上面的“猜想”比较“假大空”,这些天也看了一些分析一码通背后技术的视频,笔者就想先从一个点切入,直观简洁的表达出来,思来想去还是从【缓存】开始。

笔者搭建了一个套环境:

前端Vue、后端SpringBoot,前后端分离.
模拟写了一个获取“一码通”的接口,然后给这个接口简单加了缓存,部署在阿里的ECS上.
前端用Nginx,采用Docker部署Nginx
后端通过jar方式部署,jdk1.8
Redis部署的是单机,采用Docker部署。

效果如下:

在这里插入图片描述

后端Controller层代码:

 /**
     * 加载二维码
     *
     * @return
     */
    @GetMapping("")
    @Cacheable(value = {"qr_code"})
    public String getMyQrCode() {
        return qrcodeService.getQrcode();
    }

在这里插入图片描述

缓存后的效果如下:

在这里插入图片描述
有了这样的环境,后期想加什么就非常方便了,“舞台”已经搭好。

好了,今天就分享到这里。在这里要感谢读者的评论,你们的评论让在下找到了些许灵感。
下期打算正式从【缓存】角度开始,一步一步探索和分析如何应对【高并发】。

再会!

<template> <div class="modal-overlay" > <el-form class="search-form"> <div class="form-item-div"> <el-form-item label="设备IP" class="form-item"> <el-input style="height:25px;width:150px;font-weight: bold;"></el-input> </el-form-item> <el-button type="primary" size="small">搜索</el-button> </div> <div class="form-item-div"> <el-form-item label="设备ID" class="form-item"> <el-input style="height:25px;width:150px;font-weight: bold;"></el-input> </el-form-item> <el-button type="primary" size="small">搜索</el-button> </div> <el-form-item class="reset_button"> <el-button type="primary">重置</el-button> </el-form-item> </el-form> <div class="modal-content" v-if="props.device.id"> <h2 style="width: 100%;margin:5px;">{{ props.device.id }}</h2> <div class="info-section"> <h3 style="width: 100%;margin:5px;background-color:#5f9ea0;">状态</h3> <div class="status-div"> <div class="status-indicator" :style="{ backgroundColor: statusColor }"></div> <span>{{ statusText }}</span> </div> </div> <div class="info-section"> <h3 style="width: 100%;margin:5px;background-color:#5f9ea0;">视频链接</h3> <button @click="showVideo">Load</button> <button >Unload</button> <button >DFC</button> <button >D/S L</button> <button >D/S R</button> <button >A/H L</button> <button >A/H R</button> <button >Wafer</button> </div> <div class="info-section"> <h3 style="width: 100%;margin:5px;background-color:#5f9ea0;">程序安装</h3> <div class="program-item" v-for="(installed, name) in props.device.programs" :key="name"> <span>{{ name }}:</span> <span :class="['status', installed ? 'installed' : 'not-installed']"> {{ installed ? '已安装' : '未安装' }} </span> </div> </div> </div> <div v-else>请点击设备或输入IP/ID搜索</div> <div> <VideoAspect v-if="videoOpen" :device="selectedDevice" @close="handleVideoClose"></VideoAspect> </div> </div> </template> <script setup> import { computed, ref, watch } from 'vue'; import VideoAspect from './VideoAspect.vue' const props = defineProps({ device: { type: Object, required: true }, // device:{ // id: null, // position: null, // size: { width: 2, height: 1, depth: 1 }, // status: 'normal', // normal/warning/error // videos: [ // { name: '主视角', url: 'rtsp://camera1/main' }, // { name: '辅助视角', url: 'rtsp://camera1/sub' } // ], // programs: { // AAA: true, // 已安装 // BBB: false // 未安装 // } // } }); const selectedDevice=ref({}) const videoOpen=ref(false); watch( props,(newProps) =>{ console.log(newProps) },{deep:true} ) const showVideo=(event)=>{ selectedDevice.value=props.device videoOpen.value=true; console.log(videoOpen.value); event.stopPropagation(); } const handleVideoClose=()=>{ videoOpen.value=false; } const statusColor = computed(() => { const colors = { normal: '#4CAF50', warning: '#FFC107', error: '#F44336' }; return colors[props.device.status] || '#2196F3'; }); const statusText = computed(() => { const texts = { normal: '正常', warning: '警告', error: '故障' }; return texts[props.device.status] || '未知'; }); </script> <style scoped> .modal-overlay { top: 0; left: 0; right: 0; bottom: 0; width: 100%; height:100%; } .search-form{ margin-top: 10px; margin-left: 10px; margin-right:10px; } .form-item-div{ display: flex; flex-direction: row; justify-content: center; align-items: center; max-width: 250px; margin: 0 auto; height: 50px; } .form-item-div .el-form-item { margin-bottom: 0; /* 避免垂直方向的多余间距 */ } .form-item{ padding-right: 5px; font-weight: bold; } .reset_button{ margin: 0 auto; } .modal-content { padding-top: 1rem; padding-bottom: 1rem; display: flex; flex-direction: column; justify-content: space-between; align-items: center; width: 100%; } .info-section{ width: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; } .info-section button{ width: 100px; margin: 5px; } .status-indicator { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 8px; } .program-item { display: flex; flex-direction: row; margin-bottom: 8px; justify-content: center; align-items: center; } .program-item span:first-child { width: 60px; font-weight: bold; } .status.installed { color: #4CAF50; } .status.not-installed { color: #F44336; } </style>好好看我的代码,重置按钮怎么居中
最新发布
09-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值