人人都是 Serverless 架构师 | 弹幕应用开发实战

作者 | 寒斜(阿里云云原生中间件前端负责人)
如何使用 Serverless 架构实现全双工通信的应用,Serverless 架构中数据库是如何使用的,本篇文章将为您揭开答案。
Serverless 的理念是即时弹性,用完即走。服务并非长时间运行,这也就意味着像 websocket 这种长链接的请求模式看起来并不适合 Serverless。
是否有其它的办法即可以满足长连接模式请求,又能够利用 Serverless 本身特性呢?
答案是肯定的,上一篇文章我们谈及了网关的关键作用,所以这次也是通过网关来解决全双工通信的问题。本次将以弹幕场景为例,为大家展开我们是怎么使用 Serverless 架构来实现这个场景的。

应用效果预览
弹幕应用的实用场景比较多,比如运营推广,年会活动等。但是通常实现一套带管控的流程,且部署发布的话,一般会花费比较长的时间。本篇实战则可以让你在 2 分钟之内就部署好自己的弹幕应用。同时做到支持炫彩和弹幕内容管控,你可以用它来丰富公司年会的形式。文末也会贴上源码,可以供大家参考和二次定制。

架构一览
整体架构依然采用 dns 解析 -> 网关 -> oss | fc 。不一样的是分了 3 个静态资源的工程,函数部分则采用事件驱动和 http 相结合,并且 api 部分采用 tablestore 进行数据的持久化。

流程说明
弹幕应用总工由大屏幕, 个人用户,管理员三个客户端,以及一个注册设备的服务 & api 服务组成。客户端跟服务端的长链接由网关来承载,每次客户端连接到网关的时候,网关都会存储设备编号,并且触发一次注册函数,设备编号存储到 tablestore。
当用户发起弹幕的时候经网关到 api 服务,api 服务会做一次查询先判断弹幕是否被管制,如果无管制则直接查找当前的大屏幕设备 id,并且进行网关的下行调用,网关在发到前端页面,显示数据。如果被管制,则查询在线的管理员设备,将弹幕下行通知到网关,网关发送给管理员前端页面。
数据表设计
- equipment(设备)
| 字段 | 类型
| 说明 |
| --- | --- | --- |
| id
| string
| 设备表主键
|
| deviceld
| string | 设备id |
| docld
| string | 备用字段
|
| type
| string | 设备类型(screen | admin)
|
barrage(弹幕)
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| gid | string | 分区键 |
| id | integer | 主键自增 |
| fromId | string | 弹幕作者id |
| fromName | string | 来源作者名称 |
| color | string | 弹幕颜色 |
| fontSize | string | 弹幕字体大小 |
| checkStatus | integer | 弹幕状态0(未处理)1(审批通过)2(审批未过) |
| sendTime | string | 弹幕发送时间 |
| checkTime | string | 弹幕更新时间 |
| message | string | 弹幕内容 |interceptor (过滤器)
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| id | integer | 主键/分区键 |
| status | integer | 拦截状态0不拦截 1拦截 2拦截加过滤 |
| filterWords | string | 过滤字段 |
1、准备工作
同前篇《人人都是 Serverless 架构师 | 现代化 Web 应用开发实战》文章一样需要提前准备好域名,并安装好 Serverless Devs 开发者工具,以及下面的产品:
- 云解析 DNS
- API 网关
- 函数计算
- 对象存储 OSS
- Tablestore
这次我们引入了 tablestore 的数据库记性数据的持久化功能,同样需要创建好数据库实例备用。
2、操作步骤
为了更好的展示效果,本次演示使用 ServerlessDesktop 来给大家演示一下如何 2 分钟部署一个复杂的弹幕应用。你可以根据自身需要选择 Serverless Devs Cli 或者 Serverless Desktop 对弹幕应用进行初始化和部署构建。
1)秘钥配置
可参考密钥获取文档:
http://www.serverless-devs.com/zh-cn/docs/provider-config/alibabacloud.html
2)初始化

本次初始化除了需要将应用模板下载到本地之外,还会帮忙初始化 tablestore 的表和数据,因此需要预配置几个参数:
- 秘钥别名 - 对应你的阿里云账号
- 域名 - 自定义域名
- bucketName - oss 的 bucket 名称
- endpoint - 对应 tablestore 实例的公网访问地址
- instance - 对应 tablestore 的实例名
预配置参数写好后点击 “确定”,接下来的工作就叫给 Serverless Devs,它会帮我们初始化弹幕应用的表。
3)构建部署
初始化之后,我们重新进入配置页面,对项目进行部署。配置信息 -> 全量操作 -> deploy 点击后其他的就交给 Serverless Devs了,它会帮助我们完成:
- 大屏幕,管理后台和玩家的前端部署;
- 注册函数以及 api 函数的部署
- 以及网关的路由设置和网关的域名绑定
4) 部署效果查看
- 网关

- 函数计算

- Oss

- DNS

此时访问_ barragego.serverless-developer.com _发现访问不同,检查发现原因是 apigateway 的域名和 oss 域名都未绑定成功,我们手动处理一下:


接下来再访问 barragego.serverless-developer.com 即可看到效果:
2、数据库明细
数据库方面想拿出来说一下,主要本次用的数据库确实比较新,也就是 tablestore。
1)数据库配置传递
可以看到,我们在初始化应用的时候是填写了数据库的公网访问地址和实例名称信息的,初始化的时候会把用户的输入配置写入到 s.yaml 中,这里如果是比较敏感的信息建议从 s.yaml 提取出来放到 .env 环境中,并且 ignore 掉这个文件,减少数据库信息被泄露到代码仓库的风险。
最终 Devs 会把这两个基本信息放到函数计算的环境变量中然后各运行时可以通过环境变量取到这些值,比如这里是 nodejs 的运行环境,则通过 process.env.instance 获取。
除了实例名称和公网访问地址外数据库的初始化还需要 用户的秘钥信息。鉴于秘钥信息的敏感性比较高,不建议直接把秘钥信息配置到 s.yaml 里,而是通过给函数服务授权 tablestore 角色权限,让函数内置临时秘钥信息。
- 函数服务授权配置如下:

- 函数内获取秘钥信息如下:

2)数据库初始化
为了减少数据库初始化次数,我们可以在函数的 initializer 方法中初始化,当函数未被释放的时候可以直接使用数据库的实例而不必重新连接。这样可以降低请求响应时间。单实例多并发的情况下比较实用。
exports.initializer = (context, callback) => {
try {
const ak = context.credentials.accessKeyId;
const sk = context.credentials.accessKeySecret;
const stsToken = context.credentials.securityToken;
SAT.init(endpoint, instance, ak, sk, stsToken);
internal = { tableClient: SAT, TableStore };
callback();
} catch (err) {
callback(err.message);
}
}
数据库实例初始化之后,我们通过赋值给全局变量来从其他的方法中取得实例,进行后续的操作。
3)CRUD
tablestore 原生的 api 去做 CRUD 操作用户体验不够友好,tablestore 社区提供了一个很好的封装 SAT。我们用它来做基础的增删改查会非常的方便,代码看起来也非常整洁。
// 单主键查询
const getInterceptor = async (ctx) => {
const { tableClient } = ctx.req.requestContext.internal;
const res = await tableClient.table('interceptor').get(1, cols = []);
return res;
}
// 查询全部
const getAllEquipment = async (tableClient,TableStore) => {
const res = await tableClient.table('equipment').getRange(TableStore.INF_MIN, TableStore.INF_MAX, cols = [])
return Object.keys(res).map((key)=> res[key]);
}
// 双主键(一个分区键,一个自增键)的插入
const addBarrage = async (ctx) => {
const { tableClient, TableStore } = ctx.req.requestContext.internal;
const { fromId, fromName, color, fontSize = '28px', checkStatus = 0, message } = ctx.request.body;
const currentTime = Date.now().toString();
const newData = Object.assign({}, { fromId, fromName, color, fontSize, checkStatus: parseInt(checkStatus), message }, { sendTime: currentTime, checkTime: currentTime });
const res = await tableClient.table('barrage', ['gid', 'id']).put([1, TableStore.PK_AUTO_INCR], newData, c = 'I');
return res;
}
// 更新
const updateBarrage = async (ctx) => {
const { tableClient } = ctx.req.requestContext.internal;
const { checkStatus } = ctx.request.body;
const { id } = ctx.request.params;
const currentTime = Date.now().toString();
const res = await tableClient.table('barrage', ['gid', 'id']).update([1, parseInt(id)], { checkStatus: parseInt(checkStatus), checkTime: currentTime }, c = 'I')
return res;
}
// 条件查询
const getBarrageByCondition = async (ctx) => {
const { tableClient, TableStore } = ctx.req.requestContext.internal;
const res = await tableClient.table('barrage').search('index', ['checkStatus', 0])
return res;
}
当然如果你想做更高级的查询,就需要自己去查阅官网文档了
总结
这个项目本身是对 Serverless 如何使用 websocket 的一个展示示例。你可以把它变成任意相近形态的应用,比如聊天室,多人协作平台等。
应用本身也还有很多改进空间,比如增加点赞效果,管控部分可以加上管理员的登录注册等。总之你可以根据自身需求定制更高级的功能,相关的源码已经提供出来供大家参考。下个篇章我会继续跟大家聊一聊 Serverless 和低代码的场景,并分享一个我们最近做的实践。
文中涉及网址汇总:
Serverless Devs:https://github.com/Serverless-Devs
云解析DNS:https://wanwang.aliyun.com/domain/dns
API网关:https://www.aliyun.com/product/apigateway
函数计算:https://www.aliyun.com/product/fc
对象存储OSS:https://www.aliyun.com/product/oss
ServerlessDesktop:http://www.serverless-devs.com/zh-cn/desktop/index.html
Serverless Devs Cli:http://www.serverless-devs.com/zh-cn/cli/index.html
Serverless Hub:https://serverlesshub.resume.net.cn/#/hubs/specialview
Tablestore表格存储:https://www.aliyun.com/product/ots
官网文档:https://help.aliyun.com/document_detail/27304.html?spm=5176.54465.J_7985555940.4.15942e0c3qkHbU
源码:https://github.com/devsapp/start-barrage
更多内容关注 Serverless 微信公众号(ID:serverlessdevs),汇集 Serverless 技术最全内容,定期举办 Serverless 活动、直播,用户最佳实践。
人人都是 Serverless 架构师 | 弹幕应用开发实战的更多相关文章
- 诚聘.NET架构师、高级开发工程师(2019年8月29日发布)
招聘单位是ABP架构设计交流群(134710707)群主阳铭所在的公司 公司简介 七二四科技有限公司成立于2015年,成立之初便由金茂资本按估值2亿投资2200万,进行“健康724”平台搭建,2017 ...
- 葡萄城首席架构师:前端开发与Web表格控件技术解读
讲师:Issam Elbaytam,葡萄城集团全球首席架构师(Chief Software Architect of GrapeCity Global).曾任 Data Dynamics.Inc 创始 ...
- 空中网招聘Java架构师、数据库开发等各类人才
爱好网络游戏吗?爱好网站开发技术吗? 有没有想过可以成为史诗级MMO RPG<激战2>运营团队中的一员? 如果下面的职位有合适你的,加入我们吧! http://gw2.kongzhong. ...
- 阿里云云开发平台助力风变科技Serverless架构升级实战
阿里云云开发平台助力风变科技Serverless架构升级实战 背景 风变科技 一个希望通过技术去推动下一代基础教育的组织.旗下产品包括第一代的熊猫书院(读书类产品).第二代的熊猫小课(泛学科综合学习平 ...
- 2010“架构师接龙”问答--杨卫华VS赵劼(转)
add by zhj:虽然是几年前的文章,但还是很有参考价值的 原文:http://blog.zhaojie.me/2010/05/programmer-magazine-2010-5-archite ...
- 程序员、架构师、技术总监、CTO
程序员 程序员,英文名coder/programmer,大家常自嘲叫码农的阶段.这个角色职责是把需求或产品实现为用户可用的软件产品. 此职位为执行级别.另外因为经验较少,一般需要求助别人,或与别人一起 ...
- IT架构师介绍-软件架构设计学习第一天(非原创)
文章大纲 一.架构师定义二.架构师分类与具备能力三.研发人员发展的技术路线四.架构师知识体系五.参考文章 一.架构师定义 什么是架构师,这个聊架构话题时永恒的问题.每个公司对架构师的定位也有所 ...
- 好好讲一讲,到底什么是Java高级架构师!
一. 什么是架构师 曾经有这么个段子: 甲:我已经应聘到一家中型软件公司了,今天上班的时候,全公司的人都来欢迎我. 乙:羡慕ing,都什么人来了? 甲:CEO.COO.CTO.All of 程序员,还 ...
- 如何从普通程序员晋升为架构师 面向过程编程OP和面向编程OO
引言 计算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训练就可以做 ...
- 架构之:serverless架构
目录 简介 什么是serverless serverless的例子 简单的三层服务 消息驱动 FaaS FaaS的缺点 FaaS的优点 总结 简介 不知道什么时候,出现了一个叫做Serverless架 ...
随机推荐
- Docker 安装教程
一.离线安装 一.CentOS 离线安装 一.下载地址 1.选择系统的型号,选择linux-CentOS 下载地址 2.上传文件到CentOS 服务器 #选择文件 rz 二.开始安装 1.解压压缩包 ...
- [USACO2007OPEN G]Cheapest Palindrome
题目描述 Keeping track of all the cows can be a tricky task so Farmer John has installed a system to aut ...
- 浅析 ArrayList
by emanjusaka from https://www.emanjusaka.top/2023/12/java-arrayList 彼岸花开可奈何 本文欢迎分享与聚合,全文转载请留下原文地址. ...
- 如何使用 Helm 在 K8s 上集成 Prometheus 和 Grafana|Part 1
本系列将分成三个部分,您将学习如何使用 Helm 在 Kubernetes 上集成 Prometheus 和 Grafana,以及如何在 Grafana 上创建一个简单的控制面板.Prometheus ...
- Selenium-[实例]猫眼电影爬取
import random import time from selenium import webdriver from selenium.webdriver import ActionChains ...
- ElasticSearch之Search settings
相关参数 indices.query.bool.max_clause_count 本参数当前已失效. search.max_buckets 本参数用于控制在单个响应中返回的聚合的桶的数量. 默认值为6 ...
- hwclock详解
linux下hwclock命令详解 hwclock(hardware clock) 功能说明:显示与设定硬件时钟. 语 法:hwclock [--adjust][--debug][--directis ...
- JavaFx FXML入门(五)
JavaFx FXML入门(五) JavaFX 从入门入门到入土系列 JavaFx的FXML类似安卓中的视图文件,可以添加样式,添加css,添加id然后在java代码中绑定点击事件.可以使用工具编辑: ...
- javacv图片美颜处理,视频美颜处理
javacv图片美颜处理,视频美颜处理 国产剧明星演戏自带十级滤镜,是众所周知的秘密: 使用opencv也能实现一定的美颜效果: 一.图片美颜 代码 package top.lingkang.test ...
- 面试官:请列举 Spring 的事务会失效的场景
在日常工作中,如果对 Spring 的事务管理功能使用不当,则会造成 Spring 事务不生效的问题.而针对 Spring 事务不生效的问题,也是在跳槽面试中被问的比较频繁的一个问题. 今天,我们就一 ...