跳到主要内容

即时通讯中的在线状态查询

在客户端中展示用户的在线状态是即时通讯类软件的常见功能。它的应用场景十分广泛,例如聊天好友是否在线、公司办公交流时的同事是否在线、以及群成员是否在线等等。

本文会介绍如何使用 LeanEngine 来快速实现即时通讯中的在线状态查询。

准备工作

在开始之前,你需要了解以下内容:

  • 云引擎快速入门:了解云引擎是什么,是如何运作的。
  • 云函数:部署在服务端的代码。我们会使用云函数来实现 LeanCache 的查询以及即时通讯上下线 Hook 的逻辑。
  • LeanCache:高性能、高可用的 Key-Value 内存存储服务。
  • 即时通讯 Hook 函数:在本篇文档中,我们使用了即时通讯客户端上下线事件的 hook 函数。

示例 Demo

我们在 leanengine-nodejs-demos 这个项目里提供了一份代码示例供参考。你可以直接把这里的代码部署到自己的应用中。

实现步骤

我们通过 hook 拿到 clientId 的在线状态,将这些状态存储到 LeanCache 中。客户端定期查询云函数来获得用户的在线状态。本篇文档在云引擎初始项目的基础上来实现相关功能。

创建 LeanCache 实例

在应用中创建一个 LeanCache 实例,推荐使用 volatile-lru 删除策略。

安装依赖

请参考[在云引擎中使用 LeanCache](leancache_guide.html#在云引擎中使用(Node.js 环境))。

连接 Redis

首先我们要和 LeanCache 中的 redis 建立连接。在初始项目的根目录中,我们创建一个新的文件 redis.js 用于创建 Redis 实例。代码如下:

const Redis = require('ioredis')

// 创建 redis client,连接 LeanCache 实例
function createClient() {
// 本地环境下此环境变量为 undefined, 会链接到默认的 127.0.0.1:6379,
// ⚠️注意,需替换 `<LeanCache-实例名称>` 为实际创建的实例的名称。假如你的实例名是 statusCache,这里需要写 REDIS_URL_statusCache
const redisClient = new Redis(process.env['REDIS_URL_<LeanCache-实例名称>'])

// 监听 redis 的 error 事件,打印错误信息
redisClient.on('error', function(err) {
console.error('redisClient error', err)
})

return redisClient
}

module.exports = {
redisClient: createClient(),
createClient: createClient
}

获取并存储上下线状态

现在我们在项目的 functions 文件夹中创建 rtm-onoff-status.js 文件撰写上下线时的存储逻辑。

// 引入依赖
var AV = require('leanengine')
const {redisClient} = require('../redis')

onIMClientOffline 中拿到下线的 clientId,将 clientId 和下线状态存储到 LeanCache 中。代码如下:

AV.Cloud.onIMClientOffline(async (request) => {
// 设置某一客户端 ID 对应的值为 0,表示下线状态,同时设置过期计时
// 对于下线后长久未上线的客户端 ID,可以用过期时间来删除数据节省空间
redisClient.set(request.params.peerId, 0, 'EX', 604800)
})

onIMClientOnline 中拿到上线的 clientId,将 clientId 和上线状态存储到 LeanCache 中。代码如下:

AV.Cloud.onIMClientOnline(async (request) => {
// 设置某一客户端 ID 对应的值为 1,表示上线状态,同时清空过期计时
redisClient.set(request.params.peerId, 1)
})

撰写返回用户状态的云函数

现在我们撰写供客户端调用的云函数,在这个云函数中返回用户的在线状态。在 rtm-onoff-status.js 中添加如下代码:

AV.Cloud.define('getOnOffStatus', async (request) => {
// 约定 key: ”peerIds” 对应的值是一组客户端的 ID
return redisClient.mget(request.params.peerIds)
})

到现在我们的逻辑已经写完了,接下来只需要在主文件中加载 rtm-onoff-status.js ,客户端就可以调用这里的云函数了。我们在 app.js 中添加以下代码:

// 加载上下线状态中的云函数
require('./functions/rtm-onoff-status');

部署项目

代码写完后,用命令行工具将代码部署到服务端。部署成功后,就可以使用 SDK 或者 REST API 调用云函数来查询上下线状态了。

客户端查询

客户端可以通过 LeanCloud SDK 调用部署成功的云函数,示例代码如下所示。

async Task GetOnOffStatusWithPeerIds(List<string> peerIdList) {
if (peerIdList == null || peerIdList.Count == 0) {
return;
}
try {
Dictionary<string, object> paramters = new Dictionary<string, object> {
{ "peerIds", peerIdList }
};
List<string> results = await AVCloud.CallFunctionAsync<List<string>>("getOnOffStatus", paramters);
foreach (string result in results) {
if (result == "1") {
// 在线
} else {
// 离线
}
}
} catch (Exception e) {
// TODO 处理错误
}
}
对于一些需要较为实时的更新上下线状态的场景,比如好友列表页面,群成员信息列表页面等等,可以通过轮询的方式来更新状态信息。