前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >腾讯云新产品“云开发”尝鲜体验

腾讯云新产品“云开发”尝鲜体验

原创
作者头像
黄希彤
修改于 2019-11-29 03:23:38
修改于 2019-11-29 03:23:38
10.8K00
代码可运行
举报
文章被收录于专栏:黄希彤的专栏黄希彤的专栏
运行总次数:0
代码可运行

最近用云开发写仿了一个很古老的小游戏 http://stonelf.gitee.io/letter/letter.html 大家可以点进去玩一下。分享一下过程中踩的一些坑。

云开发(Tencent Cloud Base,TCB)是腾讯云为移动开发者提供的一站式后端云服务,可以看作是云函数SCF的升级版。

作为推进serverless的急先锋,SCF提供了弹性的计算能力,也能通过api网关提供弹性的接入能力,但是SCF服务里面不包括后台数据库,因此虽然你可以通过SDK连接到云数据库,但是始终要多关心一个数据库Server,这让我们在说起serverless时,有时显得不够原教旨主义。

而TCB给开发者提供了一个免费和几乎免维护的的no-sql数据库(可以付费升级),这就让原教旨主义的无服务器开发的有了更多的可玩性。此外还很贴心的提供了容易上手的web端、小程序端和服务器端的SDK,让玩转TCB的门槛大大降低。尤其是有一套包装好的服务器端推送的SDK实现(见 数据库web端SDK 的最后一段《数据库实时推送》),可以很方便的开发实时应用。

由于闲闲还在美国幼儿园“留学”,这几天想复刻一个异地互动的flash游戏letters,正好可以用得上这两个特性。

letters是一个很傻的游戏,任何人都可以访问网站看到当前的字母排列,然后可以在屏幕上拖动字母,其他正在访问网页的人会即时看到字母被拖走了,因此也可以多人合作来把字母排列成特定的样子,或者相互搞破坏偷走别人的字母让他拼不成想要的样子。原游戏基于flash实现,现在已经难以怀旧了。重新开发这个游戏除了实现字母拖放互动之外,还想支持现代浏览器和平板,同时还想允许把一个字母换成别的字母,在换掉的时候别人的浏览器上也要实时显示出变化。

实现上很简单:

首先是实现一些基础的页面上的拖放逻辑,并兼容pad。为了兼容不同的显示设备和不同的浏览器大小,字体要随着屏幕宽度缩放,而位置全部要采用百分比定位。这是纯前端部分的工作,可以在文末的连接中跳转到游戏网页上查看源码。

然后就是需要捕获到每次拖放结束的事件,把被拖放的字母的新位置发送给后端的云函数,这部分的代码很简单,拼凑一个http post请求把要发送的数据丢到body里面就好。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function sendData(data){
	fetch("//service-j3t56zj5-1258721286.ap-shanghai.apigateway.myqcloud.com/release/", {
		cache: "no-cache",
		method: 'POST',
		headers: {
			'Accept': 'application/json',
			'Content-Type': 'application/json'
		},
		body: JSON.stringify(data)
	}).then(function(response) {
		return response.json()
	}).then(function(json) {
		if (isNaN(json.errorCode)) {
			console.log("发送成功")
		} else {
			console.log(JSON.stringify(json))
		}
	}).catch(function(ex) {
		console.log('parsing failed', ex)
	})
}

后端的服务程序也很简单,接收到更新的字母后往数据库里面写。不过要考虑到第一个进来玩的人由于数据库里什么都没有,要生成一点原始数据给他玩。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'use strict';
const app = require("tcb-admin-node");
const chars = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9","?","?","?","?","?","?","?","?","?","?","❤️","?","?"]

exports.main = async (event, context, callback) => {
    console.log("\nevent.body:"+event.body)
    let parameters = JSON.parse(event.body),id=-1,x=-1,y=-1,c='';
    if(!!parameters){
        if(!isNaN(parameters["id"])){
            id=parseInt(parameters["id"]);
        }
        if(!isNaN(parameters["x"])){
            x=parameters["x"]-0;
        }
        if(!isNaN(parameters["y"])){
            y=parameters["y"]-0;
        }
        if(parameters["char"] && parameters["char"].length<3){
            c=parameters["char"]
        }
    }
    app.init({env: 'game-acebe0'})    
    const db = app.database();
    const _ = db.command
    let collection = db.collection('game');
    let all = collection.where({char:_.neq('')})
    let data = (await all.orderBy("_id", "asc").get()).data
    if(!data){
        await db.createCollection("game")
        collection = db.collection('game');
        data = [];
    }
    if(data.length<chars.length){ 
        var dataHash = {};
        for(var i=0;i<data.length;i++){
            dataHash[data[i]["_id"]]=true;
        }
        for(let i=0;i<chars.length;i++){
            if(!dataHash[i]){
                let t = {
                    _id:i,
                    char:chars[i],
                    x:6*(i%15)+5,
                    y:7*Math.floor(i/15),
                    color:Math.floor(Math.random()*256*256*256)
                }
                collection.add(t)
                data.push(t)
            }
        }
    }
    if(id>=0 && id<chars.length){//id 合法
        let query =collection.where({"_id":id-0})
        if(x>=0 && x<=100 && y>=0 && y<=100 && c.length==0){ //坐标合法
           let now = Date.now();
            let q=await query.update({"x":x,"y":y})
            console.log("\n 更新时间"+(Date.now()-now)+"毫秒,更新了"+q.updated+"条记录")
            data[id]["x"]=x
            data[id]["y"]=y
        }
        if(c && c.length>0){
            console.log("change char")
            await query.update({"char":c})
        }
    }
    return data
}

TCB的云函数和SCF的一样可以通过api-gateway提供http/https接入能力,只是不像SCF那样可以直接在云函数里面添加api-gateway,而是需要在同服务区的api-gateway里面去把cloud function绑定到api的后端配置中。如果不熟悉api-gateway配置也可以直接把TCB的云函数代码粘贴到SCF的编辑器里面当普通的云函数配置运行,然后就可以在函数服务的触发方式里面添加api-gateway并一步到位的发布服务了。TCB的服务器SDK在SCF中不但工作良好,而且beta用户还可以启用依赖自动安装这样的黑科技,连开发的“服务器”都不需要,真正实现原教旨主义的serverless。唯一要注意的是TCB和SCF的云函数入口有exports.main_handler 和 exports.main 的写法差异。

这里我遇到了云开发的第一个大坑:写初始数据的时候无法批量写入。这就导致我只能一条一条的写入,而很多条数据如果串行写入的话等待数据库返回的时间就会被累加,任何网络抖动都会导致整个函数超时退出。如果并行写入的话会超过免费用户可用的数据库连接数上限导致部分写失败。刚开始我每次检查到数据库的初始数据不完整就重新初始化,然后又一次大量的写入导致部分失败……10分钟不到就把一整天的写操作限额用光了。

一个填坑方案是等待云开发的批量写入接口放出来,不过我想到了 《云原生应用的“十二要素”》中大家一再强调的一个原则:

面向失败的设计:

……大多数云计算的基础设施天生就是短暂的,与本地环境的硬件相比,也更容易出现故障。结合我们大多数人在设计分布式系统时所遵循的原则,你必须设计出能够容忍服务消失或者被重新部署的系统。

是的,我们可以并且应该在设计上让系统容忍这个错误并继续良好运作。具体讲,我先一股脑把所有的初始数据同步丢进去写数据库然后基于部分成功的结果让系统运作起来,然后在下次函数运行的时候看看哪些操作写失败了,再补写一下。通常补写两三次以后就全部都成功了。

在写操作完成后,需要让所有的网页端侦听到数据库发生了什么变化,并把这些变化用动画表现到网页上。参考SDK文档,很容易就用webSDK实现了网页端到侦听:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fetch("//service-1c18mywx-1258721286.ap-shanghai.apigateway.myqcloud.com/release/").then(
	(response) => {
		return response.json()
	}).then((json) => {
	ticket = json.ticket;
	return auth.signInWithTicket(ticket)
}).then(() => {
	// 登录成功
	const db = app.database();
	const _ = db.command
	const collection = db.collection('game');
	let ref = collection.where({
		_id: _.gt(-1)
	}).watch({
		onChange: snapshot => {
			var docs = snapshot.docChanges;
			if (docs.length > 0) {
				show(docs);
			} else {
				console.log("获取初始化数据失败")
			}
		},
		onError: error => {
			console.log("收到error", error)
		}
	})
})

这里有个小坑,要获得侦听数据库的权限,需要先接收到服务器端下发的一个ticket来授权,也就是上面代码的“// 登录成功”前面的部分。而服务区端需要写一个生成ticket的云函数并通过API网关把它发布出去:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'use strict';
const tcb = require('tcb-admin-node');
exports.main = (event, context, callback) => {
    tcb.init({
    // ...
    env: 'game-acebe0',
    credentials: {"private_key_id":".........................",
    "private_key":"-----BEGIN RSA PRIVATE KEY-----\n...............\n-----END RSA PRIVATE KEY-----\n"}
    });
    let customUserId = Math.floor(Math.random()*10000000).toString();

const ticket = tcb.auth().createTicket(customUserId, {
  refresh: 10 * 60 * 1000 // 每十分钟刷新一次登录态, 默认为一小时
});
return {"ticket":ticket};
};

因为这是个开放的匿名游戏,所以没有对授权做什么限制,谁都可以申请都ticket来获取服务器数据,但是这样有DoS隐患。还好用的是免费服务,如果被攻击导致访问量超过限额,服务会自动终止,危害有限。

此外对数据库权限也要限制为“所有用户可读,仅管理员可写”,这样稍微提升一点点干坏事的门槛(虽然还是谁都可以通过云函数匿名写,但是能写的字段和写的方式收到代码逻辑的限制)。

完成了授权和客户端登录,在网页上就可以侦听到所有人的拖动和字符修改操作并且做相应的渲染了。至此一个游戏的逻辑大体完成。网页端发补到了gitee page上:http://stonelf.gitee.io/letter/letter.html 需要看完整的前端代码只要打开页面后查看页面源码就可以了。

总结一下过程中遇到的坑和吸取的经验教训:

1 云开发暂时还没有批量写的能力,大量数据不管是顺序写还是并行写都容易失败,这不能通过全量重新写来解决。

——伟大领袖教导我们:面向失败做设计

2 云开发的云函数没有打通api-gateway来提供http服务,要自己去同服务区的api-gateway中绑定云函数,或者把云函数放到SCF中去。

3 web前端的server-push比自己主动轮询后台数据要更及时,而且可以提供大得多的免费并发访问能力,而且,还不用耗费api-gateway和云函数的访问和执行限额。

4 web前端的SDK能力很强大,需要配合数据库的权限配置来限制访问者进行意想之外的写操作。

最后,其实挺希望云函数能有一个跨实例的快速的存储共享机制的。因为云函数自己没有状态,只能通过数据库来维护状态,而且数据库操作受到网络抖动、并发数限制等因素等影响,在延迟和读写成功率上都难以保障,需要做更多的容错设计。如果有一块小小的共享存储空间可以保存一点session等信息并让它保持在一个设定的session过期时间内都可以访问,很多设计可以简单很多。如果实例能被限制在同一个母机上,这个存储用内存实现就最好了。如果实例跨了一个集群内的多台主机,在集群内部实现一个共享的存储访问,也比跑出去访问数据库要可靠和快速的多。按照程序运行内存的收费标准(MB秒)收费或者提供免费额度就可以了

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
十一张图解析区块链原理
区块链概念很火,尤其是2018年伊始在各互联网指数上热度都极大上扬。区块链到底是怎么回事?区块链原理到底是什么?本文就是为揭开区块链原理而来,让我们仔细研究下区块链,探究区块链的奥秘。
阿仁
2018/08/07
5.1K0
十一张图解析区块链原理
什么是比特币?解释你需要了解的比特币知识
如果你不熟悉加密货币,那么你的第一个问题很可能是“什么是比特币?”。用简单的话讲,比特币是一种基于密码技术实现安全性的加密货币或者说是一种数字财产。比特币和大多数(但不是全部)的加密货币使用区块链技术。
青橙.
2018/03/09
4.7K1
什么是比特币?解释你需要了解的比特币知识
区块链是什么,一文给您讲清楚
未来已经来临,只是尚未流行。用这一句来描述当下的比特币区块链再合适不过了。从上周开始,曾经不可一世的比特币开始从高点回落,跌幅一度超过40%,接近腰斩。说到比特币,自然而然就要谈其背后的核心技术——区块链。区块链是比特币的底层技术和基础架构,本质上是一个去中心化的数据库,它是一串使用密码学方法相关联产生的数据块,每一个数据块中包含了一次比特币网络交易的信息,用于验证其信息的有效性和生成下一个区块。 1 最初的设想 比特币最初的构想来自上世纪初期奥地利经济学派著名经济学家、诺贝尔经济学得主哈耶克。他在《货
企鹅号小编
2018/01/15
1.3K0
区块链是什么,一文给您讲清楚
比特币和区块链是什么?看完这篇文章不再懵
实际上全球各种虚拟货币已经超过了1300种,其中市值排名前几名的除了比特币还有下面的这几种虚拟货币。
進无尽
2018/09/12
1.3K0
比特币和区块链是什么?看完这篇文章不再懵
1000字让你看懂区块链
区块链不是比特币!区块链不是比特币!区块链不是比特币! 重要的事放前面,并且说三遍。 身边很多朋友听到区块链,都会点头说,哦,是比特币嘛? 比特币确实和区块链有着密不可分的联系,但这种说法实在是太随意。区块链并非就是比特币,而是比特币的一个重要概念;比特币只是基于区块链诞生的有一种匿名虚拟货币,或者说,只是区块链这个概念的一个应用。 除了比特币以外,区块链还有着更多的应用。 专业解释是,区块链本质上是一个去中心化的数据库,是一连串使用密码学方法产生相关联的数据块,每一个数据块中包含了一段时间内全网交易的
企鹅号小编
2018/01/11
7880
1000字让你看懂区块链
半小时读懂区块链在互联网营销上的应用——核心问题还远未解决!
互联网数据官创始人/纷析数据创始人兼CEO
iCDO互联网数据官
2018/02/27
1.1K0
半小时读懂区块链在互联网营销上的应用——核心问题还远未解决!
区块链技术简介(一)
短短几天,“区块链”成为一大热词。“把区块链作为核心技术自主创新重要突破口”,“加快推动区块链技术和产业创新发展”。
葆宁
2022/01/06
5450
区块链技术简介(一)
bitcoin-01-区块链初识
投身加密货币研究有一段时间了,其间了解到了比特币的原理和应用,想把了解到的知识整理成一个简单直白的系列科普文章,希望可以帮助大家轻松简单学习并使用加密货币。 本篇作为开篇,仅提一些简单概念,以免概念太多,让人望而却步。
潇洒
2023/10/23
3480
bitcoin-01-区块链初识
由比特币说起 - 区块链的前世今生及未来趋势
摘要 比特币越来越火,虽在国内尚不属于合法货币,但仍未能阻止人们火热的投资热情,也由此引发了人们对区块链的关注及重视。区块链(也包括比特币)做为源于开源社区的一项技术性创新,却由于去中心化的特点,已然形成一种文化。影响力也超越了技术本身。那么,比特币是什么?它是怎么出现的?现在发展到什么程度了?未来会发展成什么样子?他的技术原理是什么?区块链又是怎么回事?它的技术原理又是什么?为什么会得到了众多政府、机构、企业、个人的关注和青睐。凯文凯利曾说过:未来已经到来,只是尚未流行。欢迎大家一起来感受区块链的前世今生
IT大咖说
2018/04/04
7950
写给小白的「区块链」故事
区块链是比特币的底层技术和基础架构,本质上是一个去中心化的数据库。区块链是一串使用密码学方法相关联产生的数据块,每一个数据块中包含了一次比特币网络交易的信息,用于验证其信息的有效性(防伪)并生成下一个区块。
HelloGitHub
2021/05/08
4770
写给小白的「区块链」故事
用最简单的图文带你看懂区块链
用最简单的图文带你看懂区块链 匿名用户- 保密 保密 昨天 14:46 除非过着与世隔绝的生活,否则你或多或少有听说过比特币和区块链,毕竟,这可是当下媒体们最喜欢报道的话题,甚至连那些从未参与进来的人们也开始津津乐道了。很多不懂技术的朋友纷纷找我探听,我猜还有不少人想弄明白区块链是怎么回事儿,所以,是时候写篇通俗易懂的文章来解释一下了。 为什么我们需要区块链这么复杂的玩意儿? 区块链究竟是什么?又,为什么我们需要用到这么复杂的系统呢? 我想与其用一大堆专业术语来解释,倒不如先看看它解决了什么问题: 试
企鹅号小编
2018/01/17
1.6K0
用最简单的图文带你看懂区块链
别误会了,区块链不等于比特币!解说什么是竞争式区块链、分配式区块链
作者:JRChian 来源:techbang 比特币最近又涨到了新高,你也可以听到各种虚拟货币打算ICO。也因为比特币的关系,“区块链”这个名词常常伴随着比特币一起出现,区块链似乎和比特币画上了等
企鹅号小编
2017/12/28
1.2K0
别误会了,区块链不等于比特币!解说什么是竞争式区块链、分配式区块链
除了带来比特币,区块链技术还会掀起一场怎样的风暴?
原文标题:How blockchain will revolutionise far more than money
IT阅读排行榜
2018/08/15
4560
除了带来比特币,区块链技术还会掀起一场怎样的风暴?
区块链是什么(上)超通俗的区块链入门干货
区块链是比特币的底层技术,不等同于比特币。有人说比特币就是一场泡沫,甚至放话“比特币是传销”。区块链作为继互联网后的新一波技术浪潮,本身无罪,况且炒币只是区块链里最初级的玩法。读完这篇文章,我们就能弄懂大部分区块链基础知识,从而离保守和狭隘远一点。
互链脉搏
2018/05/18
2.7K0
区块链是什么(上)超通俗的区块链入门干货
从比特币说起,区块链到底是个啥?
“ 火币网技术副总裁为你详解比特币产生的背景以及其背后的核心——区块链。 1 比特币大起底 随着信息技术的发展,人们的生活逐渐网络化,数字化。人类社会因此发生着深刻的变化。对数字货币的探索,就是在这样的背景下应运而生的。其实相关的研究在上世纪八九十年代,就开始了。 在数字货币的探索实践中,比特币是目前表现最好的一个。说到比特币的缘起,就不得不谈到一个略显神秘的团体:密码朋克(CypherPunk)。这个团体是密码天才们的松散联盟。在比特币的创新中,大量借鉴了密码朋克成员的贡献。 密码朋克本身就是数字货币
企鹅号小编
2018/02/09
7930
从比特币说起,区块链到底是个啥?
极简区块链手册:什么是区块链?什么是比特币?
前言:疯狂的时代 这个时代变化太快,互联网金融刚刚热了几年,金融科技便取而代之。一波波新概念让我们眼花缭乱,在不断鼓噪的创新颠覆中,莫名的焦虑感笼罩着所有人。相信我,你并不孤独!我也是那焦虑的一员。我就是这样的一个焦虑症患者,一直关注比特币的挖矿、算法逻辑和区块链的各种新消息,不时沉浸在瞬间的快乐和间歇性沮丧之中。面对所有变化——金融的、艺术的、科技的、社会的,我们都会坚定地向往和跟随这些创新,即便大多数会走向失败,过程却是充满着大大小小的快活之处。我相信区块链也会是这样的。 先问自己一个问题,如果不懂
企鹅号小编
2018/01/24
2.6K0
极简区块链手册:什么是区块链?什么是比特币?
比特币和区块链(3):比特币的共识机制
0 上一篇我们详细介绍了不可篡改的账本区块链的数据结构的实现。其核心技术第一是数字签名,比特币采用的是椭圆曲线数字签名算法。第二是加密级别的哈希,比特币采用的是SHA256。 然而在我们的系统里,依然只有一个寡头负责记账。我们固然不用担心交易记录被伪造,因为有数字签名。我们也不用担心区块被篡改,因为可以通过哈希值校验。但是我们无法防止这个寡头故意不记账或者故意丢区块。所以这个系统是一个人人可以查账,但是大家却必须相信寡头不作恶的系统。 比特币系统显然不会停留在这个设计上。所以寡头需要被取代掉。比特币的做
用户1564362
2018/04/08
1.4K0
比特币和区块链(3):比特币的共识机制
用脑残的方式来理解虚拟货币和区块链技术
最近比特币等虚拟货币价格大涨,造就了N多的富翁和负翁。现在到处都在谈论区块链技术,貌似不知道一点或者不谈论这些都不好意思说自己是IT人员一样。其实一直以来我也就知道比特币是一种虚拟货币,至于什么区块链啊,挖矿啊,矿池什么的,到底表示的是什么?我也不懂。
欧阳大哥2013
2018/08/22
1.7K0
用脑残的方式来理解虚拟货币和区块链技术
如何正确投资比特币、区块链和其他加密货币?
原文地址:https://medium.com/@nellsonx/how-to-properly-invest-in-bitcoin-blockchain-and-other-cryptocurrencies-in-2017-32d59e2ff435
Ksher
2018/04/02
1.8K0
如何正确投资比特币、区块链和其他加密货币?
区块链 | 比特币如何实现—《区块链历史链条》2
11比特币为什么还没有挖完 比特币系统靠调节难度系数保证比特币不被太快挖完。每10分钟,全网矿工共同计算一道难题,竞争记账权及比特币奖励。如果全网算力不断增长,比特币将很快被挖矿。为了保证比特币稳定在约10分钟挖出一个区块,中本聪设计矿工挖矿获得比特币的难度每过2016个区块(约2周时间)动态调整一次,令调整后的难度使得每生成一个区块的预期时间为10分钟。现在的难度系数约为480PH/s,大约是创世区块的680亿倍,也就是说,以现在的算力,全网矿工需要经过约3000万亿亿次哈希运算才能找到一个符合条件的答案
码神联盟
2018/04/03
3.3K0
推荐阅读
相关推荐
十一张图解析区块链原理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档