云引擎从起步到现在将近 2 年,一直为开发者免费提供服务,其所服务的应用数量也在不断增长。为了更好地满足开发者对应用性能的可控需求,同时实现我们对后端支撑资源的合理配置,保证云引擎的健康成长,我们将于 2016 年 4 月 2 日(周六)对云引擎进行重要升级。
新版云引擎开始支持 Node.js 4.x 环境,优化了代码部署流程,并且最大的改变是:增加了多实例的管理功能——开发者可以自主决定启动多少个云引擎实例,以及每个实例的规格;同时我们推出了免费和付费两种使用方案。
云引擎从起步到现在将近 2 年,一直为开发者免费提供服务,其所服务的应用数量也在不断增长。为了更好地满足开发者对应用性能的可控需求,同时实现我们对后端支撑资源的合理配置,保证云引擎的健康成长,我们将于 2016 年 4 月 2 日(周六)对云引擎进行重要升级。
新版云引擎开始支持 Node.js 4.x 环境,优化了代码部署流程,并且最大的改变是:增加了多实例的管理功能——开发者可以自主决定启动多少个云引擎实例,以及每个实例的规格;同时我们推出了免费和付费两种使用方案。
LeanCache 是为云引擎用户提供的高性能、高可用的内存存储服务。与我们以往的数据存储服务相比,它不仅能够处理更多的并发连接和请求数,极大地提高应用性能,而且还能降低数据存储的使用成本。像秒杀、抢红包、数据量少但读写比例很高等场景都适合使用 LeanCache。
在云引擎中访问一个容量为 2GB 的 LeanCache 实例,每秒可以处理将近 70,000 次的请求,而一般情况下访问存储服务的请求峰值为每秒 800 次,相差将近 90 倍。除了更高的性能,LeanCache 还可以帮助用户节省费用。因为交由 LeanCache 处理的请求不计入存储 API 调用次数,所以用户可以把一些高频率的查询从按 API 调用次数收费的存储服务分流至 LeanCache 上,通过降低总的 API 调用次数来减少费用。
LeanCache 基于 Redis 技术,同时支持缓存数据存储和持久化存储,可以在不中断服务的情况下在线扩容。同时,LeanCache 支持在多个应用之间共享数据,所以如果多个云引擎节点需要协同工作和通信,LeanCache 也是正确的选择。
PHP 作为 Web 平台使用最为广泛的语言之一,其易于部署的特性赢得了广大开发者的支持。今天我们非常高兴地发布了基于 PHP 的 LeanCloud SDK – 0.1.0 版,欢迎 PHP 粉丝们来测试使用,并为我们提供意见和建议。
0.1.0 版本主要支持数据存储,包括用户的管理、对象的存储查询,以及文件存储,可以在 PHP 5.3 及以上的运行环境中使用。部署到云引擎的功能将会在后续版本中支持。
基于 PHP SDK,我们可以很容易地创建数据对象,将其保存到 LeanCloud 云端。这跟向传统数据库写入数据不一样,应该说是过程简化了不少。现在你用不着提前到数据库里创建好表,设置好要用的字段和数据类型,只要有了对象有了数据就直接往云端写,没有的表会自动建,没有的字段会自动加,过程颇有些「行云流水」的意境。
很多工程师使用 LeanCloud 之后,发现一个人就可以 hold 住一个完整项目,尤其是一个 Web 项目。原因很简单,本来复杂繁琐的数据库操作,通过使用 LeanCloud 的 JavaScript SDK 变得轻而易举,再结合 LeanCloud 提供服务器端容器 —— 云引擎 LeanEngine(支持 Node.js 和 Python 两种环境),就可以很高效地开发出一个 Web 端项目。
开始尝试 LeanCloud 时项目并不大,也不算复杂,大家都是很简单地去写代码,但是随着使用的深入,开发变得越来越顺手,有些工程师开始尝试设计复杂的项目。只要项目复杂了,就会有很多底层的事情需要考虑,比如协作分工、自动化流程、代码组织结构、框架选择、国际化方案等等。LeanCloud 的很多项目就是基于自身所提供的服务,在开发过程中我们遇到过很多问题,也为此纠结过,所以我们将目前使用的 Web 全栈方案整理成一个新的项目,作为一个 Generator 或者 Seed,供大家交流和使用。
项目名为「LeanEngine-Full-Stack」,就放在 LeanCloud 官方的 GitHub 仓库中,地址为 https://github.com/BaaSBeginner/LeanEngine-Full-Stack。
一直以来 HTTP 协议都是使用「请求/响应」的模型,在 Web 应用越来越复杂的今天,这种模型的限制越来越明显。
很多场景下,我们想要服务器主动发送通知给浏览器,甚至我们想在浏览器中实现一个实时对战的网络游戏。这个时候 HTML5 规范中的 WebSocket 可以很好地满足我们的需求。
对于使用 LeanEngine 的用户,我们也可以直接在 LeanEngine 环境中使用 WebSocket,来构建应用了。下面我们以 LeanEngine NodeJS 运行时环境为例,实现一个 WebSocket echo server(echo server 是指返回任何接收到信息的服务)。
在云代码 2.0 中,大家可以通过使用自定义的第三方包,灵活地进行开发。但由于架构在沙箱环境中,云代码 2.0 在功能上会受到局限。为此,我们对其进行重构和改进,现在正式推出云代码 3.0。同时,我们将「云代码」正式更名为「云引擎」,即 LeanEngine,旨在打造一个更加通用的多运行时平台。
最新的云引擎,具备两个明显的特征:「去沙箱」和「支持 Python 运行时」。
现在您可以方便的通过邮件订阅我们的 blog,我们会在每周一的上午六点(UTC+08:00)将最新的 LeanCloud 讯息发送到您的邮箱,您可以在 blog 的侧栏找到订阅表单
Under the hood: 我们之前通过 Jetpack 的 Subscriptions 功能为用户提供邮件订阅功能,但由于服务器在国内导致与 WordPress.com 的服务器通信经常受干扰,因此决定用 MailChimp 的服务继续提供订阅功能。如果您正在通过之前的 Jetpack 插件订阅本 blog,您可以重新订阅
尊敬的用户:
此前, LeanCloud 的短信服务一直采用实时扣费,即要提前充足够现金,每发一条短信将扣费 0.06 元。由此,在每月初因其它服务的费用扣款时,会将用户的短信预算也扣除,导致某些用户余额不足无法使用短信功能。为解决该问题,我们决定从 4 月 15 日起,正式拆分 LeanCloud 系统中的现金余额和短信余额。
我们建议需要使用短信服务的用户,即日起购买足够的短信额度,以避免因短信余额不足而无法发送短信。您既可以用现金余额也可以用支付宝购买短信额度:
此外,在您的短信余额用完之前,LeanCloud 系统会通过短信和邮件向您发送通知。因此,我们强烈建议您在开发者账户信息中填写手机联系方式,以接收我们的提醒短信。
在过渡期间——即日至 4 月 15 日,短信消费将先从「当前账户余额」中扣除,如若失败将从「短信账户」中扣除。
感谢您选择使用我们的服务。
The LeanCloud Team
自去年 LeanCloud 发布实时通信服务之后,我们收到了很多用户反馈,经过工程师对需求的消化和对业务的提炼,我们很高兴今天正式发布了实时通信 2.0 版本。新版本除了继续坚持我们的设计理念(灵活、解耦、可组合、可定制),我们更主要地针对第一版用户使用中的痛点做了重点改进,增加了 「对话」 这一实体概念和相应的 API,帮助开发者更有效地管理消息的上下文。另外值得一提的是,新版本中提供的多媒体消息格式类,开发者可以更加快捷地发送音频、视频、文件和地理位置等富媒体消息。
对话
新版本中,我们用「对话」这一概念整合所有的聊天形式:单聊、群聊和开放聊天室。每一个对话对应数据存储中 _Conversation 表的一条记录,因此开发者可以随时获取自己最近参与对话列表,这解决了我们先前版本在这方面的不足。而且,基于 LeanCloud 强大的数据存储、查询的基础,开发者还可以对「对话」记录增加自定义属性,并通过自定义的查询获取。消息现在通过对话来索引和管理,除了以被动推的方式实时到达客户端之外,用户还可以主动拉取某一对话从任意时刻开始向前的消息记录。实时通信中所有的概念和机制都对开发者透明,尽可能多地满足开发者个性化的需求。更多关于对话的信息可以在文档中找到。
新版本的 iOS 发送消息示例:
AVIMMessage *message = [AVIMMessage messageWithContent:@"hello"];
[_conversation sendMessage:message callback:^(BOOL succeeded, NSError *error){
if (error) {
// 出错了 :(
} else {
// 成功!
}
}];
接收消息:
-(void)conversation:(AVIMConversation *)conversation didReceiveCommonMessage:(AVIMMessage *)message {
// 下面的逻辑会把消息直接存入本地数据库缓存。注意:你完全可以根据自己的需要来决定实际如何处理
[self saveMessageToDatabase:message callback:^(BOOL succeeded, NSError *error) {
[[NSNotificationCenter defaultCenter] postNotificationName:LC_NOTIFICATION_MESSAGE_UPDATED object:conversation];
}];
}
富媒体消息
在第一版中,我们提供的是一个纯粹的传输层接口,用户可以通过这个接口发送各种格式的消息,比如纯文本或是格式化的消息。这曾经引起了一部分开发者关于其是否可以发送多媒体消息的困惑。在这方面,回答当然是肯定的。第二版中,我们针对这方面的疑惑,增加有补充:一套可扩展的富媒体消息格式。目前我们提供:文本(TextMessage)、图片(ImageMessage)、音频(AudioMessage)、视频(VideoMessage)、位置(LocationMessage)消息。对于图片、音频和视频等二进制消息,我们包装了文件上传等必要步骤,简化开发者的使用步骤。另外针对个性化的需求,开发者还可以在这套消息体系下定义自己特殊的消息类型,满足个性化的需求。
我们此次发布包含所有平台(Android,iOS,WindowsPhone 和 Web)的 SDK,此外还包括 REST API 用于对对话数据进行增删改查、拉取消息记录和发送消息等功能。文档中包含了整套系统中的主要概念和机制,各个平台 SDK 的使用说明等。SDK 现在已经可以在下载页面获取,欢迎大家体验。
可能不少用户还不知道,我们上个月中旬就已经对外发布了离线数据分析功能。用户可以用它来做什么,它适用于哪些应用场景,有没有应用实例?若要回答这些问题,首先让我们看看部分用户曾经向我们提出过的一些痛点或需求。为了对用户数据保密,后面提到的应用名字与数据均为虚构。
相信上面的例子对很多用户来讲都不陌生,它揭示的痛点无非是大量的数据无法通过便捷的手段进行分析。考虑到用户的需求,我们开发了支持 SQL-like 查询的离线数据分析服务。用户要做的不过是按照我们的离线数据分析使用指南开启离线数据分析服务,输入合法的 SQL 语句即可分析数据。顺便说一下,这个服务后端核心组件为 Spark SQL 与 Parquet。
接下来,就以我们的工单系统为例子,介绍如何利用离线数据分析服务来解决我们日常工作中遇到的一些问题。当然,为了更好地了解工单系统内部的结构,你可以访问这里的源代码。
首先让我们看看整个界面:
接下来就让我们针对一些统计指标分析工单系统数据:
select count(*) as `count`, type from Ticket where type is not null group by type order by `count` desc
结果如图所示(如果图中文字不够清晰,请点击查看大图):
select Ticket.objectId, Ticket.title, count(Thread.content) as `count` from Ticket inner join Thread where Ticket.objectId=Thread.ticket.objectId group by Thread.content, Ticket.objectId, Ticket.title order by `count` desc
结果如图所示:
若想知晓 iOS 平台的每条工单各有多少条回复,只需把上面的 SQL 语句做简单修改:
select Ticket.objectId, Ticket.title, count(Thread.content) as `count` from Ticket inner join Thread where Ticket.objectId=Thread.ticket.objectId and Ticket.type='ios' group by Thread.content, Ticket.objectId, Ticket.title order by `count` desc
# 注:slackName 其实就是这个工程师的用户名,因为我们还使用 Slack 来实时接收消息。
select count(distinct Ticket.objectId) as `count`, Admin.slackName from Ticket inner join Thread inner join Admin where Thread.ticket.objectId = Ticket.objectId and Admin.cid = Thread.cid and Admin.slackName is not null and unix_timestamp(Ticket.createdAt) > unix_timestamp('2014-12-01T00:00:00.000Z') group by Admin.slackName order by `count` desc
结果如图所示:
select count(distinct Thread.objectId) as `count`, Admin.slackName from Ticket inner join Thread inner join Admin where Thread.ticket.objectId = Ticket.objectId and Admin.cid = Thread.cid and Admin.slackName is not null group by Admin.slackName order by `count` desc
结果如图所示:
# substr(createdAt, 1, 10) 用来获取回复的日期(yyyy-MM-dd)
select count(*) as `count`, substr(createdAt, 1, 10) as date from Thread group by substr(createdAt, 1, 10) order by date desc
结果如图所示:
考虑到本文篇幅有限,就不再列举其他查询示例。如果您在使用离线数据分析服务的过程中遇到各种各样的问题,都可以通过工单或者邮件向我们反馈,我们会及时处理相关问题。