+
Mysql+Php/perl/python ), LEMP 架構隻是把提供 web 服務的 Apache 改用為 Nginx 。進而形成 Linux+Nginx )架構。目前企業級别應用 在創下許多驚人戰績。目前國内以張宴為代表,掀起了nginx的狂潮,首先簡單介紹下什麼是nginx.
Nginx(發音同 engine x)是一款輕量級的Web 伺服器/反向代理伺服器及電子郵件(IMAP/POP3)代理伺服器,并在一個BSD-like 協定下發行。由俄羅斯的程式設計師Igor Sysoev所開發,最初供俄國大型的入口網站及搜尋引擎Rambler(俄文:Рамблер)使用。 其特點是占有記憶體少,并發能力強,事實上nginx的并發能力确實在同類型的網頁伺服器中表現較好.目前中國大陸使用nginx網站使用者有:新浪、網易、 騰訊,另外知名的微網志Plurk也使用nginx。
為什麼Nginx的性能要比Apache高得多?
這得益于Nginx使用了最新的epoll(Linux 2.6核心)和kqueue(freebsd)網絡I/O模型,而Apache則使用的是傳統的select模型。目前Linux下能夠承受高并發通路的Squid、Memcached都采用的是epoll網絡I/O模型。
處理大量的連接配接的讀寫,Apache所采用的select網絡I/O模型非常低效。
Nginx 是一個很牛的高性能Web和反向代理伺服器, 它具有有很多非常優越的特性:
作為 Web 伺服器:相比 Apache,Nginx 使用更少的資源,支援更多的并發連接配接,展現更高的效率,這點使 Nginx 尤其受到虛拟主機提供商的歡迎。在高連接配接并發的情況下,Nginx是Apache伺服器不錯的替代品: Nginx在美國是做虛拟主機生意的老闆們經常選擇的軟體平台之一. 能夠支援高達 50,000 個并發連接配接數的響應, 感謝Nginx為我們選擇了 epoll and kqueue 作為開發模型.
Nginx作為負載均衡伺服器: Nginx 既可以在内部直接支援 Rails 和 PHP 程式對外進行服務, 也可以支援作為 HTTP代理 伺服器對外進行服務. Nginx采用C進行編寫, 不論是系統資源開銷還是CPU使用效率都比 Perlbal 要好很多. 。Nginx可作為7層負載均衡伺服器來使用。
作為郵件代理伺服器: Nginx 同時也是一個非常優秀的郵件代理伺服器(最早開發這個産品的目的之一也是作為郵件代理伺服器), Last.fm 描述了成功并且美妙的使用經驗.
Nginx 是一個安裝非常的簡單 , 配置檔案非常簡潔(還能夠支援perl文法), Bugs 非常少的伺服器: Nginx 啟動特别容易, 并且幾乎可以做到7*24不間斷運作,即使運作數個月也不需要重新啟動. 你還能夠不間斷服務的情況下進行軟體版本的更新 .
總體來說nginx的有以下八大優點:
1.高并發連接配接:官方測試能支撐5萬并發連接配接,在實際生産環境中跑到2,~3W并發連接配接。
2.記憶體消耗少:在3W并發連接配接下,開啟的10個NGINX程序才消耗150M記憶體(15M*10=150M)
3.配置檔案非常簡單:風格跟程式一樣通俗易懂。
4.成本低廉:Nginx作為開源軟體,可以免費使用,而購買F5 BIG-IP、NetScaler
等硬體負載均衡交換機則需要十多萬至幾十萬人民币。
5.支援rewrite重寫規則:能夠根據域名、URL的不同,将HTTP請求分發到不同的後端伺服器群組。
6.内置的健康檢查功能:如果Nginx Proxy後端的背景web伺服器當機了,不會音響前端通路。
7.節省帶寬:支援GZIP壓縮,可以添加浏覽器本地緩存的Header頭。
8.穩定性高:用于反向代理,當機的機率微乎其微。
介紹這麼多nginx 的優點.下面來具體實作下LEMP架構(linux+nginx+mysql+php/perl/python)
可能有朋友對靜态動态解析過程不太清楚,筆者按照自己了解簡單闡述,如有錯誤地方請前輩多加指點。
nginx隻是提供一個靜态web服務,動态web服務還需要與PHP等腳本語言結合使用。如圖所示:

用戶端在通路動态頁面時,因為apache和nginx隻能提供靜态解析,這是他們通過内置的cgi接口去尋找php等腳本語言,當需要用到資料部分時PHP會去調用背景MYSQL資料庫中的資料,之後通過解析生成靜态頁面在傳回apache/nginx伺服器,再由此傳遞給用戶端。
如果不清楚CGI和fastCGI筆者作以下簡要說明:
Perl、Python或者PHP原來在Web開發的時候應用得比較多,因為早期的web伺服器(當然還包括Apache)内建了CGI(通用網關接口)接口。CGI能夠以确定的方式讓Web伺服器在客戶機的浏覽器和外部應用程式之間交換資料。通過支援外部的、基于CGI的應用程式,Web開發人員能夠引進動态要素。使用這種接口開發經過編譯的應用程式相對來說比較複雜,但是,這種解釋性的語言通常包括這種功能,或者是直接包括這種功能(如使用PHP),或者通過标準子產品包括這種功能(如使用Perl和Python)。
FastCGI同CGI一樣是一個WEB伺服器與外部程式接口的标準,它是為解決CGI的性能問題而開發的一種技術。
CGI技術的性能缺陷:每當伺服器收到一個對CGI程式請求時,伺服器都将建立一個CGI程式的程序,CGI程式處理完請求後,将輸出發給伺服器或直接傳回用戶端,然後終止。
fastCGI對CGI技術進行了改良,一個fastCGI程序在WEB伺服器啟動時或在用戶端第一次請求時建立,它處理完用戶端請求後并不終止,而是等待處理下一個請求。另外fastCGI程式與CGI程式與伺服器的互動方式也不同,CGI程式通過環境變量、指令行、标準輸入輸出進行互動,是以CGI程式程序必須與伺服器程序在同一台實體計算機上,而fastCGI程式與伺服器程序通過網絡連接配接互動,是以fastCGI程式可以分布在不同的計算機上,這不但可以提高性能,同時也提高了系統的擴充能力。
下面開始源碼架設LEMP架構:
筆者所使用的平台為RHEL5.4 kernel版本2.6.18-164
2010年9月1日筆者在nginx官方網站上獲得的最新nginx版本資訊
簡單介紹所用包的關系以及原理
1.mysql-5.5.3-m3.tar.gz #LEMP架構中擔當資料庫伺服器即M
2.Nginx-0.7.65.tar.gz #提供web服務,提供靜态web服務
3.php5.3.3.tar.bz2 #提供php腳本語言用來解析動态頁面
需要說明以下幾點:
php在編譯安裝時,nginx要想能夠調用php提供動态php格式的網頁,必須用FastCGI來實作,但FastCGI隻是一個架構,實作FastCGI架構的有PHP-FPM,但對于5.2.x版本的php來說 預設是不支援PHP-FPM的,需要打上php-fpm的更新檔,對于5.3.2之前版本的也是需要打更新檔的,而且打更新檔的過程比較麻煩。好在5.3.3版本的PHP-FPM被直接做進了源代碼包中,在編譯安裝時隻需啟用PHP-FPM功能即可,筆者為了簡要實作功能,選用5.3.3版本來進行示範。
但如果要使用PHP-FPM的話,還需要提供以下幾個功能:
a.需要提供可以解析xml格式的文檔,需要安裝libxml2 和libxml2-devel這兩個包,好在這兩個包在安裝完開發環境後這兩個包是預設安裝過的。
b.需要安裝libevent并且在1.4.12之後的版本,不幸的是rhel5.4版本中這個包是是在1.4.12之前的,需要從新手動編譯安裝該包。
c. libiconv 用來提供網絡連接配接方式的功能元件,可以實作更快速的網絡通路,這個元件系統上是沒有裝的,需要手動編譯安裝。
通過以上說明,剩下2個包的作用應該是有所了解了。
4.libevent-1.4.14b-stable-tar.gz
5.libconv-1.13.1.tar.gz
好了,所有的準備活動已經就緒,接下來開始正式的×××LEMP架構
首先需要建構編譯環境可以直接挂載CD光牒進行yum安裝
yum -y install gcc openssl-devel zlib-devel pcre-devel yum groupinstall "Developement Tools" "Development Libraries" -yt |
好了安裝完開發環境下面就開始源碼安裝LEMP元件了
首先進入你源碼包的目錄,筆者放置的目錄是/root/soft
執行上面最後一條語句解壓
tar zxvf nginx-0.7.65.tar.gz cd nginx-0.7.65 useradd -s /sbin/nologin -M nginx # 添加一個不能登入的且沒有家目錄 名為nginx的使用者 ./configure \ #開始編譯 所帶的參數很容易了解筆者不多解釋 --prefix=/usr \ --sbin-path=/usr/sbin/nginx \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --pid-path=/var/run/nginx/nginx.pid \ --lock-path=/var/lock/nginx.lock \ --user=nginx \ --group=nginx \ --with-http_ssl_module \ --with-http_flv_module \ --with-http_stub_status_module \ --with-http_gzip_static_module \ --http-client-body-temp-path=/var/tmp/nginx/client/ \ --http-proxy-temp-path=/var/tmp/nginx/proxy/ \ --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ 編譯完成後沒有報錯就可以安裝了。 make && make install 編譯安裝完成後為了讓nginx開機啟動,筆者提供個systemV風格的腳本 vim /etc/init.d/nginxd |
把以下内容粘貼進去
#!/bin/sh # # nginx - this script starts and stops the nginx daemon # chkconfig: - 85 15 # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ # proxy and IMAP/POP3 proxy server # processname: nginx # config: /etc/nginx/nginx.conf # config: /etc/sysconfig/nginx # pidfile: /var/run/nginx.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/etc/nginx/nginx.conf" [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx lockfile=/var/lock/subsys/nginx make_dirs() { # make required directories user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -` options=`$nginx -V 2>&1 | grep 'configure arguments:'` for opt in $options; do if [ `echo $opt | grep '.*-temp-path'` ]; then value=`echo $opt | cut -d "=" -f 2` if [ ! -d "$value" ]; then # echo "creating" $value mkdir -p $value && chown -R $user $value fi fi done } start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 make_dirs echo -n $"Starting $prog: " daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval stop() { echo -n $"Stopping $prog: " killproc $prog -QUIT [ $retval -eq 0 ] && rm -f $lockfile restart() { configtest || return $? stop sleep 1 start reload() { echo -n $"Reloading $prog: " killproc $nginx -HUP RETVAL=$? force_reload() { restart configtest() { $nginx -t -c $NGINX_CONF_FILE rh_status() { status $prog rh_status_q() { rh_status >/dev/null 2>&1 case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 restart|configtest) reload) rh_status_q || exit 7 force-reload) force_reload status) rh_status condrestart|try-restart) ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2 esac |
儲存退出 并給/etc/init.d/nginxd 賦予執行權限
chmod +x /etc/init.d/nginxd
chkconfig --add nginxd ##讓入開機啟動選項中
chkconfig nginxd on #讓其開機自動啟動
service nginxd start #立即啟動nginx 服務
出現OK字樣 并且通過web浏覽器 通路該主機出現以下畫面 表示nginx 編譯完成并成功啟動
下面是編譯安裝MYSQL
Mysql
先解壓縮mysql-5.5.3-m3.tar.gz 需進入該源碼包所在目錄 筆者目錄為/root/soft tar zxvf mysql-5.5.3-m3.tar.gz #解壓縮到目前目錄 cd mysql-5.5.3-m3/ /usr/sbin/groupadd mysql #添加mysql使用者 /usr/sbin/useradd -g mysql mysql #添加mysql組 開始編譯、安裝 (具體參數不多介紹,都是些基本功能的啟用,有興趣者可以檢視mysql的官方文檔) ./configure --prefix=/usr/local/webserver/mysql/ --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-big-tables --with-readline --with-ssl --with-embedded-server --enable-local-infile --with-plugins=partition,innobase,myisammrg make && make install 編譯安裝時間可能有些長,需要耐心等待。。 chmod +w /usr/local/webserver/mysql #給mysql目錄寫的權限 chown -R mysql:mysql /usr/local/webserver/mysql #改變mysql目錄的屬組和屬主為mysql cd / mkdir /mysql/{data,binlog,relaylog} -p #建立mysql資料庫、日志存放目錄 chown -R mysql:mysql /mysql #改變/mysql的屬組和屬主為mysql 以mysql使用者帳号的身份建立資料表 /usr/local/webserver/mysql/bin/mysql_install_db --basedir=/usr/local/webserver/mysql -- --datadir=/mysql/data --user=mysql |
手動建立Mysql的配置檔案
vim /mysql/my.cnf [client] character-set-server = utf8 port = 3306 socket = /tmp/mysql.sock [mysqld] replicate-ignore-db = mysql replicate-ignore-db = test replicate-ignore-db = information_schema user = mysql basedir = /usr/local/webserver/mysql datadir = /mysql/data log-error = /mysql/mysql_error.log pid-file = /mysql/mysql.pid open_files_limit = 10240 back_log = 600 max_connections = 5000 max_connect_errors = 6000 table_cache = 614 external-locking = FALSE max_allowed_packet = 32M sort_buffer_size = 1M join_buffer_size = 1M thread_cache_size = 300 #thread_concurrency = 8 query_cache_size = 512M query_cache_limit = 2M query_cache_min_res_unit = 2k default-storage-engine = MyISAM thread_stack = 192K transaction_isolation = READ-COMMITTED tmp_table_size = 246M max_heap_table_size = 246M long_query_time = 3 log-slave-updates log-bin = /data0/mysql/3306/binlog/binlog binlog_cache_size = 4M binlog_format = MIXED max_binlog_cache_size = 8M max_binlog_size = 1G relay-log-index = /mysql/relaylog/relaylog relay-log-info-file = /mysql/relaylog/relaylog relay-log = /mysql/relaylog/relaylog expire_logs_days = 30 key_buffer_size = 256M read_buffer_size = 1M read_rnd_buffer_size = 16M bulk_insert_buffer_size = 64M myisam_sort_buffer_size = 128M myisam_max_sort_file_size = 10G myisam_repair_threads = 1 myisam_recover interactive_timeout = 120 wait_timeout = 120 skip-name-resolve #master-connect-retry = 10 slave-skip-errors = 1032,1062,126,1114,1146,1048,1396 #master-host = 192.168.1.1 #master-user = username #master-password = password #master-port = 3306 server-id = 1 innodb_additional_mem_pool_size = 16M innodb_buffer_pool_size = 512M innodb_data_file_path = ibdata1:256M:autoextend innodb_file_io_threads = 4 innodb_thread_concurrency = 8 innodb_flush_log_at_trx_commit = 2 innodb_log_buffer_size = 16M innodb_log_file_size = 128M innodb_log_files_in_group = 3 innodb_max_dirty_pages_pct = 90 innodb_lock_wait_timeout = 120 innodb_file_per_table = 0 #log-slow-queries = /mysql/slow.log #long_query_time = 10 [mysqldump] quick |
建立管理MySQL資料庫的shell腳本
vim /mysql/mysqld ###注意 下面的3,4行賬号密碼可以自行建立,第2行的預設端口3306一般不要改動。 #!/bin/sh mysql_port=3306 mysql_username="admin" mysql_password="123456" function_start_mysql() { printf "Starting MySQL...\n" /bin/sh /usr/local/webserver/mysql/bin/mysqld_safe --defaults-file=/mysql/my.cnf 2>&1 > /dev/null & function_stop_mysql() printf "Stoping MySQL...\n" /usr/local/webserver/mysql/bin/mysqladmin -u ${mysql_username} -p${mysql_password} -S /tmp/mysql.sock shutdown function_restart_mysql() printf "Restarting MySQL...\n" function_stop_mysql sleep 5 function_start_mysql function_kill_mysql() kill -9 $(ps -ef | grep 'bin/mysqld_safe' | grep ${mysql_port} | awk '{printf $2}') kill -9 $(ps -ef | grep 'libexec/mysqld' | grep ${mysql_port} | awk '{printf $2}') if [ "$1" = "start" ]; then elif [ "$1" = "stop" ]; then elif [ "$1" = "restart" ]; then function_restart_mysql elif [ "$1" = "kill" ]; then function_kill_mysql else printf "Usage: /mysql/mysqld {start|stop|restart|kill}\n" fi |
賦給shell腳本可執行權限
chmod +x /mysql/mysqld #該腳本可以用/mysql/mysqld start |restart |stop 來執行
啟動Mysql: /mysql/mysqld start 通過指令行登入管理MySQL伺服器(提示輸入密碼時直接回車): /usr/local/webserver/mysql/bin/mysql -u root -p -S /tmp/mysql.sock 輸入以下SQL語句,建立一個具有root權限的使用者(admin)和密碼(123456): GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' IDENTIFIED BY '123456'; GRANT ALL PRIVILEGES ON *.* TO 'admin'@'127.0.0.1' IDENTIFIED BY '123456'; |
至此Mysql已全部配置完成
PHP
首先 需要解壓編譯安裝
libevent-1.4.14b-stable-tar.gz
libconv-1.13.1.tar.gz
cd /root/soft 解壓編譯安裝libevent-1.4.14b-stable tar zxvf libevent-1.4.14b-stable.tar.gz cd libevent-1.4.14b-stable ./configure && make && make install --------------------------------------------------------------------------------------------------------- cd /root/soft tar zxvf libconv-1.13.1.tar.gz cd libiconv-1.13.1 ./configure make && make install |
好了,安裝PHP的準備工作完成,下面開始編譯安裝PHP
tar jxvf php-5.3.3.tar.bz2 cd php-5.3.3 ./configure --prefix=/usr/local/php --with-mysql=/usr/local/webserver/mysql --with-mysqli=/usr/local/webserver/mysql/bin/mysql_config --with-openssl --enable-fpm --with-libevent-dir=/usr/local --enable-mbstring --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --with-iconv-dir=/usr/local #需要說明兩點 1.--with-mysql和--with-mysqli的路徑是你mysql的具體所在的目錄 2.--enable-fpm 啟動fpm .其他都是些基本選項 ,簡單易懂 出現以下畫面表示編譯成功 下面就是安裝了 make ZEND_EXTRA_LIBS='-liconv' #因為-liconv的目錄不是在/usr/local下是以安裝時需要手動指定 說明: 如果在make 時,mysql的路徑沒有錯誤,但一直error,嘗試使用低版本的mysql在進行此步驟,因為可能存在版本差異的路徑bug。。 make install cp /root/soft/php-5.3.3/php.ini-production /usr/local/php/etc/php.ini |
全部安裝工作準備已經完成,剩下進行一些配置.
首先修改下面來配置修改 /usr/local/php/etc/php-fpm.conf 該配置檔案隻用修改以下四點 ; Note: Used when pm is set to either 'static' or 'dynamic' ; Note: This value is mandatory. pm.max_children = 50 ; The number of child processes created on startup. ; Note: Used only when pm is set to 'dynamic' ; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 pm.start_servers = 10 ; The desired minimum number of idle server processes. ; Note: Mandatory when pm is set to 'dynamic' pm.min_spare_servers = 5 ; The desired maximum number of idle server processes. pm.max_spare_servers = 35 隻需要把藍色部分前面的注釋去掉,修改完成,試着啟動 /usr/local/php/sbin/php-fpm & 啟動後用netstat -tnlp 檢視 如果有如圖所示端口 測表示正常啟動 如需要開機自動啟動 則可以添加到/etc/rc.d/rc.local中 vim /etc/rc.d/rc.local 在空白行添加 /usr/local/php/sbin/php-fpm & |
配置fastcgi_params 檔案 cd /etc/nginx/ vim fastcgi_params 将裡面内容替換為 fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; 儲存退出 |
下面就是最後修改nginx.conf配置檔案 vim /etc/nginx/nginx.conf 首先将 #user nobody; 改為user nginx; 之後找到 location ~ \.php$ { root /www; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; include fastcgi_params; } 把前面注釋全部去掉 root 後面的路徑是你網頁檔案所放置的路徑,筆者放在/www下 該目錄如果不存在的話還需要手動建立。 找到 location / { root /www; index index.php index.html index.htm; 修改為如上所示 主要是添加index 後面的index.php 修改完成後儲存退出,重新啟動nginx服務 service nginxd restart 之後編輯/www/index.php 在其中添加 <?php phpinfo(); ?> 之後用web浏覽器通路 如果出現如下畫面 表示服務成功,并能連接配接到php |
下面是測試msql 的連接配接 把剛才/www/index.php中的内容修改成 $link=mysql_connect("localhost","root","123456"); if(!$link) echo "FAILD!"; else echo "OK!"; 然後重新整理web頁面,如果出現OK!字樣 測表示正常連接配接 |