在直播软件源码开发过程中,消息系统是非常关键的,无论是直播间内的消息还是平台内的消息,都关系着用户的使用体验,所以今天我们先用一个简单的"拉"模型搭建一个简单的直播间消息系统。
基本实现思路:
直播软件源码客户端每隔一个极短的时间,例如1秒亦或者更短的时间,根据直播间的id来调用服务端的接口,轮询该直播间发生的消息,服务端这边我们使用redis的SortedSet的数据结构来存储消息,其中key是直播间的房间id,score是服务器接收到该消息事件生成的时间戳,value可以简单地直接存储该消息序列化后的字符串,这样可以按照时间顺序地去存储消息,并且配置过期消息的删除逻辑,整个消息的存储就可以简单地搭建起来。
消息存储用java的伪代码所示:
long time = new Date().getTime();
try {
// redis中插入消息数据
jedisTemplate.zadd(V_UNIQUE_ROOM_ID, time, JSON.toJSONString(roomMessage));
// 按照概率性的去删除redis中过期的消息数据
if (probability()) {
deleteOverTimeCache(V_UNIQUE_ROOM_ID);
}
} catch (Exception e) {
log.error("message save error", e);
}
可以看到直播软件源码消息存储,如果使用redis的sortedSet进行存储还是比较方便的,接下来我们需要处理就是redis中过期消息的删除,因为在直播软件源码中无效的过期消息是没有价值的(所有的消息可以做持久化存储),redis中如果单一的key存储的消息过多,也会导致消息的慢查,和内存的使用量不断增大,这是我们不想看到的,这边因为是示例代码,所以简单地处理一下删除逻辑。
private void deleteOverTimeCache(String roomId) {
Long totalCount = jedisTemplate.zcard(roomId);
log.info("deleteOldTimeCache size is {}", totalCount);
if (totalCount < 600) {
return;
}
// 倒序删除过期数据
Set<Tuple> tuples = jedisTemplate.zrangeWithScores(roomId, -601, -1);
if (CollectionUtils.isNotEmpty(tuples)) {
for (Tuple tuple : tuples) {
// 这是第一个-600条的那个score
double score = tuple.getScore();
jedisTemplate.zremrangeByScore(roomId, 0d, score);
break;
}
}
}
上面的伪代码probability()首先先做一个概率性的判断,例如我们做百分之一的随机判断,判断该次请求是否要进行消息的删除(请注意我们删除的逻辑是放在插入的逻辑之中的。如果每一次插入都需要判断是否要删除过期数据,会影响插入的性能)。如果通过概率性判断后,我们就优先判断直播软件源码中某一直播间的消息个数,如果消息个数还是比较少的话,则退出删除逻辑,如果超过消息阀值,则按照时间倒序删除已经过期的消息。
说完了http短轮询消息的存储后,我们最后再简单地说一下客户端消息查询实现逻辑。直播软件源码客户端通过直播间id和时间戳两个字段来请求服务端以查询直播间消息,其中"时间戳"是每一次服务端返回的,这个时间戳是渐进式的,当下一次客户端来请求服务端的数据的时候,都会带来上次服务端返回的时间戳,伪代码如下:
@Override
public RoomMessage queryRoomMessages(MessageMessageReq messageMessageReq) {
RoomMessage result = new RoomMessage();
long timestamp = messageMessageReq.getTimestamp();
Set<Tuple> tuples = null;
if (timestamp == 0) {
// 如果传递是0,说明这个客户端终端是第一次来轮询,我们只要返回一个最近最新的消息返回即可
tuples = jedisTemplate.zrevrangeWithScores(UNIQUE_ROOM_ID, 0, 0);
} else
// 加上一毫秒,返回后续的消息,每次返回5个,防止客户端因为低端手机原因,过多的消息渲染不出来
tuples = jedisTemplate.zrangeByScoreWithScores(UNIQUE_ROOM_ID, timestamp + 1, System.currentTimeMillis(), 0, 5);
}
List<EachRoomMessage> eachRoomMessages = new ArrayList<>();
long lastTimestamp = 0L;
if (!CollectionUtils.isEmpty(tuples)) {
for (Tuple tuple : tuples) {
//最后一次循环后,会把最后一条消息产生的时间戳,返回给客户端,这样下次客户端就可以拿着这个时间戳来进行查询
lastTimestamp = new Double(tuple.getScore()).longValue();
eachRoomMessages.add(JSON.parseObject(tuple.getElement(), EachRoomMessage.class));
}
}
result.setTimestamp(lastTimestamp);
result.setEachRoomMessages(eachRoomMessages);
return result;
}
上述三段比较完整地代码主要陈述了一个依赖http短轮询这种方式快速实现的直播软件源码直播间的能力,这种方式是比较粗糙的,不过却是一个很好的实现思路。以上就是“直播软件源码开发,直播间内消息系统的实现”的全部内容,希望对大家有帮助。