SONA项目调研

本文详细介绍了比心语音开发的SONA开源项目,涵盖了关键功能代码、RTC实时音视频处理、房间IM功能、Netty和Mercury网络处理、模块间的交互,以及如何在基础架构上进行业务扩展和优化。
摘要由CSDN通过智能技术生成

前言

本篇笔记着重于两方面:
1.开源项目实现的功能。关键功能具体代码。
2.在此架构上做二次开发,具体操作。(业务扩展,架构优化)

更详细开源项目信息请查看参考文献》

开源背景

SONA****官网描述如下。

SONA 简介

  • sona 是一个由比心语音技术团队开发,用于快速搭建语音房产品的全端解决方案,支撑了比心聊天室、直播、游戏房等业务。
  • sona 提供了包括房间管理、实时音视频、房间IM在内的丰富的能力,快捷的接入方式,以及可商用的性能和稳定性。
  • sona 用统一的接入方式封装了不同RTC厂商sdk,方便使用各厂家的用户能以最小成本接入和切换。
    SONA 核心功能
  • 基础房间管理能力:房间操作、人员权限、房间管理、在线列表等
  • RTC(实时音视频):rtc推拉流、转推CDN拉流、混流、录制等
  • 房间IM:聊天室消息、群组消息、点对点消息、广播消息
    SONA 优势
  • 一站式解决语音房间底层技术问题,让你可以专注于业务功能开发。
  • 集成了多家RTC云商,细粒度到可以支持单房间一键热切云商sdk。
  • 高吞吐低延迟的IM,通过消息分级控制,确保重要消息如高价值礼物不会丢失。

项目概述

完整版比心

项目流程图(完整版~~)~~

部署架构
image.png
系统结构

比心陪玩业务(完整版)

image.png

模块依赖图

yuque_diagram.jpg

图讲项目


连接方式
发送消息的频率是否是配置的

SONA架构图

详细介绍参照官网描述。

image.png

核心功能

详细官网核心功能描述。

RTC(实时音视频)
云商回调

详情查看官网

image.png

音视频主要流程

房间IM
消息全链路查询
SONA一共支持 4 种消息:
  • 聊天室消息

当前房间是聊天室模式,比如直播间这种,一条消息发送给房间内的所有在线用户

  • 群组消息

当前房间是群组模式,比如游戏房这种,一条消息发送给房间内的所有用户

  • 点对点消息

不论是群组模式还是聊天室模式,都可以使用点对点消息,一条消息指定发送给房间内的某个或者某些用户,未被指定的用户是收不到的

  • 广播消息

只支持聊天室模式,一条消息同时发送给多个房间,比如给所有聊天室都发送横幅等场景,就可以使用

消息发送(长短连接)

详情查看官网。

发送流程图

基础房间管理能力
在线列表
  1. 对于群组模式的房间,获取列表就是 当前群组的所有用户列表,不管用户是否长连在线
  2. 对于聊天室模式的房间,获取在线列表,是拿到当前房间内所有长链在线的用户列表
    对于sona来说,用户是否在线,完全依赖长连接,长连在就认为在线,长链不在就认为离线

详见官网描述

image.png

模块介绍

gateway网关

网关流程

Netty 请求处理

image.png
Netty 使用 主从Reactor模型 bossGroup 负责处理 accept 事件 , workerGroup 负责处理 read 、write 事件 其中 ChannelPipeline 是一个双向链表,netty 里面定义了十几种事件,触发之后会顺序调用所有 ChannelHandler 的指定方法,ChannelHandler的调用都是由 workerGroup中的同一个 eventloop 线程执行,不存在线程之间的切换。

Mercury 请求处理

image.png
Netty 中 ChannelPipeline 这种无锁化的设计,避免了上下文切换,在海量请求的情况下能提供很高的性能。但是也存在风险,如果执行某个 ChannelHandler 出现了阻塞,会拖累这个 eventloop 线程所负责的其他请求。 在实际场景中,ChannelHandler里面一般都会执行一些 IO 操作,比如RPC调用,MQ等,无法保证不会出现阻塞的情况。所以很多高性能的分布式框架中都会使用三层处理模型,额外增加一个业务线程池,将耗时的IO操作放在这个业务线程池里面执行,这样就不会阻塞 workerGroup 中的线程了,Mercury 中也是这么设计的。

调用代码流程
代码流程图

比心业务流程图.jpg

关键代码
NettyServerInitializer

netty启动时,初始化handler,encoder,decoder.
关键代码如下:

public ChannelFuture start() {
   
    ChannelFuture cf = null;
    ChannelFuture cfWs = null;
    try {
   
        ServerBootstrap bootstrap = new ServerBootstrap();
        bossGroup = NettyFactory.eventLoopGroup(1, "bossLoopGroup");
        workerGroup = NettyFactory.eventLoopGroup(4, "workerLoopGroup");
        bootstrap.group(bossGroup, workerGroup)
            .channel(NettyFactory.serverSocketChannelClass())
            .option(ChannelOption.SO_BACKLOG, 2048)
            .childOption(ChannelOption.TCP_NODELAY, true)
            .childOption(ChannelOption.SO_KEEPALIVE, true)
            .option(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
            .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(64 * 1024, 128 * 1024))
            //初始化handle
            .childHandler(new NettyServerInitializer());
        cf = bootstrap.bind(PORT).sync();
        channel = cf.channel();
        cfWs = bootstrap.bind(PORT_WS).sync();
        channelWs = cfWs.channel();
    } catch (Exception e) {
   
        log.error("Netty server start fail", e);
    } finally {
   
        if (cf != null && cf.isSuccess() && cfWs != null && cfWs.isSuccess()) {
   
            log.info("Netty server listening ready for connections...");
        } else {
   
            log.error("Netty server start up error!");
        }
    }
    printNettyConfig();
    return cf;
}

//handled调用链
private static final NettyServerHandler NETTY_SERVER_HANDLER = new NettyServerHandler(ChannelHandlerWrap.wrap(new MercuryServerHandler()));
//编码、解码
private static fi
  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哼哼牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值