一级日韩免费大片,亚洲一区二区三区高清,性欧美乱妇高清come,久久婷婷国产麻豆91天堂,亚洲av无码a片在线观看

如何使用PHP構建一個(gè)高性能的彈幕后端服務(wù)

時(shí)間:2024-08-31 13:41:48 PHP 我要投稿
  • 相關(guān)推薦

如何使用PHP構建一個(gè)高性能的彈幕后端服務(wù)

  現在很多網(wǎng)站都流行使用“彈幕”這種形式來(lái)實(shí)現互動(dòng)?吹浆F在各種網(wǎng)站都有酷炫的彈幕飛過(guò),我們是不是也想給自己的網(wǎng)站加入彈幕功能呢?如何使用PHP構建一個(gè)高性能的彈幕后端服務(wù)呢?下面小編為大家解答一下,希望能幫到您!

  首先彈幕的后端其實(shí)說(shuō)白了和公共聊天室的后端原理十分相似,都是一個(gè)客戶(hù)端發(fā)送消息給服務(wù)端,服務(wù)端再將收到的消息廣播給其他的客戶(hù)端。對于后端來(lái)說(shuō)他們幾乎沒(méi)區別,區別就在于前端。

  好在我們有一個(gè)前端彈幕插件,這個(gè)插件是一個(gè)jquery插件,github地址:https://github.com/chiruom/jquery.danmu.js,基本上會(huì )使用jquery語(yǔ)法,看看示例代碼就可以傻瓜化使用。

  前端已經(jīng)有了解決方案,但是后端呢?前端如何與后端通訊?用傳統的ajax輪詢(xún)嗎?不行,這樣效率太低,想想各大火爆的直播平臺都是同一時(shí)間幾萬(wàn)人在線(xiàn),幾千人同時(shí)發(fā)彈幕,如果靠ajax輪詢(xún)一個(gè)php接口的話(huà)服務(wù)器會(huì )吃不消的。且彈幕消息存儲方案略顯復雜,有人問(wèn)為什么要存儲呢?因為ajax使用的HTTP協(xié)議是無(wú)狀態(tài)協(xié)議,A客戶(hù)端和B客戶(hù)端之間對于服務(wù)器來(lái)說(shuō)沒(méi)有任何標志,如果服務(wù)器要確保A客戶(hù)端和B客戶(hù)端分別在兩次請求的時(shí)候服務(wù)器只返回這兩個(gè)客戶(hù)端沒(méi)有獲取過(guò)的彈幕消息,那么服務(wù)器端就必須使用一個(gè)緩存來(lái)標識某某客戶(hù)端看過(guò)哪條彈幕消息。綜上所述ajax可以實(shí)現小規模的彈幕通信方案,但是很麻煩。

  好在最新的HTML5中加入了WebSocket協(xié)議,我們可以通過(guò)WebSocket這種基于HTTP協(xié)議之上的即時(shí)通信協(xié)議來(lái)替代ajax這種傳統的我問(wèn)你答的老舊通信模式。而我們是PHPer,對于我們這種只懂PHP的人該如何編寫(xiě)WebSocket服務(wù)端呢?好在我們又得知PHP有一個(gè)Swoole擴展,我們在PHP語(yǔ)言中使用它可以很方便的構建一個(gè)WebSocket服務(wù)端。

  關(guān)于Swoole的介紹可以參照他的官網(wǎng)http://www.swoole.com/,下面引用官網(wǎng)對它的一段簡(jiǎn)短的介紹。

  PHP的異步、并行、高性能網(wǎng)絡(luò )通信引擎,使用純C語(yǔ)言編寫(xiě),提供了PHP語(yǔ)言的異步多線(xiàn)程服務(wù)器,異步TCP/UDP網(wǎng)絡(luò )客戶(hù)端,異步MySQL,異步Redis,數據庫連接池,AsyncTask,消息隊列,毫秒定時(shí)器,異步文件讀寫(xiě),異步DNS查詢(xún)。 Swoole內置了Http/WebSocket服務(wù)器端/客戶(hù)端、Http2.0服務(wù)器端。

  Swoole可以廣泛應用于互聯(lián)網(wǎng)、移動(dòng)通信、企業(yè)軟件、云計算、網(wǎng)絡(luò )游戲、物聯(lián)網(wǎng)(IOT)、車(chē)聯(lián)網(wǎng)、智能家居等領(lǐng)域。 使用PHP+Swoole作為網(wǎng)絡(luò )通信框架,可以使企業(yè)IT研發(fā)團隊的效率大大提升,更加專(zhuān)注于開(kāi)發(fā)創(chuàng )新產(chǎn)品。

  先別被Swoole這么多的功能?chē)樀搅。我們先關(guān)注這里面的重點(diǎn)

  Swoole內置了Http/WebSocket服務(wù)器端/客戶(hù)端

  意味著(zhù)我們可以通過(guò)它構建WebSocket的服務(wù)端?吹竭@里我們是不是就急急忙忙去拿官網(wǎng)的WebSocket服務(wù)端代碼做測試呢?不,Swoole是一個(gè)PHP擴展,意味著(zhù)我們還得去安裝它。是不是直接去下載so文件然后在php.ini中加入extension=swoole.so就可以了呢?還不是,我們先去看看Swoole擴展的依賴(lài),這也是我們使用任何語(yǔ)言的任何外部包,外部模塊,外部擴展最先要了解的問(wèn)題。

  參考官網(wǎng):http://wiki.swoole.com/wiki/page/7.html

  環(huán)境依賴(lài)

  僅支持Linux,FreeBSD,MacOS,3類(lèi)操作系統

  Linux內核版本2.3.32以上

  PHP5.3.10以上版本,包括PHP7

  gcc4.4以上版本或者clang

  cmake2.4+,編譯為libswoole.so作為C/C++庫時(shí)需要使用cmake

  PHP版本依賴(lài)

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

  swoole不依賴(lài)php的stream、sockets、pcntl、posix、sysvmsg等擴展。PHP只需安裝最基本的擴展即可

  意味著(zhù)我們Windows下是無(wú)法使用這個(gè)擴展了(其實(shí)可以借助cygwin在win下使用swoole,但是考慮到我們使用swoole擴展就是為了性能,也為了熟悉以后的生產(chǎn)環(huán)節部署做準備,強烈推薦在linux下開(kāi)發(fā)),那么我們把開(kāi)發(fā)環(huán)境轉移到Linux下進(jìn)行吧。

  接著(zhù)還要求Linux內核版本為2.3.32以上,PHP為5.3.10以上,那么我們就用最新的CentOS吧,這個(gè)版本的yum安裝的php直接就是PHP7最新版,根本無(wú)需考慮其他問(wèn)題,當然你喜歡圖形界面,用Ubuntu也可以。其他的基本上最新的Linux發(fā)行版都是符合版本要求的。

  接著(zhù)我們便來(lái)安裝這個(gè)擴展,推薦使用PECL來(lái)安裝,只需要一條

  pecl install swoole

  即可,非常方便。當然你要編譯安裝,具體步驟請參考http://wiki.swoole.com/wiki/page/6.html

  安裝完擴展之后在命令行下輸入

  php -m

  檢查,如果有swoole那么說(shuō)明安裝成功了。

  接下來(lái)就正式開(kāi)始我們的編碼旅程了。

  開(kāi)始編碼旅程之前我們先看看最基礎的效果原型是什么樣子

  沒(méi)錯就是這個(gè)樣子,兩個(gè)瀏覽器之前完全獨立使用Websocket連接服務(wù)端,因此對于服務(wù)端來(lái)說(shuō)這兩個(gè)瀏覽器就相當于兩個(gè)完全處在不同機器上的客戶(hù)端。

  效果看完了就開(kāi)始來(lái)講代碼吧。

  我們先看看官網(wǎng)的WebSocket服務(wù)端示例代碼。

  $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();

  我們看到這個(gè)代碼的第一行先是new了一個(gè)WebSocket服務(wù)端對象,并且在構造方法中的第一個(gè)參數指定了服務(wù)端監聽(tīng)的IP,第二個(gè)參數指定了服務(wù)端監聽(tīng)的端口。然后使用on方法為每一個(gè)事件設置了回調函數,最后一行start方法正式開(kāi)始運行服務(wù)端。

  這種寫(xiě)法非常像Javascript里面的異步調用,這也是Swoole中的事件驅動(dòng)異步非阻塞特性,正因為是這種特性,每一個(gè)獨立的事件(請求)會(huì )在服務(wù)端接收到之后分別異步處理,他們之間無(wú)需互相等待,這也是Swoole性能高的原因所在。

  我們來(lái)分別剖析一下每一個(gè)事件的含義。

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

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

  });

  顧名思義,Open表示打開(kāi)一個(gè)新的鏈接,并且在事件觸發(fā)之后echo出連接上服務(wù)端的客戶(hù)端id,該客戶(hù)端唯一id為回調函數第二個(gè)參數中的fd字段。這也是服務(wù)端區分客戶(hù)端的唯一id。

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

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

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

  });

  同樣顧名思義,Message表示消息到達服務(wù)端的事件,并且在事件觸發(fā)之后echo出發(fā)送給服務(wù)端的數據,該數據為回調函數第二個(gè)參數的data字段。另外我們還看到它調用了$server->push,這是回調函數的第一個(gè)參數中的push方法,它是一個(gè)服務(wù)端給客戶(hù)的發(fā)送數據的方法,第一個(gè)參數為要發(fā)送的客戶(hù)端id,第二個(gè)為要發(fā)送的數據,這里的含義是向發(fā)給服務(wù)端消息的那個(gè)客戶(hù)端發(fā)送["hello", "world"]這個(gè)數組(方括號寫(xiě)數組為PHP5.4的新特性,如果你是PHP5.3請使用傳統的array工廠(chǎng)函數生成數組)經(jīng)過(guò)json序列化之后的數據。

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

  echo "connection close: ".$fd;

  });

  最后一個(gè)事件Close更加容易理解,就是關(guān)閉事件,當然關(guān)閉的不是服務(wù)端,而是客戶(hù)端,可以理解為客戶(hù)端與服務(wù)端斷開(kāi)連接的事件;卣{函數中的代碼含義為echo出與服務(wù)端斷開(kāi)連接的那個(gè)客戶(hù)端id。

  基本的API都清楚了,下面就直接看代碼吧,短短二十行而已。

  https://github.com/cw1997/danmu-demo/blob/master/server.php

  $server = new swoole_websocket_server("0.0.0.0", 1997);

  $server->on('open', function (swoole_websocket_server $server, $request) {

  echo "server: handshake success with fd{$request->fd} ";

  //$request->fd 是客戶(hù)端id

  });

  $server->on('message', function (swoole_websocket_server $server, $frame) {

  echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},

  fin:{$frame->finish} ";

  //$frame->fd 是客戶(hù)端id,$frame->data是客戶(hù)端發(fā)送的數據

  //服務(wù)端向客戶(hù)端發(fā)送數據是用$server->push( '客戶(hù)端id' , '內容')

  $data = $frame->data;

  foreach($server->connections as $fd){

  $server->push($fd , $data);//循環(huán)廣播

  }});

  $server->on('close', function ($ser, $fd) {

  echo "client {$fd} closed ";

  });

  $server->start();

  這里最核心的廣播代碼其實(shí)還用到了一個(gè)之前沒(méi)有提到過(guò)的成員,也就是swoole_websocket_server對象的connections成員,這個(gè)成員中保存了所有已連接上該WebSocket服務(wù)端的fd,也就是客戶(hù)端id。因此我們只要在message事件中使用foreach遍歷該成員,循環(huán)將所有服務(wù)端收到的彈幕消息都發(fā)送給其他已連接上該服務(wù)端的客戶(hù)端即可。

  后端講完了再講講前端吧。

  前端代碼也不是很多https://github.com/cw1997/danmu-demo/blob/master/

  var ws = new WebSocket("ws://192.168.1.107:1997");

  ws.onopen = function(){

  console.log("握手成功");

  ws.send('hello world!!!');

  };

  ws.onmessage = function(e){

  console.log("message:" + e.data);

  var time = jQuery('#danmu').data("nowtime") + 1;

  var text_obj = '{ "text":"' + e.data + '" , "color":"green" ,"size":"1","position":"0","time":"' + time + '" ,"isnew":" "}'; //構造加上了innew屬性的字符串danmu對象

  console.log(text_obj);

  var new_obj = eval('(' + text_obj + ')'); //轉化為js對象

  jQuery('#danmu').danmu("add_danmu", new_obj); //向插件中添加該danmu對象

  };

  ws.onerror = function(){

  console.log("error");

  };

  核心代碼都在這里,使用new WebSocket("ws://192.168.1.107:1997")創(chuàng )建一個(gè)WebSocket客戶(hù)端連接對象,通過(guò)該對象的各種事件進(jìn)行對應的操作,和服務(wù)端是不是很像?更多代碼解釋可以參考源代碼中的注釋?zhuān)@里不做更多介紹。

  看到這里相信作為一名PHPer的你也可以開(kāi)發(fā)出屬于自己的彈幕系統了。這里展示的只是一個(gè)最基礎最原始的彈幕平臺。我們也了解到了使用PHP開(kāi)發(fā)一個(gè)彈幕平臺需要涉及到的技術(shù)有WebSocket,Swoole擴展,甚至碰到了很多初級開(kāi)發(fā)者平時(shí)不怎么接觸的工具,比如說(shuō)PECL,比如說(shuō)Linux。

  其實(shí)PHP結合Swoole擴展還可以做很多事情,比如說(shuō)對接各種家電,對接各種硬件接口實(shí)現在Web端實(shí)時(shí)控制家電,又比如說(shuō)結合樹(shù)莓派做智能小車(chē),通過(guò)web端進(jìn)行遙控等等,各種新奇的玩法等你發(fā)現。誰(shuí)說(shuō)PHP只能做Web開(kāi)發(fā)?PHP擁有了Swoole擴展其實(shí)能做的事情還有很多,Swoole就像他的宣傳標題一樣:重新定義PHP。

【如何使用PHP構建一個(gè)高性能的彈幕后端服務(wù)】相關(guān)文章:

如何使用 SQL 構建動(dòng)態(tài)數據透視表介紹09-12

PHP中curl的使用實(shí)例07-31

如何學(xué)好PHP知識09-20

構建高性能J2EE應用的技巧07-20

PHP中函數的使用說(shuō)明09-01

新手如何學(xué)習PHP語(yǔ)言10-19

php在新浪云中使用imagick的方法07-14

php如何過(guò)濾危險html代碼09-21

淺析通如何加強php的安全09-19

一级日韩免费大片,亚洲一区二区三区高清,性欧美乱妇高清come,久久婷婷国产麻豆91天堂,亚洲av无码a片在线观看