前段时间赶项目,忙结婚,各大技术平台都没时间上,不过还是抽出点时间为自己的婚礼做了一点小玩具,今天我就来给大家分享一下。

  先来看一下效果

这个项目是基于微信个人订阅号的,订阅号的开发在此我就不再赘述了。

基本开发思路是,服务器接收到用户文本信息,用正则匹配一下然后去掉前面的cg#(这一步其实可有可无,不过为了区分其他的指令而加上),然后存进服务器。本地用浏览器跑一个轮播图,然后拿到弹幕信息就可以在浏览器播放了。

   这里有2个关键点:

  1、本地如何拿到弹幕信息?两台物理机器如何实时获取信息?这里的信息延迟我要求不能超过1s。这里我找到有两个方案,A 本地设置定时器直接请求远程服务器拉取弹幕信息。B 本地与远程服务器建立一个socket长连接,服务器主动写数据。

  2、这个场景交互比较频繁,IO相对比较密集(婚礼上并发可能会高达100+),存数据库的话压力会比较大,如果挂掉了本少爷的脸也挂不住了-_-||

  好,接着来一个一个的解决,先从技术选型开始。

  1、如果数据库扛不住,那么我不存数据库,直接存缓存行得通吗?弹幕信息带有时序性的属性,redis自带队列数据结构,这很适合,redis对外宣称的并发数为3-5w,刚好之前被推荐买了一本redis实战,也看完了,就用来实践一下。服务器拿到弹幕信息后存进队列

         /**
* [saveInfo description]
* @param object $postObj 微信XML实体
* @return [type] [description]
*/
private function saveInfo($postObj) {
// 数据处理
$openid = $postObj->FromUserName;
$content = preg_replace("/^(cg#){1}/i", "", $postObj->Content); // 准备存入队列的json数据
$value = array(
"openid" => $openid,
"content" => $content,
"time" => strval(microtime())
);
$json = json_encode($value); // 把用户的弹幕内容存进队列中
$result = $this->lpush(BARRAGE_KEY, $json); return $result?$json:false;
}

  (原本已经调了用户接口,打算搞抽奖的,但我没有搞企业服务号,所以后面就去掉了这一部分了,就是用fromUser这个openID去获取用户nickname,headurl等信息)

  2、好了,存好的弹幕信息,就差本地去拿了,获取弹幕信息的方式影响到整个程序能否成功运行,这里我想到的两个方案不知孰优孰劣,唯有一试。

  首先尝试定时获取,写一个js定时器去请求远程服务器,进而拉取弹幕信息。方法甫一运行,本地就卡的不要不要的,轮播图也变成了幻灯片,毋论接收弹幕了。另外,这里还会有浏览器跨域的问题存在。

  然后,查资料得知,redis本身是依赖于socket运行的,还有自带现成发布订阅功能(publish和subscribe),跟我的需求完美契合。所以我重点写好建立连接和接收数据的回调就好了。

  

  建立连接的代码(这个我为了方便,是用php指令来运行脚本的):

         /**
* [pullBarrages 拉取腾讯云中最新的弹幕]
*/
public function pullBarrages() {
try {
set_time_limit(0);
ini_set("default_socket_timeout", -1);
ignore_user_abort(TRUE);
// 首先同步一次弹幕
$this->synchronizeBarrages();
// 订阅新的弹幕频道并保存
$this->subscribe(array(BARRAGE_CHANNEL), array($this, "saveBarrage"));
} catch (Exception $e) {
// 连接超时出现异常时重新建立长连接
$host = "IP";
$port = ;
$this->redis = new RedisCache();
$this->redis->connect($host, $port);
// 检查同步远程主机的弹幕同步情况
$this->synchronizeBarrages();
// 重新调用长连接订阅方法
$this->pullBarrages();
}
}

  这里我写了一段监听异常的代码,因为连接之后过了大概60秒就自动断开,所以我捕捉到异常就重新建立连接并且确认是否有没有拉取到的弹幕信息。不清楚是PHP对socket的支持不太好还是我的PHP环境的原因(我的PHP用的是集成环境),这里我没有太多时间去深究,如果有知道的大牛请告诉我,谢谢~

  接收到数据之后的回调函数:

         /**
* [saveBarrages description]
* @param object $redis redis对象
* @param string $channel 订阅的频道
* @param string $barrage 频道订阅返回的弹幕信息
* @return Boolean 存储结果
*/
public function saveBarrage($redis, $channel, $barrage) {
$localRedis = new RedisCache();
$localRedis->connect("127.0.0.1", 6379); $result = $localRedis->lpush(BARRAGE_KEY, $barrage);
if ($result) {
echo "barrage save success!" . PHP_EOL;
}else {
echo "barrage save fail!" . PHP_EOL;
}
echo date("Y-m-d H:i:s") . PHP_EOL;
}

  本地拿到了服务器的弹幕信息,剩下的就随便怎么玩都可以了,拿到弹幕信息大概是秒达的感觉。前端浏览器现在也是有websocket,但是我不会用,所以选择了在浏览器设置一个定时器去请求本地环境的弹幕数据,间隔自己定就可以了(关于前端的东西不细讲,后端做前端的诀窍就是找插件,哈哈)。

  还有一点,就是我为了方便写代码,把redis对象省略了,用到了__call方法来调用,这个在我之前的博客中提到过。

  断断续续的完成这篇博客,以上写的可能有点乱,抱歉。这次就分享这么多,下次有其他东西再来分享~~

  

  2017.12.04编辑:

  关于链接被断开,通过捕捉异常来重新连接redis的部分找到了比较好的解决办法了,自动断开连接是因为redis的subscribe方默认在60s内没有接收到信息的话,就会自动断开,只需要添加一行代码:

$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);

  让redis不超时就可以了。

利用redis自制幻灯片弹幕的更多相关文章

  1. 利用Redis解决Url过长的问题

    做网站,接手别人的代码,发现url有时候会过长导致页面直接翻掉. 后来想了一下可以利用redis将太长的地方暂存,加载页面时获取即可. 存Redis: /// <summary> /// ...

  2. 利用Redis cache优化app查询速度实践

    注意:本篇文章译自speeding up existing app with a redis cache,如需要转载请注明出处. 发现问题 在应用解决方法之前,我们需要对我们面对的问题有一个清晰的认识 ...

  3. [翻译]利用REDIS来搭建可靠分布式锁的提议

    本系列都是翻译REDIS作者的博文  另外加上我自己的一点点理解  希望有问题大家一起讨论 http://antirez.com/news/77 原文地址 在利用REDIS做分布式锁时基本持有2种观点 ...

  4. 利用redis写webshell

    redis和mongodb我之所见 最近自己在做一些个人的小创作.小项目,其中用到了mongodb和redis,最初可能对这二者没有深入的认识.都是所谓的“非关系型数据库”,有什么区别么? 实际上,在 ...

  5. 如何利用redis来进行分布式集群系统的限流设计

    在很多高并发请求的情况下,我们经常需要对系统进行限流,而且需要对应用集群进行全局的限流,那么我们如何类实现呢. 我们可以利用redis的缓存来进行实现,并且结合mysql数据库一起,先来看一个流程图. ...

  6. 利用redis实现分布式锁知识点总结及相关改进

    利用redis实现分布式锁知识点总结及相关改进 先上原文,本文只为总结及对相关内容的质疑并提出若干意见,原文内容更详细https://www.cnblogs.com/linjiqin/p/800383 ...

  7. 利用redis实现分布式锁

    分布式锁一般有三种实现方式: 1. 数据库乐观锁: 2. 基于ZooKeeper的分布式锁: 3. 基于Redis的分布式锁: 这里大概说一下三种方式的优缺点,数据库乐观锁优点是实现简单,只需要for ...

  8. 利用Redis发布订阅完成tomcat集群下的消息通知

    以下为个人想法,如果有说的不对的地方请各位大佬见谅! 这是博主的第一篇博客,可能排版以及一些描述有不合理的地方还请勿喷,希望大家尽可能的多给我这样的新人一些鼓励让我能在写博客的道路上走下去. 进入正题 ...

  9. Watchdogs利用Redis实施大规模挖矿,常见数据库蠕虫如何破?

    背景 2月20日17时许,阿里云安全监测到一起大规模挖矿事件,判断为Watchdogs蠕虫导致,并在第一时间进行了应急处置. 该蠕虫短时间内即造成大量Linux主机沦陷,一方面是利用Redis未授权访 ...

随机推荐

  1. Spring mvc,uploadifive 文件上传实践(转自:https://segmentfault.com/a/1190000004503262)

     1.前台页面: 引入js和css 全选复制放进笔记 <link type="text/css" rel="stylesheet" href=&quo ...

  2. ROS(indigo)_pr2_simulator仿真(gazebo)示例

    ROS(indigo)_pr2_simulator仿真(gazebo)示例 1 开启pr2仿真 ~$ roslaunch gazebo_ros empty_world.launch ~$ roslau ...

  3. 【shell脚本练习】grep sed awk

    下面是简单学习之后做得练习题,如果有不对的或者说解题思路不好的,请交流啊. Grep 练习 文件名grepfile Steve Blenheim:238-923-7366:95 Latham Lane ...

  4. Leetcode_6_ZigZag Conversion

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41408021 看完这篇文章,你可能会学到到知识如下: (1 ...

  5. GDB 资料汇总

    很全的关于 GDB 调试的指导: GDB中应该知道的几个调试方法 用 GDB 调试程序 100个gdb调试小技巧 CGDB中文手册 Beej's Quick Guide to GDB

  6. libgdx 1.4.1发布

    (转载自http://www.libgdx.cn/topic/4/libgdx-1-4-1%E5%8F%91%E5%B8%83) libgdx从未停止进步的脚步.10月10日,libgdx1.4.1发 ...

  7. ffdshow 源代码分析 9: 编解码器有关类的总结

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  8. SpriteBuilder中音频文件格式的需要注意的地方

    就像在SpriteBuilder项目子目录中的其他资源文件一样,音频文件夹需要确定完整的文件夹路径. 并且如果音频文件输出格式为MP4,则扩展为.m4a(audio-only MPEG4)而不是.mp ...

  9. SpriteBuilder中的碰撞分类(Categories)和掩码(Masks)

    假如有2种对象player和触发器(trigger),当玩家进入到触发器区域时则由触发器对象通知所有注册过触发器通知的对象,然后由这些对象自行选择做一些事情,比如:阻碍player的前景,触发陷阱等等 ...

  10. Android实训案例(七)——四大组件之一Service初步了解,实现通话录音功能,抽调接口

    Service Service的神奇之处,在于他不需要界面,一切的操作都在后台操作,所以很多全局性(手机助手,语音助手)之类的应用很长需要这个,我们今天也来玩玩 我们新建一个工程--ServiceDe ...