1.什么是LNMP?
也许大家对LAMP比较熟悉,LAMP代表Linux下Apache、MySQL、PHP这种网站服务器架构;同上LNMP代表的就是Linux下Nginx、MySQL、PHP这种网站服务器架构。
2.我们为什么要采用LNMP这种架构呢?
使用Linux、PHP外加MySQL的优点我就无需多说相信大家也都很明了。
Nginx是一个轻量级且高效的Linux下的Web服务器软件,最初是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的反向代理工具,02年的时候他将源代码公开出来,成为了一个开源软件。
Nginx相当的稳定、功能丰富、安装配置简单、低系统资源……
3.LNMP这种架构有什么优势?
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,而且在访问静态页面的时候有着无与伦比的性能和效率。
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。
Nginx 配置文件非常简洁(还能够支持perl语法),Bugs少,启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下进行软件版本的升级。
Nginx的官方网站:http://nginx.org/
接下来,依然是,一步步搭建LNMP的开始!最后,我们将通过手动的检测,去发现自己构建的LNMP到底有多大的能力!
阅读示例:
文中所有需要在终端界面输入的命令,都是用代码框的形式展现
如:
- ulimit
-SHn 65535 - /usr/local/php/sbin/php-fpm
start
文中所有使用文本编辑器打开或者编辑配置文件的内容,都使用“引用框”来展现。配置文件中写入的内容都在引用框中用灰色字体展现。
如:
vim /etc/profile PATH=$PATH:/usr/local/mysql/bin |
一、准备工作:
(1)我们采用虚拟机的形式来构建整个服务器。
虚拟机:512M内存(你会看到512M内存的情况下Nginx带来的超高并发请求)
系统:Redhat5.4 (Kernel:2.6.18)
(2)我们编译安装所需的开发组件包都是通过yum直接安装的。yum源指向的是http://mirrors.163.com,当然如果你使用自己的光盘也是可以的。构建LNMP所需要的编译源码包,大都通过官方网站下载。
需要准备的源码包,及其下载地址:(在下载之前最好先建立一个目录方便保存我们的源码包,本文使用/root/lnmp) wget wget http://fastlnmp.googlecode.com/files/php-5.2.14.tar.gz wget http://php-fpm.org/downloads/php-5.2.14-fpm-0.5.14.diff.gz wget http://download.softagency.net/mysql/Downloads/MySQL-5.5/mysql-5.5.15-linux2.6-i686.tar.gz wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz wget http://lcmp.googlecode.com/files/libmcrypt-2.5.8.tar.gz wget http://vps.googlecode.com/files/mcrypt-2.6.8.tar.gz wget http://lnmp-v4.googlecode.com/files/memcache-2.2.5.tgz wget http://acelnmp.googlecode.com/files/mhash-0.9.9.9.tar.gz wget http://acelnmp.googlecode.com/files/pcre-8.10.tar.gz wget http://acelnmp.googlecode.com/files/eaccelerator-0.9.6.1.tar.bz2 wget http://vps.googlecode.com/files/PDO_MYSQL-1.0.2.tgz wget ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz wget http://lnmpp.googlecode.com/files/imagick-2.3.0.tgz |
二,完整编译安装的开始!
(1)编译安装PHP 5.2.14所需的支持库:
- tar
zxvf libiconv-1.13.1.tar.gz - cd
libiconv-1.13.1/ - ./configure
–prefix=/usr/local - make
- make
install - cd
../
- tar
zxvf libmcrypt-2.5.8.tar.gz - cd
libmcrypt-2.5.8/ - ./configure
- make
- make
install - /sbin/ldconfig
- cd
libltdl/ - ./configure
–enable-ltdl-install - make
- make
install - cd
../../
- tar
zxvf mhash-0.9.9.9.tar.gz - cd
mhash-0.9.9.9/ - ./configure
- make
- make
install - cd
../
- ln
-s /usr/local/lib/libmcrypt.la /usr/lib/libmcrypt.la - ln
-s /usr/local/lib/libmcrypt.so /usr/lib/libmcrypt.so - ln
-s /usr/local/lib/libmcrypt.so.4 /usr/lib/libmcrypt.so.4 - ln
-s /usr/local/lib/libmcrypt.so.4.4.8 /usr/lib/libmcrypt.so.4.4.8 - ln
-s /usr/local/lib/libmhash.a /usr/lib/libmhash.a - ln
-s /usr/local/lib/libmhash.la /usr/lib/libmhash.la - ln
-s /usr/local/lib/libmhash.so /usr/lib/libmhash.so - ln
-s /usr/local/lib/libmhash.so.2 /usr/lib/libmhash.so.2 - ln
-s /usr/local/lib/libmhash.so.2.0.1 /usr/lib/libmhash.so.2.0.1 - ln
-s /usr/local/bin/libmcrypt-config /usr/bin/libmcrypt-config
- tar
zxvf mcrypt-2.6.8.tar.gz - cd
mcrypt-2.6.8/ - /sbin/ldconfig
- ./configure
- make
- make
install - cd
../
(2)绿色二进制包安装MySQL 5.5.15
①:安装过程
- ##
为MySQL建立用户和组 - groupadd
-g 3306 mysql - useradd
-g mysql -u 3306 -s /sbin/nologin -M mysql -
- ##
二进制安装方式 - tar
xf mysql-5.5.15-linux2.6-i686.tar.gz -C /usr/local - ln
-sv /usr/local/mysql-5.5.15-linux.2.6-i686 /usr/local/mysql -
- mkdir
/mydata ## 创建数据保存目录 - chown
-R mysql:mysql /mydata/ - cd
/usr/local/mysql - scripts/mysql_install_db
–user=mysql –datadir=/mydata/data - chown
-R root . -
- ##
加入启动脚本 - cp
support-files/mysql.server /etc/init.d/mysqld - chkconfig
–add mysqld -
- ##修改配置文件
- cp
support-files/my-large.cnf /etc/my.cnf - ## 加入mySQL命令
- export PATH=$PATH:/usr/local/mysql/bin
- ## 定义头文件
- ln -sv /usr/local/mysql/include /usr/include/mysql
- ldconfig
②:配置过程
vim /etc/my.cnf 在[mysqld]段内加入并修改以下两处 datadir = /mydata/data thread_concurrency 2 |
vim /etc/profile PATH=$PATH:/usr/local/mysql/bin |
vim /etc/ld.so.conf.d/mysql.conf /usr/local/mysql/lib |
③:启用过程
- service
mysqld start - cd /root/lnmp
输入以下SQL语句,创建一个具有root权限的用户(admin)和密码(12345678): GRANT ALL PRIVILEGES ON *.* TO ‘admin’@'localhost’ IDENTIFIED BY ’12345678′; GRANT ALL PRIVILEGES ON *.* TO ‘admin’@’127.0.0.1′ IDENTIFIED BY ’12345678′; |
(3)编译安装PHP(FastCGI模式)
- tar
zxvf php-5.2.14.tar.gz - gzip
-cd php-5.2.14-fpm-0.5.14.diff.gz | patch -d php-5.2.14 -p1 - cd
php-5.2.14/ -
- ./configure
–prefix=/usr/local/php \ - –with-config-file-path=/usr/local/php/etc
\ - –with-mysql=/usr/local/mysql
\ - –with-mysqli=/usr/local/mysql/bin/mysql_config
\ - –with-iconv-dir=/usr/local
\ - –with-freetype-dir
\ - –with-jpeg-dir
\ - –with-png-dir
\ - –with-zlib
\ - –with-libxml-dir=/usr
\ - –enable-xml
\ - –disable-rpath
\ - –enable-discard-path
\ - –enable-safe-mode
\ - –enable-bcmath
\ - –enable-shmop
\ - –enable-sysvsem
\ - –enable-inline-optimization
\ - –with-curl
–with-curlwrappers \ - –enable-mbregex
\ - –enable-fastcgi
\ - –enable-fpm
\ - –enable-force-cgi-redirect
\ - –enable-mbstring
–with-mcrypt \ - –with-gd
–enable-gd-native-ttf \ - –with-openssl
\ - –with-mhash
\ - –enable-pcntl
\ - –enable-sockets
\ - –with-ldap
\ - –with-ldap-sasl
\ - –with-xmlrpc
\ - –enable-zip
\ - –enable-soap
-
- make
ZEND_EXTRA_LIBS=‘-liconv’ - make
install - cp
php.ini-dist /usr/local/php/etc/php.ini - cd
../
(4)编译安装PHP5扩展模块
- tar
zxvf memcache-2.2.5.tgz - cd
memcache-2.2.5/ - /usr/local/php/bin/phpize
- ./configure
–with-php-config=/usr/local/php/bin/php-config - make
- make
install - cd
../
- tar
jxvf eaccelerator-0.9.6.1.tar.bz2 - cd
eaccelerator-0.9.6.1/ - /usr/local/php/bin/phpize
- ./configure
–enable-eaccelerator=shared \ - –with-php-config=/usr/local/php/bin/php-config
- make
- make
install - cd
../
- tar
zxvf PDO_MYSQL-1.0.2.tgz - cd
PDO_MYSQL-1.0.2/ - /usr/local/php/bin/phpize
- ./configure
–with-php-config=/usr/local/php/bin/php-config \ - –with-pdo-mysql=/usr/local/mysql
- make
- make
install - cd
../
- tar
zxvf ImageMagick.tar.gz - cd
ImageMagick-6.5.1-2/ - ./configure
- make
- make
install - cd
../
- tar
zxvf imagick-2.3.0.tgz - cd
imagick-2.3.0/ - /usr/local/php/bin/phpize
- ./configure
–with-php-config=/usr/local/php/bin/php-config - make
- make
install - cd
../
(5)修改php.ini文件
手工修改: 查找/usr/local/php/etc/php.ini中的extension_dir = “./” 修改为 extension_dir = “/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/” 增加以下几行 extension = “memcache.so” extension = “pdo_mysql.so” extension = “imagick.so” 再查找output_buffering = Off 再查找 |
(6)配置eAccelerator加速PHP:
- mkdir
-p /usr/local/eaccelerator_cache - vi
/usr/local/php/etc/php.ini
跳到配置文件的最末尾,加上以下配置信息:
[eaccelerator] zend_extension=”/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/eaccelerator.so” eaccelerator.shm_size=”64″ eaccelerator.cache_dir=”/usr/local/eaccelerator_cache” eaccelerator.enable=”1″ eaccelerator.optimizer=”1″ eaccelerator.check_mtime=”1″ eaccelerator.debug=”0″ eaccelerator.filter=”" eaccelerator.shm_max=”0″ eaccelerator.shm_ttl=”3600″ eaccelerator.shm_prune_period=”3600″ eaccelerator.shm_only=”0″ eaccelerator.compress=”1″ eaccelerator.compress_level=”9″ |
(7)创建www用户和组,以及虚拟主机使用的目录:
- /usr/sbin/groupadd
www - /usr/sbin/useradd
-g www www - mkdir
-p /web - chmod
+w /web - chown
-R www:www /web
(8)创建php-fpm配置文件(php-fpm是为PHP打的一个FastCGI管理补丁,可以平滑变更php.ini配置而无需重启php-cgi):
在/usr/local/php/etc/目录中创建php-fpm.conf文件:
- rm
-f /usr/local/php/etc/php-fpm.conf - vim
/usr/local/php/etc/php-fpm.conf
输入以下内容 <?xml version=”1.0″ ?> <configuration> </configuration> |
(9)启动php-cgi进程,监听127.0.0.1的9000端口,进程数为128(如果服务器内存小于3GB,可以只开启64个进程),用户为www:
- ulimit
-SHn 65535 - /usr/local/php/sbin/php-fpm
start
注意:如果要重启,可以使用 reload 命令
三、安装Nginx 1.1.3
(1)安装Nginx所需的pcre库:
- tar
zxvf pcre-8.10.tar.gz - cd
pcre-8.10/ - ./configure
- make
&& make install - cd
../
(2)安装Nginx
- tar
zxvf nginx-1.1.3.tar.gz - cd
nginx-1.1.3/ -
- ./configure
–user=www \ - –group=www
\ - –prefix=/usr/local/nginx
\ - –with-http_stub_status_module
\ - –with-http_ssl_module
-
- make
&& make install - cd
../
(3)创建Nginx日志目录
- mkdir
-p /web/logs - chmod
+w /web/logs - chown
-R www:www /web/logs
(4)创建Nginx配置文件
在/usr/local/nginx/conf/目录中创建nginx.conf文件:
- rm
-f /usr/local/nginx/conf/nginx.conf - vi
/usr/local/nginx/conf/nginx.conf
输入以下内容:
user worker_processes 8; error_log pid #Specifies the value for maximum file descriptors that can be opened by this process. worker_rlimit_nofile 65535; events { use epoll; worker_connections 65535; } http { include default_type #charset server_names_hash_bucket_size 128; client_header_buffer_size 32k; large_client_header_buffers 4 32k; client_max_body_size 8m; sendfile on; tcp_nopush keepalive_timeout 60; tcp_nodelay on; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; gzip on; gzip_min_length gzip_buffers gzip_http_version 1.0; gzip_comp_level 2; gzip_types gzip_vary on; #limit_zone server { listen server_name index index.html index.htm index.php; root #limit_conn location ~ .*\.(php|php5)?$ { #fastcgi_pass fastcgi_pass fastcgi_index index.php; include fcgi.conf; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires } location ~ .*\.(js|css)?$ { expires } location /status { stub_status on; } log_format ‘$status $body_bytes_sent “$http_referer” ‘ ‘”$http_user_agent” $http_x_forwarded_for’; access_log } } |
②、在/usr/local/nginx/conf/目录中创建.conf文件:
- vi
/usr/local/nginx/conf/fcgi.conf
输入以下内容:
fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param fastcgi_param # PHP only, required if PHP was built with –enable-force-cgi-redirect fastcgi_param |
(5)启动Nginx
- ulimit
-SHn 65535 - /usr/local/nginx/sbin/nginx
(6)配置开机自动启动Nginx + PHP
- vim
/etc/rc.local
在末尾增加以下内容:
ulimit -SHn 65535 /usr/local/php/sbin/php-fpm start /usr/local/nginx/sbin/nginx |
四、简单优化,实现高并发!
(1)Nginx的优化
一般来说nginx 配置文件中对优化比较有作用的为以下几项:
worker_processes 8; nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数。 worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 为每个进程分配cpu,上例中将8 个进程分配到8 个cpu,当然可以写多个,或者将一个进程分配到多个cpu。 worker_rlimit_nofile 102400; 这个指令是指当一个nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx 进程数相除,但是nginx 分配请求并不是那么均匀,所以最好与ulimit-n 的值保持一致。 use epoll; 使用epoll 的I/O 模型,这个不用说了吧。 worker_connections 102400; 每个进程允许的最多连接数, 理论上每台nginx 服务器的最大连接数为worker_processes*worker_connections。 keepalive_timeout 60; keepalive 超时时间。 client_header_buffer_size 4k; 客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE 取得。 open_file_cache max=102400 inactive=20s; 这个将为打开文件指定缓存,默认是没有启用的,max 指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。 open_file_cache_valid 30s; 这个是指多长时间检查一次缓存的有效信息。 open_file_cache_min_uses 1; open_file_cache 指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。 |
(2)关于内核参数的优化:请修改文件/etc/sysctl.conf
net.ipv4.tcp_max_tw_buckets = 6000 timewait 的数量,默认是180000。 net.ipv4.ip_local_port_range = 1024 65000 允许系统打开的端口范围。 net.ipv4.tcp_tw_recycle = 1 启用timewait 快速回收。 net.ipv4.tcp_tw_reuse = 1 开启重用。允许将TIME-WAIT sockets 重新用于新的TCP 连接。 net.ipv4.tcp_syncookies = 1 开启SYN Cookies,当出现SYN 等待队列溢出时,启用cookies 来处理。 net.core.somaxconn = 262144 web 应用中listen 函数的backlog 默认会给我们内核参数的net.core.somaxconn 限制到128,而nginx 定义的NGX_LISTEN_BACKLOG 默认为511,所以有必要调整这个值。 net.core.netdev_max_backlog = 262144 每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。 net.ipv4.tcp_max_orphans = 262144 系统中最多有多少个TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS 攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。 net.ipv4.tcp_max_syn_backlog = 262144 记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M 内存的系统而言,缺省值是1024,小内存的系统则是128。 net.ipv4.tcp_timestamps = 0 时间戳可以避免序列号的卷绕。一个1Gbps 的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。 net.ipv4.tcp_synack_retries = 1 为了打开对端的连接,内核需要发送一个SYN 并附带一个回应前面一个SYN 的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。 net.ipv4.tcp_syn_retries = 1 在内核放弃建立连接之前发送SYN 包的数量。 net.ipv4.tcp_fin_timeout = 1 如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2 状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒。2.2 内核的通常值是180 秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB 服务器,也有因为大量的死套接字而内存溢出的风险,FIN- WAIT-2 的危险性比FIN-WAIT-1 要小,因为它最多只能吃掉1.5K 内存,但是它们的生存期长些。 net.ipv4.tcp_keepalive_time = 30 当keepalive 起用的时候,TCP 发送keepalive 消息的频度。缺省是2 小时。 |
(3)关于FastCGI 的几个指令:
fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 keys_zone=TEST:10m 这个指令为FastCGI 缓存指定一个路径,目录结构等级,关键字区域存储时间和非活动删除时间。 fastcgi_connect_timeout 300; 指定连接到后端FastCGI 的超时时间。 fastcgi_send_timeout 300; 向FastCGI 传送请求的超时时间,这个值是指已经完成两次握手后向FastCGI 传送请求的超时时间。 fastcgi_read_timeout 300; 接收FastCGI 应答的超时时间,这个值是指已经完成两次握手后接收FastCGI 应答的超时时间。 fastcgi_buffer_size 4k; 指定读取FastCGI 应答第一部分需要用多大的缓冲区,一般第一部分应答不会超过1k,由于页面大小为4k,所以这里设置为4k。 fastcgi_buffers 8 4k; 指定本地需要用多少和多大的缓冲区来缓冲FastCGI 的应答。 fastcgi_busy_buffers_size 8k; 这个指令我也不知道是做什么用,只知道默认值是fastcgi_buffers 的两倍。 fastcgi_temp_file_write_size 8k; 在写入fastcgi_temp_path 时将用多大的数据块,默认值是fastcgi_buffers 的两倍。 fastcgi_cache TEST 开启FastCGI 缓存并且为其制定一个名称。个人感觉开启缓存非常有用,可以有效降低CPU 负载,并且防止502 错误。 fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 fastcgi_cache_valid any 为指定的应答代码指定缓存时间,如上例中将200,302 应答缓存一小时,301 应答缓存1 天,其他为1 分钟。 fastcgi_cache_min_uses 1; 缓存在fastcgi_cache_path 指令inactive 参数值时间内的最少使用次数,如上例,如果在5 分钟内某文件1 次也没有被使用,那么这个文件将被移除。 fastcgi_cache_use_stale error timeout invalid_header http_500; 不知道这个参数的作用,猜想应该是让nginx 知道哪些类型的缓存是没用的。 |
(4)使用php-fpm 来管理FastCGI,可以修改配置文件中的以下值:
<value name=”max_children”>60</value> 同时处理的并发请求数,即它将开启最多60 个子线程来处理并发连接。 <value name=”rlimit_files”>102400</value> 最多打开文件数。 <value name=”max_requests”>204800</value> 每个进程在重置之前能够执行的最多请求数。 |
(5)下面贴几张测试结果图。
测试是使用apache自带的ab命令进行压力测试:
- ab
-c 10000 -n 20000 http://192.168.0.156/index.php
没有优化前:不管如何,就是上不了1W5……
优化之后:轻轻松松突破2W
你可曾想过这是512M内存的实力?
也希望各位能在实现之后使用Webbench测试工具进行并发峰值5W+的测试,我相信,512M的服务器,完全能够轻松对付。
感谢各位的阅读~
如果你觉得这篇博文对你有用,欢迎留言讨论~(反贼在这里感激不尽~哈!)