分类目录归档:新功能

最好的 SDK,只为服务世界上最好的语言—— LeanCloud SDK for PHP 正式发布

PHP 作为 Web 平台使用最为广泛的语言之一,其易于部署的特性赢得了广大开发者的支持。今天我们非常高兴地发布了基于 PHP 的 LeanCloud SDK – 0.1.0 版,欢迎 PHP 粉丝们来测试使用,并为我们提供意见和建议。

0.1.0 版本主要支持 数据存储 ,包括用户的管理、对象的存储查询,以及文件存储,可以在 PHP 5.3 及以上的运行环境中使用。部署到云引擎的功能将会在后续版本中支持。

基于 PHP SDK,我们可以很容易地创建数据对象,将其保存到 LeanCloud 云端。这跟向传统数据库写入数据不一样,应该说是过程简化了不少。现在你用不着提前到数据库里创建好表,设置好要用的字段和数据类型,只要有了对象有了数据就直接往云端写,没有的表会自动建,没有的字段会自动加,过程颇有些「行云流水」的意境。

继续阅读

基于 LeanCloud 云引擎的 Web 全栈方案:LeanEngine-Full-Stack

很多工程师使用 LeanCloud 之后,发现一个人就可以 hold 住一个完整项目,尤其是一个 Web 项目。原因很简单,本来复杂繁琐的数据库操作,通过使用 LeanCloud 的 JavaScript SDK 变得轻而易举,再结合 LeanCloud 提供服务器端容器 —— 云引擎 LeanEngine(支持 Node.js 和 Python 两种环境),就可以很高效地开发出一个 Web 端项目。

QQ20151009-1@2x

背景

开始尝试 LeanCloud 时项目并不大,也不算复杂,大家都是很简单地去写代码,但是随着使用的深入,开发变得越来越顺手,有些工程师开始尝试设计复杂的项目。只要项目复杂了,就会有很多底层的事情需要考虑,比如协作分工、自动化流程、代码组织结构、框架选择、国际化方案等等。LeanCloud 的很多项目就是基于自身所提供的服务,在开发过程中我们遇到过很多问题,也为此纠结过,所以我们将目前使用的 Web 全栈方案整理成一个新的项目,作为一个 Generator 或者 Seed,供大家交流和使用。

简介

项目名为「LeanEngine-Full-Stack」,就放在 LeanCloud 官方的 GitHub 仓库中,地址为 https://github.com/BaaSBeginner/LeanEngine-Full-Stack

继续阅读

LeanEngine 中使用 WebSocket

一直以来 HTTP 协议都是使用「请求/响应」的模型,在 Web 应用越来越复杂的今天,这种模型的限制越来越明显。

很多场景下,我们想要服务器主动发送通知给浏览器,甚至我们想在浏览器中实现一个实时对战的网络游戏。这个时候 HTML5 规范中的 WebSocket 可以很好地满足我们的需求。

对于使用 LeanEngine 的用户,我们也可以直接在 LeanEngine 环境中使用 WebSocket,来构建应用了。下面我们以 LeanEngine NodeJS 运行时环境为例,实现一个 WebSocket echo server(echo server 是指返回任何接收到信息的服务)。

继续阅读

云代码正式更名「云引擎」,3.0 版本重磅上线

在云代码 2.0 中,大家可以通过使用自定义的第三方包,灵活地进行开发。但由于架构在沙箱环境中,云代码 2.0 在功能上会受到局限。为此,我们对其进行重构和改进,现在正式推出云代码 3.0。同时,我们将「云代码」正式更名为「云引擎」,即 LeanEngine,旨在打造一个更加通用的多运行时平台。

最新的云引擎,具备两个明显的特征:「去沙箱」和「支持 Python 运行时」。

继续阅读

我们增加了 MailChimp 邮件订阅功能

现在您可以方便的通过邮件订阅我们的 blog,我们会在 每周一的上午六点(UTC+08:00) 将最新的 LeanCloud 讯息发送到您的邮箱,您可以在 blog 的侧栏找到订阅表单

Under the hood: 我们之前通过 Jetpack 的 Subscriptions 功能为用户提供邮件订阅功能,但由于服务器在国内导致与 WordPress.com 的服务器通信经常受干扰,因此决定用 MailChimp 的服务继续提供订阅功能。如果您正在通过之前的 Jetpack 插件订阅本 blog,您可以重新订阅

「重要通知」LeanCloud 系统中现金账户与短信账户将进行拆分

尊敬的用户:

此前, LeanCloud 的短信服务一直采用实时扣费,即要提前充足够现金,每发一条短信将扣费 0.06 元。由此,在每月初因其它服务的费用扣款时,会将用户的短信预算也扣除,导致某些用户余额不足无法使用短信功能。为解决该问题,我们决定从 4 月 15 日起,正式拆分 LeanCloud 系统中的现金余额和短信余额。

我们建议需要使用短信服务的用户,即日起购买足够的短信额度,以避免因短信余额不足而无法发送短信。您既可以用现金余额也可以用支付宝 购买短信额度
Screen Shot 2015-03-26 at 7.09.33 PM
此外,在您的短信余额用完之前,LeanCloud 系统会通过短信和邮件向您发送通知。因此,我们强烈建议您在开发者账户信息中填写手机联系方式,以接收我们的提醒短信。

在过渡期间——即日至 4 月 15 日,短信消费将先从「当前账户余额」中扣除,如若失败将从「短信账户」中扣除。

感谢您选择使用我们的服务。

The LeanCloud Team

实时通信 2.0:对话 API 和多媒体消息

自去年 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 现在已经可以在 下载页面 获取,欢迎大家体验。

LeanCloud 离线数据分析功能介绍

可能不少用户还不知道,我们上个月中旬就已经对外发布了离线数据分析功能。用户可以用它来做什么,它适用于哪些应用场景,有没有应用实例?若要回答这些问题,首先让我们看看部分用户曾经向我们提出过的一些痛点或需求。为了对用户数据保密,后面提到的应用名字与数据均为虚构。

  • 某应用 TestA 发布几个月之后,由于用户量暴涨,存储在我们这里的数据规模急剧上涨。这就导致了一个无法忽视的问题:他们在应用刚发布的那段时间会每天从我们这里导出数据,自己写程序做数据分析。而当数据规模(几十 GB)越来越大,受限于网络文件下载速度,每日导出数据再自己做分析已经变得越来越困难。因此,他们希望我们能提供数据分析服务,支持 SQL-like 的查询。
  • 某应用 TestB 每天都会针对应用数据做一些分析报告,主要目的是知晓应用当前的关键数据指标。按照最初的方案,他们需要每日导出数据,自己写脚本程序处理应用数据。实际上,这样的工作对一个需要快速迭代产品的团队来说颇为繁琐,也比较消耗时间。
  • 我们的 工单系统 也是构建在 Leancloud 之上,每一条工单数据都是通过我们的存储组件写入我们的云端数据库。工单系统同时也作为我们的一个示例公开了源代码,从源代码就可以了解到它和其他用户的应用没有本质区别(从数据存储这个角度看)。我们的工程师除了需要非常及时地处理用户提交的工单,也需要了解工单系统的一些统计指标,例如自己最近回复了多少工单、不同平台工单的处理速度等等。如果有一个支持 SQL-like 的查询服务,那么要统计这些指标就会变得很容易。

相信上面的例子对很多用户来讲都不陌生,它揭示的痛点无非是大量的数据无法通过便捷的手段进行分析。考虑到用户的需求,我们开发了支持 SQL-like 查询的离线数据分析服务。用户要做的不过是按照我们的 离线数据分析使用指南 开启离线数据分析服务,输入合法的 SQL 语句即可分析数据。顺便说一下,这个服务后端核心组件为 Spark SQLParquet

接下来,就以我们的工单系统为例子,介绍如何利用离线数据分析服务来解决我们日常工作中遇到的一些问题。当然,为了更好地了解工单系统内部的结构,你可以访问 这里 的源代码。

首先让我们看看整个界面:

bigquery-0

接下来就让我们针对一些统计指标分析工单系统数据:

  • 统计不同平台类型(type)的工单数量,并按大小排序
select count(*) as `count`, type from Ticket where type is not null group by type order by `count` desc

结果如图所示(如果图中文字不够清晰,请点击查看大图):

bigquery-1

  • 统计每个工单(Ticket)各有多少条回复(Thread),并按回复数大小排序
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

结果如图所示:

bigquery-2

若想知晓 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
  • 统计所有工程师最近一个多月处理了多少条工单(Ticket),并按处理数量排序。Admin、Thread、Ticket 这三张表参与了 join 计算,其中 Admin 存放了工程师的个人信息,它和回复(Thread)通过 cid 关联。而回复(Thread)与工单(Ticket)则是通过工单的 objectId 来做关联。
# 注: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

结果如图所示:

bigquery-3

  • 统计所有工程师总共有多少次回复(Thread),并按回复数排序。同工单数的查询类似,这里也需要三张表做 join。
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

结果如图所示:

bigquery-4

  • 统计每天各有多少条回复(Thread)
# 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

结果如图所示:

bigquery-5

考虑到本文篇幅有限,就不再列举其他查询示例。如果您在使用离线数据分析服务的过程中遇到各种各样的问题,都可以通过工单或者邮件向我们反馈,我们会及时处理相关问题。

实时通信云代码集成发布

大家好,我们又发布了一个坳口的功能,实时通信的 云代码集成 。简单地说,现在用户可以通过 自定义云函数 作为 hook,修改实时通信默认的执行流程,增加应用自定义的业务逻辑。

第一阶段我们支持两个 hook:_messageReceived(消息到达服务器)和 _receiversOffline(收件人离线)。

_messageReceived 发生在消息到达服务器,服务器解析完收件人 id 之后,消息存入离线队列之前。这个阶段云函数可以获得的信息包括消息内容、收件人 id 列表、时间戳、发件人等等,用户的云代码可以通过返回值修改消息内容,修改收件人列表甚至直接丢弃消息。这个 hook 可以帮助用户实现自定义的消息处理,甚至实现请求-响应式的模型。

潜在的用例:

  1. 更新数据库,例如记录用户最近发消息时间
  2. 修改消息内容,删除广告,敏感信息(尽管我们已经内置了敏感词过滤)
  3. 修改收件人列表,自动转发消息到他人
  4. 完全颠覆传统实时通信模型,执行服务器端业务逻辑

Screenshot from 2015-01-08 15:09:29

_receiversOffline 发生在消息发送完成后,离线通知触发前。这个阶段云函数可以获得消息内容,离线收件人 id,关联的群组 id 等。用户可以通过云代码返回值指定离线通知的内容,被通知的用户 id,或者直接跳过默认的推送通知(比如在 hook 中触发短信、邮件等其他通知方式)。这个 hook 可以解决之前大家反馈比较多的推送消息不能动态定义的问题。

云代码集成是可选功能,已有的功能不受此次升级影响。关于云代码集成更完整的参数列表和详细说明,请 参考我们的文档

更 lean 更便捷,云代码「精益模式」上线

很多用户使用 Cloud Code 云代码 是为了在服务端提供一些个性化的方法供各终端调用,而不希望关心诸如代码托管、npm 依赖管理等问题。为此我们提供了在线维护 Cloud Code 的功能。

提醒

使用此功能,你需要注意:

  • 会替代您之前 git 或者命令行部署的项目。
  • 暂不提供 Web hosting 功能。
  • 维护的所有函数可以生成并导出一个完整的项目,供 git 或命令行部署(即将推出)。
  • 之前由项目维护的云代码方法并不会显示在此处,可以认为「定义函数」和使用项目维护的云代码是两套代码。具体使用什么代码,是由最后一次部署使用什么功能决定(「定义函数」的每一个添加、修改、发布、删除动作都是一个部署动作)。

cloud_code_snippet

左上角的「创建函数」可以新创建一个函数。中间部分是已经创建好的函数,并可以进行一些维护操作。

函数类型

有几种函数类型:

  • Function:对应 AV.Cloud.define 定义的方法。
  • Hook:对应 AV.Cloud.beforeSave 等回调定义的方法。
  • Global:对应全局变量,一些全局变量和公共函数可以定义在这里。

这些函数的使用场景和具体细节,参见:Cloud 函数

创建函数

如果需要创建一个新的函数,可以点击「创建函数」按钮,您将看到如下窗口:

cloud_code_snippet_create

您需要设置的部分包括:

  • 函数类型
  • 函数名称
  • 数据具体的代码片段(注意,你不需要输入函数定义部分,即 AV.Cloud.define(...) 部分)
  • 注释
  • 全部 OK 后点击「保存」,或者放弃编辑点击「关闭」

您可以在代码框中填入下列代码:

var name = request.params.name;
if (name) {
    response.success('Hello ' + name);
} else {
    response.error('name?')
}

点击保存后,Cloud Code 会在后台编译、保存,并将代码部署到「测试环境」,这个过程可能需要十几秒钟的时间,请耐心等待。全部完成后,页面上方会提示「已更新到测试环境」;如果有错误(比如编译错误)则会出现类似提示: 加载代码出错: SyntaxError: Unexpected token )

发布

如果函数部署「测试环境」成功,就可以点击「发布」按钮将函数发布到「生产环境」。同样该过程可能需要十几秒钟的时间,请耐心等待。全部完成后,页面上方会提示「已发布到生产环境」。

同步

对于某个函数,可能生产环境运行一个版本,而测试环境正在开发一个新的版本,两个环境的代码是不一致的,这时函数列表页面相关函数的「测试环境」按钮会变成蓝色:

cloud_code_snippet_diff_version

当您在测试环境开发完成,点击「发布」后,两个环境的代码将会统一,这时「测试环境」按钮变为灰色。

测试

如果需要测试,可以点击相应函数的「调用」按钮,你将看到如下窗口:

cloud_code_snippet_invoke

选择调用环境,并输入调用参数,点击「运行」按钮即可看到调用结果。如果调用返回的 Http Status Code 不是 200,则页面上方会提示相关错误信息。

历史版本

如果您想看某个函数之前曾经部署过的代码,可以在函数列表页面点击「历史」按钮,将会弹出类似下面的窗口:

cloud_code_snippet_history

您可以点击时间来查看不同时间部署的代码。

删除

如果您确定某个函数已经不再需要,可以在函数列表页面点击「删除」按钮将其删除。 注意 :删除后该函数和其所有历史记录都将被删除,而且不能恢复。删除动作会重新部署测试和生产环境,这个过程可能需要十几秒钟的时间,请耐心等待。