說到長鏈結大家肯定不陌生,就是復用乙個鏈結持續不斷的進行資料互動,它不像那些***似的服務,需要頻繁的開啟和關閉鏈結,效率低的同時還增加了業務的複雜度。在襠下很多網際網路業務場景都需要長連線的支援,比如:遊戲、聊天、資訊推送等等等,今天我們就一步一步來揭秘php長連線的玩法。我相信任何一項技術的實施都是因為業務場景的需要,所以這次我們還拿聊天室說事兒。
0x00 初試牛刀
記得以前用php寫聊天室還是用polling的方式,毫無疑問,一提到polling,肯定會有人說long polling,沒錯!long polling也很不錯,但在nginx+fpm上面玩這個多少有些費勁,畢竟乙個請求需要佔乙個php程序(就算是用apache+php_mod,也需要乙個請求乙個執行緒),所以要是幾個人隨便玩玩還行,一旦放到線上人多起來,這基本就廢了。所以還是採用polling的方式,這樣不會阻塞程序,並且乙個請求能立即得到響應,但是帶來的新問題是需要不停的向伺服器傳送請求,而且隨著間隔的時間越大導致訊息延遲就越大。
0x01 華麗變身
在經歷了上面那種一秒一小卡,三秒一大卡的場面!再也看不下去了,於是決定變身為真正的男人,哦不對,應該是真正的長連線。去他媽的polling, 去他媽的long polling,去他媽的webserver,統統靠邊站,讓flash socket(或者說websocket)來統治這個世界!開始了真正意義上的長連線之旅。要玩長連線總是少不了跟socket打交道吧,作為世界上最好的語言(沒有之一),socket的封裝自然是少不了滴。抄起socket_***就開幹,於是就有了下面這一託**,長連線是吧?延遲是吧?socket是吧?湯藥費是吧?so easy....
$sfd = socket_create(af_inet, sock_stream, 0);socket_bind($sfd, "0.0.0.0", 1234);
socket_listen($sfd, 511);
socket_set_option($sfd, sol_socket, so_reuseaddr, 1);
socket_set_nonblock($sfd);
$rfds = array($sfd);
$wfds = array();
doelseelse
} }
//write event
foreach($ws
as$fd)
}while(true);
0x02 登峰造極
從玩socket的那天起,google就輕言細語的跟我說,高併發下的select不要用啊,效率底啊,win要用iocp啊, linux要用epoll啊,blablablabla...哦!好吧,既然google都這麼說了,我也不能跟他老人家較真不是,又一次決定(為什麼要說又呢?)要聽google話,把epoll搞起來,可總不能自己寫啊?像我這麼懶的人還是整個擴充套件好了,libevent走你!經過瘋狂的編(co)碼(py),神作終於出山,具體能有多高效,能撐多少併發,不造,反正沒用select了,我奏是屌!
$sfd = stream_socket_server ('tcp:', $errno, $errstr);stream_set_blocking($sfd, 0);
$base = event_base_new();
$event = event_new();
event_set($event, $sfd, ev_read | ev_persist, 'ev_accept', $base);
event_base_set($event, $base);
event_add($event);
event_base_loop($base);
function ev_accept($socket, $flag, $base)
function ev_error($buffer, $error, $connection)
function ev_read($buffer, $connection)
0x03 絕處逢生
隨著人數的增長,併發的提公升,單個程序已經滿足不了需求了,田伯光的故事告訴我們,單挑是鬥不過**的,咋整?俗話說,大事化小,小事化,停!!別化了,再化就沒了。拆吧,把單程序拆成多程序,可是拆完之後又面臨新的問題,程序間通訊、負載均衡、session唯一等。既然已經提出這樣的問題,肯定是有解決方案,現成的就有擴充套件和庫來解決這個事,比如:swoole,workerman等?相比之下swoole更屌一些,性、功能,呃!好像這樣簡寫不太雅觀,好吧,效能和功能更屌一些(桶哥,請原諒我的無聊~)。。。。等一下!!!但是,我們在使用php來開發web的時候,也沒有使用webserver相關的庫來做開發對不對?咱只是簡單的echo而已。這些繁雜的事都交給了nginx或者是apache,是他們義無反顧的頂在前面,讓我們可以專心寫邏輯。寫web我們只需要簡單的配置nginx和fpm就好了,那寫socket服務呢?我們為什麼不能像nginx+fpm一樣簡單配置就好了呢??當然能,必須能。。。。。看這個劇情怕是廣告要來了。。。
0x04 出其不意
寫socket服務不比寫web高階,都是打碼,都是完成需求,通訊那層都是固定的,只不過乙個由nginx完成,另乙個由自己完成。。可是現在不需要自己完成了,類似nginx+fpm的方案,fooking+fpm=php長連線,gateway用於承載連線,router用於**訊息,程序間通訊?負載均衡?session唯一?so easy..
$sid = $_server['sessionid'];//這是sessionid$data = file_get_contents("php://input");//這樣就能拿到請求內容了
//想要返回訊息只需要兩步
header('content-length: 11');//返回給客戶端位元組數
echo
"hello world";
//想要給別的使用者發訊息
include
'api.php';
$router = new routerclient('router host', 'router port');
$router->sendmsg(使用者sessionid, "**** you");
//想要給所有人要訊息
$router->sendallmsg("**** all");
//想給指定組發訊息(類似redis的pub/sub)
PHP長連線實現
每次我們訪問php指令碼的時候,都是當所有的php指令碼執行完成後,我們才得到返回結果。如果我們需要乙個指令碼持續的執行,那麼我們就要通過php長連線的方式,來達到執行目的。每個php指令碼都限制了執行時間,所以我們需要通過 set time limit 來設定乙個指令碼的執行時間為無限長 然後使用...
什麼是長連線 短連線?
某些朋友對長 短連線的概念存在誤解,下面我們嘗試釐清這2個概念。1 一般情況下,client成功連線到server後,會傳送1個或幾個請求,收到server端1個或幾個應答 然後!就會非常識趣地馬上呼叫close 關閉連線了。這就叫短連線。2 某些情況下,如果client有很多資料要傳給server...
php 長連線心跳 利用PHP長連線提高效能
問題介紹 最近有 php 使用者反饋對雲資料庫 memcache 版做效能測試的結果,達不到預期的效能指標。通過了解具體情況,大多數使用者在使用 php 連線雲資料庫 memcache 版時,都是通過走 apache web 服務再連雲資料庫 memcache 版,使用的是短連線。而每個短連線的開銷...