PHP 百分网手机站

如何使用PHP构建一个高性能的弹幕后端服务

时间:2018-04-21 16:51:08 PHP 我要投稿

如何使用PHP构建一个高性能的弹幕后端服务

  现在很多网站都流行使用“弹幕”这种形式来实现互动。看到现在各种网站都有酷炫的弹幕飞过,我们是不是也想给自己的网站加入弹幕功能呢?如何使用PHP构建一个高性能的弹幕后端服务呢?下面小编为大家解答一下,希望能帮到您!

  首先弹幕的后端其实说白了和公共聊天室的后端原理十分相似,都是一个客户端发送消息给服务端,服务端再将收到的消息广播给其他的客户端。对于后端来说他们几乎没区别,区别就在于前端。

  好在我们有一个前端弹幕插件,这个插件是一个jquery插件,github地址:https://github.com/chiruom/jquery.danmu.js,基本上会使用jquery语法,看看示例代码就可以傻瓜化使用。

  前端已经有了解决方案,但是后端呢?前端如何与后端通讯?用传统的ajax轮询吗?不行,这样效率太低,想想各大火爆的直播平台都是同一时间几万人在线,几千人同时发弹幕,如果靠ajax轮询一个php接口的话服务器会吃不消的。且弹幕消息存储方案略显复杂,有人问为什么要存储呢?因为ajax使用的HTTP协议是无状态协议,A客户端和B客户端之间对于服务器来说没有任何标志,如果服务器要确保A客户端和B客户端分别在两次请求的时候服务器只返回这两个客户端没有获取过的弹幕消息,那么服务器端就必须使用一个缓存来标识某某客户端看过哪条弹幕消息。综上所述ajax可以实现小规模的弹幕通信方案,但是很麻烦。

  好在最新的HTML5中加入了WebSocket协议,我们可以通过WebSocket这种基于HTTP协议之上的即时通信协议来替代ajax这种传统的我问你答的老旧通信模式。而我们是PHPer,对于我们这种只懂PHP的人该如何编写WebSocket服务端呢?好在我们又得知PHP有一个Swoole扩展,我们在PHP语言中使用它可以很方便的构建一个WebSocket服务端。

  关于Swoole的介绍可以参照他的官网http://www.swoole.com/,下面引用官网对它的一段简短的介绍。

  PHP的异步、并行、高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。 Swoole内置了Http/WebSocket服务器端/客户端、Http2.0服务器端。

  Swoole可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。 使用PHP+Swoole作为网络通信框架,可以使企业IT研发团队的效率大大提升,更加专注于开发创新产品。

  先别被Swoole这么多的功能吓到了。我们先关注这里面的重点

  Swoole内置了Http/WebSocket服务器端/客户端

  意味着我们可以通过它构建WebSocket的服务端。看到这里我们是不是就急急忙忙去拿官网的WebSocket服务端代码做测试呢?不,Swoole是一个PHP扩展,意味着我们还得去安装它。是不是直接去下载so文件然后在php.ini中加入extension=swoole.so就可以了呢?还不是,我们先去看看Swoole扩展的依赖,这也是我们使用任何语言的任何外部包,外部模块,外部扩展最先要了解的问题。

  参考官网:http://wiki.swoole.com/wiki/page/7.html

  环境依赖

  仅支持Linux,FreeBSD,MacOS,3类操作系统

  Linux内核版本2.3.32以上

  PHP5.3.10以上版本,包括PHP7

  gcc4.4以上版本或者clang

  cmake2.4+,编译为libswoole.so作为C/C++库时需要使用cmake

  PHP版本依赖

  swoole仅支持PHP5.3.10或更高版本,建议使用PHP5.4+

  swoole不依赖php的stream、sockets、pcntl、posix、sysvmsg等扩展。PHP只需安装最基本的扩展即可

  意味着我们Windows下是无法使用这个扩展了(其实可以借助cygwin在win下使用swoole,但是考虑到我们使用swoole扩展就是为了性能,也为了熟悉以后的生产环节部署做准备,强烈推荐在linux下开发),那么我们把开发环境转移到Linux下进行吧。

  接着还要求Linux内核版本为2.3.32以上,PHP为5.3.10以上,那么我们就用最新的CentOS吧,这个版本的yum安装的php直接就是PHP7最新版,根本无需考虑其他问题,当然你喜欢图形界面,用Ubuntu也可以。其他的基本上最新的Linux发行版都是符合版本要求的。

  接着我们便来安装这个扩展,推荐使用PECL来安装,只需要一条

  pecl install swoole

  即可,非常方便。当然你要编译安装,具体步骤请参考http://wiki.swoole.com/wiki/page/6.html

  安装完扩展之后在命令行下输入

  php -m

  检查,如果有swoole那么说明安装成功了。

  接下来就正式开始我们的编码旅程了。

  开始编码旅程之前我们先看看最基础的效果原型是什么样子

  没错就是这个样子,两个浏览器之前完全独立使用Websocket连接服务端,因此对于服务端来说这两个浏览器就相当于两个完全处在不同机器上的客户端。

  效果看完了就开始来讲代码吧。

  我们先看看官网的WebSocket服务端示例代码。

  $serv = new SwooleWebsocketServer("127.0.0.1", 9502);

  $serv->on('Open', function($server, $req) {

  echo "connection open: ".$req->fd;

  });

  $serv->on('Message', function($server, $frame) {

  echo "message: ".$frame->data;

  $server->push($frame->fd, json_encode(["hello", "world"]));

  });

  $serv->on('Close', function($server, $fd) {

  echo "connection close: ".$fd;

  });

  $serv->start();

  我们看到这个代码的第一行先是new了一个WebSocket服务端对象,并且在构造方法中的第一个参数指定了服务端监听的IP,第二个参数指定了服务端监听的端口。然后使用on方法为每一个事件设置了回调函数,最后一行start方法正式开始运行服务端。

  这种写法非常像Javascript里面的异步调用,这也是Swoole中的事件驱动异步非阻塞特性,正因为是这种特性,每一个独立的事件(请求)会在服务端接收到之后分别异步处理,他们之间无需互相等待,这也是Swoole性能高的原因所在。