- 英雄联盟线下赛事背后的技术实践
近几年,随着电子竞技的赛事火热,越来越多的游戏推出了自己的电竞赛事,玩家们也更多的走进线下,为喜欢的战队打call,体验线下观赛的魅力。于是提升玩家现场的观赛体验也就成为了我们新的研究课题。 有赖于以往对线下活动的支持经验,我们认为基于用户手机去做O2O的全场运营活动同样能为大型赛事活动提供较好的用户体验。 那么如何实现一个O2O的运营活动呢? 技术载体研发 在O2O 活动运营中,存在两类目标受众,一是用户端,也就是现场观众;一是管理端,即现场工作人员。所以我们需要基于两个目标受众来研发对应程序。 面向现场观众,我们连接了基于小程序为起点的互动场景: ① 小程序互动 小程序免下载特性,在线下活动场合非常适用。所以小程序是我们首选的用户端交互载体。基于互动小程序 ,玩家可以在小程序内进行拍照分享留念、获取官方摄影师拍摄的现场精美图片、进入现场观赛聊天室内聊天以及参与现场答题互动赢大奖。 ② 现场大屏互动 为了促进玩家的现场参与度,我们在现场的大屏幕展示了一些东西来促进现场玩家的互动,包含现场玩家签到头像上大屏、玩家在小程序分享的内容上大屏、聊天室弹幕上现场环屏和答题排行榜前十名上大屏播报。 面向工作人员,我们提供了大而全的WEB管理端: WEB管理端的基础功能配置包含小程序首页的Banner图配置以及小程序内的文案标题和一些互动的开关配置。在八周年活动的三天时间里,每天的互动奖品信息和参与规则都会有变化,通过服务端的配置可以节省小程序审核的所需要的时间,大大提高了现场运营的灵活性。 此外,在WEB管理端,我们还提供内容审核、互动抽奖等功能。 现场运营工作部署 在O2O活动运营这个场景下,技术人员不能仅是完成技术载体研发,在强技术的线下运营活动中,由于技术信息的不对称可能会导致现场运营方案运行的不流畅,为了避免这种状况发生,技术人员除了能研发出“技术载体”外,还需要承担一部分的线下客服或工作人员的调配工作,包括现场设备调试、软件使用培训等。是的,你不仅仅是开发工程师。 技术选型:云开发 我们选择了小程序云来搭建我们的后端服务,原因有以下几点: ① 弱化了后端运维概念,节省开发人力和时间 用小程序云最大的好处就是弱化了后端运维的概念,并在提供了云函数、数据库以及云存储(文件存储)的基础上,增加了完善的日志管理、服务端监控等一系列的后端服务,让开发者专注在业务逻辑上的开发上,这对于我们这种小步快跑的业务是非常合适的,也大大的节省了我们的开发时间。 ② 云开发调用,提升开发效率 小程序云在云函数中封装了一些小程序服务端API,可以很方便的通过云调用直接调用,且不需要自己维护access_token这套机制,例如模板消息发送、生成小程序码等,小程序云也在原先小程序服务端API的基础上,增加了OCR识别等通用能力,大大加强了小程序的通用处理能力。 const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { try { const result = await cloud.openapi.templateMessage.send({ touser: 'test_openid', page: '/pages/test/test', data: { keyword1: { value: '一等奖' } }, templateId: 'template_id', formId: 'form_id' }) } catch (err) { console.log(err.message) } } 小程序云开发的开发实践小结 在开发的过程中遇到的一些问题和开发实践在这边做个小总结: Q:如何在WEB端调用小程序云中的数据? 上文提到的WEB大屏投放端和WEB管理端是在WEB页面上搭建的,这就需要我们在WEB端去调用小程序云上存储的数据了。那么如何在WEB端调用到存储在小程序云数据库中的数据呢? 1)云开发HTTP API调用 首先想到的就是利用云开发HTTP invokeCloudFunction API去触发云函数调用,将数据读取和写入的逻辑通过云函数先写好,再通过HTTP接口调用。但是这种方式有几个问题: 云开发HTTP API需要在小程序云之外维护一套access_token机制和HTTP服务,会带来额外的开发成本; 云开发HTTP API触发的云函数不能携带调用者的登录态信息,我们无法判断调用者的权限信息。 所以云开发HTTP API并不合适我们这个场景。 2)TCB WEB端SDK 小程序云是由腾讯云云开发(以下简称TCB)团队为小程序这个场景开发的,现在除了小程序端,已经支持了WED端的SDK接入。这里只需要通过小程序账号登陆腾讯云官网,进入云开发控制台,就可以在WEB端通过TCB提供的SDK获取到小程序云上的数据。 Q:实时的弹幕我们是如何实现的? 除了现场大屏之外,赛事现场还设置了三条长短不一的环形屏来投放玩家在小程序聊天室的聊天内容来作为弹幕展示。 环形屏的内容也是投放WEB页面来实现的。这个场景需要比较好的实时性,我们采用了小程序云开发推出的实时数据推送能力去推送审核完的弹幕显示到环形屏幕上。 db.collection("sceneDanmu").where({ checkStatus: 2 // 已经通过审核的弹幕 }).watch({ onChange(snapshot) { if (snapshot.docChanges[0]) { if (snapshot.docChanges[0]['dataType'] === 'update') { addDanmu(snapshot.docChanges[0]["doc"]); } } }, onError(err) { // err handle } }); 需要注意的事项: 因为是在网页端通过SDK直接对数据库collection进行监听,这里的对数据的访问权限控制方式是和小程序端发起访问的一致,在这个场景下(WEB端访问),需要将被监听的文档访问权限改成所有用户可读,这样才能在web端监听到数据的变化。 数据库文档的监听条数上限是5000条,这里要对监听的文档数量做一定的评估和优化。 Q:有什么更好的云函数路由优化方式? 小程序云开发的云函数都是运行在不同的开发环境中,每个云函数都是一个功能模块,那么有的时候,为了方便维护管理和公用代码块复用,我们需要将具有相似的处理逻辑云函数合并成一个云函数,也就是路由控制,较为初级的玩法是利用switch....case语法去操作: const userAction = require('./action') exports.main = async (event, context) => { let action = event.action switch (action) { case 'actionA': return userAction.actionA(event) case 'actionB': return userAction.actionB(event) case 'actionC': return userAction.actionC(event) default: return userActiion.noAction(event) } } 但是switch....case的处理方式较为简单粗暴,更加理想化的方式是采用TCB开发的tcb-router。 tcb-router的路由控制方式是借鉴了koa2的中间件机制来实现的路由控制,通过这个机制,我们将一些权限控制、请求参数校验、错误处理等都通过中间件去实现,示例: const cloud = require('wx-server-sdk') const TcbRouter = require('tcb-router') cloud.init() exports.main = async (event, context) => { const app = new TcbRouter({ event }) app.router('add', paramsValidatorMiddleware(event, { a: paramsValidatorMiddleware.isRequire().number(), b: paramsValidatorMiddleware.isRequire().number(), }), async (ctx, next) => { let { a, b } = event ctx.body = { ret: 0, data: a + b, errmsg: 'request:ok' } }) ...... return app.serve() } Q:如何自动切换云函数中的云环境? 一个小程序账号可以创建两个云开发环境,假如云函数内的初始化函数没有显式指定云环境ID的话,并不会默认使用云函数所部署的环境,而是默认的云开发环境,也就是开通小程序云后第一个创建的云环境。如果我们第一个创建的环境为测试环境的话,那么为了在线上环境能够调用到线上环境的数据库和云存储文件,就需要在代码中显式的声明云环境ID。就像这样: const cloud = require('wx-server-sdk') cloud.init({ env: 'release-envid'}) 这样每次在测试环境测试完成后,我们想要直接部署在正式环境,还需要手动指定每个云函数的环境ID,势必会带来一定的维护成本,所以为了优化这部分的逻辑,我们可以这样写: const cloud = require('wx-server-sdk')cloud.init() exports.main = async (event, context) => { const wxContext = cloud.getWXContext() if (wxContext.ENV !== 'local') { // 本地测试获取到的上下文云环境为local,这里需要判断下 cloud.updateConfig({ env: wxContext.ENV }) } else { cloud.updateConfig({ env: '开发环境的环境Id' }) } ...... } Q:如何在云环境中使用身份证OCR完成验票? LPL赛事小程序在部分功能上的使用是需要验证玩家的购票信息,因为玩家的购票信息都是实名制的,所以小程序上会用身份证验票。因为小程序云调用支持了身份证OCR识别,所以这块很方便就可以通过云调用API实现(这里也是为小程序云团队点个赞): app.router('getIdCardNo', paramsValidatorMiddleware(event, { fileId: paramsValidatorMiddleware.isRequire().string() }), async (ctx, next) => { let getTempFileURLResult = null try { getTempFileURLResult = await cloud.getTempFileURL({ fileList: [event.fileId] }) const result = await cloud.openapi.ocr.idcard({ type: 'photo', imgUrl: getTempFileURLResult.fileList[0]['tempFileURL'] }) if (result.errcode === 0 || result.id) { ctx.body = { ret: 0, msg: '请求成功', data: { idCardNo: result.id } } } else { // err handle } } catch (err) { // err handle } })
2020-11-09 - 云开发技术企业级的一些玩法和探索——以深圳机场旅客出行服务项目为例
11月29日,腾讯云与微信小程序团队联合举办的第二届小程序·云开发技术峰会在北京举行,在会上有众多来自不同行业,不同实践者的案例分享,讲述了各自与云开发的故事…… 每一个准确把握技术浪潮的人,都是时代的幸运儿。 本篇课程,给大家分享一个企业级的项目——深圳机场旅客出行项目,在小程序云开发技术上的一些玩法和运用。 [图片] 整体介绍 深圳机场旅客出行服务项目是我们腾讯云中标深圳机场的一个项目,大概过亿,每年旅客人次数大概 5000 万。 这个分享的主要目的,就是希望给大家起到抛砖引玉的作用,开拓思维,帮助大家可以挖掘云开发技术的更多玩法。 首先先来看一下深圳机场项目的整体架构: [图片] 从这个架构上可以看出,整个机场项目是有三层架构的:第一层是 C 端,第二层是应用层,第三层是后台。而运营开发技术其实自始至终贯穿在整个项目的应用层。 其实这样的架构一切目的主要就是为了满足企业级开发的诉求,比如说收拢逻辑、快速运营(运营自闭环)、安全可靠、分工清晰。 [图片] 为了让大家对架构有更好的理解,从下图中可以看出,整个架构是三层,而整个应用层是架构在云开发基础上的。 [图片] 应用层主要是做运营、流量保护、脱敏以及业务组装等,后台主要是做协议转发和固化逻辑。 场景分享 从开发到上线、再到运营、问题排查、后续监控,其实都是完备的工具链的建设,而云开发技术在整个链条建设过程中充当的是什么样的角色?我主要选几个重要的场景给大家分享。 场景 1:性能建设 目前我做了两套的缓存机制,一套本地缓存,一套是云端缓存。本地缓存机制主要是通过请求云函数,返回时间戳,来判断它是否过期,云端缓存主要是通过 C 端传递过来的 Tag 标记,以云业务函数中的 Tag 标记来判断是否缓存。 [图片] 其实整个流程就是,每次访问 C 端会去云函数拉一个时间戳和 Tag 值,每次请求都会带上 Tag 标记,Tag 标记就和云函数的标记进行对比。 目前整个云函数如果是一些通用的缓存,是用云函数自身的内存来存储,如果有一些特色的量比较大的就是用 redis 进行缓存。这个缓存好像很简单,但其实整个缓存的穿透以及缓存的雪崩都有一些额外的异常处理。 场景 2:日志建设 我们当前完全使用的是云开发提供的日志存储方式,以前的做法是需要我们自己建立一个完整的日志系统,但用云开发比较节省能力,可以看到,我们做日志存储的时候目前就是用云开发提供的高级日志接口打印日志,这个是日志接口的代码。 [图片] 以下是我对业务层收拢日志打印的调用业务逻辑,就是把云函数的日志与小程序的日志和调用服务的日志全部收拢起来。 [图片] 下图所示是云开发控制台上对日志进行查询,目前云开发日志支持多种查询方式:全文检索、键值检索、模糊关键字检索等等。其实整个日志背后还有一套更加完备的监控和体系。 [图片] 场景 3:可靠性和稳定性建设 作为一个企业级项目,当然可靠性、稳定性建设是很广的讲法,目前我只是挑了一个点,因为项目比较大,有很多开发者来参与协作开发。 但整个协作开发中如何来保证发布流程不要把测网代码发到现网,为了避免这种情况我创建了三个环境:一个代表测试环境,一个代表预发环境,一个代表现网环境。 [图片] 这三个环境小程序里面又是如何区分的呢?其实主要是在小程序里面有一个下斜杠 config,这个就是区分核心关键字,这样就避免了每次发盘的时候都要不断的去改善环境,以防把本来测试的代码加到现网去。 场景 4:多端建设 作为一个企业级项目,它面向的群体用户是非常多样的,所以多端支持也是必然的诉求,目前深圳机场 APP 使用的是 Flutter 技术,C 端和小程序端他们应用层,所以存在 Flutter 怎么连接应用层的函数的,目前应用层提供了 Flutter—SDK,在官网是可以查得到的。 [图片] 目前深圳机场项目有 APP、小程序、H5。 没有银弹 世界上没有银弹,虽然云开发技术在我们搭建整个企业级链条上提供了非常强力的支持,但是有技术的地方就有坑,而我们要做的就是趋利避害。 云函数滥用 我们在项目开发过程中,随着需求的增长和不断的迭代,以及不是很了解项目背景的开发人员加入后产生的问题,就是云函数乱用的问题。因为我们现在创建云函数成本很低,导致云函数越来越多,也被重复开发,有点混乱。 [图片] 而对于混乱的问题我做了一个云函数路由分发,下面又有一个动作,一个云函数代表一个业务的功能块,一个动作代表一个 C 端的请求,把公共能力也封装成公共云函数,就是复用一下那个能力,比如像后台的 GRPT 请求、HTTP 请求,用这个云函数做这个事情,云函数路由分发我还申请了一个专利。这样做的目的,为了解决云函数混用,让大家写面向 C 端 API 的时候有一个规范和标准。 日志不规范 在开发过程中还有一个问题,因为现在是用云开发来打印日志,使用的成本较低,导致大家随便就在云函数里打印个日志,导致日志非常混乱,排查问题的时候会发现根本不知道哪条日志是属于我的。 [图片] 针对于这种情况我把所有 C 端以及服务端请求的用户行为全部统一成一个自建模型,全部日志遵循这个模型来建模,这样日志和上报都成为了标准的格式化数据,方便后续做一系列的分析以及告警和问题排查。这个模型里面万物皆事件。 业务框架wCore 这些是基于业务痛点解决的一些问题,其实我写了一个业务框架叫做 wCore,大家可以扫这个地址,就可以看到 wCore 的使用方式,当然目前还属于“毛坯房”的阶段, 并不是很完善,后续我会开发出来,期待大家一起完善它。 [图片] 目前这个业务框架使用在我们深圳机场项目、川航项目、深圳地铁的项目。 作者简介:龙建军,腾讯云高级应用开发工程师本文编辑自云开发峰会现场讲稿,有些文字进行了书面化处理,并匹配结合现场PPT如果你对内容感兴趣,可以点击阅读原文获取回放有关材料
2021-06-29 - 基于云开发的SaaS应用前端架构设计优化
微盟小程序SaaS业务演进 小程序SaaS是什么?简单来说,就是微盟基于底层的技术能力,为企业提供不同场景下的智慧商业解决方案,让传统行业的客户不需要任何技术的投入,也能享受智能互联的便利。 以某零售客户为例,他仅仅只需要在微盟新云平台上创建店铺,选用模板页面或者进行一些可视化搭建,就可以快速生成一个在C端消费者的微信中显示的微信或小程序商城。C端用户在小程序中可以浏览店铺、查看商品、下单购买、申请会员等,形成一个交易闭环。 [图片] 自2013年成立之初,微盟在构建SaaS服务方面便投入了很多资源,推出了适用于不同行业的解决方案,随着业务的深入发展,越来越多的大客户、品牌客户入驻,客户的需求变得更加多样,一方面,体现在前端的展现形式和消费者使用体验上;另一方面客户需要智能的后台管理,提升运营效率。 虽然,各行各业的客户都有着不同的需求,但是我们发现在技术底层上有很多可以共享的能力。因此,基于在SaaS服务上积累的经验和新技术,2017年微盟对旗下产品架构系统进行全新技术变革和战略升级,深化微盟软件产品的全行业平台能力,统一旗下用户、商户、服务商系统,构建线上线下融合、全渠道营销、开放互通的智慧商业服务生态体系。 [图片] 微盟小程序SaaS在前端应用上的挑战 SaaS前端应用,具有流量大且难预测、极致追求速度体验、自定义模板和功能需求强、多渠道等特点。微盟丰富的产品矩阵,如何能高效整合前端应用,快速满足客户的多元需求,提升小程序运行效率,成为微盟现阶段面对的挑战。 细分下来,在前端上,面临着3类挑战: 第一类挑战在C端,在确保高峰期流量稳定的同时,缩短页面加载时长,进一步优化用户体验。 第二类挑战在B端,B端客户有着不同的需求,比如小程序有近3000多个页面,我们需要提升页面的复用率。 第三类挑战是多渠道,随着去中心平台的进一步发展,客户也将在不同的渠道展开商业布局,如何确保微盟小程序在不同的平台和渠道的适配性,提高效率,这也是微盟面临的重要挑战。 [图片] 微盟SaaS前端应用优化实践 面对上面的问题,微盟是如何解决的呢?微盟在技术栈的选择上,侧重在稳定、成本、便捷、安全、服务等五个方面。基于此,微盟选择了微信和腾讯云联合推出的小程序·云开发。 1)基于云开发的架构优化 自云开发被集成于微盟SaaS系统中后,微盟的小程序SaaS接入微信的流程得到简化,可以免鉴权直接调用微信开发接口,并且实现云端解密。相比传统开发模式,“小程序·云开发”在登陆流程的终端性能提升50%以上,效果明显。 第一是微信小程序的接口调用流程得到了优化。 [图片] 举个再具体一点的例子,大家做微信开发很常见就是静默授权。 我们做了一个测试,使用了云开发中的云函数和没使用的,在性能上有3倍的差别。因为云开发的云函数和微信是一个整体,我可以把它合在一起看,他们只需要跟我们的后端进行一次交互就可以达到我们的目标了。但在之前,我们的微信客户端到我们的服务器,再到腾讯微信的服务器,有三次公网请求。我们通过接口减少和链路优化极大地减少这方面的性能损耗,所以终端的体验,从1.15秒直接降到421毫秒。 [图片] 另外用户授权,我们也通过结合云开发中的云函数来做这个事情。从1.17秒降到820毫秒。 [图片] 第二是云开发享有微信私有协议,能够帮助微盟的系统运营更加稳定。比如,基于云函数开发营销活动、节日大促等前端应用,技术人员可以专注于业务逻辑,不用操心运维和扩容方案,研发效率得到极大的提升。 再有,云开发提供更友好的开发体验,同时也支持微信第三方平台,这帮助微盟研发团队提升研发效率。 最后,是更安全。利用云函数,等于在微盟已有的安全防护体系外再进一步叠加腾讯云和微信的安全保障机制,微盟客户的小程序安全性将再提高一个台阶。 2)基于微盟微前端Kraken的优化 微盟SaaS软件目前给超过300万商户提供服务,除了对稳定性要求非常高之外,提高客户的操作效率也至关重要。因此,微盟内部对微前端进行升级和优化,以提高微盟的整体研发效率以及提升B端商户的操作体验,这个项目我们取名为Kraken。 [图片] 举个简单的例子,我们B端客户在新云平台做后端搭建的时候,往往需要做不同的创建动作,完成页面创建。我们通过微前端的建构帮助客户在一个页面停留时就能完成不同的操作需求,提升创建的流畅感,保证良好使用体验的同时,提高效率。具体来说,做一套微前端的架构有一下几个好处: 无刷新,不同子应用之间路由跳转不需要 刷新整个页面,极大提高用户体;兼容多框架,各子应用不限制框架 ;独立部署,各子应用独立发布和部署,能适应不同团队,快速发布,快速回滚;海量页面,支持上千级别;页面的加载与渲染,无限扩容;快速响应,开发更灵活,能快速响应产品需求的迭代和变化。[图片] 3)监控优化 微盟开发了一套APM系统,我们称之为HOUND,它能将消费前端与后台的数据进行融合,同时还能将不同端(小程序、H5)的数据结合在一起,实时监控。比如,我们能够准确、快速的查询到某个页面加载慢的原因以及给出解决办法。 [图片] 通过APM系统,我们提高了研发效率,提升了项目质量。 未来,微盟在小程序的重心,将充分利用“小程序·云开发”的技术优势,把合适的前端应用迁移至云开发的云函数中,进一步提升微盟小程序产品的体验和服务质量。 分享嘉宾:微盟CTO 黄骏伟关于微盟:微盟成立于2013年,是中国领军的企业云端商业及营销解决方案提供商,致力于通过产品和服务,助力企业向数字化转型,通过科技驱动商业革新,让商业变得更智慧。
2020-11-04