NginxWEB架构实战篇

NginxWEB架构实战篇

  • 1.动态网站架构
  • 2.LNMP动态网站环境部署
    • 2.1Linux部署
    • 2.2Nginx部署
    • 2.3php-fpm部署
    • 2.4MySQL部署
    • 2.5业务上线(开发那点事)
  • 3.fastcgi & php-fpm
    • 3.1静态网站
    • 3.2Nginx
    • 3.3PHP
    • 3.4php-mysql
    • 3.5MySQL
    • 3.6面试题
  • 4.php-fpm初始化配置
    • 4.1了解php-fpm相关配置文件
    • 4.2初始化php-fpm
    • 4.3启动php状态监控页面功能
  • 5.Nginx Location
    • 5.1前言
    • 5.2语法规则
    • 5.3Location优先级
    • 5.4Location示例
  • 6.Nginx Rewrite
    • 6.1什么是Rewrite
    • 6.2Rewrite相关指令
    • 6.3Rewrite flag
    • 6.4Rwrite匹配参考示例
  • 7.CA & HTTPS
    • 7.1私有CA
    • 7.2公网CA
  • 8.Nginx的平滑升级
    • 8.1原理
    • 8.2平滑升级1.12到1.14版本
    • 8.3回退到以前版本
    • 8.4总结

1.动态网站架构

资源文件识别 语言识别 框架识别
index.php 开源的php Windows/Linux+nginx+php+mysql
index.py 开源python Windows/Linux+apache+python+mysql
index.jsp 商业JAVA windows/Linux+tomcat+JDK+Oracle
index.asp 商业c# Windows+iis+asp.net+sql-server/oracle/mogodb

2.LNMP动态网站环境部署

2.1Linux部署

[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0

2.2Nginx部署

[root@localhost ~]# yum install -y nginx

2.3php-fpm部署

部署方法2选1

1.RPM部署

[root@localhost ~]# yum install -y php-fpm php-mysql php-gd
#php-fpm:php接收动态请求的程序
#php-mysql:php链接mysql的程序
#php-gd:图形库程序(GD库可以处理图片,或者生成图片)

[root@localhost ~]# systemctl restart php-fpm
#启动php-fpm

[root@localhost ~]# systemctl enable php-fpm
#开机启动php-fpm

[root@localhost ~]# netstat -anpt | grep 9000
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      1362/php-fpm: maste 

[root@localhost ~]# vim /usr/share/nginx/html/index.php
#测试php页面(php基本信息)
();
?>
#测试语句

[root@localhost ~]# 
vim /etc/nginx/conf.d/default.conf 
	server {
     
location / {
     
...
index index.php index.html;
#增加PHP主页名称:index.php
...
}
}
[root@localhost ~]# vim /etc/nginx/conf.d/default.conf 
server {
     
location / {
     
index index.php;
}
location ~ \.php$ {
     
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
#启动nginx_fastcgi功能,解除#注释修改路径即可。
}
}
[root@localhost ~]# systemctl restart nginx

浏览器观察http://192.168.36.154/index.php
NginxWEB架构实战篇_第1张图片
fastcgi_param:这个配置的意思是 在浏览器中访问的.php文件,实际读取的是$ document _root(网站根目录)下的.php文件。也就是说当访问127.0.0.1/index.php的时候,需要读取网站根目录下面的index.php文件,如果没有配置这一配置项时,nginx不回去网站根目录下访问.php文件,所以返回空白。
通过location指令,将所有以php为后缀的文件都交给127.0.0.1:9000来处理,而这里的IP地址和端口就是FastCGI进程监听的IP地址和端口。
fastcgi_param指令指定放置PHP动态程序的主目录,也就是$fastcgi_script_name前面指定的路径,这里是/usr/local/nginx/html目录,建议将这个目录与Nginx虚拟主机指定的根目录保持一致,当然也可以不一致。
fastcgi_params文件是FastCGI进程的一个参数配置文件,在安装Nginx后,会默认生成一个这样的文件,这里通过include指令将FastCGI参数配置文件包含了进来。接下来,启动nginx服务。/usr/local/nginx/sbin/nginx 到此为止,Nginx+PHP已经配置完成。

2.源码部署(可选)
部署PHP-fpm
1. 以php-fpm的方式安装php

[root@webserver ~]# yum -y install libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel \
libxml2 libxml2-devel libcurl libcurl-devel libxslt-devel openssl-devel

[root@webserver ~]# tar xf php-5.6.29.tar.xz 
[root@webserver ~]# cd php-5.6.29/
[root@webserver ~]# ./configure \
--prefix=/usr/local/php \
--with-curl \
--with-freetype-dir \
--with-gd \
--with-gettext \
--with-iconv-dir \
--with-jpeg-dir \
--with-kerberos \
--with-libdir=lib64 \
--with-libxml-dir \
--with-mysql \
--with-mysqli \
--with-openssl \
--with-pcre-regex \
--with-pdo-mysql \
--with-pdo-sqlite \
--with-pear \
--with-png-dir \
--with-xmlrpc \
--with-xsl \
--with-zlib \
--enable-fpm \
--enable-bcmath \
--enable-libxml \
--enable-inline-optimization \
--enable-gd-native-ttf \
--enable-mbregex \
--enable-mbstring \
--enable-opcache \
--enable-pcntl \
--enable-shmop \
--enable-soap \
--enable-sockets \
--enable-sysvsem \
--enable-xml \
--enable-zip
[root@webserver php-5.6.29]# make
[root@webserver php-5.6.29]# make install

2. php-fpm配置文件(影响php处理php程序的性能,例如php进程数、最大连接数配置等,运维人员关注)

[root@webserver php-5.6.29]# cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf

3. php置文件(影响php代码,例如允许客户端最大上传文件的大小,设置的timezone,php所支持的扩展功能例如是否可以连接MySQL、Memcache,程序员关注)

[root@webserver php-5.6.29]# cp php.ini-production /usr/local/php/lib/php.ini

4. init script centos6 [可选]centos6
[root@webserver php-5.6.29]# cp sapi/fpm/init.d.php-fpm /etc/rc.d/init.d/php-fpm
[root@webserver php-5.6.29]# chmod a+x /etc/rc.d/init.d/php-fpm
[root@webserver php-5.6.29]# chkconfig --add php-fpm
[root@webserver php-5.6.29]# chkconfig php-fpm on
[root@webserver php-5.6.29]# service php-fpm start
Starting php-fpm  done

5. Systemd Script centos7 [可选]

[root@webserver ~]# vim /usr/lib/systemd/system/php-fpm.service
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target

[Service]
Type=simple
PIDFile=/run/php-fpm.pid
ExecStart=/usr/local/php/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGINT $MAINPID

[Install]
WantedBy=multi-user.target

[root@webserver ~]# systemctl start php-fpm.service 
[root@webserver ~]# systemctl status php-fpm.service


[root@localhost ~]# ss -an |egrep ':80|:9000'
tcp    LISTEN     0      128    127.0.0.1:9000                  *:*                  
tcp    LISTEN     0      128                  *:80                  *:*  

2.4MySQL部署

部署方法2选1

1.RPM部署

[root@localhost ~]# yum -y install mariadb-server mariadb
	#安装mysql服务器程序和客户机程序。
[root@localhost ~]# systemctl start mariadb
	#启动mysql服务器
[root@localhost ~]# systemctl enable mariadb
	#开机启动mysql服务器
[root@localhost ~]# mysqladmin password '123456'
	#修改mysql的root密码为‘123456’
[root@localhost ~]# mysql -uroot -p'123456'
MariaDB[(none)]> create database bbs;
	#准备数据库,存放app
MariaDB[(none)]> grant all on bbs.* to phptest@'192.168.36.%' identified by '123456';
	#授权phptest用户管理bbs库
	#请注意用户名密码主机参数需要更换。
MariaDB[(none)]> flush privileges;
	#刷新权限
[root@localhost ~]# vim /usr/share/nginx/html/index.php
$link=mysql_connect('192.168.36.154','phptest','123456');
if ($link)
              echo "Successfuly";
else
              echo "Faile";
mysql_close();
?>
	#修改主页,测试MYSQL的链接状态
	#如果测试为faile,请检查数据库授权结果。
2.源码部署(了解)

2.5业务上线(开发那点事)

  • 技术点

UI:构图
前端:通过表单,文本框,提交按钮,页面布局
后端:php连接函数
后端:php插入函数
DBA:实现后台数据库的写入。
OP:业务上线

  • 准备前台html页面
[root@localhost ~]# vim /usr/share/nginx/html/1.html


"logo.jpg" />

"insert.php" method="post"> Firstname: type="text" name="firstname" /> Lastname: type="text" name="lastname" /> Age: type="text" name="age" /> type="submit" /> </form> </body> </html> #html 页面的开始 #body页面内容的开始 #form 表单,整理input #input,文本框 #/form 表单结束 #/body 页面内容结束 #/html 页面结束
  • 准备php中间件
[root@localhost ~]# vim /usr/share/nginx/html/insert.php
$con = mysql_connect("192.168.36.154","root","123456");
if (!$con)
  {
     
  die('Could not connect: ' . mysql_error());
  }

mysql_select_db("my_db", $con);
$sql="INSERT INTO Persons (FirstName, LastName, Age)
VALUES
('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";

if (!mysql_query($sql,$con))
  {
     
  die('Error: ' . mysql_error());
  }
echo "1 record added";

mysql_close($con)
?>

#mysql_connect()连接数据库函数
#mysql_select_db()选择数据库函数
#$sql 插入数据变量
#INSERT INTO mysql的插入语言。
  • 准备库和表
MariaDB[(none)]> create database my_db;
MariaDB[(none)]> use my_db;
MariaDB [(none)]> use my_db;
MariaDB [(my_db)]>  create table Persons (FirstName varchar(50), LastName varchar(50),Age int );
MariaDB [(my_db)]>  grant all on *.* to root@'%' identified by '123456';
MariaDB [(my_db)]>  grant all on *.* to root@'服务器IP' identified by '123456';
  • 输入页面

NginxWEB架构实战篇_第2张图片

  • 输出页面
[root@localhost ~]# vim /usr/share/nginx/html/select.php
	$con = mysql_connect("localhost","root","123456");
if (!$con)
  {
     
  die('Could not connect: ' . mysql_error());
  }

mysql_select_db("my_db", $con);

$result = mysql_query("SELECT * FROM Persons");

echo "";while($row = mysql_fetch_array($result)){
     echo"";echo"";echo"";echo"";}echo"
Firstname Lastname
" . $row['FirstName'] . " " . $row['LastName'] . "
"
; mysql_close($con); ?>
  • 后台数据
MariaDB [my_db]> select * from Persons;
+-----------+----------+------+
| FirstName | LastName | Age  |
+-----------+----------+------+
| xiule     | le       |   23 |
+-----------+----------+------+

  • 前台输出

浏览器访问 http://192.168.100.10/select.php 观察

3.fastcgi & php-fpm

3.1静态网站

nginx服务器能处理的是静态元素 .html .jpg .mp4 .css

3.2Nginx

ngx_fastcgi_module
处理动态请求的接口
nginx通过ngx_fastcgi_module模块链接php-fpm处理动态请求

3.3PHP

php-fpm
PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)
是一个PHP FastCGI管理器。
PHP通过php-fpm接收前台nginx的动态访问的请求,比如向后端Mysql进行查询请求后,将查询结果返回给前台nginx。

3.4php-mysql

php-mysql
php-mysql:是php链接mysql的接口程序

3.5MySQL

存储数据

3.6面试题

  • 1.什么是Fast CGI
  • 2.Nginx+FastCGI运行原理

浏览器发送http请求给服务器nginx上,nginx将这个请求转发给fast-cgi模块,fast-cgi去与php-fpm通信,php-fpm调用php解析器解析,将解析结果原路返回直到浏览器上,最终浏览器解析内容渲染。

  • 3.LNMP运行原理

LNMP的工作原理
首先解释一下LNMP的意思,指的是Linux+Nginx+Mysql+PHP。其工作原理。
首先,浏览器发送http request请求到服务器(Nginx),服务器响应并处理web请求,将一些静态资源(CSS,图片,视频等)保存服务器上,然后将php脚本通过接口传输协议(网关协议)PHP-FCGI(fast-cgi)传输给PHP-FPM(进程管理程序),PHP-FPM不做处理,然后PHP-FPM调用PHP解析器进程,PHP解析器解析php脚本信息。PHP解析器进程可以启动多个,进行并发执行。然后将解析后的脚本返回到PHP-FPM,PHP-FPM再通过fast-cgi的形式将脚本信息传送给Nginx.服务器再通过Http response的形式传送给浏览器。浏览器再进行解析与渲染然后进行呈现。
以上整个就是LNMP的工作过程。
LAMP的工作原理
LAMP其实是指Linux+Apache+Mysql+PHP的结构体系。其工作原理如下:
浏览器向服务器发送http请求,服务器 (Apache) 接受请求,由于php作为Apache的组件模块也会一起启动,它们具有相同的生命周期。Apache会将一些静态资源保存,然后去调用php处理模块进行php脚本的处理。脚本处理完后,Apache将处理完的信息通过http response的方式发送给浏览器,浏览器解析,渲染等一系列操作后呈现整个网页。
两者的区别
在LNMP中,Nginx本身对脚本不做任何的处理,而是去调用一个PHP-FPM的进程,二者是相互独立的。
在LAMP中,PHP是Apache的一个模块,具有相同的生命周期。

4.php-fpm初始化配置

4.1了解php-fpm相关配置文件

  • 1.核心配置文件
[root@localhost ~]# vim /etc/php.ini
date.timezone = PRC
	#设置PHP的时区,一般用Asia/shanghai
open_basedir
	#设置PHP脚本允许访问的目录. 一般不用设置.
	#open_basedir 将PHP所能打开的文件限制在指定的目录树中,包括文件本身。
	#当程序要使用例如fopen()或file_get_contents()打开一个文件时,这个文件的位置将会被检查。
	#当文件在指定的目录树之外,程序将拒绝打开。
  • 2.全局配置文件
[root@localhost ~]# vim /etc/php-fpm.conf 
pid = /run/php-fpm/php-fpm.pid
	#设置pid文件的位置
error_log = log/php-fpm.log
	#记录错误日志的文件
log_level = notice 
	#记录日志的等级
	#alert(必须立即处理), error(错误情况), warning(警告情况), notice(一般重要信息), debug(调试信息). 默认: notice.
 process.max = 3
	#默认没设置
	#process.max: 控制子进程最大数的全局变量, 后边的设置子进程数量的指令受到这个值的限制, 0表示无限制
daemonize = yes
	#将fpm转至后台运行
  • 3.扩展配置文件
[root@localhost ~]# vim /etc/php-fpm.d/www.conf
user = nginx
	#设置用户和用户组
listen.allowed_clients = 127.0.0.1
	#允许访问FastCGI进程的IP(nginx IP),设置any为不限制IP,
	#如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。
	#默认值是any。
	#每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接
listen = 127.0.0.1:9000 
	#fpm监听端口,即nginx中php处理的地址,一般默认值即可。可用格式为: 'ip:port'
slowlog = /var/log/php-fpm/$pool-slow.log
	#开启慢日志
pm=dynamic
	#动态模式进程管理开启
start_servers=5
	#最初开启多少进程
min_spare_server =5
	#最小的多余进程数。最少空闲。用户访问会消耗掉进程。
	#然后为了满足后续随时随地开启进程保持空闲数为5。
max_children = 50
	#最大进程数
	#max_children是PHP-FPM Pool 最大的子进程数,他数值取决于你的服务器内存。 
	#假设你打算给10G内存给当前配置的PHP-FPM Pool,一般一个PHP请求占用内存10M-40M,我们按站点每个PHP请求占用内存25M,这样max_children = 10G/25M = 409。所以,这个值可以根据情况算出来。
max_spare_servers=10
	#最大的多余进程。大规模断开后,高并发访问过后,还剩多少。
max_requests = 500
	#每个子进程能响应的请求数量,到达此数字,该PHP进程就被释放掉了。
	#max_requests是每个子进程重生之前处理的请求数, 默认值为unlimited(默认1024),可以设置小一点(如500左右),这样可以避免内存泄露带来的问题

4.2初始化php-fpm

  • 初始化前
[root@localhost ~]# ps aux |grep php
	#观察php程序存在十个进程。
  • 初始化
[root@localhost ~]# vim /etc/php-fpm.d/www.conf
#设置生产环境下常用数值。16G
pm = dynamic
#启动动态管理模式
pm.start_servers = 32
#初始启动32个进程
pm.max_children = 512
#最大进程数。(子进程数会在最大和最小数范围中变化)512个进程数是在大于16G内存的前提下。

pm.min_spare_servers = 32
#随着用户访问的增加,保持32个空闲进程。
pm.max_spare_servers = 64
#随着用户离去。杀死大量空闲进程来节约资源。
pm.max_requests = 1500
#是每个子进程重生之前处理的请求数, 默认值为unlimited(为1024)
[root@localhost ~]# systemctl restart php-fpm

关于max_children
max_children是PHP-FPM Pool 最大的子进程数,他数值取决于你的服务器内存。 假设你打算给10G内存给当前配置的PHP-FPM Pool,一般一个PHP请求占用内存10M-40M,我们按站点每个PHP请求占用内存25M,这样max_children = 10G/25M = 409。所以,这个值可以根据情况算出来

  • 初始化后
[root@localhost ~]# ps aux | grep php | wc -l
34

4.3启动php状态监控页面功能

  • 1.启动测试页功能
[root@localhost ~]# vim  /etc/php-fpm.d/www.conf
	pm.status_path = /php_status
  • 2.nginx配置页面转发
[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
location = /php_status {
     
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
include fastcgi_params;
}
[root@localhost ~]# systemctl restart nginx
[root@localhost ~]# systemctl restart php-fpm

fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
这个配置的意思是 在浏览器中访问的.php文件,实际读取的是 $document_root(网站根目录)下的.php文件 – 也就是说当访问127.0.0.1/index.php的时候,需要读取网站根目录下面的index.php文件,如果没有配置这一配置项时,nginx不回去网站根目录下访问.php文件,所以返回空白
include fastcgi_params是常用变量所在的文件名。

  • 3.访问测试页

http://192.168.36.154/php_status
NginxWEB架构实战篇_第3张图片
pool
– fpm池子名称,大多数为www
process manager
– 进程管理方式,值:static, dynamic or ondemand. dynamic
start time
– 启动日期,如果reload了php-fpm,时间会更新
start since
– 运行时长
accepted conn
– 当前池子接受的请求数
listen queue
– 请求等待队列,如果这个值不为0,那么要增加FPM的进程数量
max listen queue
– 请求等待队列最高的数量
listen queue len
– socket等待队列长度
idle processes
– 空闲进程数量
active processes
– 活跃进程数量
total processes
– 总进程数量
max active processes
– 最大的活跃进程数量(FPM启动开始算)
max children reached
– 进程最大数量限制的次数,如果这个数量不为0,那说明你的最大进程数量太小了,请改大一点。
slow requests
– 启用了php-fpm slow-log,缓慢请求的数量

5.Nginx Location

5.1前言

通常网站的部分页面,需要特殊设置。
比如,/1.html 页面,需要用户访问控制(如allow all)。
location = /1.html {
allow all;
}
那部分页面该如何表达呢?
答案:就是位置 Location URL { module }. 其中URL的表达方式中使用的正则表达式,常会有冲突的情况,请通过下面的实验,了解常见的冲突符号,并掌握其中的优先级。

5.2语法规则

location [ = | ~ | ~ * | ! ~ | ! ~* | ^~ ] /uri/ {
module;
module;
}

= 表示精确匹配,优先级也是最高的
~ 区分大小写的正则匹配
~* 不区分大小写的正则匹配
/ 通用匹配,任何请求都会匹配到
^~ 以某些字符串开头
!~ 非(区分大小写匹配的正则)
!~* 非(不区分大小写匹配的正则)

5.3Location优先级

=   >>   ^~   >>   ~|~*|!~|!
精确匹配>>字符开头>>正则匹配>>通配

5.4Location示例

通过不同的表达式,观察表达式间的优先级

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
server {
     
        listen 192.168.100.11;
        root /abcd;
        index  index.html;
location = / {
      index a.html; }
location ~ / {
      index b.html; }
location   / {
      index c.html; }
}

a.html/b.html/c.html存储不同内容即可。
访问页面。观察显示的内容。理解正则符号间的优先级。

6.Nginx Rewrite

Nginx URL重写

6.1什么是Rewrite

  1. URL Rewrite最常见的应用是URL伪静态化,是将动态页面显示为静态页面方式的一种技术。
    比如http://www.123.com/news/index.php?id=123 使用URLRewrite 转换后可以显示为http://www.123.com/news/123.html对于追求完美主义的网站设计师,就算是网页的地址也希望看起来尽量简洁明快。
    理论上,搜索引擎更喜欢静态页面形式的网页,搜索引擎对静态页面的评分一般要高于动态页面。所以,UrlRewrite可以让我们网站的网页更容易被搜索引擎所收录。
  1. 从安全角度上讲,如果在URL中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的URL地址可以给我们带来更高的安全性。
  1. 实现网站地址跳转,例如用户访问360buy.com,将其跳转到jd.com。

6.2Rewrite相关指令

  • 重定向

rewrite
将用户的访问(url),更换成指定的文件。

  • if语句

应用环境:server,location
语法:if (condition) { … }

  • 条件判断

~*
正则匹配 (不区分大小写)
!~
非正则匹配 (区分大小写)
!~*
非正则匹配 (不区分大小写)
-f 和!-f
用来判断是否存在文件
-d 和!-d
用来判断是否存在目录
-e 和!-e
用来判断是否存在文件或目录
-x 和!-x
用来判断文件是否可执行

  • 全局变量
$document_root
	#针对当前请求的根路径设置值;
$remote_addr
	#客户端地址;
$request_filename
	#当前请求的文件路径名(带网站的主目录/usr/local/nginx/html/images/a.jpg)
$request_uri
	#当前请求的文件路径名(不带网站的主目录/images/a.jpg)
$scheme 
	#用的协议,比如http或者是https
$server_name 
	#请求到达的服务器名;
$args
	#请求中的参数;
$host
	#请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
$limit_rate
	#对连接速率的限制;
$request_method
	#请求的方法,比如"GET"、"POST"等;
$remote_port
	#客户端端口号;
$remote_user
	#客户端用户名,认证用;
$query_string 
	#与$args相同;
$server_protocol 
	#请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
$server_addr  
	#服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$document_uri  
	#与$uri一样,URI地址;
$server_port  
	#请求到达的服务器端口号;

6.3Rewrite flag

每行rewrite指令最后跟一个flag标记,支持的flag标记有:
last停止处理当前ngx_http_rewrite_module,从指令之后的一个新的位置改变URI匹配搜索;
break本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect返回302临时重定向,浏览器地址会显示跳转后的URL地址

redirect url permanent返回301永久重定向,浏览器地址会显示跳转后URL地址

redirect 和 permanent区别则是返回的不同方式的重定向,对于客户端来说一般状态下是没有区别的。而对于搜索引擎,相对来说301的重定向更加友好,
如果我们把一个地址采用301跳转方式跳转的话,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。

使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会更改,那么很有可能出现URL劫持的现像。

6.4Rwrite匹配参考示例

  • 例1:

0.目的

当用户访问http://192.168.100.10/abc/a/1.html 地址时,
通过redirect 重定向至http://192.168.100.10/ccc/bbb/2.html
注意:

  1. 192.168.100.10/abc/a/1.html是否存在已经不重要了。
  2. 2.192.168.100.10/ccc/bbb/2.html页面必须存在。

1.还原默认站点

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf 
	server {
     
        listen 80;
        location / {
     
        root /usr/share/nginx/html;
        index index.html index.php index.htm;
        }
}
[root@localhost ~]# vim /usr/share/nginx/html/index.html 
	#输入下面的文字。证明这是默认主页文件
/usr/share/nginx/html/index.html

2.配置地址重写

[root@localhost ~]# mkdir /usr/share/nginx/html/ccc/bbb -p
	#创建待测试目录
[root@localhost ~]# vim /usr/share/nginx/html/ccc/bbb/2.html
	#创建待测试目标页面
[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
server {
     
	...
        location ~ /abc {
     
        rewrite   .*   /ccc/bbb/2.html permanent;

        }
	...
}
#匹配请求中的”abc“字段
#将请求中的url换成新的url

--------------------------------------------------------------------

#return 301也具有相同功能。

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
server {
     
	...
        location /abc {
     
      
        return 301 /ccc/bbb/2.html;
        }
	...
}
#匹配请求中的”abc“字段
#将请求中的url换成新的url
#return 301也具有相同功能。

--------------------------------------------------------------------

[root@localhost ~]# systemctl restart nginx

3.访问旧页面进行测试

浏览器访问 http://192.168.100.10/abc/a/1.html
重定向成功。实验完毕
NginxWEB架构实战篇_第4张图片

4.关于permanent

permanent 会将地址显示为新的URL地址(重定向之后的URL)
添加上permanent:url被替换,生成两次请求。服务器只转换了url,客户端重新申请。
不添加permanent:url是老的,服务器内部转换请求。服务器内部转换URL,内部转换页面。

5.表达式问题1

用以下匹配方式,对URL(http://192.168.100.10/abc/123.html)进行匹配有什么区别
Location = /abc
通过此URL:http://192.168.100.10/abc/123.html访问服务器,结果是否会重定向
不可行。因为需要完全匹配
Location ~ /abc
通过此URL:http://192.168.100.10/abc/123.html访问服务器,结果是否会重定向
可行。因为部分匹配即可
Location ^~ /abc
通过此URL:http://192.168.100.10/abc/123.html访问服务器,结果是否会重定向
可行。因为部分匹配即可

6.表达式问题2

如下URL( http://192.168.100.10/cde/abc/1.html)进行匹配的语句(Location ~ /abc)
会进行这样的匹配访问时
如何阻止这样的url重定向
location ~ ^/abc

  • 例2

目的:
利用正则中的”()和\1 “,
替换url中一部分的内容。
将(访问)http://192.168.100.10/2016/a/b/c/1.html
换(跳转)http://192.168.100.10/2017/a/b/c/1.html
方法:
location /2016 {
rewrite ^/2016/(.*)$ /2017/$1 permanent;
}

1.注释掉上一个实验中的重定向部分

避免实验出现交叉影响

2.配置地址重写

[root@localhost ~]# mkdir /usr/share/nginx/html/2017/a/b/c/ -p
	#准备目标目录
[root@localhost ~]# vim /usr/share/nginx/html/2017/a/b/c/1.html
	#准备目标页面
[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
	server{
     
	... 
	        location /2016 {
     
        rewrite ^/2016/(.*)$ /2017/$1 permanent;
        }
	...
}

3.访问旧页面进行测试

http://192.168.100.10/2016/a/b/c/1.html
url因为permanent被重新改写
请求也变为2次。客户端重新申请了两次。

[root@localhost ~]# cat /var/log/nginx/access.log
192.168.100.254 - - [1/Dec/2017:18:25:43 +0800] "GET /2016/a/b/c/1.html HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0" "-"
192.168.100.254 - - [1/Dec/2017:18:25:43 +0800] "GET /2017/a/b/c/1.html HTTP/1.1" 200 70 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0" "-"
  • 例3

目的:
了解判断在重定向中的使用方法。
location { rewrite } 只能替换url中的目录路径,
使用if (){rewrite}可以替换协议主机目录全部能容。
将http://www.jslinux.com
换http://jd.com

1.注释掉上一个实验中的重定向部分

2.配置地址重写

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
	server{
     
	... 
	if ( $host ~* jslinux.com ) {
     
        rewrite .*      http://jd.com permanent;
        }
    ...
}

3.访问旧页面进行测试

注意客户端jslinux.com的域名解析
访问http://jslinux.com重定向到jd.com,实验成功。

  • 例4

前言:
如果希望替换掉域名中的主机,保留后端url路径。可以使用nginx内置变量调用老的url目录路径。
示例:

http://jslinux.com/ccc/bbb/2.html
换成
http://cloud.com/ccc/bbb/2.html

1.准备一个新网站新页面
cloud.com
准备一个新页面
ccc/bbb/2.html

2.配置地址重写

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
	server{
     
	... 
	 if ( $host ~* jslinux.com ) {
     
rewrite .*      http://cloud.com$request_uri permanent;
		}
    ...
}
#注意客户端解析cloud.com的问题。

3.访问旧页面进行测试

http://jslinux.com/ccc/bbb/2.html

  • 例5

目的:
在访问的url是目录时,在URL自动添加一个“/” (如果不是目录,则不加/)
(但是先做个判断,是目录才需要加,不是目录就不加。)
当用户访问网站时,输入的URL不完整。
1.输入的URL是目录时,自动添加“/”
http://www.baidu.com/abc
2.输入的URL是文件时,不添加“/”
http://www.baidu.com/abc/index.html
3.输入的URL是目录,但已经添加"/"时,不添加“/”
http://www.baidu.com/abc/

if (-d $request_filename) {
     
rewrite ^(.*)([^/])$ http://$host$1$2/ permanent;
}

1.注释掉上一个是严重的重定向部分

2.配置地址重写

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
	server{
     
	... 
	 if (-d $request_filename) {
     
rewrite     ^(.*)([^/])$      http://$host$1$2/ permanent;
	}
    ...
}

准备目标目录

[root@localhost ~]# mkdir /usr/share/nginx/html/dir
[root@localhost ~]# echo '/usr/share/nginx/html/dir' > /usr/share/nginx/html/dir/index.html

3.访问页面进行测试

访问目录
http://jslinux.com/dir
注意发生重定向现象。观察url后方多了“/”。
访问文件
http://jslinux.com/dir/1.html
没有触发重定向现象。观察url后方没有变化。

  • 例6

目的

将旧url中的字段,引入重定向后新url中。
http://www.tianyun.com/login/tianyun.html
转为
http://www.tianyun.com/reg/login.php?user=tianyun
如何引用‘tianyun’关键字

演示(了解)

location /login {
rewrite ^/login/(.*).html$ /reg/login.php?user=$1;
}
因涉及动态站点环境,理解概念即可。

  • 例7

目的:
目录的表达方式发生了变化。
原先的“-”分割,变成了“/”目录层次

http://www.tianyun.com/qf/11-22-33/1.html
转换为
http://www.tianyun.com/qf/11/22/33/1.html

location /qf {
rewrite ^/qf/([0-9]+)-([0-9]+)-([0-9]+)(.*)$ /qf/$1/$2/$3$4 permanent;
}

1.注释掉上一个实验的重定向部分

2.配置地址重写

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
	server{
     
	... 
	 location /qf {
     
     rewrite ^/qf/([0-9]+)-([0-9]+)-([0-9]+)(.*)$ /qf/$1/$2/$3$4 permanent;
     root /usr/share/nginx/html;
           }

    ...
}
[root@localhost ~]# mkdir /usr/share/nginx/html/qf/11/22/33/ -p
	#准备目标目录
[root@localhost ~]# echo '/usr/share/nginx/html/qf/11/22/33/1.html' > /usr/share/nginx/html/qf/11/22/33/1.html
	#准备目标页面

3.访问页面进行测试

http://jslinux.com/qf/11-22-33/1.html

  • 例8

目的:
引用原URL当中的信息,重定向至目标的URL
http://alice.jslinux.com >> http://www.jslinux.com/alice
http://jack.jslinux.com >> http://www.jslinux.com/jack

if ($host ~* "^www.jslinux.com$" ) {
     
      break;
  }
if ($host ~* "^(.*)\.jslinux\.com$" ) {
     
      set $user $1;
      rewrite .* http://www.jslinux.com/$user permanent;
  }
这里break是为了跳出循环。
如不加break。
每一次重写后,主机名都符合if的判断结果,会再次被重写。
set 指令是用于定义一个变量,并且赋值。应用于server,location,if环境。

1.注释掉上一个实验中的重定向部分

2.配置地址重写

准备目标页面

[root@localhost ~]# mkdir /usr/share/nginx/html/{jack,alice}
[root@localhost ~]# echo "jack" > /usr/share/nginx/html/jack/index.html
[root@localhost ~]# echo "alice" > /usr/share/nginx/html/alice/index.html

准备客户端DNS记录

10.8.162.78 jack.jslinux.com alice.jslinux.com www.jslinux.com

Nginx Rewrite

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf
	server{
     
	... 
	if ($host ~* "^www.jslinux.com$" ) {
     
      break;
  }

if ($host ~* "^(.*)\.jslinux\.com$" ) {
     
      set $user $1;
      rewrite .* http://www.jslinux.com/$user permanent;
  }
    ...
}
#这里break是为了跳出循环。
#如不加break。
#每一次重写后,主机名都符合if的判断结果,会再次被重写。

3.访问页面进行测试

alice.jslinux.com
jack.jslinux.com

  • 例9

目的:
如果访问服务器中的特殊文件。如:.sh结尾的文件。则返回403操作拒绝错误

示例

location ~* .sh$ {
return 403;
#return 301 http://www.jslinux.com;
}

  • 例10

目的:last标记

1.准备三个页面

[root@localhost ~]# mkdir /usr/share/nginx/html/test 
[root@localhost ~]# echo 'break' > /usr/share/nginx/html/test/break.html
[root@localhost ~]# echo 'last' > /usr/share/nginx/html/test/last.html
[root@localhost ~]# echo 'test' > /usr/share/nginx/html/test/test.html

2.邀请break,last标记

[root@localhost ~]# vim /etc/nginx/conf.d/default.conf 
	server {
     
        listen 80;
        location / {
     
        root /usr/share/nginx/html;
        index index.html index.php;
        }
location /break {
     
        rewrite .* /test/break.html break;
        root /usr/share/nginx/html;
}
location /last {
     
        rewrite .* /test/last.html last;
        root /usr/share/nginx/html;
}
location /test {
     
        rewrite .* /test/test.html break;
        root /usr/share/nginx/html;
}

3.验证,理解last

http://192.168.100.10/break
break 新的URL就是终点。
http://192.168.100.10/last
last 新的URL是个开始。拿新UR匹配(下一个URL),结果匹配到test了。
http://192.168.100.10/test
注意
last标记在本条rewrite规则执行完后,会对其所在的server { … } 标签重新发起请求;
break标记则在本条规则匹配完成后,停止匹配,不再做后续的匹配。
另有些时候必须使用last,比如在使用alias指令时,而使用proxy_pass指令时则必须使用break。
如果location中rewrite后,还需要进行其他处理,如动态fastcgi请求(.PHP,.jsp)等,要用last继续发起新的请求 (根的location使用last比较好, 因为如果有.php等fastcgi请求还要继续处理)。

7.CA & HTTPS

7.1私有CA

前言:
CA 证书颁发机构(CA, Certificate Authority)
基于https的协议工作的一中虚拟主机,要构建这样的网站需要mod_ssl模块的支持。且需要提供两个文件:证书文件和私钥文件,证书文件是标识这个网站服务器身份的,私钥文件主要用来实现在服务器端对数据进行加密,然后在网站中传输的。证书在生产生活中需要到对应的机构去申请。

1.生成证书及密钥文件

Ⅰ.准备存放证书和密钥的目录

[root@localhost ~]# mkdir -p /etc/nginx/ssl

Ⅱ.生成私钥
使用openssl生成基于rsa数学算法长度为1024bit的秘钥,文件必须以key为结尾

[root@localhost ~]# openssl genrsa 1024 > /etc/nginx/ssl/server.key
Generating RSA private key, 1024 bit long modulus
...............................................................++++++
................................................................++++++
e is 65537 (0x10001)

Ⅲ.使用密钥文件生成证书-申请书

[root@localhost ~]# openssl req -new -key /etc/nginx/ssl/server.key > /etc/nginx/ssl/server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN       ###国家名(两个字
State or Province Name (full name) []:BJ  ###省会(两个字)
Locality Name (eg, city) [Default City]:BJ    ###城市
Organization Name (eg, company) [Default Company Ltd]::js ###组织名
Organizational Unit Name (eg, section) []:cloud		##组织单位名
Common Name (eg, your name or your server's hostname) []:nginx.linux.com ##服务器的名字或者你的名字
Email Address []:[email protected]   ###可选
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:       ###密码为空
An optional company name []:     ####密码为空
Common Name (eg, your name or your server's hostname) []:   ###公司名空

查看申请书

[root@localhost ~]# ls /etc/nginx/ssl/
server.csr   (证书申请)    server.key     (私钥)

Ⅳ.同意申请,生成证书

[root@localhost ~]# openssl req -x509 -days 365 -key /etc/nginx/ssl/server.key -in /etc/nginx/ssl/server.csr > /etc/nginx/ssl/server.crt

注释:
-x509:证书的格式,固定的
days:证书的有效期,生产生活中时间不同,价格不同
key:指定秘钥文件
in:指定证书申请文件

2.私有CA的https部署实战

Ⅰ.创建目录

[root@localhost ~]# mkdir /bj
[root@localhost ~]# echo "bj ssl web" > /bj/index.html

Ⅱ.编辑nginx.conf文件

[root@localhost ~]# vim /etc/nginx/conf.d/bj.conf

 server {
     
        listen       443 ssl;
        server_name  www.bj.com;

        ssl_certificate  /etc/nginx/ssl/server.crt;    
        ssl_certificate_key  /etc/nginx/ssl/server.key;

        location / {
     
            root   /bj;
            index  index.html index.htm;
        }
    }
[root@localhost ~]# nginx -t
[root@localhost ~]# nginx -s reload
[root@localhost ~]# ss -anpt | grep nginx

Ⅲ.访问测试
https://www.bj.com
会有风险提示,是因为浏览器向证书认证服务器请求,没有找到相应证书,但是本地认证成功。

7.2公网CA

认证方式相同

8.Nginx的平滑升级

8.1原理

当需要将正在运行中的nginx升级,添加/删除服务模块时,可以在不中断服务的情况下,使用新版本,重编译的Nginx可执行程序替换旧版本的可执行程序,步骤如下:
• 使用新的可执行程序替换旧的可执行程序,对于编译安装的Nginx,可以将新版本编译安装到旧版本的nginx安装路径中.替换之前,最好备份一下旧的可执行程序
• 发送以下指令: Kill –USR2 旧版本的nginx主进程号
• 旧版本的主进程将重命名它的pid文件为.oldbin (例如:/usr/local/nginx/logs/nginx.pid.oldbin),然后执行新版本的nginx可执行程序,依次启动新的主进程和新的工作进程.
• 此时,新,旧版本的nginx实例会同时运行,共同处理输入的请求.要逐步停止旧版本的nginx实例,你必须发送WINCH信号给旧的主进程,然后,它的工作进程就将开始从容关闭:kill –WINCH 旧版本的Nginx主进程号
• 一段时间后,旧的工作进程(worker process)处理了所有已连接的请求后退出,仅由新的工作进程来处理输入的请求了.
• 这时候,我们可以决定是使用新版本,还是恢复到旧的版本;
Kill –HUP 旧的主进程号:Nginx将在不重载配置文件的情况下启动它的工作进程;
Kill –QUIT 新的主进程号:从容关闭其他工作进程(woker process);
Kill –TERM 新的主进程号:强制退出;
Kill 新的主进程号或旧的主进程号:如果因为某些原因新的工作进程不能退出,则向其发送kill信号.
新的主进程退出后,旧的主进程会移除.oldbin前缀,恢复为他的.pid文件,这样,一切就都恢复到升级之前了,如果尝试升级成功,而你也希望保留新的服务器时,可发送QUIT信号给旧的主进程,使其退出而只留下新的服务器运行:

8.2平滑升级1.12到1.14版本

1.编译安装新版本nginx,指定安装目录为新目录

[root@localhost ~]# tar xf nginx-1.14.2.tar.gz -C /usr/local/src/
[root@localhost ~]# cd /usr/local/src/nginx-1.14.2/
[root@localhost ~]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx14 --with-http_stub_status_module --with-http_ssl_module && make && make install

2.查看旧的nginx主进程号和工作进程号

[root@localhost ~]# ps aux | grep nginx[x]

3.替换旧的执行程序

[root@localhost ~]# mv /usr/local/nginx/sbin/nginx{,.bak}
[root@localhost ~]# cp /usr/local/nginx14/sbin/nginx /usr/local/nginx/sbin/nginx 
[root@localhost ~]# /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.14.2

4.给主进程发送USR2信号

[root@localhost ~]# cat /usr/local/nginx/logs/nginx.pid 
68595
[root@localhost ~]# kill -USR2 68595
[root@localhost ~]# cat /usr/local/nginx/logs/nginx.pid.oldbin 
68595
#旧版本的主进程将重命名它的pid文件为.oldbin 
#(例如:/usr/local/nginx/logs/nginx.pid.oldbin),
#然后执行新版本的nginx可执行程序,依次启动新的主进程和新的工作进程.

5.给进程发送WINCH信号

[root@localhost ~]# kill -WINCH 68595
[root@localhost ~]# ps aux |grep ngin[x]
root      58943  0.0  0.3  45940  3260 ?        S    13:34   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     58944  0.0  0.1  46388  1888 ?        S    13:34   0:00 nginx: worker process
root      68595  0.0  0.1  20640  1548 ?        Ss   12:12   0:00 nginx: master process /usr/local/nginx/sbin/nginx
#一段时间后,旧的工作进程(worker process)处理了所有已连接的请求后退出,仅由新的工作进程来处理输入的请求了.

8.3回退到以前版本

原理:
这时因为旧的服务器还尚未关闭它监听的套接字,所以通过下面的几步还可以恢复旧版本:
• 发送 HUP 信号给旧的主进程 - 它将在不重载配置文件的情况下启动它的工作进程。
• 发送 QUIT 信号给新的主进程,要求其从容关闭其工作进程
• 发送 TERM 信号给新的主进程,迫使其退出
• 如果因为某些原因新的工作进程不能退出,则直接将其杀死 KILL 信号

第一步

[root@localhost ~]# kill -HUP 68595
[root@localhost ~]# ps aux | grep ngin[x]
root      58943  0.0  0.3  45940  3260 ?        S    13:34   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx     58944  0.0  0.1  46388  1888 ?        S    13:34   0:00 nginx: worker process
root      68595  0.0  0.1  20640  1548 ?        Ss   12:12   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody    80008  0.0  0.1  21060  1388 ?        S    13:50   0:00 nginx: worker process

第二部

[root@localhost ~]# kill -QUIT 58943
[root@localhost ~]# ps aux | grep ngin[x]
root      68595  0.0  0.1  20640  1548 ?        Ss   12:12   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody    80008  0.0  0.1  21060  1388 ?        S    13:50   0:00 nginx: worker process
[root@localhost ~]# cat /usr/local/nginx/logs/nginx.pid 
68595

8.4总结

新的主进程退出后,旧的主进程会自动移除 .oldbin 后缀,恢复为.pid的后缀名,如此:一切就都恢复到升级之前了。如果尝试升级成功,而你也希望保留新的服务器时,发送 QUIT 信号给旧的主进程使其退出而只留下新的服务器运行。

你可能感兴趣的:(linux,nginx,运维,服务器)