㈠ 如何使用 php 構建一個高性能的彈幕後端服務
隨著WEB2.0的流行,現在很多網站都流行使用「彈幕」這種形式來實現互動。
彈幕(barrage),中文流行詞語,原意指用大量或少量火炮提供密集炮擊。大量以字幕彈(dàn)出形式顯示的評論同時在屏幕上飄過的現象也被稱為彈幕。
作為PHPer的我們,看到現在各種網站都有酷炫的彈幕飛過,我們是不是也想給自己的網站加入彈幕功能呢?
首先彈幕的後端其實說白了和公共聊天室的後端原理十分相似,都是一個客戶端發送消息給服務端,服務端再將收到的消息廣播給其他的客戶端。對於後端來說他們幾乎沒區別,區別就在於前端。
好在我們有一個前端彈幕插件,這個插件是一個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++庫時需要使用cmakePHP版本依賴
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 Swoole\Websocket\Server("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性能高的原因所在。
我們來分別剖析一下每一個事件的含義。
$serv->on('Open', function($server, $req) {echo "connection open: ".$req->fd;
});
顧名思義,Open表示打開一個新的鏈接,並且在事件觸發之後echo出連接上服務端的客戶端id,該客戶端唯一id為回調函數第二個參數中的fd欄位。這也是服務端區分客戶端的唯一id。
$serv->on('Message', function($server, $frame) {echo "message: ".$frame->data;
$server->push($frame->fd, json_encode(["hello", "world"]));});
同樣顧名思義,Message表示消息到達服務端的事件,並且在事件觸發之後echo出發送給服務端的數據,該數據為回調函數第二個參數的data欄位。另外我們還看到它調用了$server->push,這是回調函數的第一個參數中的push方法,它是一個服務端給客戶的發送數據的方法,第一個參數為要發送的客戶端id,第二個為要發送的數據,這里的含義是向發給服務端消息的那個客戶端發送["hello", "world"]這個數組(方括弧寫數組為PHP5.4的新特性,如果你是PHP5.3請使用傳統的array工廠函數生成數組)經過json序列化之後的數據。
$serv->on('Close', function($server, $fd) {echo "connection close: ".$fd;
});
最後一個事件Close更加容易理解,就是關閉事件,當然關閉的不是服務端,而是客戶端,可以理解為客戶端與服務端斷開連接的事件。回調函數中的代碼含義為echo出與服務端斷開連接的那個客戶端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}\n";//$request->fd 是客戶端id});
$server->on('message', function (swoole_websocket_server $server, $frame) {echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";//$frame->fd 是客戶端id,$frame->data是客戶端發送的數據//服務端向客戶端發送數據是用 $server->push( '客戶端id' , '內容')$data = $frame->data;
foreach($server->connections as $fd){
$server->push($fd , $data);//循環廣播
}
});
$server->on('close', function ($ser, $fd) {echo "client {$fd} closed\n";
});
$server->start();
這里最核心的廣播代碼其實還用到了一個之前沒有提到過的成員,也就是swoole_websocket_server對象的connections成員,這個成員中保存了所有已連接上該WebSocket服務端的fd,也就是客戶端id。因此我們只要在message事件中使用foreach遍歷該成員,循環將所有服務端收到的彈幕消息都發送給其他已連接上該服務端的客戶端即可。
後端講完了再講講前端吧。
前端代碼也不是很多https://github.com/cw1997/danmu-demo/blob/master/index.htmlvar 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")創建一個WebSocket客戶端連接對象,通過該對象的各種事件進行對應的操作,和服務端是不是很像?更多代碼解釋可以參考源代碼中的注釋,這里不做更多介紹。
看到這里相信作為一名PHPer的你也可以開發出屬於自己的彈幕系統了。這里展示的只是一個最基礎最原始的彈幕平台。我們也了解到了使用PHP開發一個彈幕平台需要涉及到的技術有WebSocket,Swoole擴展,甚至碰到了很多初級開發者平時不怎麼接觸的工具,比如說PECL,比如說Linux。
其實PHP結合Swoole擴展還可以做很多事情,比如說對接各種家電,對接各種硬體介面實現在Web端實時控制家電,又比如說結合樹莓派做智能小車,通過web端進行遙控等等,各種新奇的玩法等你發現。誰說PHP只能做Web開發?PHP擁有了Swoole擴展其實能做的事情還有很多,Swoole就像他的宣傳標題一樣:重新定義PHP。
㈡ PHP7安裝intl擴展和linux安裝icu
一 PHP intl 是國際化擴展,是ICU 庫的一個包裝器。所以在安裝PHP intl擴展前要先安裝ICU庫,安裝ICU庫的具體步驟::
二 安裝intl擴展
1:進入php7.2.5源碼:
2:運行:phpize ,找不到命令時,將路徑補全:/usr/local/php7/bin/phpize(是php的安裝路徑),出現如下:
Configuring for:
PHP Api Version: 20100412
Zend Mole Api No: 20100525
Zend Extension Api No: 220100525
3:運行配置
./configure --enable-intl --with-icu-dir=/usr/local/icu/ --with-php-config=/usr/local/php7/bin/php-config
注:前面路徑為icu的安裝路徑,後面路徑為php的安裝路徑。
4:編譯擴展:make
5:復制擴展到目標文件夾
cp /user/local/php/php7.2.5/ext/intl/moles/intl.so /user/local/php7/lib/php/extensions/no-debug-non-zts-20170718
注意:也可以find / -name intl.so 查找。
6:設置擴展加入配置文件中:
[intl]
extension_dir = "/usr/local/php7/lib/php/extensions/no-debug-non-zts-20170718/"
extension=intl.so
大坑:::採用phpinfo()時,無法找到配置的intl擴展,說明配置沒有生效。。。。。。
原因:在編譯php時沒有 --with-config-file-path=PATH 指定php.ini路徑,默認的路徑為/usr/local/php7/lib,只需要將php.ini放入這個默認的路徑即可。你也可以安裝配置php時加入,如下:
./configure --prefix=/usr/local/php7 --with-config-file-path=/usr/local/php7/etc --with-curl --with-freetype-dir --with-gd --with-gettext --with-iconv-dir --with-kerberos --with-libdir=lib64 --with-libxml-dir --with-mysqli --with-openssl --with-pcre-regex --with-pdo-mysql --with-pdo-sqlite --with-pear --with-png-dir --with-xmlrpc --with-xsl --with-zlib --enable-fpm --enable-bcmath -enable-inline-optimization --enable-gd-native-ttf --enable-mbregex --enable-mbstring --enable-opcache --enable-pcntl --enable-shmop --enable-soap --enable-sockets --enable-sysvsem --enable-xml --enable-zip --enable-pcntl --with-curl --with-fpm-user=nginx --enable-ftp --enable-session --enable-xml --with-apxs2=/usr/bin/apxs
訪問:index.php中phpinfo()文件。
㈢ php中pcntl_fork是什麼意思,pcntl_fork創建子進程如何進行的
一、php中pcntl_fork函數概述
pcntl_fork()函數是php中用於創建子進程的一個函數,返回創建的子進程的pid。
該函數創建子進程具體fork的過程:
(1)調用該函數即創建一個子進程,創建成功父進程返回子進程的pid,子進程返回0;
(2)創建子進程實際上對父進程的一個拷貝,共享代碼空間,拷貝父進程的數據,也就是說父進程改變父進程的數據,子進程改變子進程
二、示例代碼分析
1.代碼示例:
<?php
$curr_pid=posix_getpid();//獲取當前的進程id
//將當前進程的id寫入文件中
echo'當前進程:'.$curr_pid.PHP_EOL;
//開始創建子進程
$son_pid=pcntl_fork();//返回子進程的id
//查看當前進程
echo'創建子進程之後當前的進程為:'.posix_getpid().PHP_EOL;
//創建了子進程之後
if($son_pid>0){
echo'子進程id:'.$son_pid.PHP_EOL;
}
2.以上代碼執行後結果為:
3.示例代碼分析:
(1)發現創建了子進程之後,系統會切換到子進程中,而子進程中的代碼是從含有pcntl_fork函數的那行執行的
(2)創建子進程之後,子進程的代碼段是拷貝pcntl_fork函數及之後的代碼段,之前的代碼段並不拷貝,但是具體的數據變數子進程仍然會拷貝
(3)可見,fork之後程序會分叉執行,即子進程執行
三、pcntl_fork的業務場景舉例
1.php的多進程中,常用pcntl_fork來實現並發,多用於一些簡單工具的實現。
2.例如監控工具,想要監控幾個不同指標的情形,可以使用主進程監控各指標的配置變化,然後對每個指標分別fork一個子進程來監控其具體的情形,當主進程發現指標的配置改變則kill掉之前的子進程重新創建子進程進行監控。
3.主進程進行業務分發操作,子進程進行具體的業務邏輯執行。(BY三人行慕課)
㈣ linux 怎麼安裝nginx
Centos7配置Nginx+PHP7Web服務
作者:JadeGlorious
1、安裝相應的擴展支持;
yuminstallgcc-c++
yuminstallpcrepcre-devel
yuminstallzlibzlib-devel
yuminstallopensslopenssl-devel
yum-yinstalllibjpeglibjpeg-devellibpnglibpng-develfreetypefreetype-devellibxml2libxml2-develmysqlpcre-devel
yum-yinstallcurl-devellibxslt-devel
集成至一行命令一次安裝
yum-yinstalllibjpeglibjpeg-devellibpnglibpng-develfreetypefreetype-devellibxml2libxml2-develmysqlpcre-develgcc-c++pcrepcre-develpcrepcre-developensslopenssl--develcurl-devellibxslt-devel
如有不能成功安裝的,單獨再安裝一次即可;
2、編譯安裝Nginx最新版本
//檢查是否已經安裝nginx
$find/-namenginx
//如果已經安裝nginx先卸載掉
$yumremovenginx
//進入習慣使用的下載目錄,下載想要使用的nginx版
$wgethttp://nginx.org/download/nginx-1.7.4.tar.gz
//解壓nginx安裝包
$tar-zxvfnginx-1.7.4.tar.gz
//進入解壓後的目錄
$cdnginx-1.7.4
//配置安裝信息,要載入什麼擴展,安裝到什麼目錄之類的
//使用--prefix參數指定nginx安裝的目錄,make、makeinstall安裝
$./configure$默認安裝在下載目錄
//指定目錄
$./configure--prefix=/usr/local/nginx//指定安裝在/usr/local/nginx
//編譯安裝
$make&&makeinstall
//檢查是否安裝成功
$whereisnginx
3、編譯安裝PHP7
//下載、解壓、進入目錄:
$wgethttp://downloads.php.net/~ab/php-7.0.6RC1.tar.gz
$tar-zxvfphp-7.0.6RC1.tar.gz$cdphp-7.0.6RC1
//配置安裝信息、擴展
$./configure--prefix=/usr/local/php--exec-prefix=/usr/local/php--bindir=/usr/local/php/bin--sbindir=/usr/local/php/sbin--includedir=/usr/local/php/include--libdir=/usr/local/php/lib/php--mandir=/usr/local/php/php/man--with-config-file-path=/usr/local/php/etc--with-mysql-sock=/var/run/mysql/mysql.sock--with-mhash--with-openssl--with-mysql=shared,mysqlnd--with-mysqli=shared,mysqlnd--with-pdo-mysql=shared,mysqlnd--with-gd--with-iconv--with-zlib--enable-zip--enable-inline-optimization--disable-debug--disable-rpath--enable-shared--enable-xml--enable-bcmath--enable-shmop--enable-sysvsem--enable-mbregex--enable-mbstring--enable-ftp--enable-gd-native-ttf--enable-pcntl--enable-sockets--with-xmlrpc--enable-soap--without-pear--with-gettext--enable-session--with-curl--with-jpeg-dir--with-freetype-dir--enable-opcache--enable-fpm--enable-fastcgi--with-fpm-user=nginx--with-fpm-group=nginx--without-gdbm--disable-fileinfo
//編譯檢查不通過,缺少什麼擴展安裝了重新檢測,通過後編譯安裝
$makeclean&&make&&makeinstall
maketest
配置文件
#cpphp.ini-development/usr/local/php/lib/php.ini
#cp/usr/local/php/etc/php-fpm.conf.default/usr/local/php/etc/php-fpm.conf
#cp/usr/local/php/etc/php-fpm.d/www.conf.default/usr/local/php/etc/php-fpm.d/www.conf#cp-R./sapi/fpm/php-fpm/etc/init.d/php-fpm
//安裝完成後修改nginx配置文件nginx.conf,添加對php的支持,指定項目目錄,完成後重啟nginx
//啟動php-fpm
#/etc/init.d/php-fpm
㈤ debian8怎麼安裝php7
debian8 編譯安裝 php7
目錄(?)[-]
Please reinstall the libcurl distributionCannot find OpenSSL
configure error Unable to locate gmph
Can not find recodeh anywhere under usr usrlocal usr optCannot find pspell
Please reinstall the mysql distribution
mcrypth not found Please reinstall libmcryptxml2-config not found
安裝編譯器
apt-get install build-essential autoconf automake libtool bison re2c獲取PHP安裝包
wget https://downloads.php.net/~ab/php-7.0.13RC1.tar.gz安裝dev包
apt-get install libxml2-dev libssl-dev libbz2-dev libjpeg-dev libpng-dev libxpm-dev libfreetype6-dev libgmp-dev libgmp3-dev libmcrypt-dev libmysqlclient15-dev libpspell-dev librecode-dev進行編譯安裝
./buildconf //用來生成configure腳本
./configure \
--prefix=/usr \
--with-config-file-path=/etc \
--enable-mbstring \
--enable-zip \
--enable-bcmath \
--enable-pcntl \
--enable-ftp \
--enable-exif \
--enable-calendar \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-wddx \
--with-curl \
--with-mcrypt \
--with-iconv \
--with-gmp \
--with-pspell \
--with-gd \
--with-jpeg-dir=/usr \
--with-png-dir=/usr \
--with-zlib-dir=/usr \
--with-xpm-dir=/usr \
--with-freetype-dir=/usr \
--with-t1lib=/usr \
--enable-gd-native-ttf \
--enable-gd-jis-conv \
--with-openssl \
--with-pdo-mysql=/usr \
--with-gettext=/usr \
--with-zlib=/usr \
--with-bz2=/usr \
--with-recode=/usr \
--with-mysqli=/usr/bin/mysql_config
備註:錯誤1:Cannot find OpenSSL's libraries 解決:
確認已安裝過 openssl、libssl-dev 包,還是會提示該錯誤;解決辦法:
root@test2:~/php-5.3.27# find / -name libssl.so輸出結果為: /usr/lib/x86_64-Linux-gnu/libssl.so初步判斷它可能只會在 /usr/lib/ 下尋找 libssl.so 文件,於是:
ln -s /usr/lib/x86_64-linux-gnu/libssl.so /usr/lib錯誤2:debian Please reinstall the libcurl distribution 解決:
# RetHat CentOS or Fedora 使用下面安裝命令yum install curl curl-devel
# Debian or Ubuntu使用下面的安裝命令
apt-get install curl
apt-get install libcurl4-gnutls-dev
錯誤3:Unable to locate gmp.h 解決:
在https://launchpad.net/debian/+source/gmp 下載 gmp源碼包,接著 ./configure && make && make install編譯 安裝
make &&make install
報錯處理
Please reinstall the libcurl distributionaptitude search libcurl4
aptitude install libcurl4-gnutls-dev
Cannot find OpenSSL』
wget https://www.openssl.org/source/openssl-1.0.2j.tar.gztar -zxvf openssl-1.0.2j.tar.gz
cd openssl-1.0.2j
./config
make && make install
configure: error: Unable to locate gmp.h
sudo apt-get install libgmp-dev libgmp3-devln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.hCan not find recode.h anywhere under /usr /usr/local /usr /opt.
apt-get install librecode-dev
Cannot find pspell
apt-get install libpspell-dev
Please reinstall the mysql distribution
apt-get install libmysqlclient15-dev
mcrypt.h not found. Please reinstall libmcrypt.
apt-get install libmcrypt-dev
xml2-config not found
apt-get install libxml2-dev
㈥ 如何在linux下安裝多個不同版本的PHP
Linux下部署php多版本共存
背景說明
自php7問世,身為最新版本控的我馬上升級體驗,但是由於伺服器上還有舊程序在運行,只好部署一個php多版本共存環境。
現有環境是lnmp
- CentOS 6.7
- nginx 1.10.1
- mariadb-10.0.26
- php 7.0.8
為了更好兼容舊的php程序,推薦使用5.4.45. 主要是兼容mysql擴展。
開始安裝
首先要下載php-5.4.45.tar.gz源碼包。
通過源碼安裝
# tar xzvf php-5.4.45.tar.gz
# cd php-5.4.45
# ./configure --prefix=/usr/local/php54 --with-config-file-path=/usr/local/php54/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype-dir=/usr/local/freetype --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --with-mcrypt --enable-ftp --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --with-gettext --disable-fileinfo --enable-intl --with-xsl
# make ZEND_EXTRA_LIBS='-liconv'
# make install
# cp php.ini-proction /usr/local/php/etc/php.ini
------------------------------------------------------------------------------------------------
php.ini 配置
post_max_size = 50M
upload_max_filesize = 50M
date.timezone = PRC
short_open_tag = On
cgi.fix_pathinfo=0
max_execution_time = 300
disable_functions=passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,popen,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server
------------------------------------------------------------------------------------------------
php-fpm.conf 配置
------------------------------
# vim /usr/local/php/etc/php-fpm.conf1
[global]
pid = /usr/local/php54/var/run/php-fpm.pid
error_log = /usr/local/php54/var/log/php-fpm.log
log_level = notice
[www]
listen = /tmp/php54-cgi.sock
listen.backlog = -1
listen.allowed_clients = 127.0.0.1:9001
listen.owner = www
listen.group = www
listen.mode = 0666
user = www
group = www
pm = dynamic
pm.max_children = 40
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 40
request_terminate_timeout = 100
request_slowlog_timeout = 0
slowlog = var/log/slow.log
----------------------------------------------------------------------------------
啟動 php-fpm
# cp sapi/fpm/init.d.php-fpm /etc/init.d/php54-fpm
# chmod +x /etc/init.d/php54-fpm
# /etc/init.d/php54-fpm start
-------------------------------------------------------------------------------------------
修改nginx配置,對需要的服務配置使用php-5.4.45
location ~ [^/]\.php(/|$)
{
try_files $uri =404;
fastcgi_pass unix:/tmp/php54-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
----------------------------------------------------------------------------------------
配置php-5.4.45 的php54-fpm 開機自動啟動
# chkconfig --add php54-fpm
# chkconfig php54-fpm on
㈦ php多線程
以下都是轉載, 簡單說下, php是不支持多線程的。。。。
PHP語言本身是不支持多線程的. 總結了一下網上關於PHP模擬多線程的方法, 總的來說, 都是利用了PHP的好夥伴們本身所具有的多線程能力. PHP的好夥伴指的就是LINUX和APACHE啦, LAMP嘛.
另外, 既然是模擬的, 就不是真正的多線程. 其實只是多進程. 進程和線程是兩個不同的概念. 好了, 以下方法都是從網上找來的.
1. 利用LINUX操作系統
<?php
for ($i=0;$i<10;$i++) {
echo $i;
sleep(5);
}
?>
上面存成test.php, 然後寫一段SHELL代碼
#!/bin/bash
for i in 1 2 3 4 5 6 7 8 9 10
do
php -q test.php &
done
2. 利用fork子進程(其實同樣是利用LINUX操作系統)
<?php
declare(ticks=1);
$bWaitFlag = FALSE; /// 是否等待進程結束
$intNum = 10; /// 進程總數
$pids = array(); /// 進程PID數組
echo ("Startn");
for($i = 0; $i < $intNum; $i++) {
$pids[$i] = pcntl_fork();/// 產生子進程,而且從當前行之下開試運行代碼,而且不繼承父進程的數據信息
if(!$pids[$i]) {
// 子進程進程代碼段_Start
$str="";
sleep(5+$i);
for ($j=0;$j<$i;$j++) {$str.="*";}
echo "$i -> " . time() . " $str n";
exit();
// 子進程進程代碼段_End
}
}
if ($bWaitFlag)
{
for($i = 0; $i < $intNum; $i++) {
pcntl_waitpid($pids[$i], $status, WUNTRACED);
echo "wait $i -> " . time() . "n";
}
}
echo ("Endn");
?>
3. 利用WEB SERVER, PHP不支持多線程, APACHE可是支持的, 呵呵.
假設我們現在運行的是a.php這個文檔. 但是我在程式中又請求WEB伺服器運行另一個b.php
那麼這兩個文檔將是同時執行的.
<?php
function runThread()
{
$fp = fsockopen('localhost', 80, $errno, $errmsg);
fputs($fp, "GET /a.php?act=brnrn");
fclose($fp);
}
function a()
{
$fp = fopen('result_a.log', 'w');
fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
fclose($fp);
}
function b()
{
$fp = fopen('result_b.log', 'w');
fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
fclose($fp);
}
if(!isset($_GET['act'])) $_GET['act'] = 'a';
if($_GET['act'] == 'a')
{
runThread();
a();
}
else if($_GET['act'] == 'b') b();
?>
當然啦,也可以把需要多線程處理的部分交給JAVA去處理, 然後在PHP里調用, 哈哈.
<?php
system('java multiThread.java');
?>
㈧ php常用擴展有哪些
php基本使用到的擴展有如下:
bcmath(精確數值處理)
bz2
calendar
Core
ctype
curl
date
dom
ereg
exif
fileinfo
filter
ftp
gettext
hash
iconv
igbinaryinotify 文件監控
json
libxml
mbstring
mhash
mysql
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
readline
redis Redis緩存
Reflection
session
shmop
SimpleXML
sockets
SPL
sqlite3
standard
sysvmsg
sysvsem
sysvshmswoole 通信引擎
tokenizer
wddx
xml
xmlreader
xmlwriter
xslyaf YAF框架必須
zip
zlib
其中最常用的擴展有:curl date json mysql mysqli openssl pdo_mysql redis session zip等
查看當前php安裝了哪些擴展,可以使用命令:php -m
㈨ PHP + Mysql多個表並行查詢如何實現
在PHP-FPM處理HTTP請求時,有時會遇到一個請求需要進行多次MySQL查詢(在報表類應用中比較常見)。通常我們會以串列方式查詢:
$link=newmysqli();
$rs1=$link->query('SELECT*FROMtable1');
while($row=$rs1->fetch_row()){...}
$rs2=$link->query('SELECT*FROMtable2');
while($row=$rs2->fetch_row()){...}
$rs3=$link->query('SELECT*FROMtable3');
while($row=$rs3->fetch_row()){...}
串列查詢方式有個缺點:在MySQL返回數據之前,PHP一直是處於空等的狀態,不會繼續往後執行。如果數據量大或者查詢復雜,MySQL響應可能會比較慢,那麼以串列方式查詢會有一些延遲。給用戶最直接的感受就是 Loading… 的圈圈一直打轉。
那麼有什麼辦法可以減少查詢MySQL的時間?用多進程並行查詢不行,因為PHP-FPM 中不允許用 pcntl_fork 一類的調用。
幸好還有 mysqlnd,mysqlnd提供了類似 stream_select 的機制(見 這篇文章) ,可以做到在單進程中對MySQL並行查詢。這主要運用了mysqli_poll 和 reap_async_query 兩個函數。
還是通過例子來介紹MySQL並行查詢的實施方法。假設要並行地向MySQL發出10個查詢,最基本的代碼應該是這樣的:
1.$links=[];
2.for($i=0;$i!==10;$i++){
3.$links[$i]=newmysqli('127.0.0.1','user','password','db1');
4.$links[$i]->query('SELECTSLEEP(1)',MYSQLI_ASYNC);
5.}
6.$allResult=[];
7.while(!empty($links)){
8.$reads=$links;
9.$errors=$reject=[];
10.if(!mysqli_poll($reads,$errors,$reject,null)){
11.continue;
12.}
13.foreach($readsas$read){
14.$idx=array_search($read,$links,true);
15.$allResult[$idx]=[];
16.$result=$read->reap_async_query();
17.while($row=$result->fetch_row()){
18.$allResult[$idx][]=$row;
19.}
20.$read->close();
21.unset($links[$idx]);
22.}
23.}
解釋下這段代碼的含義:
2~5行,同時發起10個MySQL連接,並發出查詢
注意query() 的第二個參數帶上了 MYSQLI_ASYNC 表示非阻塞查詢
10行,使用mysqli_poll 輪詢10個連接的查詢有無返回
mysqli_poll 的第一個參數$reads是個數組,包含需要輪詢那些連接。mysqli_poll 執行完後,會改寫$reads,改寫後$reads包含的是那些已經有數據返回連接。
mysqli_poll的第四個參數,控制的是輪詢的等待時間,單位是「秒」。如果像本例當中設置為null,那麼mysqli_poll輪詢是阻塞的:只有監聽的連接中,任意一個連接有數據返回了,mysqli_poll才會返回。如果等待時間設置為0,那麼每次執行mysqli_poll會立即返回,外層的while會頻繁循環。
第11~19行,遍歷已經有數據返回的連接
reap_async_query和普通query一樣,返回的是mysqli_result,可以一行行fetch數據
20~21行,對於已經獲得了數據的連接,下次mysqli_poll就不需要再輪詢這個連接了,所以關閉連接,並從$links數組刪除這個連接
當所有的連接都返回了數據,$links數組空了,while循環也就終止了。
使用並行查詢的方式,可以大大縮短處理HTTP請求的時間,假設本例中的10個SQL查詢,每個需要執行1秒。因為是並行,處理所有的查詢,也只需要1秒左右。