近日,一篇《疫苗之王》刷爆了朋友圈,疫苗的安全问题被推到了风口浪尖,腾讯安全反诈骗实验室团队推出了“腾讯安心计划”小程序,方便用户便捷地查询疫苗安全信息。

这样一个暖心的小程序是怎样做出来的?

“腾讯安心计划”小程序分为三个主要服务:小程序前端、TARS代理服务、TARS后台服务。

1. 小程序前端负责接收用户查询请求及反馈结果:

它的页面中实现了一个查询框,并且将查询框内输入的内容组成get请求发往接口URL。

1. // 小程序代码段 
2. // 疫苗批号查询输入框 
3. <template>  
4.   <input  
5.     value="{{input}}" 
6.     maxlength="20" 
7.     bindinput="handleInput" />  
8. </template>  
9.  
10.// 疫苗输入框响应参数 
11.<script>  
12.import wepy from 'wepy' 
13.export default class extends wepy.page {  
14.  data = {  
15.    input: '' 
16.  }  
17.  methods = {  
18.    handleInput(e) {  
19. const val = e.detail.value  
20. this.input = val  
21. this.search()  
22.    },  
23.    async search() {  
24. // 发送查询请求 
25. // 发出的请求类似与 xxxx.url.com/queryVaccine?number=123 
26. const resp = await wepy.request({  
27.        url: 'xxxx.url.com/queryVaccine',  
28.        data: {  
29.          number: this.input  
30.        }  
31.      })  
32. const {data} = resp.data  
33.    }  
34.  }  
35.}  
36.</script> 

2. 代理服务负责解析HTTP请求,并将其转为TARS请求发往后端:

它使用TARS-Node.JS,绑定一个接口URL(如:xxxx.url.com/queryVaccine),通过Node.JS的KOA2框架提供的get方法解析收到的请求,并获得其中的参数,然后直接传参调用后端tars服务的请求接口。


1. //  Node.js koa2 获取参数代码段 
2. const Koa = require('koa')  
3. const router = require('koa-router')()  
4. const koaBody = require('koa-bodyparser')  
5. // TARS工具 
6. const Tars = require('tars_client')  
7. // 引入TARS文件 
8. const vaccineProxy = require(‘tars/VaccineObj').App  
9. const app = new Koa()  
10. 
11.// 监听这个路径的get请求 
12.// 通过批次查询疫苗信息接口 
13.router.get('/queryVaccine', async ctx => {  
14. // 获取 get参数里面的变量 
15. // xxxx.url.com/queryVaccine?nunber=123 其中?后的参数可以这样获取 
16.  let {number} = ctx.query  
17. 
18. try {  
19. const tars = Tars.stringToProxy(  
20.      vaccineProxy.VaccineObj, 'App.Vaccine.VaccineObj' 
21.    )  
22. // 调用tars接口,传参 
23.    let result = await tars.QueryVaccine(number)  
24. // 获取结果体里面的结果信息 
25.    let info = result.response.arguments.vVaccine  
26. 
27. // 返回信息给前端 
28.    ctx.body = info  
29.  } catch(e) {  
30.    console.log(e)  
31.    ctx.body = 'error' 
32.  }  
33.})  
34. 
35.// 加载路由 
36.app.use(router.routes())  
37. 
38.// 启动服务 
39.app.host = 'localhost' 
40.app.port = 80 
41.const server = app.listen(app.port, app.host, () => {  
42.  console.log('Koa server listening on %s:%d', server.address().address, server.address().port)  
43.}); 

3. 查询服务负责提供查询结果:

它提供了一个查询本地内存的功能,首先定期从DB中捞出疫苗的信息数据,并写入内存,在收到接口请求后,在内存中查询到结果,再把结果返回给主调服务。


1. //在tars文件中定义结构体 
2. struct Vaccine  
3. {  
4.     0 require string vaccine ;  //疫苗名称 
5.     1 require string number ;    //批次 
6.     2 require string company ;  //公司 
7.     3 require string state ;   //状态  
8. };  
9.  
10.//创建疫苗信息vector vVaccine,并从数据库加载相关内容至结构体 
11.TC_Mysql::MysqlData oResults;  
12.try 
13.{  
14.    oResults = mysql.queryRecord("select vaccine,number,company,state from vaccine;");  
15.}  
16.catch (exception & e)  
17.{  
18.    LOG->error() << "VaccineData error query: " << e.what() << endl;  
19. return -1;  
20.}  
21.const size_t oResultsCnt = oResults.size();  
22. 
23.vVaccine.clear();  
24.for (size_t i=0; i<oResultsCnt; i++)  
25.{  
26.    App::Vaccine stInfo;  
27.    stInfo.vaccine=oResults[i]["vaccine"];  
28.    stInfo.number=ToUpperCaseString(oResults[i]["number"]); //批次号统一归一化为大写 
29.    stInfo.company=oResults[i]["company"];  
30.    stInfo.state=oResults[i]["state"];  
31. 
32.    vVaccine.push_back(stInfo);  
33.}  
34. 
35.//在VaccineObjImp.cpp中定义queryVaccine接口 
36.tars::Int32 VaccineObjImp::QueryVaccine(const std::string & strIn,vector<App::Vaccine> &vVaccine,tars::TarsCurrentPtr current)  
37.{  
38.    CAttrReport::getInstance()->AttrReportCount("QueryVaccine");  
39.    LOG->debug()<<"QueryVaccine"<<endl;  
40. //调用实际请求函数 
41. int ret=QueryVaccine(strIn,vVaccine);  
42. return ret;  
43.}  
44. 
45.//实际请求函数QureyVaccine函数定义 
46.int QueryVaccine(const std::string & strIn,vector<App::Vaccine> & vMatchVaccine)  
47.{  
48. if(strIn.length()<3)  
49.    {  
50. return -1;  
51.    }  
52. 
53. int size_cnt=0;  
54. 
55. const size_t cnt=VaccineHandle::getInstance()->vVaccine.size();  
56. for(size_t i=0;i<cnt;i++)  
57.    {  
58. if(size_cnt > SConfig::getInstance()->maxMatch)  
59. break;  
60. 
61. if(isNumberMatch(strIn,VaccineInfoHandle::getInstance()->vVaccineInfo[i].number))//判断批号一致 
62.        {  
63. //将查询到的内容push进查询结果vector 
64.            vNumberVaccine.push_back(VaccineHandle::getInstance()->vVaccine[i]);  
65.            size_cnt++;  
66.        }  
67.    }  
68. return 0;  
69.}  

这样,一个具备查询后台数据功能的小程序就完成了。

小程序的便捷开发与部署,不同于APP的版本管理,可以快速更新页面内容而用户无感知。TARS的多语言支持以及高可用,可以通过多种方案及手段高效实现自己的需求,同时不需要将过多的精力放在服务的容灾容错处理上。

单纯从代码开发效率来看,小程序+TARS这样的实现组合,可以在只有一个前端+一个后端开发者,或者一个全栈开发者的情况下,在一天之内就可以高效便捷地实现一个与“腾讯安心计划”功能类似的小程序了。

如果优秀的您对代码有不一样的想法,欢迎留言评论。

TARS开源地址:https://github.com/Tencent/Tars

文章来源于腾讯云开发者社区,点击查看原文