CentOS6下搭建高性能WEB服务器

前言

其实本文的作者我是个懒人,总喜欢在网上找一些现成的东西,而且还很屌丝买不起什么收费的产品,在互联网创业过程中,我早期使用Discuz所创建的一个小站,由于高峰期并发有好几百,导致服务器上其它应用程序受到影响,才开始钻研这些东西。那时什么都不懂,就会用远程桌面在Win2003系统中下载一个环境包安装,然后简单的复制与粘贴,直到后来在一些牛人的BLOG中学习,并逐渐认识了一些高人不耻上问,再加上平时与“谷哥”、“度娘”的形影不离,才逐渐成长起来。

在CentOS6下搭建高性能的LTMP环境

先给出这篇文章中的环境与硬件信息:
【这台自用服务器的硬件略屌丝有木有T.T】

操作系统 CentOS 6.5 (Linux)
WEB环境 LTMP (LNMP)
Linux + Tengine 1.5.2 (Nginx) + MariaDB 5.5.37 (MySQL) + PHP 5.4.29/5.3.28
优化组件 Memcached + Jemalloc + OPcache + Pthreads
硬件信息 Intel(R) Xeon(R) E5405 @ 2.00GHz CPU*2
2G DDR2 内存*4 (8G)
500G SATA 硬盘*2(Raid1)

或许很多人会对LTMP环境陌生,其实LTMP就是加强版本的LNMP,Tengine是由淘宝开发的Nginx分支,而MariaDB则是由MySQL的创始人新开发出的增强版MySQL,世界互联网巨头公司之一的Google就在使用,所在稳定与性能上,LTMP环境都经得起考验。

 

下图是我前段时间为了新项目开发,维护服务器时截取的,服务器在无人维护的情况下稳定运行了303天未出现任何问题,我们可以由此看出LTMP环境的稳定性。(当然这和访问压力不大也有关系)

 

另外,在服务器中遗留了一套LNMP环境,是我以前搞一个创业项目时,让一个参与者架设的,最近有时间看了下,发现架设的很不认真,自然性能上也好不到哪去,也证明了当年放弃和那人一起搞项目的正确性(好像跑题了),不过这套遗留下来的环境正好可以做测试,简单做了下承压对比,均使用PHP5.3版本,一样的程序得出两种不同结果:

 

根据对比可以看出,前后两者差距明显,在低并发的情况下,前者处理PHP文件的速度很慢,而随着并发数的增加,前者十分不稳定,甚至到了5000并发时就已经出现502错误。随后,我又进行了后者更高并发的测试,结果如下图:

→【WebBench网站压力测试教学

[返回目录]


一、获取相关开源程序

① 利用CentOS-Linux系统自带的yum命令安装、升级所需的程序库:

sudo -s
LANG=C
yum -y install gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers bison libevent-devel cmake wget

② 程序源码包下载:

建立源码包目录

mkdir -p /data0/software
cd /data0/software

下载所需源码包

wget http://tengine.taobao.org/download/tengine-1.5.2.tar.gz
wget http://cn2.php.net/distributions/php-5.4.36.tar.gz
wget http://mirrors.hustunique.com/mariadb/mariadb-5.5.41/source/mariadb-5.5.41.tar.gz
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.36.tar.gz
wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
wget http://downloads.sourceforge.net/mhash/mhash-0.9.9.9.tar.gz
wget http://downloads.sourceforge.net/mcrypt/libmcrypt-2.5.8.tar.gz
wget http://downloads.sourceforge.net/mcrypt/mcrypt-2.6.8.tar.gz
wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz
wget http://pecl.php.net/get/zendopcache-7.0.2.tgz
wget http://pecl.php.net/get/memcached-2.2.0.tgz
wget http://pecl.php.net/get/memcache-2.2.7.tgz
wget http://pecl.php.net/get/imagick-3.1.2.tgz
wget http://pecl.php.net/get/pthreads-2.0.7.tgz
wget http://www.memcached.org/files/memcached-1.4.20.tar.gz
wget ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz
wget http://www.canonware.com/download/jemalloc/jemalloc-3.6.0.tar.bz2 
wget http://www.openssl.org/source/openssl-1.0.1g.tar.gz

[返回目录]


二、安装MariaDB(MySQL) 5.5

① 编译安装Jemalloc:

tar jxvf jemalloc-3.6.0.tar.bz2
cd jemalloc-3.6.0/
./configure
make
make install
cd ../
ln -s /usr/local/lib/libjemalloc.so.1 /usr/lib/libjemalloc.so.1

如果是64位系统还需要输入

ln -s /usr/local/lib/libjemalloc.so.1 /usr/lib64/libjemalloc.so.1

② 编译安装MySQL:

创建mysql用户与用户组

/usr/sbin/groupadd mysql
/usr/sbin/useradd -g mysql mysql

编译安装MariaDB

tar zxvf mariadb-5.5.41.tar.gz
cd mariadb-5.5.41/
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/webserver/mysql -DMYSQL_UNIX_ADDR=/tmp/mysql.sock -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DEXTRA_CHARSETS=complex -DWITH_READLINE=1 -DWITH_SSL=system -DWITH_EMBEDDED_SERVER=1 -DENABLED_LOCAL_INFILE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DCMAKE_EXE_LINKER_FLAGS="-ljemalloc" -DWITH_SAFEMALLOC=OFF -DMYSQL_DATADIR=/data0/mysql/3306/data -DMYSQL_USER=mysql
make
make install
如果编译出错将参数 -DWITH_EMBEDDED_SERVER=1 删除并执行 make clean 后重新编译

③ 一些相关设置:

ln -s /usr/local/webserver/mysql/lib/libmysqlclient.so.18 /usr/lib/libmysqlclient.so.18
chmod +w /usr/local/webserver/mysql
chown -R mysql:mysql /usr/local/webserver/mysql

创建MySQL数据库存放目录

mkdir -p /data0/mysql/3306/data/
mkdir -p /data0/mysql/3306/binlog/
mkdir -p /data0/mysql/3306/relaylog/
chown -R mysql:mysql /data0/mysql/

以mysql用户帐号的身份建立数据表

/usr/local/webserver/mysql/scripts/mysql_install_db --collation-server=utf8_general_ci --basedir=/usr/local/webserver/mysql --datadir=/data0/mysql/3306/data --user=mysql

创建my.cnf配置文件

vi /usr/local/webserver/mysql/my.cnf

输入以下内容(适合4G内存以上的独立服务器或云服务器)

# Example MySQL config file for very large systems.
#
# This is for a large system with memory of 1G-2G where the system runs mainly
# MySQL.
#
# MySQL programs look for option files in a set of
# locations which depend on the deployment platform.
# You can copy this option file to one of those
# locations. For information about these locations, see:
# http://dev.mysql.com/doc/mysql/en/option-files.html
#
# In this file, you can use all long options that a program supports.
# If you want to know which options a program supports, run the program
# with the "--help" option.

# The following options will be passed to all MySQL clients
[client]
character-set-server = utf8
port                = 3306
socket                = /tmp/mysql.sock


# The MySQL server
[mysqld]
character-set-server = utf8
replicate-ignore-db = mysql
replicate-ignore-db = test
replicate-ignore-db = information_schema
user                = mysql
port                = 3306
socket                = /tmp/mysql.sock
basedir         = /usr/local/webserver/mysql
datadir         = /data0/mysql/3306/data
log-error         = /data0/mysql/3306/mysql_error.log
pid-file         = /data0/mysql/3306/mysql.pid
open_files_limit = 10240
back_log = 600
max_connections = 5000
max_connect_errors = 6000
table_cache = 512
external-locking = FALSE
key_buffer_size = 256M
max_allowed_packet = 32M
table_open_cache = 512
sort_buffer_size = 1M
join_buffer_size = 1M
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
thread_cache_size = 300
query_cache_size = 512M
query_cache_limit = 2M
query_cache_min_res_unit = 2k
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
default-storage-engine = InnoDB
thread_stack = 192K
transaction_isolation = READ-COMMITTED
tmp_table_size = 246M
max_heap_table_size = 246M
long_query_time = 2

# binary logging is required for replication
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 = /data0/mysql/3306/relaylog/relaylog
relay-log-info-file = /data0/mysql/3306/relaylog/relaylog
relay-log = /data0/mysql/3306/relaylog/relaylog
expire_logs_days = 30

interactive_timeout = 120
wait_timeout = 120

# required unique id between 1 and 2^32 - 1
# defaults to 1 if master-host is not set
# but will not function as a master if omitted
server-id        = 1

skip-name-resolve
#master-connect-retry = 10
slave-skip-errors = 1032,1062,126,1114,1146,1048,1396

# The replication master for this slave - required
#master-host     =   <hostname>
#
# The username the slave will use for authentication when connecting
# to the master - required
#master-user     =   <username>
#
# The password the slave will authenticate with when connecting to
# the master - required
#master-password =   <password>
#
# The port the master is listening on.
# optional - defaults to 3306
#master-port     =  3306

# Uncomment the following if you are using InnoDB tables
innodb_data_home_dir = /data0/mysql/3306/data
innodb_data_file_path = ibdata1:256M:autoextend
#innodb_log_group_home_dir = /data0/mysql/3306/data
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 1G
innodb_additional_mem_pool_size = 16M
# Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size = 128M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 120
innodb_file_io_threads = 4
innodb_thread_concurrency = 8
innodb_file_per_table = 1
#log-slow-queries = /data0/mysql/3306/slow.log
#long_query_time = 10

[mysqldump]
quick
max_allowed_packet = 32M

#[mysql]
#no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates

#[myisamchk]
#key_buffer_size = 256M
#sort_buffer_size = 256M
#read_buffer = 2M
#write_buffer = 2M

#[mysqlhotcopy]
#interactive-timeout

→【 MySQL5.5参数优化详解 】

对于1G~2G内存的VPS主机而言,一般使用MySQL自带的配置文件即可 @注意:按上文方法配置的请跳过这一步

cp /usr/local/webserver/mysql/support-files/my-large.cnf /usr/local/webserver/mysql/my.cnf

④ 配置MySQL服务脚本:

安装服务脚本

cd support-files/
cp mysql.server /etc/rc.d/init.d/mysqld
chmod +x /etc/init.d/mysqld
cd ../
make clean
cd ../

编辑服务脚本文件

vi /etc/init.d/mysqld

查找并修改以下变量内容

basedir=/usr/local/webserver/mysql
datadir=/data0/mysql/3306/data

加入启动项

chkconfig --add mysqld
chkconfig --level 345 mysqld on

启动MySQL服务

service mysqld start

设置数据库root用户密码 @友情提醒:最后的密码就不要跟着复制了 – -!

/usr/local/webserver/mysql/bin/mysqladmin password 12345678
数据库版本的选择:

简单说下看法。这篇文章的案例是将数据库与前端放置在同一台服务器上的,更适合于个人站长与中小型企业,当然这种环境用来做新上线产品的过渡也不错,因为随着网站的发展,并发逐渐增加,除了硬件和带宽外,数据库必定是最先遇到瓶颈问题的。首先在单台服务器或云主机上(VPS和虚拟主机就更不用说了),MySQL各种版本的差距不是很大,企业选择一些加强版本更多是用在集群环境下,另外也为了方便维护。当然在单台服务器上,不同版本的MySQL差距多少还是有一点点的:

在MySQL5.5版本上,如果只使用InnoDB引擎,Percona Server 5.5或许是个不错的选择,很多生产环境都在使用,在性能提升与维护支持上都略优于MariaDB,但MariaDB已经包含了Percona优化过的InnoDB引擎,另外一个主要原因,我正在尝试MariaDB自带的Aria引擎,这是MyISAM引擎的加强版本,个人觉得Aria引擎更适合那些以MyISAM为默认引擎开发的程序,至少在并发压力不是很大的站点上,速度不差于甚至优于InnoDN引擎,很多网站从MyISAM转InnoDB的主要原因就是为了解决表锁的问题,而Aria引擎支持行锁,对数据写入也有优化,所以随着将来引擎版本的进步,在高并发的情况下未必不如InnoDB,但目前Aria引擎的资料并不是很多,拥有那种高并发压力的生产环境都是以稳定为第一位的,大型网站依旧会选择InnoDB引擎。作者本人没有经历过那种高并发的生产环境,个人看法仅供参考,但有一点可以肯定,在5.5版本下无论是MariaDB还是Percona Server性能都要强过MySQL的原始版本。

关于MySQL5.6版本,由于我生产环境的系统是CentOS5,一些组件无法升级到高版本导致没能安装成功,但MariaDB在这个版本上来势很凶,而且创建了自己的10版本,在这个版本上采用了一些大型企业提交的意见,其中就包括国内互联网三巨头之一的淘宝网,而且MariaDB在进入稳定版后采用了5.6内核,性能不在像前几个版本那么不尽人意,相信随着小版本的升级会逐渐稳定;而Percona Server 5.6依旧走着稳定的路线,不过据一些权威测试,评其与MySQL5.6原版的差距越来越小。个人认为,生产环境还不没到升级MySQL5.6的时候,毕竟数据库不像PHP、Nginx一类的程序,不稳定可以很容易的换回,尤其在有数据库集群的环境上升级会很麻烦。另外我在虚拟机做了测试,并发不高的情况下,MySQL5.6性能相对5.5版本的提升几乎没多少,最近看了几篇关于MySQL5.7版本的文章,感觉5.6更像是一个过渡版本,真正的大幅度提升很可能在5.7版本上,当然新站与数据不多的站还是可以升级到5.6版本的,安装方法和MySQL5.5版本大同小异。

[返回目录]


三、安装PHP 5.5/5.4/5.3

由于PHP5.2版本实在过低,对很多新出的PHP扩展也无法很好的支持,就不在教程中讲解了,而PHP5.3.28依旧用在很多生产环境上,国内很多优秀的PHP程序都推荐使用5.3版本,而PHP6在我写这篇教学的几年内并不会在生产环境上普及,相信5.5、5.4、5.3这三个PHP版本依旧是几年内生产环境上的主流。

在写这篇教程的PHP安装部分前,我在本站的服务器上做了一个测试,分别使用了以上3个PHP版本,测试程序分别使用了国内的Discuz与国外的WordPress,这两款都是比较热门的PHP程序,均使用Memcached缓存,结果大致如下:

服务器系统:CentOS 5.10 Discuz WordPress
数据库查询时间 5.4 < 5.5 < 5.3 5.5 ≤ 5.4 < 5.3
PHP页面处理速度 5.5 < 5.4 < 5.3 5.5 < 5.4 < 5.3
PHP页面处理稳定性 5.5 < 5.4 = 5.3 5.5 < 5.4 = 5.3

以上测试结果或许受系统、硬件等因素的影响,只供参考使用

意外的是,5.3版本在PHP页面的处理速度上是最快的,但在连接数据库的速度方面,5.4与5.5版本的提升很明显,虽然5.3版本已经支持mysqlnd驱动,但经过测效果并不是很理想,从5.4版本后mysqlnd的性能优势才体现出来,而且很多PHP扩展逐渐不支持5.3版本了,再加上5.4.29应该是最后几个版本甚至就是最后一个版本,在维护方面要容易很多,所以我在自己的生产环境上使用了5.4版本。

其实细心的朋友应该会发现,本文给出的版本,几乎都是截止我写这篇教学时,不更新版本中最新的,因为要考虑生产环境的稳定性。如果是搭建全新的环境,推荐选择5.4或5.5版本;如果你的PHP应用程序不支持5.4以上的版本,那么5.3.28版本是最好的选择;如果生产环境中正在使用5.3版本,而且运行稳定,升级到最新的5.3.28小版本即可,等5.5版本进入最后几个版本时再考虑升级。

在前面的《获取相关开源程序》讲解中,下载的是PHP5.4.30版本,获取5.3或5.5版本只需在地址中更换对应的版本号即可,另外PHP5.5已经集成了Zendopcache功能,如果选择安装5.5版本无需下载该扩展。

[返回目录]


>安装PHP5.4/5.5(推荐)

① 安装所需的支持库

tar zxvf libiconv-1.14.tar.gz
cd libiconv-1.14/
./configure --prefix=/usr/local
make
make instal
make clean
cd ../
vi /etc/ld.so.conf

最下方输入

/usr/local/lib

然后执行

ldconfig

编译libiconv时可能遇到 “./stdio.h:1010:1: 错误: ‘gets’未声明(不在函数内)” 的问题

点击查看解决方法

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 ../
make clean
cd ../

tar zxvf mhash-0.9.9.9.tar.gz
cd mhash-0.9.9.9/
./configure
make
make install
make clean
cd ../

tar zxvf libmemcached-1.0.18.tar.gz
cd libmemcached-1.0.18/
./configure --prefix=/usr/local/libmemcached --with-memcached=/usr/local/webserver/memcached
make
make install
make clean
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
ln -s /usr/local/libmemcached/lib/libmemcached.so.11 /usr/lib/libmemcached.so.11

tar zxvf mcrypt-2.6.8.tar.gz
cd mcrypt-2.6.8/
/sbin/ldconfig
./configure
make
make install
make clean
cd ../

如果是64位系统还需要输入

cp -frp /usr/lib64/libldap* /usr/lib/

② 编译安装PHP

tar zxvf php-5.4.36.tar.gz
cd php-5.4.36/
./configure --prefix=/usr/local/webserver/php --with-config-file-path=/usr/local/webserver/php/etc --with-mysql --with-mysqli --with-pdo-mysql --with-iconv-dir=/usr/local --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --disable-mysqlnd-compression-support --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-fpm --with-mcrypt=usr/lib --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --enable-mbstring --enable-maintainer-zts
make ZEND_EXTRA_LIBS='-liconv'
make install
cp php.ini-production /usr/local/webserver/php/etc/php.ini
mv /usr/local/webserver/php/etc/php-fpm.conf.default /usr/local/webserver/php/etc/php-fpm.conf
make clean
cd ../

@提醒:成功编译PHP的请跳过下面灰框的步骤继续安装

如果安装的是PHP5.5版本,请在编译参数中加入 --enable-opcache

并跳过下文zendopcache的安装过程。另外在CentOS5系统中由于OpenSSL无法升级到更高版本,导致编译过程中出错(貌似搜不到正确的解决方法),给出两种解决方法:

# 一种比较简单,如果你不需要OpenSSL相关的功能,删除编译参数"--with-openssl"即可解决;

# 另一种需要编译升级OpenSSL版本,具体方法如下:

/*安装最新版本的OpenSSL
tar xzvf openssl-1.0.1g.tar.gz
cd openssl-1.0.1g/
./config shared zlib
make
make install
/usr/local/ssl/bin/openssl version -a
make clean
cd ../

/*替换旧版本的OpenSSL
mv /usr/bin/openssl /usr/bin/openssl.old
mv /usr/include/openssl /usr/include/openssl.old
ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/ssl/include/openssl/ /usr/include/openssl

/*配置库文件搜索路径
echo "/usr/local/ssl/lib" >> /etc/ld.so.conf
ldconfig

/*查看OpenSSL版本
openssl version -a

如果已经升级到1.0.1g版本

使用参数 --with-openssl=/usr/local/ssl

替换上文的PHP编译参数"--with-openssl"即可通过编译

③ 编译安装PHP扩展模块

tar zxvf ImageMagick.tar.gz
cd ImageMagick-6.8.9-5/
./configure
make
make install
make clean
cd ../

tar zxvf imagick-3.1.2.tgz
cd imagick-3.1.2/
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config
make
make install
make clean
cd ../

tar zxvf pthreads-2.0.7.tgz
cd pthreads-2.0.7/
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config --enable-pthreads
make
make install
make clean
cd ../

tar zxvf zendopcache-7.0.2.tgz
cd zendopcache-7.0.2/
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config
make
make install
make clean
cd ../

tar zxvf memcached-2.2.0.tgz
cd memcached-2.2.0/
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config --with-libmemcached-dir=/usr/local/libmemcached
make
make install
make clean
cd ../

tar zxvf memcache-2.2.7.tgz
cd memcache-2.2.7/
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config
make
make install
make clean
cd ../

④ 安装Memcached

编译安装Memcached

tar zxvf memcached-1.4.20.tar.gz
cd memcached-1.4.20/
./configure --prefix=/usr/local/webserver/memcached
make
make install
make clean
cd ../

如果是64位系统,可以在编译参数中加入

--enable-64bit

创建服务脚本

vi /etc/rc.d/init.d/memcached

输入以下内容

#!/bin/bash
# Init file for memcached
# chkconfig: - 80 12
# description: Distributed memory caching daemon
# processname: memcached
# config: /usr/local/webserver/memcached/memcached.conf
# pidfile: /var/run/memcached.pid

source /etc/init.d/functions

### Default variables
PORT="11211"
USER="memcached"
MAXCONN="5000"
CACHESIZE="1024"
OPTIONS=""

#BIN="/usr/local/bin"
BIN="/usr/local/webserver/memcached/bin"
SYSCONFIG="/usr/local/webserver/memcached/memcached.conf"

### Read configuration
[ -r "$SYSCONFIG" ] && source "$SYSCONFIG"

RETVAL=0
prog="memcached"
desc="Distributed memory caching"

start() {
                echo -n $"Starting $desc ($prog) on $PORT: "
                daemon $BIN/$prog -d -p $PORT -u $USER -c $MAXCONN -m $CACHESIZE $OPTIONS
                RETVAL=$?
                echo
                [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
                return $RETVAL
                }

stop() {
                echo -n $"Shutting down $desc ($prog): "
                kill `ps -aef | grep $PORT | grep -v grep | awk '{print $2}'` > /dev/null 2>&1
                RETVAL=$?
                echo
                [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
                return $RETVAL
                }

restart() {
                stop
                start
                }

reload() {
                echo -n $"Reloading $desc ($prog): "
                killproc $prog -HUP
                RETVAL=$?
                echo
                return $RETVAL
                }

case "$1" in
                start)
                        start
                        ;;
                stop)
                        stop
                        ;;
                restart)
                        restart
                        ;;
                        condrestart)
                        [ -e /var/lock/subsys/$prog ] && restart
                        RETVAL=$?
                        ;;
                reload)
                        reload
                        ;;
                status)
                        status $prog
                        RETVAL=$?
                        ;;
                *)
                echo $"Usage: $0 {start|stop|restart|condrestart|status}"
                RETVAL=1
        esac
        
exit $RETVAL
其中"MAXCONN"与"CACHESIZE"根据服务器的实际情况进行设置,本文给出的参数建议在4G内存以上的硬件环境中使用

创立memcached用户与用户组

groupadd memcached
useradd -g memcached memcached

加入启动项

chkconfig --add memcached
chkconfig memcached on
chmod +x /etc/init.d/memcached

启动Memcached服务

service memcached start

⑤ 修改PHP配置文件

修改 /usr/local/webserver/php/etc/php.ini 中的以下参数

disable_functions = passthru,system,popen,proc_open,shell_exec,chroot,assert,getcwd,scandir,chgrp,chmod,chown
expose_php = Off
html_errors = Off
upload_max_filesize = 8M
date.timezone = Asia/Shanghai
mysqlnd.collect_memory_statistics = On
session.save_handler = memcached
session.save_path = "127.0.0.1:11211"
extension_dir = "/usr/local/webserver/php/lib/php/extensions/no-debug-zts-20100525"

并在下方添加

extension = "imagick.so"
extension = "pthreads.so"
extension = "memcache.so"
extension = "memcached.so"

zend_extension = "/usr/local/webserver/php/lib/php/extensions/no-debug-zts-20100525/opcache.so"
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 4000
opcache.revalidate_freq = 60
opcache.fast_shutdown = 1
opcache.enable_cli = 1

⑥ 创建www用户和用户组

/usr/sbin/groupadd www
/usr/sbin/useradd -g www www

⑦ 设置php-fpm

vi /usr/local/webserver/php/etc/php-fpm.conf

修改以下参数

pid = run/php-fpm.pid
emergency_restart_threshold = 20
emergency_restart_interval = 60s
process_control_timeout = 5s
user = www
group = www
listen = /dev/shm/php-cgi.sock
listen.backlog = -1
listen.owner = www
listen.group = www
listen.mode = 0660
pm = dynamic
pm.max_children = 128
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 8
pm.max_requests = 16384
request_terminate_timeout = 300s
catch_workers_output = yes
其中"pm.start_servers"、"pm.min_spare_servers"、"pm.max_spare_servers"这三个参数,经过研究发现将这3个参数设置成CPU的线程数有奇效,具体原因未知(按照参数解释这样设置是错误的)

当然选择自己优化更好,"pm.max_children"的值设置为128适合4G内存以上的独立服务器或云服务器,建议根据实际情况自行修改,但不要少于CPU的线程数。

安装服务脚本

cp /data0/software/php-5.4.36/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm

加入启动项

chkconfig --add php-fpm
chkconfig php-fpm on
chmod +x /etc/rc.d/init.d/php-fpm

启动php-fpm服务

service php-fpm start

[返回目录]


>安装PHP5.3.28

① 安装所需的支持库
与PHP5.4/5.5的方法相同,请参考上文

② 编译安装PHP

tar zxvf php-5.3.28.tar.gz
cd php-5.3.28/
./configure --prefix=/usr/local/webserver/php --with-config-file-path=/usr/local/webserver/php/etc --with-mysql --with-mysqli --with-pdo-mysql --with-iconv-dir=/usr/local --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --disable-mysqlnd-compression-support --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-fpm --with-mcrypt=usr/lib --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --enable-mbstring
make ZEND_EXTRA_LIBS='-liconv'
make install
wget http://pear.php.net/go-pear.phar
/usr/local/webserver/php/bin/php go-pear.phar
cp php.ini-production /usr/local/webserver/php/etc/php.ini
mv /usr/local/webserver/php/etc/php-fpm.conf.default /usr/local/webserver/php/etc/php-fpm.conf
make clean
cd ../

③ 编译安装PHP扩展模块

除Pthreads扩展模块外,均与PHP5.4/5.5的方法相同,请参考上文

因为一个PHP程序如果不支持5.4/5.5版本,基本也用不到Pthreads扩展模块,跳过Pthreads的安装即可,作者推荐这样做。但考虑到特殊需求,且安装过程中会出现很多问题,讲解下PHP5.3.28如何安装Pthreads扩展:

修正PHP5.3.28的源码(否则编译安装时会出错)

vi Zend/zend_language_parser.h

将文件最下方的”int zendparse (void)”修改为

int zendparse (void *compiler_globals)

在上文PHP编译参数中增加

--enable-maintainer-zts

安装Pthreads 0.0.45(这是目前可以在PHP5.3下正常安装的最高版本)

wget http://pecl.php.net/get/pthreads-0.0.45.tgz
tar zxvf pthreads-0.0.45.tgz
cd pthreads-0.0.45/
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config --enable-pthreads
make
make install
make clean
cd ../

在 /usr/local/webserver/php/etc/php.ini 中将下文修改的两处”no-debug-non-zts-20090626″替换为

no-debug-zts-20090626

并在下方加入

extension = "pthreads.so"

④ 安装Memcached

与PHP5.4/5.5的方法相同,请参考上文

⑤ 修改PHP配置文件

修改 /usr/local/webserver/php/etc/php.ini 中的以下参数

disable_functions = passthru,system,popen,proc_open,shell_exec,chroot,assert,getcwd,scandir,chgrp,chmod,chown
expose_php = Off
upload_max_filesize = 8M
date.timezone = Asia/Shanghai
session.save_handler = memcached
session.save_path = "127.0.0.1:11211"
extension_dir = "/usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20090626"

并在下方添加

extension = "imagick.so"
extension = "memcache.so"
extension = "memcached.so"

zend_extension = "/usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20090626/opcache.so"
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 4000
opcache.revalidate_freq = 60
opcache.fast_shutdown = 1
opcache.enable_cli = 1

⑥ 创建www用户和用户组

与PHP5.4/5.5的方法相同,请参考上文

⑦ 设置php-fpm

vi /usr/local/webserver/php/etc/php-fpm.conf

修改以下参数

pid = run/php-fpm.pid
emergency_restart_threshold = 20
emergency_restart_interval = 60s
process_control_timeout = 5s
user = www
group = www
listen = /dev/shm/php-cgi.sock
listen.backlog = -1
pm = dynamic
pm.max_children = 128
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 8
pm.max_requests = 16384
request_terminate_timeout = 300s
catch_workers_output = yes

安装服务脚本

cp /data0/software/php-5.4.29/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm

加入启动项

chkconfig --add php-fpm
chkconfig php-fpm on
chmod +x /etc/rc.d/init.d/php-fpm

启动php-fpm服务

service php-fpm start

[返回目录]


四、安装Tengine(Nginx)

① 安装所需的pcre库:

tar zxvf pcre-8.36.tar.gz
cd pcre-8.36/
./configure --prefix=/usr/local/pcre
make
make install
make clean
cd ../

② 编译安装Tengine

tar zxvf openssl-1.0.1g.tar.gz
tar zxvf tengine-1.5.2.tar.gz
cd tengine-1.5.2/
./configure --user=www --group=www --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre=/data0/software/pcre-8.36 --with-openssl=/data0/software/openssl-1.0.1g --with-http_realip_module --with-http_concat_module --with-jemalloc=/data0/software/jemalloc-3.6.0 --dso-path=/usr/local/webserver/nginx/modules
make
make install
make clean
cd ../

③ 创建站点与日志目录

mkdir -p /data0/htdocs/wwwroot
chmod +w /data0/htdocs/wwwroot
chown -R www:www /data0/htdocs/wwwroot
mkdir -p /data0/htdocs/itwulin.com
chmod +w /data0/htdocs/itwulin.com
chown -R www:www /data0/htdocs/itwulin.com

mkdir -p /data1/logs
chmod +w /data1/logs
chown -R www:www /data1/logs

④ 创建Tengine配置文件

rm -f /usr/local/webserver/nginx/conf/nginx.conf
vi /usr/local/webserver/nginx/conf/nginx.conf

输入并保存以下内容:

user  www www;

worker_processes    auto;
worker_cpu_affinity auto;

error_log  /data1/logs/nginx_error.log  crit;
pid        /usr/local/webserver/nginx/nginx.pid;

worker_rlimit_nofile 65535;

events {
        use epoll;
        worker_connections  65535;
}

# load modules compiled as Dynamic Shared Object (DSO)
#
#dso {
#    load ngx_http_fastcgi_module.so;
#    load ngx_http_rewrite_module.so;
#}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

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      on;
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  1k;
gzip_buffers     4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types       text/plain application/x-javascript text/css application/xml;
gzip_vary on;

#limit_zone  crawler  $binary_remote_addr  10m;

server_tokens off;
#server_tag IIS/6.0;

server {
        listen       80;
        server_name  localhost;
        root   /data0/htdocs/wwwroot;
        index  index.html index.htm index.php;

        #charset gb2312;
        #limit_conn   crawler  20;

        #log_format  access  '$remote_addr - $remote_user [$time_local] "$request" '
        #                                '$status $body_bytes_sent "$http_referer" '
        #                                '"$http_user_agent" $http_x_forwarded_for';
        #access_log  /data1/logs/access.log  access;

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ .*\.(php|php5)?$ {
                fastcgi_pass  unix:/dev/shm/php-cgi.sock;
                fastcgi_index index.php;
                include fastcgi.conf;
        }

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
            expires      30d;
        }

        location ~ .*\.(js|css)?$ {
            expires      1h;
        }

        #error_page  404              /404.html;
        # redirect server error pages to the static page /50x.html
        #
        #error_page   500 502 503 504  /50x.html;
        #location = /50x.html {
        #    root   html;
        #}

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
}

server {
        listen       80;
        server_name  www.itwulin.com;
        root   /data0/htdocs/itwulin.com;
        index  index.html index.htm index.php;

        #include /usr/local/webserver/nginx/conf/rewrite.conf;
        #charset gb2312;

        #limit_req_zone $binary_remote_addr zone=one:3m rate=1r/s;
        #limit_req_zone $binary_remote_addr $uri zone=two:3m rate=1r/s;
        #limit_req_zone $binary_remote_addr $request_uri zone=three:3m rate=1r/s;
        #limit_rate   256k;

        log_format  itwulin-logs  '$remote_addr - $remote_user [$time_local] "$request" '
                                '$status $body_bytes_sent "$http_referer" '
                                '"$http_user_agent" $http_x_forwarded_for';

        access_log  /data1/logs/itwulin-logs.log  itwulin-logs;

        #location ~ /static/ {
        #concat on;
        #concat_max_files 20;
        #}

        location / {
        try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ .*\.(php|php5)?$ {
        try_files $uri =404;
        fastcgi_pass  unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
        }

        location ~ .*\.(js|css)?$ {
            expires      1h;
        }

        location ~* \.(jpg|jpeg|gif|png|bmp|swf|rar|zip|7z)$ {
        valid_referers none blocked *.itwulin.com *.baidu.com *.google.com *.google.com.hk ;
        if ($invalid_referer) {
        return 412;
        }
        expires      30d;
        break;
        }
}

server {
        listen       80;
        server_name  itwulin.com;
        rewrite ^/(.*)$ http://www.itwulin.com/$1 permanent;
        if ($host != 'www.itwulin.com' ) {
        rewrite ^/(.*)$ http://www.itwulin.com/$1 permanent;
        }
}

server {
        listen       80;
        server_name  status.itwulin.com;

        location / {
                stub_status on;
                access_log off;
        }
}

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

    # HTTPS server
    #
    #server {
    #    listen       443;
    #    server_name  localhost;
    #    ssl                  on;
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;
    #    ssl_session_timeout  5m;
    #    ssl_protocols  SSLv2 SSLv3 TLSv1;
    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers   on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

#ADD

}

⑤ 创建Tengine服务

创建服务脚本

vi /etc/rc.d/init.d/nginx

输入以下内容

#!/bin/bash
# Tengine Startup script# processname: nginx
# chkconfig: - 85 15
# description: nginx is a World Wide Web server. It is used to serve
# pidfile: /var/run/nginx.pid
# config: /usr/local/webserver/nginx/conf/nginx.conf
nginxd=/usr/local/webserver/nginx/sbin/nginx
nginx_config=/usr/local/webserver/nginx/conf/nginx.conf
nginx_pid=/usr/local/webserver/nginx/logs/nginx.pid
RETVAL=0
prog="nginx"
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -x $nginxd ] || exit 0
# Start nginx daemons functions.
start() {
if [ -e $nginx_pid ];then
echo "tengine already running...."
exit 1
fi
echo -n $"Starting $prog: "
daemon $nginxd -c ${nginx_config}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/nginx
return $RETVAL
}
# Stop nginx daemons functions.
stop() {
echo -n $"Stopping $prog: "
killproc $nginxd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/nginx /usr/local/webserver/nginx/logs/nginx.pid
}
reload() {
echo -n $"Reloading $prog: "
#kill -HUP `cat ${nginx_pid}`
killproc $nginxd -HUP
RETVAL=$?
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
stop
start
;;

status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $prog {start|stop|restart|reload|status|help}"
exit 1
esac
exit $RETVAL

加入启动项

chkconfig --add nginx
chkconfig nginx on
chmod +x /etc/rc.d/init.d/nginx

启动Tengine服务

service nginx start

[返回目录]


五、Linux的设置与优化

① 配置防火墙

/sbin/iptables -I INPUT -p tcp --dport 22 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
/etc/rc.d/init.d/iptables save
service iptables restart

② 修改ulimit连接数最大值

ulimit -SHn 65535
vi /etc/profile

在最下方添加

ulimit -SHn 65535

③ 系统性能优化

vi /etc/sysctl.conf

在最下方添加

# ADD
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog =  32768
net.core.somaxconn = 32768

net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

net.ipv4.tcp_tw_recycle = 1
#net.ipv4.tcp_tw_len = 1
net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_max_orphans = 3276800

#net.ipv4.tcp_fin_timeout = 30
#net.ipv4.tcp_keepalive_time = 120
net.ipv4.ip_local_port_range = 1024  65535

vm.swappiness = 10

使配置立即生效

/sbin/sysctl -p

④ 编写每天定时切割Tengine(Nginx)日志的脚本

vi /usr/local/webserver/nginx/sbin/cut_nginx_log.sh

输入以下内容

#!/bin/bash
# This script run at 00:00

# The Nginx logs path
logs_path="/usr/local/webserver/nginx/logs/"
mkdir -p ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/
mv ${logs_path}access.log ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/access_$(date -d "yesterday" +"%Y%m%d").log
kill -USR1 `cat /usr/local/webserver/nginx/nginx.pid`

保存后输入

crontab -e

输入以下内容

MAILTO=""
00 00 * * * /bin/bash  /usr/local/webserver/nginx/sbin/cut_nginx_log.sh

至此,一台高性能的Web服务器配置完毕了!

 

本文更新记录:

2014年06月10日 → MariaDB版本由5.5.37更新至5.5.38
2014年06月26日 → PHP版本由5.4.29更新至5.4.30
2014年07月02日 → 防火墙补充22端口的开放,防止一些对LINUX不熟悉的用户开启防火墙后造成SSH无法连接
2014年07月04日 → 由于MariaDB的国内镜像挂掉,更新了下载地址
2014年07月10日 → 增加了编译libiconv出错的解决方案
2014年07月11日 → 增加了安装libiconv的步骤,防止部分应用程序调用libiconv.so.2出错
2014年07月25日 → PHP版本由5.4.30更新至5.4.31
2014年09月08日 → PHP版本由5.4.31更新至5.4.32,MariaDB版本由5.5.38更新至5.5.39
2014年10月25日 → PHP版本由5.4.32更新至5.4.34,MariaDB版本由5.5.38更新至5.5.40
2014年12月19日 → PHP版本由5.4.34更新至5.4.36
2014年12月19日 → PHP版本由5.4.34更新至5.4.36
2014年12月31日 → MariaDB版本由5.5.40更新至5.5.41,PCRE版本由8.35更新至8.36