2015年开始的百播大战,熊猫TV是其中比较特别的一员。

说熊猫TV是含着金钥匙出生的公子哥不为过。还未上线,就频频曝光,科技号,微博稿,站上风口浪尖。内测期间更是有不少淘宝店高价倒卖邀请码,光内测时用户注册数量就达几十万,火爆程度可见一斑。笔者作为写下熊猫TV第二行代码的Coder,见证了熊猫TV成立以来的风风雨雨。直播技术坑不少,本文简单揭秘熊猫TV这一年的技术架构演进,分析各个阶段面临的主要问题和应对方案,给大家做直播系统提供一定的参考。

熊猫架构 0.1- 来不及了,老司机快上车

这个阶段最大的目标就是按预期时间上线。

图1 项目规划时间表

组团队不表,10人左右的Web团队,从接需求,到上线,我们用了不到三个月。

这个阶段面临的最大难题:两个月就内测!

怎么办?找老战友刷刷刷!花钱买买买!作为一群经验丰富的老司机,我们用买零件翻新车的方法。网站内测公测阶段,需要满足用户登录注册、关注主播、看视频、发弹幕、加房管、领任务、送免费竹子等核心功能,采用了复用模块+主业务全新开发的策略。

➤复用模块

复用模块得益于团队的前360技术背景,根据直播秀场类项目上的技术积累,利用PHP框架Pylon、发版工具Rigger,在老战友的帮助下,重新搭建了一套QBus消息组件,长连接系统,改进的Redis、MongoDB和MySQL集群,视频云服务,敏感词服务,搜索服务,这个项目才有了强大的基础支撑,才有可能在两个月时间就上线。

  • 视频模块——从新搭建视频云,RTMP推流拉流,接入三家CDN作为互备。这其中需要自己实现统一调用接口和服务,方便切换CDN: 推流地址、拉流地址、转码规定、开播断流回调、一键断流、连接数查询、流截图、直播时长查询。基本上每个接口都很重要!例如一键断流万一失效,则可能面临停业整顿风险;人数不准,主播挂人气刷榜,则可能导致不公平竞争而影响平台的体验与口碑。

  • 分布式基本组件:复用Syslog-ng日志收集系统、Kafka消息队列QBus、MySQL主从库、Redis主从库、MongoDB、SSDB大容量存储。

  • 长连消息:单机百万长连,支持千万用户同时在线,性能够用,保证聊天弹幕稳定性。

  • 图床:很重要的一环,房间截图,用户头像。

  • CMS系统:配置各种推荐位,直播间的CDN调度。

➤主业务开发

虽然是个新项目,我们并未做一个一篮子应用,把所有接口放在一个项目,而是按功能模块分好项目,每人负责一个,对主站panda.tv项目提供内网API,部署方便互不影响,开发效率也比较高。

  • Flash播放器:ActionScript开发、视频播放、弹幕展现。

  • 主站pandaren:页面展现,各个子服务的串联整合;Daemon Worker负责截图更新。

  • 用户体系ruc:用户注册登录、用户信息。

  • 房间服务vill:包括房间信息、房间列表、更新房间人气。

  • 关系服务uprofile:包括订阅关系、观看历史、主播申请、内测邀请码 。

  • 数值服务count:竹子赠送、主播身高、用户经验。

  • 消息服务homer:用于房间划分,长连Session ID和熊猫TV房间用户ID的转换。

  • 权限系统buffon:房间管理、房管、黑名单。

  • 任务服务bee:新手任务、观看定时奖励。

  • 主播直播时长bloodstone:主播固定工资需要按每月直播时长计算。

➤架构哲学和设计

熊猫TV架构第一原则是高可用

  • 网络:需要应对国内复杂的网络环境,使用内网光纤互联的多IDC来覆盖多运营商。

  • 资源:DB和缓存都是集群化,配置Virtual IP方便切换。

  • 隔离性:不同业务不同机器,防止雪崩效应;核心和非核心业务隔离,流量扛不住情况保重点业务。

  • 降级:从Nginx和API层设置接口开关、Cache开关、DB开关,出问题一键切换。

  • 超时控制:主站每个依赖业务设置5秒超时,并有报警和错误日志。

  • 异步:用户不关心实时结果的大写入量业务使用异步方式更新,提高核心服务性能。

  • 监控:服务器错误设置log监控、接口监控报警,随时处理线上异常。

架构目标(SLA)

根据以往新项目经验,预估支撑1000TPS ,百万日活用户,单房间10万左右在线弹幕;平均响应时间在100ms,99.9%在1s内;千万级别数据量;99.9%的可用性(全年宕机在9小时以下)。

架构选型

四层负载均衡:LVS,目前基本是业界标配,如果使用云服务的话可以用厂商提供的负载均衡,如阿里云SLB和亚马逊ELB等,这种第三方依赖都需要严格引流压测确认DB层、缓存层、Web层是否有坑;

  • Web层:Nginx+PHP-FPM,开发迅速,适合团队技术现状,但需要针对服务器,做一定的调优配置。

  • 缓存层:Redis主从库、SSDB大容量存储,会在各个业务块儿使用,增加系统性能。

  • 存储层:MySQL主从库存储重要业务数据,属性变化不大。MongoDB数据库存储字段不固定变更较多的数值明细记录。SSDB存储观看记录关注等列表较长,且性能要求较高的数据。分表分库上考虑用户注册量和主播播放频率,用户中心、主播播放时长采用了按用户ID Sharding和 按年Sharding两种策略。业务初期暂时没有分库需求。

  • 消息队列:实现业务解耦,使用当前较流行的Kafka队列。

设计实现

机器配置采用6核16G的虚拟机。服务部署单独的XEN虚拟机集群,互不影响,进行多机房互备,机房间光纤专线内网互通。

图2 整体架构

120台虚拟机分给十多个业务,主站用了40+,三个IDC——电信联通移动同时使用,流量大的主机房在电信,其他两个机房部署Redis、MySQL从库,写都在电信。预估的注册在线人数百万级,QPS万级。接口使用PHP-FPM对外服务,单机性能平均500QPS+,内测邀请制,内测一个月期间十几万人涌入,解决了一些小Bug,然后大家颇有信心迎接公测。

熊猫架构1.0——一只穿云箭千军万马来相见

这个阶段属于填坑,最主要目标是网站稳定可用。虽然每个服务都有多机房灾备,微服务化也做了较好隔离,但0.1不到一个月便宣告夭折,我们低估了熊猫TV的明星效应,低估了黑色产业链的薅羊毛能力。公测一开始,熊猫就炸了(水友术语,指网站不可用)。

➤重点问题

  1. 网站首页和房间页不可用,无法进房间看视频;

  2. 已经在直播间的用户直播卡、弹幕卡、弹幕发不出去。

分析:网站因注册和用户信息、首页、房间页访问量过大导致FPM进程跑满,接口和模版渲染耦合,本身占的调用时长就会过多,服务间断性不可用,Redis缓存首页推荐位和用户信息只需几百MB,但连接数过多,内存占用到10G+,导致Redis响应缓慢不可用,垃圾号疯狂注册,第一天便破百万,用户中心出现服务异常,缓存命中率低,进而雪崩。

聊天弹幕爆发,时段非常集中,每日晚8点到凌晨2点为网站高峰时段,如图3所示。

图3 某个Redis端口QPS情况

这些也是直播网站会一直面临的核心稳定性问题,针对这些问题,大架构框架没有变动,加班加点,两周时间就上线了新一版架构优化。

➤高性能

主站重点接口Lua化:消息限制发送频率,并改造为Lua接口,十倍提速,避免占用主站PHP-FPM资源;赠送竹子也改造为Lua接口;用户中心取用户信息也改为Lua接口,直接从缓存读。

用户ID发号器改造,不依赖MySQL自增ID,提高并发性能。

➤高可用

首页和房间页静态化,Worker机抓取生成模版,分钟级别更新,然后rsync到各个服务器,Nginx直接读HTML文件生成首页、房间页,其他个人动态信息都走Ajax请求,保证不会出现白屏情况。

重点Redis增加到10+ Slave,Slave间树型同步,叶子节点从库从上级从库同步,避免一主多从传输数据延迟。从库的增加也避免主库网络负荷和连接数过多,导致响应延迟过大,服务不可用。

核心业务增加部署服务器,应对集中峰值访问。

➤其他问题解决和功能完善

安全性上:所有80接口做XSS校验,CSRF token防范,对接口做几十道安全检测,防止被拖库,防止Cookie被盗用;反垃圾反盗号反外挂:含敏感词聊天信息过滤,垃圾IP封禁;注册和任务都增加图片验证码,识别机器刷用户刷竹子;房间人气值采用复杂策略,用算法综合判断确认合理性,防刷防挂;主播审核更加严格,身份证银行卡姓名等信息都要求录入,可以追究责任到真人,甚至有视频验证,严防色情内容。

功能上:建立游戏娱乐户外等分类模块,运营自助增加分类;部署并自行运维第三方搜索服务,支持主播昵称、标题、房间号等维度搜索,过滤直播状态、主播地区、封禁状态等条件;礼物系统抽奖投票等系统上线,增加主播收益渠道,增加互动。

优化效果:全年未出现过白页、首页不可访问情况,支撑千万级PV,百万级日活,单房间最高达到百万级在线,视频流量近TB级;接口平均响应时间20ms左右,99.9%在1s内;各个系统数据存储量破千万,MongoDB、SSDB等大容量库很好地支持了业务。

熊猫架构 2.0 - 新视界,大不同

到2.0阶段,初期的刷脸靠战友帮搭建基础服务和买第三方服务,已不能精细化、定制化地支撑业务快速发展,而此时人员配置也开始完善,熊猫TV开始了全新的2.0自主研发阶段。

本阶段也属于稳步发展阶段, 最主要的目标是视频流畅清晰、弹幕互动效果稳定。

➤视频优化

接入决策上,接入更多家CDN,并对CDN稳定性做指标考核和严要求:根据卡顿率、延迟时间、首屏时间、声音视频同步率等指标,结合运营经验,创建了一套立体化多维度的CDN-SLA体系,决定给予流量多少,主播级别,主播数量。这样也增加CDN的危机感,更好服务用户。

视频流调度互备上,如图4所示。

图4 视频流调度互备上

主播推流区分默认配置和管理员配置,推向对他而言网络状况最好的CDN,CDN自身节点实现各地的复制,CDN之间实现推流互备,一个CDN挂掉,不影响使用,用户根据PC或手机端区分,从对应配置的CDN拉流看视频,从而实现最佳观看效果,Web端用户也可切换备用线路,当默认CDN出现问题,则选择从其他家CDN进行拉流。

这样就保证观看的流畅和视频的整体高可用。

➤全新开发长连接系统riven来提供弹幕服务

图5 riven 整体流程

建立连接:

  • 通过房间ID获取网关IP;

  • 根据网关IP建立长连接;

  • 更新网关上房间ID和长连接的对应关系。

下发消息:

  • 同步消息;

  • 生成消息机房对其他机房进行同步;

  • 同步消息的机房不在进行同步行为;

  • 根据房间ID获取房间所在的网关地址列表;

  • 向网关列表下发消息投递通知;

  • 网关查询本地房间对应的所有连接,并进行消息投递。

使用Golang+Redis全新开发,对消息级别、消息发送和消息内容做了一定优化。级别上区分多种Level消息,在高峰期、网卡被打满极端情况下,丢掉部分不重要消息;消息发送进行打包方式发送,一个房间的消息一次批量推送几十条,减少TCP交互;消息内容去掉无用字段,减少长度,例如礼物消息一条减少了168字节,假设高峰期一个房间十万人在线,一条礼物消息能节16MB,大主播房间按1000个礼物一小时算,能节省16GB流量,非常可观,所以一定要注意消息内容的压缩和缩减。

整体架构上的改变:一年以来用户量爆炸式增长,达到日活用户近千万,PV上亿,同时直播主播近万间,流量峰值TB级别。技术人员也扩充了4倍,随着王校长驱动开发、尹素婉驱动开发(尹素婉是韩国第一女主播)、PDD驱动开发(PDD是前职业选手,著名LOL主播,弹幕量大,观众百万)等模式的驱动开发,熊猫快速步入2.0时代,技术架构也有了更稳固的改进,新的PHS(Panda High-Perfomace Service熊猫高性能服务体系)设计思路是增加架构层次,明确微服务边界,基础组件从外部依赖到内部自研,架构层次宏观层面分为端、接入层、平台服务化、中间层、基础层五个层次。

图6 架构层次

包括Web页、iOS、Android、各种Pad端、网吧弹窗合作、电视盒子合作App、游戏主机合作App,从各个渠道扩展业务。

  • 接入层

从大而统一的panda.tv分流出mall.panda.tv、roll.panda.tv、pay.panda.tv、open.panda.tv等,保证各个接入业务互相隔离。接入层stars.panda.tv、pandagirls.panda.tv尝试使用NodeJS提供API,前端完全自行研发,提高效率,性能也比使用我们的Pylon-PHP框架提高了6倍左右,可以满足当前流量请求。

  • 平台服务化

架构体系没有太大的变动,主要采用Golang技术栈做了整体升级。流量突发时PHP-FPM子进程新增缓慢,多进程模型切换代价较大,不能较好服务高峰请求,缓存和DB连接池复用困难,我们重点业务从PHP迁移到Golang;部署上,依赖Nginx+LVS探活实现不停机热部署;Gobase基础库,实现了一套特定业务场景Concurrent Map库;实现了配置读取模块;对MongoDB Client进行了封装,便于CRUD方式使用和对象映射;Redis连接池和CRUD操作封装,业务不需要协议命令细节,而是正常Get(key)、Set(key)即可;数据访问层结合配置服务封装分片与路由来支撑容量水平扩展;封装Log、HTTP请求和HTTP Param解析等基础类。

通过对Golang半年的使用,我们建立了自己的一套技术开发体系:Gvt创建项目和管理依赖,Ansible管理服务器和分发部署,Postman进行文档编排和代码测试, Teamcity实现持续集成。

业务上,CDN调度项目TrafficCoop,高性能,灵活配置Web端和移动端CDN信息;API-Proxy项目 ,原生Golang Router,使用OAuth 2.0,提供对外网关,中转内部服务;礼物系统全面使用Golang+Redis+MongoDB保证稳定性和高峰处理。新业务原则需要快速开发,性能要求较低的业务使用PHP,性能要求高的业务用Golang、NodeJS。

用户中心则持续演进:支持FaceBook等账号接入;电话语音验证码防外挂,异地IP重新登录机制防盗,个人身份指纹识别,做到彻底防盗号。另外为提高接口安全性,解决DNS劫持等问题对服务HTTPS化,各业务根据需要跟Ops申请HTTPS证书或SAN(多域名)证书。

  • 中间层改进

视频效果优化:接入更多CDN厂商,进行评测对比,及时反馈问题,督促其合理设置缓存值,实现视频播放流畅化。

Flash调整弹幕展现策略:实现既能有满屏感,又不会因同屏弹幕过多卡住浏览器,达到观看和互动的平衡。

文本反作弊:机器学习训练房间弹幕内容,模型上对广告、色情、敏感词、黑白名单等进行打分评定。

增加图片墙鉴黄服务:30秒刷新房间截图,接入多家鉴黄API,合理评分,快速发现直播内容异常。

图床自建:图片存储从Cassandra迁移到公有云对象存储,节省运维成本,直接使用第三方CDN,加速图片访问。

  • 基础层

Kafka队列自建:基础组专人开发维护,更快更好解决问题;竹子经验计数、用户关系等从SSDB迁移到Redis Cluster,保证性能无瓶颈,数据量暴增无压力。

Spark Streaming平台搭建:弹幕内容分析与舆情,CDN质量实时监控,用户行为实时感知。

另外一个比较大的架构变动是业务机房迁移。实现了DB迁移,公有云互备。二十多人演练数十次,按照两页的迁移清单,所有业务重新部署,DB重新导入,停机维护一整夜,所有服务从原有机房一次性成功迁移到两个公有云上。

总结

熊猫TV架构改进思路是应对峰值流量高度集中的直播需求,总结几条经验:

  • 不能依赖单个CDN。可自建,可用第三方,但中国网络环境太复杂,必须高度重视容灾。海外推拉流也需要十分关注。

  • 弹幕消息一定要做策略优化。广播蝴蝶效应明显,峰值可能将机房整体带宽打满。区分弹幕优先级,做好降级预案。

  • 提高金钱敏感度。直播网站由于有很清晰的变现模式,要严防褥羊毛,严防色情内容,火速响应监管,支付礼物交互一定是高可用、严监控。

  • N个大主播 = 半个网站峰值。必须考虑某些特殊主播的火爆人气,做好视频弹幕房间信息上的峰值应对。

熊猫TV因快速上线和爆炸式增长,从严重依赖外部服务,到自主自建核心业务,弯路走了不少,也对直播技术有了更深的理解,积累了丰富的经验,技术团队也从20人左右快速扩展到百人团队,为熊猫TV在百家直播平台中挺立飞奔奠定了技术基础。未来我们会在以下方面继续努力:

  • 自助式运营处理:帮助运营自助处理问题,直接和CDN对接,帮助技术人员从简单重复问题处理中脱身。

  • 反作弊:基于大数据处理体系的用户画像、设备画像、IP画像、内容画像,多维度构建反垃圾反盗号功能 。

  • 长连优化:支撑千万用户在线的高并发实时弹幕和聊天。

  • 礼物商城:优化计数对账,幂等处理整个支付到特效抽奖、弹幕消息、消费记录、统计等流程。

  • Golang、NodeJS服务化:替代性能较差需要各种优化的PHP,服务端接口全面Golang化,前端也在合适的场景使用NodeJS提高服务性能。此外需针对KV存储做value压缩,节省流量,提高接口速度。

  • 数据挖掘和机器学习:渠道分析、用户分析等便于产品和高层决策,甚至开发出机器人主播互动。

  • 推荐:在综艺化娱乐化多元化的内容基础上,个性化推荐用户感兴趣的直播内容。

  • 搜索:自建搜索,从用户维度、聊天维度更好服务用户。

  • 日志收集分析:高性能日志方案探索,更快更迅速发现业务问题,分析流量变化。

  • 广告系统:友好娱乐化的广告展现,精准推送,严禁的计费系统。

  • 支付:国际化支持,多种银行卡信用卡接入,多种货币支持。

  • NewSQL:引入TiDB等新SQL技术到某些业务,替换Redis、MongoDB、MySQL,更方便友好地进行技术开发。

直播面临的核心问题是网站稳定可用、视频流畅清晰、弹幕互动效果稳定。直播技术看似简单,一家视频云可以帮助创业公司一两个月就构建出一个直播App,但其中的运营难点、技术难点、流量带宽问题都需要谨慎处理,希望本文能帮助直播行业技术人员跳过一些坑,架构设计时作为技术参考。

作者简介:沈冠璞,熊猫TV高级应用开发工程师,近7年后端开发经验,曾任职新浪微博、360等互联网公司,负责短链接、微博Card对象、网游页游平台业务。对高并发海量数据业务设计有丰富经验;经历熊猫TV从0到1 海量PV和存储的快速扩张发展场景,有大中型互联网网站高可用设计架构经验。在MDCC 2016上,沈冠璞将结合自身经验,解析在热门时段大主播高峰值情景下优化礼物系统技巧,带来题为《百万弹幕下的直播礼物系统》的分享。

最新文章

  1. ue4 ios
  2. Linux/Unix双机建立信任教程
  3. Android开发常见问题
  4. svn的管理与维护要点—纯手工编写
  5. [IOS UIScrollView+PageControl]信息展示横幅
  6. Replace Nested Conditional with Guard Clauses(用卫语句代替嵌套循环)
  7. Vue.js学习 Item1 --快速入门
  8. 状压DP
  9. centos7 install mysql
  10. java基础 二分查找算法
  11. Activity组件的生命周期
  12. Hadoop1.0.4伪分布式安装
  13. OpenCV FileStorage 使用记录
  14. NGUI实现一个背包功能
  15. Eclipse中配置weka,以及添加算法
  16. 函数响应式编程及ReactiveObjC学习笔记 (四)
  17. SpringMVC之HandlerMapping的使用
  18. CCT之CAMERA TUNNING调试学习总结
  19. NTP服务和DNS服务(week3_day3)--技术流ken
  20. SQL两个事务update同一张表出现的死锁问题(waitfor delay)

热门文章

  1. XML的一些点
  2. 关于用phonegap 3.0+ 打包后sencha touch按钮点击切换动画延迟接近一秒的以及界面闪烁的解决方案
  3. java中生成流水号的一个例子(使用BerkeleyDB)
  4. 2-sat(tarjan算法)hdu(1824)
  5. Oracle数据类型clob和blob
  6. MySQL Bugs: #34354: Feature request: EXPLAIN ALTER TABLE https://bugs.mysql.com/bug.php?id=34354
  7. apt-get install 和 pip install的区别
  8. day18(JDBC事务&连接池介绍&DBUtils工具介绍&BaseServlet作用)
  9. mysql 数据操作 单表查询 where约束 工作模式
  10. MySql创建函数与过程,触发器, shell脚本与sql的相互调用。