LNMP环境配置
2.安装PHP
3.安装Nginx1
3.1 安装
3.2 编写Nginx启动脚本,并加入系统服务
3.3
3.4更改Nginx配置文件
4.Nginx配置
4.1 默认虚拟主机
4.2 用户认证
4.3 域名重定向
4.4 Nginx的访问日志
4.5 配置静态文件不记录日志并添加过期时间
4.6 Nginx防盗链
4.7 访问控制
4.7.1 限制访问目录
4.7.2 黑(白)名单
4.7.3 URL限制
4.7.4 user_agent限制
4.8 Nginx解析PHP
4.9 🥇 Nginx代理
ps:如何关闭Nginx版本信息?
4.9.2 负载均衡实例
dig命令
Nginx负载均衡
4.10 Nginx配置SSL
4.10.1HTTPS的通信过程:
4.10.2 SSL证书
4.10.3 Nginx配置SSL
5.php-fpm配置
5.1 php-fpm的pool
5.2 php-fpm的慢执行日志
5.3 php-fpm定义open_basedir
5.4 php-fpm进程管理
LNMP环境配置
nginx静态页面的处理有优势
1.安装Mysql
LNMP中mysql的安装步骤和lamp一样
# /usr/local/src/ # wget http://mirrors.sohu.com/mysql/MySQL-5.6/mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz # tar zxvf mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz # mv mysql-5.6.35-linux-glibc2.5-x86_64 /usr/local/mysql # useradd -s /sbin/nologin mysql # cd /usr/local/mysql # mkdir -p /data/mysql # chown -R mysql:mysql /data/mysql # ./scripts/mysql_install_db --user=mysql --datadir=/data/mysql # cp support-files/my-default.cnf /etc/my.cnf # vim /etc/my.cnf //修改参数 innodb_buffer_size = 128M log_bin = aminglinux basedir = /usr/local/mysql datadir = /data/mysql port = 3306 server_id = 128 socket = /tmp/mysql.sock join_buffer_size = 128M sort_buffer_size = 2M red_rnd_buffer_size = 2M sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES # cp support-files/mysql.server /etc/init.d/mysqld # chmod 755 /etc/init.d/mysqld # vim /etc/init.d/mysqld datadir=/data/mysql # chkconfig --add mysqld # chkconfig mysqld on # service mysqld start # ps aux |grep mysqld
2.安装PHP
针对Nginx的PHP安装和Apache的PHP安装是有区别的。因为Nginx中的PHP是以fastcgi的方式结合Nginx的,可以理解为Nginx代理了PHP的fastcgi,而httpd是把PHP作为自己的模块来调用的。PHP的官方下载地址为:httpd://www.php.net/downloads.php。
# cd /usr/loca/src/ # wget http://cn2.php.net/distributions/php-5.6.30.tar.gz # tar zxf php-5.6.30.tar.gz # useradd -s /sbin/nologin php-fpm //该账号用来运行php-fpm服务。在LNMP环境中,PHP以一个服务PHP-fpm的形式出现,独立存在与Linux系统中,方便管理 # cd php-5.6.30 # yum install -y libxml2-devel openssl openssl-devel bzip2 bzip2-devel libpng libpng-devel freetype freetype-devel epel-release libmcrypt-devel # ./configure \ --prefix=/usr/local/php-fpm \ --with-config-file-path=/usr/local/php-fpm/etc \ --enable-fpm \ --with-fpm-user=php-fpm \ --with-fpm-group=php-fpm \ --with-mysql=/usr/local/mysql \ --with-mysql-sock=/tmp/mysql.sock \ --with-libxml-dir \ --with-gd \ --with-jpeg-dir \ --with-png-dir \ --with-freetype-dir \ --with-iconv-dir \ --with-zlib-dir \ --with-mcrypt \ --enable-soap \ --enable-gd-native-ttf \ --enable-ftp \ --enable-mbstring \ --enable-exif --disable-ipv6 \ --with-pear \ --with-curl \ --with-openssl //报错 # yum install -y libcurl-devel # make //还有报错 # vim Makefile // 在大概102行,-lcrypt后面加 “-lpthread” //继续报错 # make //继续报错 # make clean && make # make install //以上每一步可以使用echo $?判断是否正确 # cp php.ini-production /usr/local/php-fpm/etc/php.ini # vim /usr/local/php-fpm/etc/php-fpm.conf //写入 [global] pid = /usr/local/php-fpm/var/run/php-fpm.pid error_log = /usr/local/php-fpm/var/log/php-fpm.log [www] listen = /tmp/php-fcgi.sock listen.mode = 666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024 # /usr/local/php-fpm/sbin/php-fpm -t //检验配置 test is successful
启动php-fpm
# cp /usr/local/src/php-5.6.30/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm # chmod 755 /etc/init.d/php-fpm # useradd -s /sbin/nologin php-fpm # service php-fpm start # chkconfig php-fpm on # ps aux |grep php-fpm //大概有20+个进程
3.安装Nginx1
官方网站http://nginx.org
3.1 安装
# cd /usr/local/src/ # wget http://nginx.org/download/nginx-1.10.3.tar.gz # tar zxvf nginx1.10.3.tar.gz # cd nginx-1.10.3 # ./configure --prefix=/usr/local/nginx # make # make install
3.2 编写Nginx启动脚本,并加入系统服务
# vim /etc/init.d/nginx #!/bin/bash # chkconfig: - 30 21 # description: http service # Source Function Library . /etc/init.d/functions # Nginx Settings NGINX_SBIN="/usr/loca/nginx/sbin/nginx" NGINX_CONF="/usr/local/nginx/conf/nginx.conf" NGINX_PID="/usr/local/nginx/logs/nginx.pid" RETVAL=0 prog="Nginx" start() { echo -n $"Starting $prog: " mkdir -p /dev/shm/nginx_temp daemon $NGINX_SBIN -c $NGINX_CONF_RETVAL echo return $RETVAL } stop() { echo -n $"Stopping $prog: " killproc -p $NGINX_PID $NGINX_SBIN -TERM rm -rf /dev/shm/nginx_temp RETVAL=$? echo return $RETVAL } reload() { echo -n $"Reloading $prog: " killproc -p $NGINX_PID $NGINX_SBIN -HUP RETVAL=$? echo return $RETVAL } restart() { stop start } configtest() { $NGINX_SBIN -c $NGINX_CONF -t return 0 } case "$1" in start) start ;; stop) stop ;; reload) reload ;; restart) restart ;; configtest) configtest ;; *) echo $"Usage: $0 {start|stop|reload|restart|configtest}" RETVAL=1 esac exit $RETVAL
3.3
# chmod 755 /etc/init.d/nginx # chkconfig --add nginx # chkconfig nginx on
3.4更改Nginx配置文件
# > /usr/local/nginx/conf/nginx.conf # vim /usr/local/nginx/conf/nginx.conf usr nobody nobody; worker_processes 2; error_log /usr/local/nginx/log/nginx_error.log crit; pid /usr/local/nginx/log/nginx.pid; worker_rlimit_nofile 51200; events { user epoll; worker_connections 6000; } http { include mime.types; defautl_type application/octet-stream; server_names_hash_bucket_size 3526; server_names_hash_max_size 4096; log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_local]' ' $host "$request_uri" $status' ' "$http_referer" "$http_user_agent"'; sendfile on; tcp_nopush on; keepalive_timeout 30; client_header_timeout 3m; client_body_timeout 3m; send_timeout 3m; connection_poool_size 245; client_header_buffer_size 1k; large_client_header_buffers 8 4k; request_pool_size 4k; output_buffers 4 32k; postpone_output 1460; client_max_body_size 10m; client_body_buffer_size 256k; client_body_temp_path /usr/local/nginx/client_body_temp; proxy_temp_path /usr/localnginx/proxy_temp; fastcgi_temp_path /usr/local/ghinx/fastcgi_temp; fastcgi_intercept_errors on; tcp-nodelay on; gzip on; gzip_min_length 1k; gzip_buffers 4.8k; gzip_comp_level 5; gzip_http_version 1.1; gzip_types text/plain application/x-javascript text/css text/htm application/xml; server { listen 80; server_name localhost; index index.html index.htm index.php root /usr/local/nginx/html; location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/tmp/php-fcgi.sock; fastcgi_index.php; fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name; } } } # /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful # service nginx start # ps aux |grep nginx # vim /usr/local/nginx/html/2.php <?php echo "test php scripts."; ?> # curl localhost/2.php test php scripts. //php解析正常
4.Nginx配置
4.1 默认虚拟主机
跟http类似,第一个被Nginx加载的虚拟主机就是默认主机。
但和httpd不相同的地方时,它还有一个配置用来标记默认虚拟主机。若没有标记,第一个虚拟主机为默认虚拟主机。
修改主配置文件/usr/local/nginx/conf/nginx.conf,在结束符}上面加入一行配置,如下:
include vhost/*.conf;
}
// /usr/local/nginx/conf/vhost/下面所有以.conf结尾的文件都会被加载。虚拟主机配置文件放到vhost目录下。
# mkdir /usr/local/nginx/conf/vhost # cd //usr/local/nginx/conf/vhost # vim default.conf server { listen 80 default_server; // 有这个default_server标记的就是默认虚拟主机 server_name aaa.com; index index.html index.htm index.php; root /data/nginx/default; //网站目录 } # /usr/local/nginx/sbin/nginx -t nginx:... is ok nginx:... test is successful # /usr/local/nginx/sbin/nginx -s reload # echo "default_server" > /data/nginx/default/index.html //创建索引页 # curl -x127.0.0.1:80 aaa.com default_server # curl -x127.0.0.1:80 1212.com //访问一个没有定义过的域名,也会访问到aaa.com default_server
4.2 用户认证
创建一个新的虚拟主机
# cd /usr/local/nginx/conf/vhost/ # vim test.com.conf server { listen 80; server_name test.com; index index.html index.htm index.php; root /data/nginx/test.com; //网站目录 location / { auth_basic "Auth"; auth_basic_user_file /usr/local/nginx/conf/htpasswd; } } # yum install -y htppd //安装httpd,也可以使用之前的编译安装的apache2.4 # htpasswd -c /usr/local/nginx/conf/htpasswd aming // 创建aming用户 //输入密码 //htpasswd -cmb /usr/local/nginx/conf/htpasswd aming test123 -c为创建密码文件,第二次不需要加入,否则会覆盖 # /usr/local/nginx/sbin/nginx -t ... ok ... successful # /usr/local/nginx/sbin/nginx -s reload
auth_basic打开认证,auth_basic_user_file指定用户密码文件,前提是这个用户密码文件存在。而生成用户密码文件的工具需要借助httpd的htpasswd,Nginx不自带这个工具。
验证:
# mkdir /data/nginx/test.com # echo "test.com" > /data/nginx/test.com/index.html # curl -I -x127.0.0.1:80 test.com // 401 Unauthorized //401说明网站需要验证
//在windows的hosts文件,加入一行:192.168.188.128 test.com
//浏览器输入test.com,弹出验证对话框。
如果针对某个目录做用户认证,需要修改location后面的路径
location /admin/ { auth_basic "Auth"; auth_basic_user_file /usr/local/nginx/conf/htpasswd; } }
4.3 域名重定向
Nginx的域名重定向和httpd的类似,如下:
# server { listen 80; server_name test.com test1.com test2.com; index index.html index.htm index.php; root /data/nginx/test.com; if ($host != 'test.com' ) { rewrite ^/(.*)$ http://test.com/$1 permanent; //permanent(永久重定向,相当于httpd的R=301) } }
ps:redirect,相当于httpd的R=302。
测试:
# /usr/local/nginx/sbin/nginx -t ... ok ... successful # /usr/local/nginx/sbin/nginx -s reload # curl -I -x127.0.0.1:80 test1.com/123.txt -I //301 permanently
4.4 Nginx的访问日志
先看看Nginx的日志格式:
# grep -A2 log_format /usr/loca/nginx/conf/nginx.conf log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_local]' ' $host "request_uri" $status' ' "$http_referer" "$http_user_agent"';
和httpd类似,也是在主配置文件中定义的日志文件格式。combined_realip为日志格式的名字,后面可以调用它;
$remote_addr为访问网站的用户的入口IP;
$http_x_forwarded_for为代理服务器的IP,如果使用了代理,则会记录代理的IP;
$time_local为当前的时间;
$host为访问的主机名
$request_uri为访问的URL地址;
$status为状态码;
$http_referer为referer地址;
$http_user_agent为user_agent;
然后再到虚拟主机配置文件中指定访问日志的路径:
server { listen 80; servername test.com test1.com test2.com; index index.html index.htm index.php; if ($host != 'test.com' ) { rewrite ^/(.*)$ http://test.com/$1 permanent; } access_log /tmp/1.log combined_realip; }
使用access_log来制定日志的存储路径,最后面指定日志的格式名字,测试:
# /usr/local/nginx/sbin/nginx -t ... ok ... successful # /usr/local/nginx/sbin/nginx -s reload # curl -x127.0.0.1:80 test.com/111 ... <head><title>404 Not Found</title></head> ... # cat /tmp/1.log 127.0.0.1 - [26/Mar?2017:22:02:01 -0800] test.com "/111" 404 "-" "curl/7.29.0"
Nginx的日志很简单,不想httpd还有自带的切割工具,要想切割Nginx日志需要借助系统的切割工具或者自定义脚本。
Nginx日志切割脚本:
# vim /usr/local/sbin/nginx_log_rotate.sh #!/bin/bash ## 假设nginx的日志存放路径为/data/logs/ d=`date -d "-1 day" +%Y%m%d` logdir="/data/logs" nginx_pid="/usr/local/nginx/logs/nginx.pid" cd $logdir for log in `ls *.log` do mv $log $log-$d done /bin/kill -HUP `cat $nginx_pid` #crontab -e 0 0 * * * /bin/bash /usr/local/sbin/nginx_log_rotate.sh
或脚本2:
# vim /usr/local/sbin/nginx_log_rotate.sh #!/bin/bash #此脚本用于自动分割Nginx的日志,包括access.log和error.log #每天00:00执行此脚本,将前一天的access.log重命名为access-xxxx-xx-xx.log格式,并重新打开日志文件 ## 假设nginx的日志存放路径为/data/logs/ d=`date -d "-1 day" +%Y-%m-%d` logdir="/data/logs" nginx_pid="/usr/local/nginx/logs/nginx.pid" cd $logdir for log in `ls *.log` do mv ${logdir}$log ${logdir}$log-${d} #mv ${logdir}access.log ${logdir}access-${d}.log #mv ${logdir}error.log ${logdir}error-${d}.log done /bin/kill -HUP `cat $nginx_pid` #kill -USER1 `cat $nginx_pid` chmod +x /usr/local/sbin/nginx_log_rotate.sh #crontab -e 0 0 * * * /bin/bash /usr/local/sbin/nginx_log_rotate.sh
4.5 配置静态文件不记录日志并添加过期时间
# vim /usr/local/sbin/nginx_log_rotate.sh #!/bin/bash #此脚本用于自动分割Nginx的日志,包括access.log和error.log #每天00:00执行此脚本,将前一天的access.log重命名为access-xxxx-xx-xx.log格式,并重新打开日志文件 ## 假设nginx的日志存放路径为/data/logs/ d=`date -d "-1 day" +%Y-%m-%d` logdir="/data/logs" nginx_pid="/usr/local/nginx/logs/nginx.pid" cd $logdir for log in `ls *.log` do mv ${logdir}$log ${logdir}$log-${d} #mv ${logdir}access.log ${logdir}access-${d}.log #mv ${logdir}error.log ${logdir}error-${d}.log done /bin/kill -HUP `cat $nginx_pid` #kill -USER1 `cat $nginx_pid` chmod +x /usr/local/sbin/nginx_log_rotate.sh #crontab -e 0 0 * * * /bin/bash /usr/local/sbin/nginx_log_rotate.sh
使用location ~可以指定对应的静态文件,expires配置过期时间,而access_log配置为off就可不记录访问日志了。
模拟测试:
# /usr/local/nginx/sbin/nginx -t ... ok ... successful # echo "111" > /data/nginx/test.com/1.js # echo "222" > /data/nginx/test.com/2.jpg # touch /data/nginx/test/com/1.jss // 创建一个对比的文件 # curl -I -x127.0.0.1:80 test.com/1.js //200 ok 缓存过期时间为12小时(max-age=43200) # curl -I -x127.0.0.1:80 test.com/2.jpg //200 ok访问jpg类型的文件,缓存过期时间为7小时(max-age=604800) # curl -I -x127.0.0.1:80 test.com/1.jss //200 ok # cat /tmp/1.log //只记录了js和jpg
4.6 Nginx防盗链
思路和httpd的一样,由于和过期时间、不记录日志有部分重合,可以把两部分组合在一起:
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip|doc|pdf|gz|bz2|jpeg|bmp|xls)$ { expires 7d; valid_referers none blocked server_names *.test.com ; if ($invalid_referer){ return 403; } access_log off; }
测试:
# /usr/local/nginx/sbin/nginx -t ... ok ... successful # /usr/local/nginx/sbin/nginx -s reload # curl -x127.0.0.1:80 -I -e "http://aaa.com/1.txt" test.com/2.jpg //403 forbidden # curl -x127.0.0.1:80 -I -e "http://test.com/1.txt" test.com/2.jpg //200 ok
过期时间、防盗链功能
4.7 访问控制
4.7.1 限制访问目录
和httpd一样,Nginx也需要限制某些IP不能访问或者只允许某些IP访问。配置方法和httpd很想,但更加简洁了,而且不想httpd那样全部遍历一遍。比如,“使访问admin目录的请求只允许192.168.188.1和127.0.0.1访问”,配置文件如下:
location /admin/ { allow 192.168.188.1; allow 127.0.0.1; deny all; }
配置httpd的时候,有一个order,来定义先allow还是先deny,在Nginx里并没有,只要匹配规则就结束了。假如来源IP为192.168.188.129,它会从上到下逐一去匹配。
测试:
# mkdir /data/nginx/test.com/admin # echo "123" > /data/nginx/test.com/admin/1.html # curl -x127.0.0.1:80 test.com/admin/1.html 123 # curl -x192.168.188.128:80 test.com/admin/1.html ... <head><title>403 Forbidden</title></head> ...
4.7.2 黑(白)名单
配置文件中的IP也可以是IP段,比如可以写成allow 192.168.188.0/24。如果只拒绝某几个IP,如下:
location /admin/ { deny 192.168.188.1; deny 127.0.0.1; } //如果是黑名单的形式,就不需要写allow all了,因为默认就是允许所有。
4.7.3 URL限制
除了这种简单地限制目录外,也可以根据正则匹配来限制,如下:
location ~ .*(abc|image)/.*\.php$ { deny all; } //把访问的URL中带有abc或者image字符串,并且是PHP的请求拒绝访问。
4.7.4 user_agent限制
if ($http_user_agent ~ 'Spider/3.0|YoudaoBot|Tomato') { return 403; } 只要user_agent中含有这三个字符串的一种,都会被拒绝,return 403为直接返回403的状态码,也可以替换成deny all。
4.8 Nginx解析PHP
在LAMP中,PHP是作为httpd的一个模块出现的,只要PHP模被加载,就能解析PHP脚本。
在LNMP中,PHP是以一个服务(php-fpm)的形式存在的,首先要启动php-fpm如无,然后Nginx再和php-fpm通信。
处理PHP脚本解析的工作是有php-fpm来完成的,Nginx仅仅是一个“搬运工”,它把用户的请求传递给php-fpm,php-fpm处理完后把结果传递给Nginx,Nginx再把结果返回给用户。
Nginx和PHP联系起来(上面已有展示),/usr/local/nginx/conf/vhost/test.com.conf:
# vim /usr/local/nginx/conf/vhost/test.com.conf server { listen 80; server_name test.com test1.com test2.com index index.html inex.htm index.php; root /data/nginx/test.com; if ($host != 'test.com' ) { rewrite ^/(.*)$ http://test.com/$1 permanent; } location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/tmp/php-fcgi.sock; fastcgi_index index.php fastcgi_param SCRIPT_FILENAME /data/nginx/test.com$$fastcgi_script_name; } access_log /tmp/1.log combined_realip; }
fastcgi_pass用来指定php-fpm的地址,如果php-fpm监听的是一个tcp:port地址(如127.0.0.1:9000),那么也需要在这里改成fastcgi_pass 127.0.0.1:9000。这个地址一定要和php-fpm服务监听的地址匹配,否则会报502错误。
fastcgi_param SCRIPT_FILENAME后面跟的路径为该站点的根目录,和前面定义的root路径保持一致。配置错误出现404.
4.9 🥇 Nginx代理
4.9.1 Nginx代理配置
Nginx的代理功能非常实用,这也是Nginx比httpd越来越受欢迎的一个原因。一家公司有很多台服务器,为了节省成本,不能为所有服务器都分配公网IP,而如果一个没有公网IP的服务器要提供Web服务,就可以通过代理来实现。
用户
Nginx代理
Web服务器
如果Nginx后面有多台Web服务器,如果同时代理,那Nginx在这里就起到了一个负载均衡的作用,这个功能在生产环境中用的也特别多。Nginx代理配置:
# cd /usr/local/nginx/conf/vhost # vim proxy.conf server { listen 80; servername ask.apelearn.com; location / { proxy_pass http://121.201.9.155/; //现在有效地址:47.104.7.242 proxy_set_header Host $host; //后端Web服务器的域名和当前配置文件中的server_name保持一致 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
proxy_pass指定要代理的域名的服务器IP,这里的IP就是(ask.apelearn.com)
后三行为定义发往后端Web服务器的请求头,
第二行必须有,否则代理不成功,它表示后端Web服务器的域名和当前配置文件中的server_name保持一致(即ask.apelearn.com)
第三行和第四行可以省略,前面在描述Nginx日志格式的时候介绍过这两个参数,表示的含义是一样的。
$remote_addr为访问网站的用户的入口IP;
$http_x_forwarded_for为代理服务器的IP,如果使用了代理,则会记录代理的IP;
测试:
# /usr/local/nginx/sbin/nginx -t ... ok ... successful # /usr/local/nginx/sbin/nginx -s reload # curl -x127.0.0.1:80 ask.apelearn.com -I //200 ok server: nginx/1.10.3 //虚拟机Nginx # curl ask.apelearn.com -I //200 ok server: nginx/1.0.12 //公网服务器Nginx
ps:如何关闭Nginx版本信息?
4.9.2 负载均衡实例
编写Nginx虚拟主机配置文件之前,先查看一下www.qq.com域名对应的IP
dig命令
# dig www.qq.com ; <<>> DiG 9.9.4-RedHat-9.9.4-38.el7_3.1 <<>> www.qq.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9330 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; QUESTION SECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;www.qq.com. IN A ;; ANSWER SECTION: www.qq.com. 213 IN A 61.135.157.156 www.qq.com. 213 IN A 125.39.240.113 ;; Query time: 22 msec ;; SERVER: 119.29.29.29#53(119.29.29.29) ;; WHEN: 四 3月 30 11:14:37 CST 2013 ;; MSG SIZE rcvd: 71 //有两个IP,这两个IP都可以访问www.qq.com,验证一下: # curl -x61.135.157.156:80 www.qq.com -I //200 ok # curl -x125.39.240.113:80 www.qq.com -I //200 ok
Nginx负载均衡
上面的测试两个IP返回的结果一样,他使用的Web Server软件为squid(一种代理软件)。有两个IP就可以走负载均衡,配置如下:
# vim /usr/local/nginx/conf/vhost/load.conf upstream qq_com { ip_hash; //负载均衡的算法 server 61.135.157.156:80; server 125.39.240.113:80; } server { listen 80; server_name www.qq.com; location / { proxy_pass http://qq_com; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
proxy_pass指定要代理的域名的服务器IP,这里的IP就是(ask.apelearn.com)
后三行为定义发往后端Web服务器的请求头,
第二行必须有,否则代理不成功,它表示后端Web服务器的域名和当前配置文件中的server_name保持一致(即ask.apelearn.com)
第三行和第四行可以省略,前面在描述Nginx日志格式的时候介绍过这两个参数,表示的含义是一样的。
$remote_addr为访问网站的用户的入口IP;
$http_x_forwarded_for为代理服务器的IP,如果使用了代理,则会记录代理的IP;
和简单的代理不同,负载均衡多了一个upstream,在这里定义后端的Web Server,可以是一个或多个。
其中ip_hash为负载均衡的算法,它表示根据IP地址把请求分到不同的服务器上。
比如用户A的IP为1.1.1.1,用户B访问的时候会到第二个Web Server上。
这种算法用在把session存到本机磁盘上的情况(过段时间再次打开网站还是登录状态,session还存在这台服务器上)。
测试:
# /usr/local/nginx/sbin/nginx -t ... ok ... successful # /usr/local/nginx/sbin/nginx -s reload # curl -x127.0.0.1:80 www.qq.com -I //200 ok
虚拟机也可以访问www.qq.ocm,说明代理已起作用
4.10 Nginx配置SSL
HTTPS通信,即使数据包被截获,我们也无法破译里面的内容。
4.10.1HTTPS的通信过程:
通信过程大致如下:
-
(1)浏览器发送一个HTTPS请求给服务器
-
(2)服务器要有一套数字证书,可以自己制作(后面操作有制作的证书),也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面,这套证书其实是一对公钥和私钥。
-
(3)服务器会把公钥传输给客户端
-
(4)客户端(浏览器)收到公钥后,会验证其是否合法有效,无效会有警告提醒,有效则会生成一串随机字符串,并用收到的公钥加密。
-
(5)客户端把加密后的随机字符串传输给服务器
-
(6)服务器收到加密随机字符串后,先用私钥解密(公钥加密,私钥解密),获取到这一串随机字符串后,再用这串随机字符串加密传输的数据(该加密为“对称加密”;即是将数据和私钥,也就是这个随机字符串通过某种算法混合在一起,这样除非知道私钥,否则无法获取数据内容)。
-
(7)服务器把加密后的数据传输给客户端。
-
(8)客户端收到数据后,在用自己的私钥(随机字符串)解密。
4.10.2 SSL证书
服务器上必须有一对公钥和私钥(即SSL证书),如果网站对外提供服务,则需要购买被各大浏览器厂商认可的SSL证书。(阿铭曾在沃通购买过SSL证书,可以做个参考)。目前各大SSL证书服务商已经不再提供免费的SSL证书服务,所以做本实验的时候,只能在Linux机器上生成一对自定义的SSL证书,这个证书不能使用在生产环境中,配置如下:
# cd /usr/local/nginx/conf # openssl genrsa -des3 -out tmp.key 2048 // yum install -y openssl // 这一步是生成key文件(通常称为“私钥”),2048为加密字符串长度,会让我们出入一个密码,密码不能太短。 # openssl rsa -in tmp.key -out amingluinux.key ... //这一步是把刚刚生成的tmp.key再转换成aminglinux.key,目的是删除刚才设置的密码,如果key文件有密码,则必须在Nginx加载它的时候输入它的密码,因此很不方便 # rm -f tmp.ksy # openssl req -new -key aminglinux.key -out aminglinux.csr ... Common Name (...) []:aming.com ... A challenge password []:123456 //这一步是生成证书请求文件,这个并不是上文提到的公钥,但这个文件是必须要有的,我们要拿key文件和这个CSR文件一起生成最终的公钥文件。其中Common Name为后面配置Nginx配置文件的server_name # openssl x509 -req -days 365 -in aminglinux.csr -signkey aminglinux.key -out aminglinux.crt Signture ok subject=/C=XX/L=Default City/0=Default Company Ltd/CN=aming.com Getting Private key //说明:这样最终才生成CRT证书文件,
以上操作的最终目的是生成aminglinux.key和aminglinux.crt这两个文件。购买SSL证书只要是得到这两个文件。
4.10.3 Nginx配置SSL
有了SSL证书,Nginx配置如下:
# vim /usr/local/nginx/conf/vhost/ssl.conf server { listen 443; server_name aming.com index index.html index.php; root /data/nginx/aming.com; ssl on; ssl_certificate aminglinux.crt; ssl_certificate_key aminglinux.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/tmp/php-fcgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /data } }
检查配置:
# /usr/local/nginx/sbin/nginx -t nginx: [emerg] unknown directive "ssl" in /usr/local/nginx/conf/vhost/ssl.conf:8 nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
ps:当前的Nginx并不支持SSL,这是因为在Nginx编译时,并没有额外配置支持SSL的参数,要解决该问题只能重新编译一遍Nginx。
如下:
//重新编译 # cd /usr/lcoal/src/nginx-1.10.3/ # ./configure --prefix=/usr/local/nginx --with-http_ssl_module # make # make install //校验 # /usr/lcoal/nginx/sbinx -t ...ok ...successful //测试文件 # mkdir /data/nginx/aming.com # echo "<?php phpinfo(); ?>" > /data/nginx/aming.com/1.php # /etc/init.d/nginx restart # vim /etc/hosts 192.168.188.128 aming.com
用浏览器访问https://aming.com/1.php会提示不安全(自制证书没有得到浏览器认可)。
继续访问:页面点击高级》添加例外》确认安全例外
访问https://www.12306.cn同样也会提示不安全,证书是它自己颁发的,不被浏览器承认。
5.php-fpm配置
和LAMP不同的是,在LNMP架构中,php-fpm作为独立的一个服务存在。既然是独立服务,那么必然有自己的配置文件。
php-fpm的配置文件为/usr/local/php-fpm/etc/php-fpm.conf,它同样也支持include语句,类似于nginx.conf里面的include。
5.1 php-fpm的pool
在php环境中,一个站点可以引用多个pool池,避免多个站点共同使用单个pool池进程,导致pool进程用完,用户访问站点出现502情况。单个pool池最大可以定义50个进程同时使用。
Nginx可以配置多个虚拟主机,php-fpm同样也支持配置多个pool,每一个pool可以监听一个端口,也可以监听一个socket,这个概念已在前面的章节在前面的章节中有所阐述。阿铭把php-fpm.conf做一个更改:
[global] pid = /usr/local/php-fpm/etc/php-fpm.pid error_log = /usr/local/php-fpm/var/log/php-fpm.log include = etc/php-fpm.d/*.conf
ps:
安装PHP时配置文件的pool在/usr/local/php-fpm/etc/php-fpm.conf,现在是把pool写成独立的配置文件(etc/php-fpm.d/目录下)
//include的这一行比较特殊,注意等号后面的路径,必须写上etc目录,然后需要创建*配置文件目录*和子配置文件:
# mkdir /usr/local/php-fpm/etc/php-fpm.d # cd /usr/local/php-fpm/etc/php-fpm.d # vim www.conf [www] listen = /tmp/www.sock listen.mode=666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers = 20 pm.mi_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024 # vim aming.conf [aming] listen = /tmp/aming.sock listen.mode=666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers =20 pm.mi_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500r rlimit_files =1024
第一个pool监听/tmp/www.sock,第二个pool监听/tmp/aming.sock。这样可以在Nginx不同的虚拟主机中调用不同的pool,从而达到相互隔离的目的,两个pool互不影响。
# /usr/local/php-fpm/sbin/php-fpm -t ... successful # /etc/init.d/php-fpm restart Gracefully shutting down php-fpm . done Starting php-fpm done # ls /tmp/*.sock /tmp/aming.sock /tmp/mysql.sock /tmp/php-fcgi.sock
/tmp/php-fcgi.sock在配置Nginx解析PHP(/usr/local/nginx/conf/vhost/test.com.conf)中
5.2 php-fpm的慢执行日志
通过php-fpm的慢执行日志,可以清晰了解PHP的脚本哪里执行时间长,他可以定位到具体行。PHP网站访问卡顿问题,可以看慢执行日志
# vim /usr/loca/php-fpm/etc/php-fpm.d/www.conf //最后面追加 request_slowlog_timeout = 1 //定义超时时间,PHP脚本执行时间超过1秒会被记录 slowlog = /usr/local/php-fpm/var/log/www-slow.log //定义慢执行日志的路径和名字
5.3 php-fpm定义open_basedir
httpd设置有讲述过
httpd可以针对每个虚拟主机设置一个open_basedir,php-fpm同样也可以针对不同的pool设置不同的open_basedir。
# vim /usr/local/php-fpm/etc/php-fpm.d/aming.conf //最后面加入 php_admin_value[open_basedir]=/data/www/:/tmp/
只要在对应的Nginx虚拟主机配置文件中调用对应的pool,就可以使用open_basedir来物理隔离多个站点,从而达到安全的目的。
5.4 php-fpm进程管理
该配置在/usr/local/php-fpm/etc/php-fpm.conf 或 /usr/local/php-fpm/etc/php-fpm.d/xxx.conf
看一段配置:
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.mi_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
-
第一行,定义php-fpm的子进程启动模式(dynamic,static)
dynamic为动态模式;一开始只启动少量的子进程,根据实际需求,动态地增加或者减少子进程,最多不会超过pm.max_children定义的数值。
static模式;这种模式下子进程的数量由pm.max_children决定,一次性启动这么多,不会减少也不会增加
-
pm.start_servers针对dynamic模式,它定义php-fpm服务在启动服务时产生的子进程的数量
-
pm.min_spare_servers针对dynamic模式,它定义在空闲时段子进程数的最少数量,如果达到这个数值是,php-fpm服务会自动派生新的子进程。
-
pm.max_spare_servers也是针对dynamic模式的,他定义在空闲时段子进程数的最大值,如果高于这个数值就开始清理空闲的子进程。
-
pm.max_requests针对dynamix模式,它定义一个子进程最多的请求书,也就是一个php-fpm的子进程中最多可以处理这么多请求,当达到这个数值时,它会自动退出。