優化前準備工做
Centos準備及配置
準備安裝包及軟件:
http://pan.baidu.com/s/1chHQF 下載解壓到U盤便可安裝
http://pan.baidu.com/s/15TUWf 其它版本的centos 在這裏
http://pan.baidu.com/s/1Dv3me SecureCRT,遠程linux管理軟件
1 安裝完centos
2 啓動SecureCRT 遠程鏈接linux服務器
若連不上,請檢查一下幾項:網絡防火牆 sshd
3 若sshd未啓動,則啓動sshd # /usr/sbin/sshd
若啓動時出現以下錯誤:
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_dsa_key
其緣由是在 SSH 鏈接協議中須要有 RSA 或 DSA 密鑰的鑑權。所以,咱們能夠在服務器端使用 ssh-keygen 程序來生成一對公鑰
/私鑰對
執行 # ssh-keygen -t rsa -b 1024 -f /etc/ssh/ssh_host_rsa_key 一路回車
命令執行成功後,在 /etc/ssh 下會看到有兩個文件生成:ssh_host_rsa_key 和 ssh_host_rsa_key.pub ,前者是私鑰,後者是公鑰。
此時,啓用SecureCRT遠程鏈接linux服務器,通常會成功!
4 配置yum更新源
配置國內更新源:參考個人這篇文章
http://www.cnblogs.com/buffer/p/3426908.html
而後執行命令,更新緩存:
# yum clean metadata
# yum clean dbcache
# yum makecache
5 安裝lrzsz工具
用於windows和linux間傳輸文件
# yum -y install lrzsz
6 配置固定ip
修改或者增長 /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
IPADDR=192.168.1.104
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
ONBOOT=yes
USERCTL=no //是否容許非root用戶控制該設備
BOOTPROTO=static
修改DNS配置文件: vi /etc/resolv.conf 增長
nameserver 192.168.1.1 #主DNS
nameserver 8.8.8.8 #次DNS
search localdomain
關閉NetworkManager,由於在命令行模式下,NetworkManager 和network兩個服務衝突。重啓:# service network restart
7 配置vi
配置vi 做爲後面的編程IDE,基本配置步驟請參考個人這篇文章:
http://www.cnblogs.com/buffer/p/3429221.html
8 安裝必要的編譯工具及必需的庫文件
yum -y install make apr* autoconf automake curl-devel gcc gcc-c++ zlib-devel openssl openssl-devel pcre-devel gd kernel keyutils patch perl kernel-headers compat* mpfr cpp glibc libgomp libstdc++-devel ppl cloog-ppl keyutils-libs-devel libcom_err-devel libsepol-devel libselinux-devel krb5-devel zlib-devel libXpm* freetype libjpeg* libpng* php-common php-gd ncurses* libtool* libxml2 libxml2-devel patch cmake
總共148M左右,具體每一項的做用,你們感興趣的能夠查一查
9配置防火牆(服務器安全優化)
安全規劃:開啓 80 22 端口並打開回路(迴環地址 127.0.0.1)
# iptables –P INPUT ACCEPT
# iptables –P OUTPUT ACCEPT
# iptables –P FORWARD ACCEPT
以上幾步操做是爲了在清除全部規則以前,經過全部請求,若是遠程操做的話,防止遠程連接斷開。
接下來清除服務器內置規則和用戶自定義規則:
# iptables –F
# iptables -X
打開ssh端口,用於遠程連接用:
# iptables –A INPUT –p tcp –-dport 22 –j ACCEPT
# iptables -A OUTPUT -p tcp --sport 22 -m state --state ESTABLISHED,RELATED -j ACCEPT容許已創建的連接經過22端口向外發送數據包
而後關閉INPUT 和FORWARD請求:
# iptables –P INPUT DROP
# iptables –P FORWARD DROP
接下來設置環路,使得ping 127.0.0.1這樣的包額能夠經過。後面php會使用這個規則,
Nginx中設置php-fpm訪問地址:http://127.0.0.1:9000即用到這個規則
# iptables –A INPUT –i lo –j ACCEPT
接下來設置容許其餘機器ping 本機,也能夠不容許,不容許會更加安全。
# iptables –A INPUT –p icmp –j ACCEPT
接下來開放web服務端口 80
# iptables –A INPUT –p tcp –dport 80 –j ACCEPT
# iptables -A OUTPUT -p tcp --sport 80 -m state --state ESTABLISHED,RELATED -j ACCEPT容許已創建的連接經過80端口向外發送數據包
接下來開放 53端口用於DNS解析
# iptables -A INPUT -p udp --dport 53 -j ACCEPT
# iptables -A OUTPUT -p udp --sport 53 -m state --state ESTABLISHED,RELATED -j ACCEPT
最後保存設置:
# service iptables save
# service iptables restart
至此已經完成關閉除22 80以外的全部對外端口,服務器能夠經過任意端口向外發請求,可是外面的請求只能經過 80和22端口進入到內部。
也能夠直接下載這個腳本執行便可完成基本防火牆設置:
http://pan.baidu.com/s/17qiUG
附件:
linux端口號大全請參考我這篇文章
http://www.cnblogs.com/buffer/p/3386132.html
iptables 詳解,請參考我這篇文章:
http://www.cnblogs.com/buffer/archive/2012/09/24/2700609.html
10 修改啓動模式,默認命令行啓動
# vi /etc/inittab
將id:5:initdefault:改成id:3:initdefault:保存便可
從說明裏能夠看出,5 是啓動桌面x-window 3是啓動命令行文本模式
以上爲配置linux基礎工做環境
php
準備nginx 基礎工做環境
1 安裝nginx
下載源碼包nginx-1.4.2.tar.gz:http://pan.baidu.com/s/1chQ76
建立nginx運行的用戶組及用戶:www www
#groupadd www
# useradd -g www www -s /bin/false 建立nginx運行帳戶www並加入到www組,不容許www用戶直接登陸系統
編譯安裝:
# ./configure --prefix=/usr/local/webserver/nginx --user=www --group=www --with-http_ssl_module --with-http_gzip_static_module
--with-pcre=/usr/local/webserver/softs/libs/pcre-8.32
--with-openssl=/usr/local/webserver/softs/libs/openssl-1.0.0d
# make & make install
查看編譯安裝參數命令:# ./configure –help
這裏須要兩個源碼包pcre和openssl:
pcre-8.32.tar.gz下載:http://pan.baidu.com/s/1pFcIw
openssl-1.0.0d.tar.gz下載:http://pan.baidu.com/s/1fYYv
設置nginx開機啓動:
具體設置步驟請參考我這篇文章:
http://www.cnblogs.com/buffer/archive/2011/08/15/2138762.html
配置完以後,能夠經過命令啓動nginx服務:# service nginx start
配置nginx虛擬主機。
至此nginx服務搭建完畢。
2 編譯安裝mysql
下載源碼包mysql-5.5.15.tar.gz:http://pan.baidu.com/s/1chRcF
建立mysql服務運行的用戶 mysql 並加入組www
# useradd –g www mysql –s /bin/false
建立mysql數據庫數據存放目錄:
# mkdir -p /usr/local/webserver/mysql/data
設置MySQL數據庫目錄權限
#chown –R mysql:www /usr/local/webserver/mysql/data
下面開始編譯安裝mysql:
# cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/webserver/mysql
-DMYSQL_DATADIR=/usr/local/webserver/mysql/data
-DSYSCONFDIR=/etc/
# make && make install
配置mysql:
# cp ./support-files/my-huge.cnf /etc/my.cnf
編輯配置文件,在 [mysqld] 部分增長下面一行,添加MySQL數據庫數據路徑
datadir = /usr/local/webserver/mysql/data/mysql
接下來,生成mysql系統數據庫:
# ./scripts/mysql_install_db --user=mysql
接下來,將mysql加入系統服務開機啓動:
# cp ./support-files/mysql.server /etc/rc.d/init.d/mysqld
增長執行權限:
# chmod 755 /etc/init.d/mysqld
加入開機啓動:
# chkconfig mysqld on
編輯啓動文件修改mysql路徑及mysql數據文件目錄:
# vi /etc/rc.d/init.d/mysqld
basedir = /usr/local/webserver/mysql
datadir = /usr/local/webserver/mysql /data/mysql
接下來能夠啓動mysql服務了
Service mysqld start
mysql後續配置
設置mysql密碼:
#./bin/mysql_secure_installation
根據提示輸入密碼,刪除anonymous用戶,禁止以root身份遠程登陸,刪除test數據庫等
接下來,把myslq的庫文件連接到系統默認的位置,這樣在編譯PHP等軟件時能夠不用指定mysql的庫文件地址:
# ln -s /usr/local/webserver/mysql/lib/mysql /usr/lib/mysql
# ln -s /usr/local/webserver/mysql/include/mysql /usr/include/mysql
最後,把mysql服務加入系統環境變量,方便調用mysql客戶端登陸mysql
# vi /etc/profile增長下面一行
export PATH=$PATH:/usr/local/webserver/mysql/bin
至此,mysql編譯安裝及配置已經所有完成。最好重啓一下系統,使修改生效。
html
編譯安裝php
下載源碼包php-5.5.5.tar.gz:http://pan.baidu.com/s/1zi33B
安裝php以前須要編譯安裝libmcrypt,到這裏下載:http://pan.baidu.com/s/1uyM1L
編譯安裝libmcrypt:
# ./configure
# make && install
接下來編譯安裝php:
# ./configure --prefix=/usr/local/webserver/php --with-mysql=mysqlnd
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-zlib --with-libxml-dir
--with-gd --with-jpeg-dir --with-png-dir=/usr/lib --with-ttf --with-iconv
--with-openssl --with-mcrypt --enable-static --enable-maintainer-zts
--enable-zend-multibyte --enable-inline-optimization --enable-sockets
--enable-wddx --enable-zip --enable-calendar --enable-bcmath--enable-soap
--enable-mbstring --without-sqlite --disable-ipv6--with-mhash
--with-mcrypt --enable-fpm
# make && make install
with-mcrypt:擴展加密算法,若是隻用md5的話,則不須要此選項
接下來配置php:
# cp php.ini-production /usr/local/webserver/php/etc/php.ini從源文件目錄下複製php配置文件到安裝目錄
# rm -rf /etc/php.ini刪除系統自帶配置文件
# ln -s /usr/local/webserver/php/etc/php.ini /etc/php.ini添加軟連接
# vi /usr/local/webserver/php/etc/php.ini
禁用不安全函數:
找到:disable_functions =修改成:
disable_functions =
passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,
ini_alter,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,
stream_socket_server,escapeshellcmd,dll,popen,disk_free_space,checkdnsrr,checkdnsrr,
getservbyname,getservbyport,disk_total_space,posix_ctermid,posix_get_last_error,
posix_getcwd, posix_getegid,posix_geteuid,posix_getgid, posix_getgrgid,posix_getgrnam,
posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix_getppid,
posix_getpwnam,posix_getpwuid, posix_getrlimit, posix_getsid,posix_getuid,
posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid, posix_setpgid,
posix_setsid,posix_setuid,posix_strerror,posix_times,posix_ttyname,posix_uname
列出PHP能夠禁用的函數,若是某些程序須要用到這個函數,能夠刪除,取消禁用。
找到:;date.timezone =修改成:date.timezone = PRC #設置時區
找到:expose_php = On修改成:expose_php = OFF #禁止顯示php版本的信息
接下來配置php-fpm.conf
# cp php/etc/php-fpm.conf.default php/etc/php-fpm.conf
拷貝模板文件爲php-fpm配置文件
# vi php/etc/php-fpm.conf
user = www 設置php-fpm運行帳號爲www
group = www 設置php-fpm運行組爲www
pid = run/php-fpm.pid 取消前面的分號
將php-fpm加入系統服務病設置開機啓動:
# cp php-5.5.5/sapi/fpm/init.d.php-fpm /etc/rc.d/init.d/php-fpm
拷貝php-fpm到啓動目錄
# chmod +x /etc/rc.d/init.d/php-fpm 添加執行權限
# chkconfig php-fpm on 設置開機啓動
啓動php-fpm: # service php-fpm start
至此,php已經編譯安裝完成。
Lnmp已經所有初步編譯安裝及配置完畢,下一步,分別對lnmp 進行優化。
mysql
LNMP優化
本文LNMP優化從系統安全,系統資源佔用率,及web服務併發負載這三個方面體現,而且主要體如今web服務併發負載這一方面。
本文中使用的服務器配置:centos 6.4 2G內存
本文用到主要從Linux優化、nginx優化、mysql優化、php優化這四個方面依次着手,而且用到的優化效果測試工具備如下幾項:
1 服務併發測試工具——apache bench(即ab.exe)
這裏下載:http://pan.baidu.com/s/1y2BlC除此以外,註明的web併發測試工具還有http_load 、webbench 、Loadrunner等
2 網絡負載監控工具——nload
這裏下載:http://pan.baidu.com/s/126vnm
3 linux系統內存、IO、CPU、網絡狀態監測命令等。更直觀的能夠安裝nmon工具及
nmon analyser ,前者是系統各項指標檢測工具,後者是將檢測結果數據圖表化的工具。
這裏下載:
32位 nmon 下載: http://pan.baidu.com/s/1sxkmI
64位 nmon下載: http://pan.baidu.com/s/1rbr6C
nmon analyser 工具下載:http://pan.baidu.com/s/1Caaa8 這是一個windows上的用excel宏作的excel圖表工具
這兩款工具具體使用方法見個人這篇文章:
http://blog.csdn.net/neubuffer/article/details/16881167
爲了體現優化效果,本文將優化以前和優化以後的效果保存以做對比。而且每作一步優化都會進行測試比較。
安裝完linux,並安裝了基本web服務軟件nginx、mysql、php以後,
優化以前的系統內存資源佔用狀況及進程明細,以下圖1所示:
內存佔用了274M
![](http://static.javashuo.com/static/loading.gif)
圖1
優化以前的系統資源CPU利用率及平均負載狀況,以下圖2所示:
![](http://static.javashuo.com/static/loading.gif)
圖2
load average: 0.51, 0.30, 0.12指的是 系統負載,即任務隊列的平均長度,三個數值分別爲 1分鐘、5分鐘、15分鐘前到如今的平均值。
Cpu(s): 0.1% us 用戶空間佔用CPU百分比
0.2% sy 內核空間佔用CPU百分比
0.0% ni 用戶進程空間內改變過優先級的進程佔用CPU百分比
99.3.0% id 空閒CPU百分比
0.4% wa 等待輸入輸出的CPU時間百分比
Mem 和 Swap 中的buffers和cached分別指用做內核緩存的內存量及緩衝的交換區總量
優化以前的web併發負載狀況,以下圖3所示:模擬1000個客戶端發送200000個請求,每分鐘併發 5280.34,而且出現大量TIME_WAIT
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖3
20萬併發資源消耗狀況以下圖4 所示:
![](http://static.javashuo.com/static/loading.gif)
系統資源使用狀況CPU 和 IO
![](http://static.javashuo.com/static/loading.gif)
CPU
![](http://static.javashuo.com/static/loading.gif)
磁盤
![](http://static.javashuo.com/static/loading.gif)
網絡
圖4
此時看一下nginx錯誤日誌,出現大量failed (24: Too many open files) ,而且 /var/log/message 中也出現 possible SYN flooding on port 80. Sending cookies.
下面開始一步一步優化,將上面日誌中的警告或錯誤解決掉,而且提升服務器併發負載能力輕鬆達到1萬以上併發,讓有限的資源發揮最大性能
好的,讓咱們開始吧!linux
首先進行linux優化加固
Linux優化加固最好的辦法就是提高硬件配置,好比提升CPU運算能力,增大內存容量,提升硬盤吞吐率等。
本文談的Linux優化加固是在不提高硬件配置的狀況下,經過優化內核配置,從而提升linux服務效率,從三個方面進行:安全加固、內核調優、優化網絡,本文主要講解內核調優及網絡優化。nginx
1優化linux 啓動項
使用ntsysv工具將不須要的服務關閉
優化啓動服務以前的內存使用狀況:使用了 275M
![](http://static.javashuo.com/static/loading.gif)
圖5
進行優化,默認啓動服務能夠只保留如下六項必要服務:
iptables sshd crond syslog network messagebus
同時也要保留 nginx、mysql、php默認啓動
系統服務解釋請參考個人這篇文章:http://www.cnblogs.com/buffer/p/3386346.html
優化以後內存使用狀況,使用了224M,節省了近50m內存,不要小看這50M內存,關鍵時候能夠起很大做用
![](http://static.javashuo.com/static/loading.gif)
圖6
c++
2 安全加固
Linux安全加固主要針對iptables進行,控制全部INPUT數據包,除了必要的端口打開以外,其他的端口一概關閉。禁用用戶ping服務器等會更加安全。詳情見LNMP優化準備工做—9配置防火牆(服務器安全優化)。
刪除沒必要要的用戶:
# cp /etc/passwd /etc/passwd.sav
# cp /etc/group /etc/group.sav
# for a in adm lp sync news uucp operator games gopher mailnull nscd rpc;
do /usr/sbin/userdel $a -f; done
# for a in lp news uucp games gopher users floopy nscd rpc rpcuser nfsnobody;
do /usr/sbin/groupdel $a ; doneweb
3網絡優化
通常狀況下,Nginx經過TCP socket來鏈接客戶端與上游應用,默認安裝的系統對TCP有許多門限值與限制,經過內核參數來設定。這些參數的默認值每每是爲通常的用途而定的,並不能知足web服務器所需的高流量、短生命的要求。
對於網絡參數調優能夠修改 /etc/sysctl.conf 這個文件。修改完以後使用 #sysctl –p 讓內核配置生效。
3.1 內核調優——調整TIMEWAIT,解決出現大量TIMEWAIT問題
在調整TIMEWAIT參數以前,先解釋一下tcp連接請求和tcp關閉請求中的報文響應流程。如圖7所示爲一個完整的數據報格式。
![E:\baiduyundownload\傳智播客\lnmp優化\配置文件\200711211195609944859.jpg](http://static.javashuo.com/static/loading.gif)
圖7
Tcp的連接及斷開過程當中間是通過一系列狀態變換的。有這些狀態:
創建連接狀態:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED
關閉連接狀態:FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT 和 CLOSED。
各狀態參數解釋請參考我這篇文章:
http://blog.csdn.net/neubuffer/article/details/16853747
創建連接時,須要通過三次握手協議,創建連接時的握手協議以下圖8所示。
redis
收到客戶端發來的ack
進入ESTABLISHED
|
|
收到服務器發來的ack
進入ESTABLISHED
|
|
![](http://static.javashuo.com/static/loading.gif)
圖8
Tcp連接創建過程在服務器端不會產生TIME_WAIT狀態,所以本文不做爲重要知識點講解。
斷開連接時,須要通過四次握手協議,斷開連接時的握手協議以下圖9所示。
算法
發送FIN表示沒有數據發送給客戶端了,接着進入
FIN-WAIT-1
|
|
![](http://static.javashuo.com/static/loading.gif)
圖9
Linux系統下,TCP鏈接主動斷開後,會以TIME_WAIT狀態保留必定的時間,而後纔會釋放端口。當併發請求過多的時候,就會產生大量的TIME_WAIT狀態的鏈接,沒法及時斷開的話,會佔用大量的端口資源和服務器資源。這個時候咱們能夠優化TCP的內核參數,來及時將TIME_WAIT狀態的端口清理掉。
經過 ab.exe 模擬1000個客戶端發起200000個併發請求,而後統計linux tcp等待個數,結果以下圖10:
![](http://static.javashuo.com/static/loading.gif)
圖10
從圖7中能夠看出,有24986個連接等待。
接下來咱們優化一下TIMEWAIT,而後再統計。
# vi /etc/sysctl.conf
在文件中加入下面幾行內容:
net.ipv4.tcp_syncookies = 1 開啓SYN Cookies,當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少許SYN攻擊,默認爲0,表示關閉;
net.ipv4.tcp_tw_reuse = 1 開啓重用。容許將TIME-WAIT sockets從新用於新的TCP鏈接,默認爲0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 開啓TCP鏈接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉;
net.ipv4.tcp_fin_timeout = 30 修改系統默認的 TIMEOUT 時間,
查看系統默認timeout時間: # cat /proc/sys/net/ipv4/tcp_fin_timeout 默認爲60秒。
![](http://static.javashuo.com/static/loading.gif)
接下來,優化tcp keepalive時間,在sysctl.conf中增長如下幾行:
net.ipv4.tcp_keepalive_time = 1200 #TCP發送keepalive消息的頻度。默認爲2小時,改小。tcp連接在空閒 1200秒以後,內核發起關閉連接probe
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3 #若是probe 3次(每次30秒)不成功,內核才完全放棄
接下來優化其它一些參數:
net.ipv4.ip_local_port_range = 1024 65000
#向外鏈接的端口範圍。默認爲32768到61000,範圍改大
net.ipv4.tcp_max_syn_backlog = 2148
#SYN隊列的長度。默認爲1024,改大
net.ipv4.tcp_max_tw_buckets = 5000
#系統同時保持TIME_WAIT套接字的最大數量,超過這個數字,TIME_WAIT套接字將馬上被清除並打印警告信息。默認爲180000
net.core.netdev_max_backlog = 1000
#進入包的最大設備隊列,默認300,改大
net.core.somaxconn = 511 # socket的監聽隊列backlog的上限,默認值爲128,二nginx的默認爲511 限制了nginx發揮,NGX_LISTEN_BACKLOG 511
修改完以後,執行# /sbin/sysctl –p 讓設置生效
關於網絡參數詳解及優化,請參考我這篇文章:
http://blog.csdn.net/neubuffer/article/details/16859829
也能夠直接下載優化過的文件放到/etc 目錄下:http://pan.baidu.com/s/1uyZ7s
從新經過 ab.exe 模擬1000個客戶端發起200000個併發請求,而後統計linux tcp等待TIMEWAIT個數 netstat -tnp | awk '{print $6}' | sort | uniq -c ,結果以下圖11:
![](http://static.javashuo.com/static/loading.gif)
圖11
從圖11中能夠看出,連接等待數大量下降,節省了資源。
可是此時併發量,仍是在6000多,沒什麼提高,這是爲何呢?
這時候看一下nginx的錯誤日誌,# tail nginx/logs/error.log 結果如圖12所示:
![E:\baiduyundownload\傳智播客\lnmp優化\搜狗截圖20131121021437.png](http://static.javashuo.com/static/loading.gif)
圖12
從錯誤日誌結果中能夠看出,打開的文件太多,出現這個錯誤的緣由主要是因爲linux的打開文件描述符的數目太小形成的。
須要修改文件描述符限制。接下來優化內核文件描述符參數。
3.2 內核調優——調整文件描述符限制
查看用戶文件描述符限制:
# ulimit –Hn 查看硬限制
# ulimit –Sn 查看軟限制
![](http://static.javashuo.com/static/loading.gif)
增大文件描述符限制:
查看系統file-max參數,系統全部進程一共能夠打開的文件句柄描述符數量
# cat /proc/sys/fs/file-max 結果爲183972 在這裏夠用了不須要修改。
此值通常默認爲系統內存的10%(系統內存以kb計算),通常夠用,根據狀況能夠調大該值。經過編輯/etc/sysctl.conf 添加內容:fs.file-max=102400 來調整。
因而可知本實驗中出現的問題因爲用戶軟硬文件句柄數太小致使的,那麼咱們增長當前用戶軟硬文件句柄數:
# vi /etc/security/limits.conf 添加如下內容,表示限制全部用戶打開文件句柄數的軟硬限制到102400個。你也能夠根據系統須要,限制某個用戶。
* hard nofile 102400
* soft nofile 102400
保存,重啓linux讓剛纔的修改生效。
File-max 和 ulimit 的區別是前者指的系統全部文件描述符限制,針對整個系統;然後者指的是用戶的文件描述符限制,針對的是用戶。
從新經過 ab.exe 模擬1000個客戶端發起200000個併發請求,而後統計linux tcp等待個數 netstat -tnp | awk '{print $6}' | sort | uniq -c ,結果以下圖13:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖13
看一下系統各項性能指標,如圖14所示:
![](http://static.javashuo.com/static/loading.gif)
系統總體CPU 及 IO
![](http://static.javashuo.com/static/loading.gif)
CPU
![](http://static.javashuo.com/static/loading.gif)
磁盤
![](http://static.javashuo.com/static/loading.gif)
網絡
圖14
從結果中能夠看出,與優化前相比沒有太大提高。
這時候再看一下nginx的錯誤日誌,# tail nginx/logs/error.log 仍是有打開文件過多錯誤。可是,這時候看一下 /var/log/message 裏面已經沒有警告了。
繼續找緣由,猜測是否是nginx的限制呢?
sql
進行nginx優化
前面修改了linux的文件描述符限制及linux內核參數,接下來優化nginx:
修改 # vi nginx/conf/nginx.conf
1 增長nginx工做進程數並綁定到不一樣的CPU上,本文所用的硬件有4個CPU,顧開闢4個進程,以下:
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000; #綁定進程和CPU對應
2 增長每一個進程打開文件句柄數,理論值應該是最多打開文件數(ulimit -n)與nginx進程數相除,可是nginx分配請求並非那麼均勻,因此最好與ulimit -n的值保持至關。
worker_rlimit_nofile 50000;
3 採用epoll 模式,並增大每一個進程鏈接數限制:
events {
use epoll; //異步非阻塞I/O模型
worker_connections 204800;
}
4 設置客戶端請求頭部緩衝區大小爲系統分頁大小的整數倍,能夠用命令查看系統分頁大小:# getconf PAGESIZE 。若是常常出現 400錯誤,則和值有關,調大便可。
http{
client_header_buffer_size 4k;
large_client_header_buffers 4 4k;
}
5 打開請求文件緩存
http{
open_file_cache max=102400 inactive=60s;
說明:打開文件指定緩存,默認是沒有啓用的,max 指定緩存數量,建議和打開文件數一致,inactive 是指通過60s時間文件沒被請求後刪除緩存。
open_file_cache_valid 80s;
說明:80s 檢查一次緩存的有效信息。
open_file_cache_min_uses 1;
說明:文件使用次數,判斷有效與否。inactive 時間內一次沒被使用,它將被移除。
}
重啓nginx:# service nginx restart
再次經過 ab 模擬1000個客戶端發起200000個併發請求,而後統計linux tcp等待個數 netstat -tnp | awk '{print $6}' | sort | uniq -c ,結果以下圖15:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖15
看一下系統資源利用狀況,以下圖16所示:
系統總體CPU及IO
![](http://static.javashuo.com/static/loading.gif)
CPU
![](http://static.javashuo.com/static/loading.gif)
磁盤
![](http://static.javashuo.com/static/loading.gif)
網絡
![](http://static.javashuo.com/static/loading.gif)
圖16
由以上結果可見,優化以後併發達到1.1萬多。而且TIMEWAIT數量大大減小,性能有明顯提高。
實際上此時併發能夠達到將近2w,因爲ab併發性能成爲瓶頸。咱們能夠開3個ab,每一個ab分別併發1000發送20萬個請求。實驗結果以下圖17所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖17 每一個併發達到0.62萬 總共併發大於1.8萬
系統資源利用狀況以下圖18所示:
![](http://static.javashuo.com/static/loading.gif)
系統總體CPU及IO
![](http://static.javashuo.com/static/loading.gif)
CPU
![](http://static.javashuo.com/static/loading.gif)
磁盤
![](http://static.javashuo.com/static/loading.gif)
網絡
![](http://static.javashuo.com/static/loading.gif)
內存空閒率
圖18
由結果可知,優化以後,只用了不到200M內存,併發請求達到近2W,系統併發有了很大提高。其中,三個AB程序佔了200M內存中的近50%。
進行mysql優化
提高mysql性能須要從三個方面着手,首先是硬件,提高硬件配置效果最明顯;其次是mysql參數配置優化;還有數據讀寫架構優化。本文主要講mysql參數配置優化,順便解釋一下硬件配置和程序中使用mysql架構優化問題。
對於硬件配置這不用說,任何服務都是基於硬件之上的,提高硬件配置,原則上會提高服務效率,好比使用更大內存,使用磁盤高級raid,數據分區使用固態IO卡,使用xfs文件系統等。
對於mysql架構設計優化,這個很是重要,sql語句優化,表存儲引擎(MyISAM,
InnoDB)選擇,使用索引,增長redis或者memcached緩存層等。將傳統web服務的2層架構(webserver+db)變成三層架構(webserver+cache+db)甚至四層架構(webserver+logicserver+cache+db),由cache來承擔分流大併發讀寫操做。
對於存儲引擎選擇有2個原則:第一個原則,大量讀少許寫 選用MyISAM,大量寫少許讀選用InnoDB。針對不一樣的需求使用不一樣的存儲引擎。第二個原則,能不用InnoDB儘可能不用InnoDB。總之,若是你想追求99.9%的穩定性,方便的擴展性和高可用性仍是儘可能用MyISAM吧。
至於爲何呢?
1 MyISAM的索引和數據是分開的,而且索引是有壓縮的,內存使用率就對應提升了很多。能加載更多索引,而InnoDB是索引和數據是緊密捆綁的,沒有使用壓縮從而會形成InnoDB比MyISAM體積龐大很多。
2 InnoDB的行級鎖是相對的,那個只有where主鍵時是有效,非主鍵的都會鎖全表的。若是在執行一個SQL語句時MySQL不能肯定要掃描的範圍,InnoDB表一樣會鎖全表,例如update table set num=1 where name like 「%aaa%」
3 MyISAM相對簡單因此在效率上要優於InnoDB。小型應用使用MyISAM是不錯的選擇。另外,MyISAM表是保存成文件的形式,在跨平臺的數據轉移很方便。
總之,儘可能不使用InnoDB,InnoDB主要用於須要外鍵,事務等企業級支持,代價是速度比MyISAM有倍數的降低。
下面主要講mysql參數配置優化:
準備一個工具:http://pan.baidu.com/s/1M8Ectuning-primer.sh mysql性能報告工具。
在開始優化以前先測試一下當前mysql併發狀況及系統資源消耗狀況。用mysql自帶的併發測試工具,測試myisam及innodb引擎,開啓100個併發分別寫入20000條數據而且查詢20000次。統計消耗時間及系統資源使用狀況。
下圖19結果展現了分別讀寫myisam和innodb效率:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖19
下圖20是對應的資源消耗狀況:
![](http://static.javashuo.com/static/loading.gif)
系統總體CPU及IO
![](http://static.javashuo.com/static/loading.gif)
CPU
![](http://static.javashuo.com/static/loading.gif)
磁盤
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
內存
圖20
經過結果能夠看出mysql佔用內存過高。寫入2萬次myisam引擎平均須要2秒鐘,innodb平均須要70秒鐘,寫入時瓶頸出如今IO。讀取2萬次 兩種引擎須要時間至關,4.3秒左右,讀取瓶頸出如今CPU。
接下來經過運行tuning-primer.sh工具,獲取初步配置建議:
# chmod +x tuning-primer.sh
# sh tuning-primer.sh 根據提示繼續
結果中紅色部分是當前配置不恰當的地方,根據實際狀況進行優化。
接下來咱們開始一步一步優化 /etc/my.cnf
本文重點以優化MyISAM 引擎爲例。在[mysqld]部分增長如下內容:
1關閉innodb引擎
default-storage-engine=MYISAM
innodb=OFF
2 開啓慢查詢日誌記錄,便於抓出查詢速度較慢的語句進行優化查詢。
long_query_time=2 #當某個查詢時間超過2s時記錄下來
log-slow-queries= /usr/local/webserver/mysql/logs/slowquery.log
3 調整max_connections
容許的同時連接的客戶端數量,默認數值是100。若是常常看到 Too many connections 錯誤,則增大該值。小型服務器通常默認100就夠了,本文這裏設置爲200
3 優化myisam 寫入效率。
分別併發100,200,寫入10萬次,統計系統資源使用狀況,如圖21所示:
bin/mysqlslap --concurrency=100 --iterations=1 --number-int-cols=4 --number-char-cols=35 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=write --engine=myisam --number-of-queries=100000 --debug-info --verbose -uroot -predis123
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
併發100系統總體CPU及IO 併發100空閒內存
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
併發200系統總體CPU及IO 併發200空閒內存
圖21
由上圖資源使用狀況可見,myisam寫入的主要瓶頸在系統CPU和IO,因此經過配置參數來作寫入優化提高空間有限,這時候就得考慮作數據庫集羣了。
4 優化myisam 讀取效率
分別併發100,200,讀取10萬次,統計系統資源使用狀況,如圖22所示:
bin/mysqlslap --concurrency=100 --iterations=1 --number-int-cols=4 --number-char-cols=35 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=read --engine=myisam --number-of-queries=100000 --debug-info --verbose -uroot -predis123
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
併發100系統總體CPU及IO 併發100空閒內存
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
併發200系統總體CPU及IO 併發200空閒內存
圖23
由上圖資源使用狀況,myisam併發讀主要瓶頸在CPU,且內存空閒率也比較多。下面經過優化myisam參數,提高併發讀效率。修改 /etc/my.cnf mysql配置文件。
4.1 增長 key_buffer_size
用於索引塊的緩衝區大小,增長它可更好處理索引,若是隻是使用MyISAM表,能夠把它設置爲可用內存的 30-40%。具體根據mysql當前負載狀況設置,要看Key_reads和 Key_read_requests比例,若是Key_reads 從硬盤讀取鍵的數據塊的次數。若是Key_reads較大,則Key_buffer_size值可能過小。能夠用Key_reads/Key_read_requests計算緩存損失率。
![](http://static.javashuo.com/static/loading.gif)
本文將key_buffer_size設置爲 256M
4.2 增長read_buffer_size大小
順序讀取數據時的緩衝區大小,該參數分配的內存也是以每鏈接爲單位的。read_buffer_size 是用來當須要順序讀取數據的時候,沒法使用索引的狀況下的全表掃描,全索引掃描等狀況下,會按照數據的存儲順序依次讀取數據塊,每次讀取的數據快首先會暫存在 read_buffer_size 中,當 buffer 空間被寫滿或者所有數據讀取結束後,再將 buffer 中的數據返回給上層調用者,以提升效率。
本文將read_buffer_size 設置爲 2M。
4.3 增長 query_cache_size 大小
該參數對應 緩存sql語句及其結果的功能。在下次接收到一樣的查詢請求時,再也不執行實際查詢處理而直接返 回結果,有這樣的查詢緩存能提升查詢的速度,使查詢性能獲得優化,前提條件是你有大量的相同或類似的查詢,而不多改變表裏的數據,不然沒有必要使用此功 能。注意:若是你查詢的表更新比較頻繁,並且不多有 相同的查詢,最好不要使用查詢緩存。設置完以後最好是跟蹤一段時間,查看是否運行良好。在必定的負載壓力下,若是緩存命中率過低了,就啓用它。
本文將query_cache_size設置爲32M
4.4另外還有其它參數,根據系統狀況調整。
thread_cache — 線程的建立和銷燬的開銷可能很大,由於每一個線程的鏈接/斷開都須要。我一般至少設置爲 16。
table_cache — 緩存打開的表。一般要加大緩存數量,使得足以最大限度地緩存打開的表。若是你有200多個表的話,那麼設置爲 1024 也許比較合適(每一個線程都須要打開表),若是鏈接數比較大那麼就加大它的值。
關於INNODB的參數本文暫不做講解。
保存以上修改,重啓mysql,一樣分別併發100,200 讀取10萬次,統計消耗時間,及系統資源使用狀況,以下圖24所示。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
併發100系統總體CPU及IO 併發100空閒內存
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
併發200系統總體CPU及IO 併發200空閒內存
圖24
因而可知,優化以後與優化以前對比,myisam總體讀取性能有了很大提高。
進行php優化
對於一個web服務來講,除去mysql瓶頸,最影響性能的瓶頸是php等動態語言。而數據庫瓶頸,能夠經過第三方解決方案緩解,好比採用分佈式數據庫,採用內存數據庫加速等。解決了數據庫瓶頸,接下來就要解決動態語言php瓶頸了。好的解決辦法無非這幾種:
1 頁面靜態化,儘可能避免請求動態解析。
2 採用第三方php加速器,經過緩存PHP代碼編譯後的結果來提升PHP腳本的性能,優化PHP代碼執行速度,下降服務器負載,能夠提升PHP應用執行速度最高達幾倍,甚至十幾倍。比較有名的加速器有,Zend Opcache,xcache,eAccelerator。
在php 5.5 及以上的版本中已經內置了Zend Opcache,而本文用的php 5.5.5,所以不須要作這步優化了。
3 經過配置php參數,充分利用系統硬件資源,從而提升服務效率。本文主要講解這一部分。
在優化以前仍是作個測試,並統計系統資源使用狀況。
首先編寫一個php頁面,使用ab工具,啓動1000個併發,發起1萬個請求。
測試結果以下圖25所示。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
系統總體CPU及IO狀況內存
圖25
每秒系統處理請求 166.34個併發,很是低。而且經過資源消耗狀況看,在請求開始的前10s CPU使用率很是高,接下來接着CPU使用率突降,IO一直波動。另外,內存使用一直較低。
接下來查看一下系統日誌及nginx錯誤日誌:
# tail /var/log/message
![](http://static.javashuo.com/static/loading.gif)
系統提示相似洪水攻擊。
![](http://static.javashuo.com/static/loading.gif)
Nginx錯誤日誌中則出現大量連接php錯誤
![](http://static.javashuo.com/static/loading.gif)
另外,TIME_WAIT數也相對太高
由此推斷,php鏈接數配置太低?
下面開始優化php配置,vi php/etc/php-fpm.conf
1 增大php-fpm對打開文件描述符的限制
rlimit_files = 65536
2設置容許訪問Fastcgi進程解析器的IP地址,更加安全
listen.allowed_clients = 127.0.0.1
3 增大請求緩衝隊列大小
listen.backlog = 2048 默認爲128,有點小,增大這個參數,能夠解決系統日誌中攻擊提示問題以及nginx錯誤日誌中的連接錯誤。
4 pm.max_requests = 1024由 500改成1024
此時再作測試,結果以下圖26所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
併發提高了,達到882.28個每秒,比優化前的166.34 提高了5倍之多,而且TIME_WAIT數量也大大減小,降到合理範圍內。
![](http://static.javashuo.com/static/loading.gif)
系統總體CPU及IO使用狀況
![](http://static.javashuo.com/static/loading.gif)
內存使用狀況
圖26
繼續優化,達到併發5000以上,才告一段落:
在nginx配置中使用fast_cgi緩存,在http段加入如下內容:
fastcgi_temp_path /dev/shm/fastcgi_temp;
#cache設置
fastcgi_cache_path /dev/shm/fastcgi_cache levels=1:2
keys_zone=cfcache:10m inactive=50m max_size=256;
//爲FastCGI緩存指定一個路徑,目錄結構等級,關鍵字區域存儲時間和非活動刪除時間。以及最大佔用空間。
fastcgi_cache_key "$request_method://$host$request_uri";
fastcgi_cache_methods GET HEAD;
fastcgi_cache cfcache; //開啓FastCGI緩存而且爲其制定一個名稱。
fastcgi_cache_valid 200 302 301 1h;
fastcgi_cache_valid any 5m; //爲指定應答代碼指定緩存時間,這裏指定200 302 301應答緩存1小時,其他任何應答緩存5分鐘
fastcgi_cache_min_uses 1; //緩存在fastcgi_cache_path內文件在inactive參數值時間內的最少使用次數,如上例,這裏在50分鐘內某文件1次也沒有被使用,那麼這個文件將被移除。
fastcgi_cache_use_stale error timeout invalid_header http_500;//對於error timeout invalid_header http_500等類型的應答內容不緩存
fastcgi_ignore_client_abort on;//忽略客戶端終止請求
重啓nginx ,併發1000發送10萬個請求,統計執行效率及系統資源消耗狀況。以下圖27所示。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖27
由測試結果可知,優化以後併發達到 6004.95個。系統CPU及IO利用率也比較合理,內存佔用較小,總體比較理想。
優化總結
本文采用的測試機是普通的2G內存筆記本,再作優化沒有多大意義,實際生產環境中在運行着大併發請求的真實服務器上進行優化比較準確。本文Lnmp優化到此告一段落吧。
經過合理架構,合理代碼邏輯,通過優化以後服務輕鬆能夠達到併發1-2w。
http://php.itcast.cn/news/20140211/10284488889.shtml