什么是 Nginx ?
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP(邮件服务)。
Nginx可作为负载均衡服务:Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务,也可以支持作为 HTTP代理服务对外进行服务。
Nginx服务功能:
访问控制、虚拟主机、地址跳转、反向代理、负载均衡
高性能的HTTP服务器
反向代理服务器、七层负载均衡器
邮件代理服务器
特点
善于处理静态请求
擅长处理高并发
nginx服务开启时,会生成一个master(控制)进程,然后 master 进程会分出多个 worker(工作进程) ,最后每个用户的请求都由 worker 的子线程处理。
用线程处理客户请求,而线程是共享内存的,只需要开启少量的进程,多个线程就可以共享进程的内存。所以占用的内存小
工作模式 master - worker 模式
特点:
Nginx启动后,会有一个master和一个worker进程
Master进程负责处理系统信号、加载配置、管理worker进程
Worker进程负责处理具体的业务逻辑
优点:
工作进程可设置
稳定性好
充分利用多核cpu、提高性能
工作模式
一个请求进来,会有一个worker进程去处理;处理发生阻塞时,worker进程不会一直等,而是处理其他事情,等有结果回来再继续处理这个请求
Nginx 处理客户端请求的过程
1、客户端发起访问
2、nginx通过客户端输入的URL判断客户端是要访问动态资源还是静态资源
3、如果是静态资源,那么nginx直接将结果返回给客户端
4、如果是动态资源,那么nginx将请求的数据发送给 fastCGI(快速通用网关接口) ,然后通过 fastcgi_pass 将用户的请求发给 php-fpm。 php-fpm 将动态资源转换成静态后在返回给 Nginx 。Nginx将结果返回给客户端
fastCGI
FastCGI由CGI(通用网关接口)发展而来、采用C/S结构
FastCGI是一种可伸缩的、高速的在HTTP服务器和动态脚本间通信的接口,包括PHP
FastCGI可以将HTTP服务器和脚本解析服务器分离,同时在脚本解析服务器上启动一个或多个脚本解析守护进程,如php-fpm
当HTTP服务器每次遇到动态请求时,直接交付FastCGI进程执行,然后把结果返回给浏览器
php-fpm
Nginx将php动态请求发送给fastcgi管理进程来处理
Php-fpm是一个php fastcgi管理器,只用于PHP解析
Php-fpm提供了更好的PHP进程管理方式,有效控制内存、进程等
PHP编译安装时需要添加—enable-fpm选项
PHP编译安装后需要加载php-fpm配置、启动进程
nginx处理并发
nginx 以 epoll 作为开发模型,处理请求的方式为 异步非阻塞;
epoll 是 Linux 内核的可扩展 I/O 事件通知机制,为系统中基于事件驱动的模型。此模式下nginx可轻松处理百万级的并发连接。
异步非阻塞:调用发出后,该进程继续其他任务,让 I/O 线程去处理,等结果返回时再回来继续执行.
同步阻塞:调用发出后,一直等待消息结果
相关配置
安装 Nginx
1、安装基础依赖、解压openssl源码包
[root@zerbufan ~]# yum -y install zlib zlib-devel pcre pcre-devel openssl-devel
2、查看 openssl 的版本
[root@zerbufan ~]# openssl version #查看版本
OpenSSL 1.0.2k-fips 26 Jan 2017 #openssl的版本需要在1.0.2e以上,当前版本满足要求
#若openssl的版本不满足要求可以去下载源码包:https://www.openssl.org/source/
#下载后解压重新安装 1.0.2e以上版本的 openssl
3、创建 Nginx 用户
[root@zerbufan ~]# useradd -M -s /sbin/nologin nginx
4、安装 Nginx ,若想要Nginx 支持http2协议,那么需要nginx的版本在1.9.5以上
[root@zerbufan nginx-1.13.8]# pwd
/lnmp/nginx-1.13.8 #进入到解压后的目录中 当前nginx的版本为1.13.8 满足要求
# 指定安装位置,开启指定功能
[root@zerbufan nginx-1.13.8]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-stream
#若刚才重新安装了 openssl 则在执行 ./configure 的时候还需要添加 --with-openssl=/root/lnmp/openssl-1.0.2h 这条选项,没有重新安装则不需要
[root@zerbufan nginx-1.13.8]# echo $?
[root@zerbufan nginx-1.13.8]# make && make install
[root@zerbufan nginx-1.13.8]# echo $?
5、查看nginx的安装信息
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -V #查看nginx的安装信息
nginx version: nginx/1.13.8
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-stream
[root@zerbufan ~]#
6、安装完成后 启动服务、测试
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t #检测配置文件
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx #开启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s stop #停止服务
/usr/local/nginx/sbin/nginx -s reload (热重启,不停止服务)
[root@zerbufan ~]# ss -anpt | grep :80 #查看端口
[root@zerbufan ~]# curl localhost #访问默认网页测试
配置文件结构
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf
..... #全局块,配置影响nginx全局的属性,如用户信息、worker数等
worker_processes 1; #控制 worker 进程的数量 一般按照CPU的内核数量设置
pid /usr/local/nginx/logs/nginx.pid;#主进程PID保存文件
events { #events块,配置nginx与用户的允许同时建立的网络连接数
....#使用epoll模型,对于2.6以上的内核,建议使用epoll模型以提高性能
worker_connections 51200;#工作进程的最大连接数量
}
http { #http块,配置代理、缓存等参数
.... #http全局块
server { #server块,配置虚拟主机参数,一个http可有多server
....
location [pattern]{ #location块,配置请求路由及对应处理
...
}
location (.*)\.php$ {
用正则匹配具体的访问对象;
}
location [pattern]{
...#跳转等规则
}
}
server { #配置多个server块
....
location [pattern]{
...
}
location [pattern]{
...
}
}
}
一个http可以有多个server 、一个 server 就是一个虚拟主机,一个server 可以有多个 location
统计模块 (监控 Nginx 的整体访问情况)
#安装时添加模块选项:--with-http_stub_status_module,nginx内置的状态监控页面,可用于监控nginx的整理访问情况
#在主配置文件的 server 中添加location ,在 location中开启统计模块
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf
location /nginx_status {
stub_status on;
}
修改配置文件后重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t #检测配置文件
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload #重启服务(热重启)
页面访问:http://域名或IP/nginx_status
#结果分析:
"Active connections"表示当前的活动连接数;
"server accepts handled requests"表示已经处理的连接信息;
三个数字依次表示已经处理的连接数、成功的TCP握手次数、已处理的请求数
"Reading: 0 Writing: 1 Waiting: 0" 表示正在读取客户端的连接数、响应数据到客户端的数、等待再次请求的连接数
测试
访问控制
基于 用户名、密码的验证访问
1、修改配置文件
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf
#在想验证的location下面添加,以根区域为例
location / {
root html;
index index.html index.htm index.php;
#添加下面这两行信息
auth_basic "welcome you here";
auth_basic_user_file /usr/local/nginx/html/a.psd;
}
2、创建认证文件,htpasswd命令是安装包httpd-tools拥有的命令
[root@zerbufan ~]# cd /usr/local/nginx/ #先进入到目录下
[root@zerbufan nginx]# htpasswd -c /usr/local/nginx/html/a.psd user88 #执行命令创建用户名设置用户密码
New password: #设置用户密码
Re-type new password: #再次输入刚才的密码
Adding password for user user88 #创建用户成功
注意:只用第一次创建用户使用 -c 选项;以后再次创建用户需使用 -m 选项
[root@zerbufan nginx]# htpasswd -m /usr/local/nginx/html/a.psd user99
New password:
Re-type new password:
Adding password for user user99
3、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t #检测配置文件
设置访问控制后不要使用热重启
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s stop
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx
验证
基于IP地址的访问控制 (顺序优先)
拒绝个别,允许所有
1、编辑配置文件
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
root html;
index index.html index.htm index.php;
deny 192.168.56.101; #拒绝访问的IP #注意 deny 和 allow 的顺序
allow 192.168.56.0/24; #允许访问的IP
}
2、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
允许个别,拒绝所有
1、编辑配置文件
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
root html;
index index.html index.htm index.php;
allow 192.168.56.101; #允许访问的IP
deny 192.168.56.0/24; #拒绝访问的IP #注意allow和deny的顺序
}
2、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
虚拟主机 (基于域名)
1、#在配置文件中添加不同的 server 区域(一个server 就是一个虚拟主机)
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.new.com;
location / {
root html/new;
index index.html index.htm;
}
}
server {
listen 80;
server_name www.old.com;
location / {
root html/old;
index index.html index.htm;
}
}
2、创建虚拟主机网页主目录存放目录
[root@zerbufan ~]# cd /usr/local/nginx/html/ #进入到网页主目录下
[root@zerbufan html]# mkdir ./new #创建第一个虚拟主机的网页目录存放位置
[root@zerbufan html]# mkdir ./old #创建第二个虚拟主机的网页目录存放位置
[root@zerbufan html]# echo "new linux" > ./new/index.html #写 index.html文件
[root@zerbufan html]# echo "old linux" > ./old/index.html
3、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
域名跳转 ( old 跳转到 new )
1、基于上面的虚拟主机进行域名跳转实验
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf #编辑配置文件
server {
listen 80;
server_name www.new.com;
location / {
root html/new;
index index.html index.htm;
}
}
server {
listen 80;
server_name www.old.com;
location / {
rewrite .* http://www.new.com permanent;
}
}
2、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
实现 https 加密
1、生成证书,默认路径在PREFIX/conf目录下
[root@zerbufan ~]# cd /usr/local/nginx/conf/ #进入目录准备生成证书
#建立服务器私钥,生成RSA密钥
[root@zerbufan conf]# openssl genrsa -out ./cert.key 1024
#需要依次输入国家,地区,组织,email。最重要的是有一个common name,可以写你的名字或者域名。如果为了https申请,这个必须和域名吻合,否则会引发浏览器警报。生成的csr文件交给CA签名后形成服务端自己的证书
[root@zerbufan conf]# openssl req -new -key ./cert.key -out ./cert.csr
#模拟交给 CA机构签名
[root@zerbufan conf]# openssl x509 -req -days 365 -sha256 -in ./cert.csr -signkey ./cert.key -out ./cert.pem
2、修改主配置文件,修改server端口为443、添加验证配置
#HTTPS server #这条注释注意不要取消
server {
listen 443 ssl;
server_name www.new.com; #要加密的域名
ssl_certificate cert.pem; #证书
ssl_certificate_key cert.key; #证书密钥
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html/new; #加密的网页主目录存放位置
index index.html index.htm;
}
}
}
3、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
验证时手动输入 https://域名
端口自动跳转 (80 端口 自动跳转到 443 端口)
1、修改配置文件
[root@zerbufan ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.old.com;
location / {
rewrite .* http://www.new.com permanent; #先从old跳转到new
}
}
-------------------------------------------
server {
listen 80;
server_name www.new.com;
location / {
rewrite .* https://www.new.com permanent; # new 从http跳转到 https
}
}
---------------------------------------------
#开启https的配置
server {
listen 443 ssl;
server_name www.new.com;
ssl_certificate cert.pem;
ssl_certificate_key cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html/new;
index index.html index.htm;
}
}
}
2、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
http2 协议
1、生成证书,默认路径在PREFIX/conf目录下(上面在做端口跳转时已经由证书了,就不用再次生成证书了)
[root@zerbufan ~]# cd /usr/local/nginx/conf/ #进入目录准备生成证书
#建立服务器私钥,生成RSA密钥
[root@zerbufan conf]# openssl genrsa -out ./cert.key 1024
#需要依次输入国家,地区,组织,email。最重要的是有一个common name,可以写你的名字或者域名。如果为了https申请,这个必须和域名吻合,否则会引发浏览器警报。生成的csr文件交给CA签名后形成服务端自己的证书
[root@zerbufan conf]# openssl req -new -key ./cert.key -out ./cert.csr
#模拟交给 CA机构签名
[root@zerbufan conf]# openssl x509 -req -days 365 -sha256 -in ./cert.csr -signkey ./cert.key -out ./cert.pem
2、修改配置文件(基于上面的端口跳转)
#HTTPS server
server {
listen 443 ssl http2; #在这里直接添加 http2 即可
server_name www.new.com;
ssl_certificate cert.pem;
ssl_certificate_key cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html/new;
index index.html index.htm;
}
}
}
3、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
反向代理
1、搭建真实服务,确保真实服务可以正常访问
2、修改nginx 代理服务器的配置文件
server {
listen 80;
server_name www.xxxx.com; #客户端访问的域名
location / {
proxy_pass http://192.168.56.101:80; #真实服务器的IP
} 代理其他主机也可填其他域名,实现跳转
2、修改配置文件后重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
访问代理服务器的域名,展现出真实机的服务页面
负载均衡
1、配置两个被代理的真实服务器
#服务器 1 :192.168.56.101
[root@zerbufan ~]# yum -y install httpd
[root@zerbufan ~]# echo "zhangsan 192.168.56.101" > /var/www/html/index.html
[root@zerbufan ~]# systemctl start httpd
#服务器 2 :192.168.56.10
[root@ngls-lisi ~]# yum -y install httpd
[root@ngls-lisi ~]# echo "lisi 192.168.56.10" > /var/www/html/index.html
[root@ngls-lisi ~]# systemctl start httpd
#这里配置了两个不同的页面 是为了方便区分实验效果。
----------------------
2、配置 nginx 代理服务器的配置文件
#upstream标签需要添加在 server 标签的前面
upstream lisi {
#weight 表示权重,数字越大,权重越大。
server 192.168.56.101:80 weight=3; #真实服务器1的ip
server 192.168.56.10:80 weight=2; #真实服务器2的IP
}
server {
listen 80;
server_name www.xxxx.com;
location / {
proxy_pass http://lisi; #添加反向代理,代理的地址写上面 upstream 声明的名字
proxy_set_header Host $host; #重写请求头部,保证网站所有页面都可以访问成功
}
3、重启服务
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -t
[root@zerbufan ~]# /usr/local/nginx/sbin/nginx -s reload
验证
多次请求 www.xxxx.com 可以看到得到的数据 3次来自服务器1 两次来自服务器2