nginx详解

轻量级的高性能 Web 服务器、反向代理服务器及电子邮件(IMAP/POP3)代理服务器,同时也是一款轻量级的套接字服务

一 nginx的特点

 1.1 功能多、用途广
(1)如果是一些静态文件(html、css、js、图片)nginx可以直接返回

(2)在web层服务放一个nginx,可以为web服务器增加很多功能
——–》动静分离
——–》增强安全
——–》uri路径的rewrite
——–》控制一些静态文件缓存到访问者

——–》日志记录

     fastcgi_pass         #对接协议
     proxy_pass
     uwsgi_pass

(3)七层负载均衡

(4)四层负载均衡

1.2 性能强悍(epoll网络io模型)

    (1)内存消耗少,启动极快
    (2)采用异步非阻塞事件驱动模型(epoll网络IO模型),从而使其高并发能力极强,在互联网项目中广泛应用。
    (3)开源软件,免费
    (4)稳定性高,用于反向代理(负载均衡),宕机的概率微乎其微。
    (5)支持热部署。在不间断服务的情况下,对软件版本升级。

二、安装nginx

     1、yum 安装
    安装最新stable版:从官网找源:https://nginx.org/en/linux_packages.html    
    其他的stable版,可以从其他源里找
    例如epel
    yum install epel -y
    
    2、源码安装   可以定制化
    yum install gcc* glibc* -y
    yum install -y pcre pcre-devel
    yum install -y zlib zlib-devel
    yum install -y openssl openssl-devel

    wget https://nginx.org/download/nginx-1.22.1.tar.gz

[root@localhost opt]# tar -zxvf /opt/nginx-1.12.2.tar.gz    # 解压到当前目录
[root@localhost opt]# cd nginx-1.22.1/
# 配置参数(具体参数可以./configure –help命令查看)
[root@localhost nginx-1.22.1]# ./configure –prefix=/usr/local/nginx1.12.2 –with-http_stub_status_module –with-http_ssl_module 
make   # 编译
make install    # 安装   
[root@localhost nginx-1.22.1]# /usr/local/nginx1.12.2/sbin/nginx -v        # 验证
nginx version: nginx/1.22.1 
# 制作软连接:一般./configure指定的prefix目录都会具体到nginx的版本,这样方便区分,但是在用的时候一般都会做软连接,这样既方便用也方便后续升级
[root@localhost nginx-1.22.1]# ln -s /usr/local/nginx1.12.2 /usr/local/nginx
# 配置环境变量/etc/profile.d/nginx.sh
export PATH=$PATH:/usr/local/nginx/sbin    #使指令全局有效 
# system管理配置
#源码包安装后没有办法使用system管理,需要我们自己配置
[root@localhost /usr/lib/systemd/system]# vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx – high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
 
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
 
[Install]
WantedBy=multi-user.target
 
[root@localhost ~]# systemctl daemon-reload                 #加载新的unit (*.service)配置文件
   

三、nginx相关文件介绍

 以rpm包为例
    主配置文件:
        /etc/nginx/nginx.conf    
        补充:主配置文件里还会用include引入一些子配置到当前位置

                        include /etc/nginx/conf.d/*.conf
        
    代理相关的配置:
        /etc/nginx/fastcgi_params
        /etc/nginx/uwsgi_params
        
    编码相关:
        /etc/nginx/mime.types       # content-type与扩展名
    
    管理命令
        /usr/sbin/nginx
        
    日志相关文件
        /var/log/nginx                        
        logrotate—->/etc/logrotate.d/nginx         #nginx的日志切割配置            

    
四、nginx常用命名参数  

     nginx -c /etc/nginx/nginx.conf        #启动 Nginx 服务器并指定配置文件路径(源码安装下使用)

    
    # 对于已经启动的nginx,我们可以用-s为该进程发信号
    nginx -s reload # 不重启nginx的情况下重新加载配置文件

    nginx -t               # 检查配置是否有错误 syntax is ok代表正常

五、nginx平滑升级

    ln -s /usr/local/nginx1.20.1     /usr/local/nginx
    源码编译安装了一个新版本/usr/local/nginx1.22.0
    rm -rf  /usr/local/nginx    # 删除旧的不会影响nginx进程运行因为已经加载至内存中
    ln -s /usr/local/nginx1.22.0     /usr/local/nginx

    改动配置后,reload重载
    /usr/local/nginx/sbin/nginx -s reload

六、nginx的基础配置(含日志)

                       

一些全局配置    # 1、全局配置
 
events { … } # 2、事件驱动配置
 
http{          # 3、http模块配置
   upstream {}
   server{

        location  { … }
    }
}
 
stream{        # 4、stream模块配置
   upstream {}
   server{

        location  { … }
    }
}

    main:全局配置,所有其他配置块都包含在其内部
    events 块:控制Nginx处理连接的方式
    http 块:Nginx处理http请求的主要配置块。
         upstream块:配置负载均衡
         server块:Nginx中主机配置块,可用于配置多个虚拟主机
              localtion块:可以有多个,用于匹配uri路径
    stream块:stream做四层负载均衡并不常用
          upstream块:配置负载均衡
          server块:四层的server块内部必然是不能写location匹配uri地址
    补充:
        1、http块与stream块内的upstream及server块均可以有多个
        2、在 Nginx 配置文件中,每一条指令配置都必须以 “;” 分号结束

——————————————————————————————————————————— #######    内层定制的优先级高于外层,内层定制以内层为准,内层没有遵循外层     #######    
 

    全局配置:

      # 1、运行用户(nginx子进程用户)        nginx本身的进程用户身份取决于启动它的用户
      user nobody;
 
      # 2、工作的worker进程数,通过与cpu核数保持一致,设置为auto,nginx会自动配置为核数。
      #    注意:nginx启动后还有一个master进程负责与用户交互响应会话,具体干活的是worker进程
        worker_processes  auto;  
 
      # 3、全局错误日志:日志级别有:debug、info、notice、warn、error、crit、alert
       #error_log  logs/error.log;
         error_log  logs/error.log  notice;
         error_log  logs/error.log  info;
 
       # 4、PID文件
         pid        logs/nginx.pid; 
 
       # 5、include用来引入配置文件
       #    下述指令的含义:nginx启动时会加载动态dynamic模块的所有配置,确保动态模块都加载                到nginx中
          include /usr/share/nginx/modules/*.conf;
    
———————————————————————————————————————————    
    events配置:
        网络io模型:
            

            epoll(最强)———>nginx能抗住高并发的原因之一
                每个网络io都捆绑自己的事件(回调函数)
                    一旦数据到达,就立即自己主动触发事件–》告知自己的数据已经抵达                       
                nginx只需要去队列去现成的链接来处理即可(这些现成的链接共同的特点都是数据已经                  放到你的操作系统里了
                                               
            select: 遍历网络链路看是否有请求到达
                问题:链接越多,效率越低
            poll
                
        
        控制nginx支持的最大并发量:
            worker_processes 4;
            worker_connections 1024;    # 单个worker(默认单线程)能处理的最大链接数

          ### 当前nginx服务器能处理的最大并发请求数=worker_processes*worker_connections

            注意,配置的时候要注意(并不是越大越好):
                1、结合硬件
                2、结合文件描述符的设置,调大描述符也要调大
            

———————————————————————————————————————————

http模块配置:

http {

    #1、设定日志输出模板
       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; 

    #2、网络io优化参数(http)

        sendfile  on;

         减少数据在操作系统的内核态和用户态之间的拷贝次数—-从硬盘读取数据到操作系统用户态           缓冲区,再从用户态缓冲区发送至操作系统网络缓冲区(内核态),最后调用网卡发送数据           至网络;如果开启sedfile,内核会将数据直接从硬盘取出发送到网络中。 

        tcp_nopush  on;

         通常与sendfile一起用,当 tcp_nopush 设置为 on 时,Nginx 将尽可能发送较大的 TCP 数据           包,减少 TCP 报文的数量,提高传输效率。这对于减少网络传输中的 TCP 慢启动阶段,减           少网络延迟和提高网络吞吐量非常有用。这在传输大型文件或使用 HTTP/1.1 的 Keep-Alive           长连接时特别有效。

         tcp_nodelay  on;

          数据不在缓冲区停留或等接受到ack才发出,这会减少延迟,但可能会造成网络利用率低。            这个选项在处理需要快速响应的短数据流(例如HTTP/1.1的keep-alive连接)时非常有用。

          keepalive_timeout  65;             #开启长连接

          keepalive_requests  100;         #每个长连接在关闭前能处理的最大请求数量

          gzip on;    #开启gzip压缩,节省带块加速网络传输

          client_header_buffer_size    128k;   #用于保存客户端请求头的缓冲区的大小,当客户端发                                                                         送的请求头超过这个大小时Nginx 将使用临时文件来                                                                         保存请求头。这可以防止恶意客户端发送大量数据来                                                                         消耗服务器资源

          large_client_header_buffers  4 128k;   #设置多个缓冲区来保存

          include  /etc/nginx/mime.types;     #定义了nginx可以识别的网络资源类型,例如css、js、                                                                      jpg等从而加入标识到响应包中使浏览器能启用对应的                                                                        功能来解析数据

          default_type application/octet-stream;  #标识这种内容不会被浏览器解析,而是作为一个下                                                                            载文件来处理

 ###  include /etc/nginx/conf.d/*.conf  ——–>将所有server写成 .conf文件放入对应目录中使主配置文件简洁美观

server {

        #侦听80端口
        listen    80;
        listen [::]:80; # [::]: 这代表 IPv6 地址中的一个缩写,它等同于所有的 IPv6 地址,类似于 IPv4 中的 0.0.0.0
        server_name  www.nginx.cn;        #定义使用 www.nginx.cn访问      
        root /usr/share/nginx/html;   # 定义服务器的默认网站根目录位置强烈建议用绝对路径
        access_log  logs/nginx.access.log  main;      #设定本虚拟主机的访问日志
        #默认请求(兜底)
        location / {

            root /a/b/c; # 优先级高于外部  
            index index.php index.html index.htm;     #定义首页索引文件的名称(按顺序依次查找)  
        }
        # 定义错误提示页面,出现以下状态码,uri定位到/50x.html,然后触发二次localtion匹配,直接对上location = /50x.html;不写location = /50x.html也可以,会依次对所有的location进行遍历匹配,最后匹配不到使用server层的默认路径大大增加了匹配所用的时间。
        error_page   500 502 503 504 /50x.html;
        location = /50x.html {                                 # =号的匹配更精确,所以优先级更高
           # 这里没有指定root目录,所以向外层查找,找到server层里定义的root,去该root指定的目录下找/50x.html
        }
 
        #静态文件,nginx自己处理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {            
                                      #如果频繁更新,则可以设置得小一点。
            expires 30d;       #过期30天,静态文件不怎么更新,过期可以设大一点,
            # 这里没有指定root,那去外层也就是server层定义的root指定的目录里找文件
        }         # ——->nginx返回给客户端浏览器的响应包里自动设置缓存时间
 
        #PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
        location ~ .php$ {

            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include fastcgi_params;
        }      
        location ~ /.ht {

            deny all;     #禁止访问 .htxxx 文件
        }
    }
}

补充:nginx作为反向代理服务器

#与后端服务器建立长连接—-增加keepalive设置(1.1.4或以上版本生效)

   upstream backend {

       server backend1.example.com;
       server backend2.example.com;
       keepalive 32;
   }

# upstream与server属于同一层级,隶属于http模块,可以一同写写成 .conf文件放入对应目录中使主配置文件简洁美观

———————————————————————————————————————————           

日志模块配置:            
    # 一般在server层内使用日志,server内定义了日志访问路径和格式就以server内的为准,server没有定制的就以http层定义的日志访问格式和路径为准

   # 每个server指定自己的日志文件,但需统一放到定义好的日志路径上

   # 根据实际情况不记录日志(四层负载均衡)或者调整运行日志的级别可以优化nginx的运行——-减少io操作减轻nginx的压力

   # 补充:日志写入涉及到io行为,所以并不是越多越好

日志定制的位置与优先级
    全局
    
        http层
            
            server层
        
日志的种类:
    访问日志
        日志的格式——一般位于http块内
             log_format 日志格式名 日志格式
        日志的路径——-一般位于server块内
            access_log  日志路径  日志格式名;
   

    错误日志
        不能定制日志的格式,但是可以定制日志级别            
            emerg  (表示系统不可用)
            alert  (需要立即采取措施)
            crit   (更严重的错误)
            error  错误
            warn  警告
            notice(默认)
            info——->软件正运行(运行日志)
            debug(调试时使用,记录大量详细信息)

#日志格式参数

$remote_addr        # 记录客户端IP地址
$remote_user        # 记录客户端用户名
$time_local         # 记录通用的本地时间
$time_iso8601       # 记录ISO8601标准格式下的本地时间
$request            # 记录请求的方法以及请求的http协议
$status             # 记录请求状态码(用于定位错误信息)
$body_bytes_sent    # 发送给客户端的资源字节数,不包括响应头的大小
$bytes_sent         # 发送给客户端的总字节数
$msec               # 日志写入时间。单位为秒,精度是毫秒。
$http_referer       # 记录从哪个页面链接访问过来的(反爬的一种方法)
$http_user_agent    # 记录客户端浏览器相关信息
$http_x_forwarded_for #记录经过的所有服务器的IP地址
$X-Real-IP         #记录起始的客户端IP地址和上一层客户端的IP地址
$request_length     # 请求的长度(包括请求行, 请求头和请求正文)。
$request_time       # 请求花费的时间,单位为秒,精度毫秒
# 注:如果Nginx位于负载均衡器,nginx反向代理之后, web服务器无法直接获取到客 户端真实的IP地址。
# $remote_addr获取的是反向代理的IP地址。 反向代理服务器在转发请求的http头信息中,
# 增加X-Forwarded-For信息,用来记录客户端IP地址和客户端请求的服务器地址。
                    
 

日志切割

logrotate—–由cron定时任务调度的一个程序,定时任务通常在/etc/cron.daily/目录下

应用程序如果是由rpm包安装会自动生成对应的logrotate配置文件

## cat /etc/logrotate.d/nginx 

/var/log/nginx/*.log { # 指定要切割的日志
 
        daily   #每天切割日志
        missingok   #忽略日志丢失
        rotate 52   #日志保留时间 52天
        compress   #日志压缩
        delaycompress  #延时压缩
        not if empty    #不切割空日志
        create 640 nginx adm    #切割好的日志权限
        sharedscripts   #开始执行脚本
        postrotate  #标注脚本内容
                if [ -f /var/run/nginx.pid ]; then#判断nginx启动
                        kill -USR1 `cat /var/run/nginx.pid`   #access.log不存在时,重新生成一个,存在则继续用已存在的不会产生新的access.log
 
                fi
        endscript   #脚本执行完毕
}

# 同时,你可以使用下列命令来强制执行一次logrotate:
/usr/sbin/logrotate -f /etc/logrotate.conf
/usr/sbin/logrotate -f /etc/logrotate.d/nginx

七、如何应对高并发(TCP详解)

一、nginx的抗并发能力很强,能不能更强(******)

 # 在使用网络io模型 epoll 的基础上

1.1 半连接队列与全连接队列

socket抽象层——-把传输层的tcp/udp协议封装成简单的功能供应用层应用程序调用

bind()—-绑定ip+port(一个端口多个ip)      listen()—-开辟半连接池,监听半连接队列(SYN队列

connect()—-连接至服务端    accept()—-取全连接队列(accepet队列)的连接进行收发消息

write()—-基于连接写消息           read()—-基于连接读消息      close()—-关闭连接

### 底层依然是tcp的三次握手(操作系统的内核进行操作)

# 在建立好连接通道后双方通信还需基于规定的协议去交流,理解——-应用层协议(基于特定的协议规则去封装、解封装)

tcp—-stream(流式协议)

 半连接队列(尚未完成三次握手)—->系统内核            全连接队列(完成三次握手)—->应用程序

优化:

somaxconn tcp_max_syn_backlog 是 Linux 内核的参数,默认值都是 128
sysctl -w net.core.somaxconn=65530    # 设置全连接池大小
sysctl -w net.ipv4.tcp_max_syn_backlog=10240   # 设置半链接池大小

1.2 nginx有两种工作模式
两种工作模式,总的来说一样的地方:一个master管理多个worker进程
    1、master进程:负责管理worker进程的生命周期,
                    发信号都是给master进程发                    
                    master进程是所有worker进程的爹                    
    2、worker进程:负责具体工作
    
工作模式1(默认):所有worker进程共享同一个全连接队列
1、工作介绍
(1)master进程负责bind()、listen()之后,负责创建出多个worker进程
    补充:listen就是通知操作系统开启一个半连接池、对应着也得开启一个全连接池
               该全连接池是所有worker进程共享的
          
(2)所有worker进程,都会去同一个全连接队列里用accept()取走一个全连接
     然后进行收发消息
     
     补充:worker进程在取连接的时候无法预判该链接一会承载的请求是耗时还是不耗时
            即woker进程是基于链接调度的,而不是请求
                        
2、特点:所有worker进程共享一个全连接队列(都是由master的listen发起的)
3、优点:
    某个worker进程拿到一个链接之后,该链接里发来的请求
    是非常耗时的,此时该worker的处理能力在变弱–》从全连接队列里拿新链接来处理的能力变慢   
    此时不会影响其他worker的处理能力,因为大家的队列是共享的
        
    总结:基于共享的方式,会平衡所有worker进程的压力

4、缺点:
    全连接队里是共享的,而worker是并发/并行去队列里拿链接的
    这涉及到争抢问题,需要加锁处理,会带来额外的损耗

工作模式2:每个worker进程独享自己单独的一个全连接队列
1、工作模式介绍
(1)还是由master进程发起listen监听端口
    每个worker进程会重用reuse主进程的那个端口,即端口都一样
    但是每个worker会单独开辟一个自己的全连接队列
    
(2)每个worker进程都处理自己独享的那一个全连接队列
    其他worker进程无法看到你的这个队列    
    
2、特点::每个worker进程都独享自己的listener全连接队列
3、优点:
不需要多个进程/线程竞争某个公共资源,减少竞争的资源消耗,处理效率自然提高了。
4、缺点:
当某个worker进程处理不过来,其他worker不能为其分摊压力

server {

        listen 80 reuseport;
        listen 443 ssl http2 reuseport;
        server_name   xxx.xxx.com;
        charset utf-8;

# 同一个nginx实例下针对同一个ip+port,只需要其中一个设置了reuseport即可全部生效

ss -lnt |grep 8089  # 4个worker进程reuse了相同的端口
LISTEN 0 511 *:8089 *:* 
LISTEN 0 511 *:8089 *:* 
LISTEN 0 511 *:8089 *:* 
LISTEN 0 511 *:8089 *:* 
 
netstat -an |grep -w 8089
tcp 0 0 0.0.0.0:8089 0.0.0.0:* LISTEN
#因为是resuse重用的同一个端口,所以在系统层面netstat -an|grep 8089你当然只能看到一个端口
|

|

|

/

线程的争抢问题加锁处理所消耗的cpu资源远远小于进程之间的争抢问题,所以基于进程独享全连接队列模式可以进行进一步优化

默认情况下nginx每个worker进程都是单线程的

为每个worker进程开始多线程
    1、查看是否支持
    [root@web01 ~]# nginx -V 2>&1 | sed “s/s+–/
–/g” |grep threads
     –with-threads # 支持

    2、配置开启

[root@web01 ~]# cat /etc/nginx/nginx.conf
……
user egon;
worker_processes 4;
events {

    use epoll;
    worker_connections 1024;
}
 
thread_pool egon_pool threads=3 max_queue=1024;  # 定义线程池(全局设置)

# threads 线程数     max_queue 最大队列大小
http {

    #aio threads;
    aio threads=egon_pool;  # 启用线程池 
    # 启用线程池与reuseport并不冲突
    server {

        listen 8089 reuseport backlog=10240;
  

 [root@web01 ~]# ps aux |grep nginx
    root        7101  0.0  0.0  39352  2012 ?        Ss   5月31   0:00 nginx: master process /usr/sbin/nginx
    nginx      12813  0.0  0.0  39808  1936 ?        S    10:50   0:00 nginx: worker process
    nginx      12814  0.0  0.0  39808  1936 ?        S    10:50   0:00 nginx: worker process
    nginx      12815  0.0  0.0  39808  1936 ?        S    10:50   0:00 nginx: worker process
    nginx      12816  0.0  0.0  39808  1936 ?        S    10:50   0:00 nginx: worker process
    root       12953  0.0  0.0 112824   988 pts/0    R+   11:07   0:00 grep –color=auto nginx  
    [root@web01 ~]# pstree 7101
    nginx───4*[nginx]
    [root@web01 ~]# pstree -p 7101
    nginx(7101)─┬─nginx(12813)
                ├─nginx(12814)
                ├─nginx(12815)
                └─nginx(12816)

    [root@web01 ~]# nginx -s reload              # 重载配置
    [root@web01 ~]# ps aux |grep nginx
    root        7101  0.0  0.0  39352  2012 ?        Ss   5月31   0:00 nginx: master process /usr/sbin/nginx
    nginx      12965  0.0  0.0  64380  1820 ?        Sl   11:08   0:00 nginx: worker process
    nginx      12966  0.0  0.0  64380  1820 ?        Sl   11:08   0:00 nginx: worker process
    nginx      12967  0.0  0.0  64380  1820 ?        Sl   11:08   0:00 nginx: worker process
    nginx      12968  0.0  0.0  64380  1820 ?        Sl   11:08   0:00 nginx: worker process
    root       12982  0.0  0.0 112824   988 pts/0    R+   11:08   0:00 grep –color=auto nginx
    [root@web01 ~]# pstree -p 7101
    nginx(7101)─┬─nginx(12965)─┬─{nginx}(12972)
                │              ├─{nginx}(12973)
                │              └─{nginx}(12974)
                ├─nginx(12966)─┬─{nginx}(12975)
                │              ├─{nginx}(12976)
                │              └─{nginx}(12977)
                ├─nginx(12967)─┬─{nginx}(12978)
                │              ├─{nginx}(12979)
                │              └─{nginx}(12980)
                └─nginx(12968)─┬─{nginx}(12969)
                               ├─{nginx}(12970)
                               └─{nginx}(12971)

nginx应对高并发发总结:
    1、开启了reuseport,让每个worker独享自己的全连接队列,减少了进程层面的资源争抢    
    2、为了解决worker进程繁忙的情况下无人帮其分摊的压力的问题,在worker进程内开启了多线程
        好处:
            1、缓解压力
            2、让cpu的使用分配更加均匀

        坏处:
            1、又需要考虑资源争抢问题(虽然也需要考虑,但至少比进程之间的资源争抢要效率高)
            2、增加了出bug风险,可能会因为某个线程的bug而引发整个进程挂掉

    3、每个线程处理网络io问题的时候用的都是epoll模型
    
                               
                               
    ingress-nginx:(并发能力强)——->进一步优化了上述的坏处
        1、开启了reuseport
        2、开启了线程池
                                       
                               
重点:nginx worker进程调度是以连接为单位,不是以请求为单位,所以无法分别请求的耗时长短

八、虚拟主机

     什么是虚拟主机?
        访问一个站点,背后一定要有软件来支撑该访问
        正常来讲,访问不同的站点,背后就应该启动不同的服务来支持
        
        而虚拟主机指的是:
            背后就一个软件,但是这个软件,可以承载不同站点的访问            
            相当于把这一个软件当成多个软件去用—》虚拟
        
        
    基于域名(最常用)

### 请求头送给nginx后,nginx解包分析,根据不同的域名匹配下面不同的server name字段所以,如果你是本地测试,你必须在hosts文件里添加解析记录,用域名访问,让请求头里带着域名,nginx才能正常解析到
windows下hosts文件路径:C:WindowsSystem32driversetchosts

### 不同的域名匹配各自对应的文件路径

192.168.71.15 www.egonlin.com bbs.egonlin.com blog.egonlin.com

[root@localhost conf]# vim nginx.conf
worker_processes  1;
events {

    worker_connections  1024;
}
http {

    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {

        listen       80;
        server_name  www.egonlin.com;   # 可以跟多个域名(取别名)
        location / {

            root   /usr/share/nginx/html/www;
            index  index.html index.htm;
        }
    }
 
    server {

        listen       80;
        server_name  bbs.egonlin.com;
        location / { 
            root   /usr/share/nginx/html/bbs;
            index  index.html index.htm;
        }   
    }   
 
    server {

        listen       80;
        server_name  blog.egonlin.com;
        location / { 
            root   /usr/share/nginx/html/blog;
            index  index.html index.htm;
        }   
    }   

    基于端口
    域名、IP相同,根据端口区分
    
    基于ip(一个服务器上需要有多个IP)

九、location匹配url的路径部分

 location是干什么用的
    location是匹配url地址的路径部分
        强调:只做匹配,匹配成功之后的查找资源与localtion无关

# 匹配到了之后,执行下面的跟的代码将请求的路径加到root路径后面进行查找,如果本层没有指定root就用上一层的root地址
                
    例如:
        nginx收到一个url请求http://192.168.71.15:8080/static/img/logo.jpg?user=john&width=100
            location只负责匹配:/static/img/logo.jpg 路径部分(端口到问号),问号之后不管        
    
location在哪里用
    四层负载均衡不能用
    只能用在七层,即只能放在http层的server层里

location的规则分类
    请求http://192.168.71.15:8080/static/img/logo.jpg?user=john&width=100 的路径部分/static/img/logo.jpg
    
    1、前缀匹配(强调强调:所有的匹配规则都必须以/开头)
    
        location = /static/img/logo.jpg   # 完全匹配,要求严丝合缝一字不落
        
        location ^~ /static/im               # 前缀匹配,^~ 后面跟着的全都普通字符,只要对上前缀就行
        
        location /static/img                  # 前缀匹配,后面跟着的全都普通字符,只要对上前缀就行
                
        后两种匹配没有优先级之分,两者都不能冲突,要谈优先级一定看谁更精准谁优先级高        
        区别到底在哪里?
            ^~的规则一旦对成功之后,就不会再走正则匹了
            而不带^~的前缀匹配,在匹配成功之后,还会再去匹配正则,正则成功之后则正则,否则还是本条
    
    2、正则匹配
        location  ~    路径部分   # 区分大小写
        location  ~*   路径部分   # 不区分大小写

location的匹配流程或者说优先级
整体的逻辑:
    先进行相对精准的——》前缀匹配
    然后进行相对模糊的—-》正则匹配    

    第一阶段:
        先用localtion = 的规则去匹配请求路径,如果能对上直接结束,则不必进行后续阶段        

### 对于需要频繁匹配的地址直接写location=规则立即完成匹配,大大缩短了匹配所用的时间,优化了nginx的性能
    第二阶段:
        在用两种前缀匹配来匹请求的路径
            location ^~ 规则
            location  规则 # 常规匹配
        
        这两种本身没有优先级之分,他们的优先级看精准度,谁精准就用是谁        
            如果是 ^~ 此时更精准的匹配成功了,那么直接结束,不必进行后续阶段
            如果是 常规的前缀 此时更精准的匹配成功了,那么不会结束,还需要仅需后续的正则匹配
            
    第三阶段:
        进行正则匹配,多个正则表达式自上而下匹配,但凡匹配成功一次,就立即结束不会再匹配后面的(正则匹配存在先后顺序)
        
        如果正则也匹配失败了,需要分两种情况看
            情况一:一与二两个阶段都是失败,那最终结果就是失败,返回上一层的ROOT路径(默认路径)中寻找
            情况二:第二阶段的 常规前缀匹配 成功,而进入的正则匹配失败了,此时就用常规匹配
    

实例:    

[root@web01 ~]# cat /etc/nginx/conf.d/www.conf
    server {

        listen       8081;
        server_name  www.egonlin.com;
 
        # 1、前缀匹配三大类
        location = /eGon/xxx {

            default_type text/plain;
            return 200 “1111111111111111111111111111111”;
        }
        location ^~ /eGon/xxx/yy {

            default_type text/plain;
            return 200 “2222222222222222222222222222222”;
        }
        location /eGon/xxx/yyy.txt {

            default_type text/plain;
            return 200 “3333333333333333333333333333333”;
        }
 
        # 2、正则匹配两大类
        #location ~* ^/eGon { # 注意写成^eGon可就是直接从e这个字符开始匹配了,而不是从uri路径的最开头左斜杠开始啊
        #    default_type text/plain;
        #    return 200 “4444444444444444444444444444444”;
        #}
        location ~* .Txt$ {

            default_type text/plain;
            return 200 “5555555555555555555555555555555”;
        }
        location ~* .TXT$ {

            default_type text/plain;
            return 200 “6666666666666666666666666666666”;
        }
        location ~ .txt$ {

            default_type text/html;
            return 200 “location ~ .text”;
        }
 
    }

十、return指令(状态码)

return—-停止处理请求且后续指令不再执行,直接返回响应码或者重定向到其他url

常见状态码(code): 
200:请求成功
301:永久转移到其他 URL                       302:临时转移到其他 URL
403:客户端没有对目标资源的访问权限   404:请求资源不存在

400:客户端发送的请求存在语法错误(恶意请求—-例如请求头过大-增大请求头缓冲区)

401:用于客户端的身份验证(nginx的访问认证模块) 
500:内部服务器错误                               503:服务端故障 

502: 网关/代理服务器无法与上游服务器通信    504:网关/代理服务器链接上游服务器超时

           301:永久重定向
                第一次请求,会打到服务端,然后由服务端发起重定向,浏览器会缓存下来本次重定向
                
                之后浏览器发起请求,就不会打到服务端,浏览器会自动帮你完成重定向

            302:临时重定向
                每次请求,都会打到服务端,然后由服务端发起重定向

###  default_type——》对应http响应头里的content_type—-让浏览器知道要调用什么模块去解析

location ^~ /return00 {

    return 403;                     #直接返回状态码
}
location ^~ /return01 {

    default_type text/plain;    #必须告诉浏览器return内容的类型—-纯文本格式
    return 200 'request success';

location ^~ /return02 {

    return 302 /hello;           #uri部分的重定向

location ^~ /return03 {

    return http://www.egonlin.com;    #整个url地址的重定向   (不指定状态码默认为302)

location ^~ /return05 {

default_type application/octet-stream;  #必须告诉浏览器return内容的类型–浏览器直接进行下载
return 200 'egon say hello';
}
 location ^~ /return06 {

    default_type text/html;    #必须告诉浏览器return内容的类型—-html文件
    return 200 'xxx.html';
}         

                        
        
 十一、root指令与alias指令             index指令 

             相同点:都是用来指定资源的查找路径的
             不同点:
                root指令是为当前location定义了访问的根目录,完整的资源路径=root指定的根目录+请求的uri路径
                alias指令也规定了一个路径,但是该目录不是根目录,alias会把自己的路径替换为localtion规则匹配的路径
                            
root:            
            192.168.71.112:9999/egon/xxx/yyy/zzz
                root /var/www/html   # 完整的路径:/var/www/html/egon/xxx/yyy/zzz

        location /egon/xxx {

            root /var/www/html;
            index index.html a.txt b.txt;
        }
 
用户请求:http://192.168.71.15/egon/xxx
nginx会去:/var/www/html/egon/xxx下依次查找index.html、a.txt、b.txt

                                                        #   如果本层没有root路径就去上一层找
                
alias:(结合location使用)   

           192.168.71.112:9999/egon/xxx/yyy/zzz            
                location /egon/xxx {

                    alias /a/b/c;   # 完整的路径:/a/b/c/yyy/zzz
                }

index 

    当客户端的请求为一个目录,nginx会返回该目录下的哪个文件作为默认页面,或者说根据index所指定的文件列表在root路径下按序查找文件作为默认响应,若存在就返回该文件;

     如果所有的都没查找到,返回403/404错误;如果开启了autoindex,则会返回目录列表

     # index 指令依赖于 root 指令来确定查找索引文件的根目录

     #  在部署静态网站时,通常会将 index.html 作为默认的索引文件。这样,当用户访问网站的根目录时,Nginx 会自动返回 index.html 页面。

location / {

            root /a/b/c; 
            index index.php index.html index.htm;     #定义首页索引文件的名称(按顺序依次查找)  
        }

      

 十二、代理指令

            proxy_pass——http协议
            fastcgi_pass——fastcgi协议
            uwsgi_pass——uwsgi协议

代理:

                          

            正向代理

                 正向代理代理的是客户端的请求                
                特点:
                    可以放在内网,也可以放在外网
                    客户端使用时,需要设置自己的代理服务(squid、varnish)

                可以通过代理服务器去访问外网   客户端访问软件服务器—>软件服务器识别请求,国内发给国内服务器,国外发给国外服务器—–>通过国外服务器访问外网
                
            透明代理

                与正向代理一样,都是用来代理客户端的请求的
                
                不一样的点:
                    1、透明代理意味着对客户端是完全透明的,即用户端
                    无需设置指向代理服务器
                    
                    2、透明代理服务器必须跟客户端在同一个内网里
                    
                主要用做:用户上网行为分析、屏蔽
                
                
                
            反向代理

              

             反向代理代理的是服务端(负载均衡)—–把反向代理服务器当成真正的服务器

            
十三、upstream模块

负载均衡             

            upstream可以包含多台主机,用于负载均衡            
            放置的地方:
                http {             #七层负载均衡
                    upstream xxx {                        
                        server 192.168.43.100:8080 max_fails=3 fail_timeout=5s;
                        server 192.168.43.101:8080 max_fails=3 fail_timeout=5s;
                        server 192.168.43.102:8080 backup;
                        server 192.168.43.103:8080 down;
                    }
                    server {}
                }
            
                stream {         #四层负载均衡
                    upstream xxx {}
                    server {}
                
                }

              

            

慢启动            

 如果正在经历高并发,瞬时并发量很高的情况下            
                如果直接新增一台机器,会到大量的流量瞬间流入新机器,导致连接池打满,用户无法访问                
                所以应该采用慢启动slow_start(仅nginx的商业版本nginx plus支持),慢启动指的是新上线的机器应该在一段时间内慢慢接受流量        
                慢慢的把该建立的链接都建立ok,才能正常提供服务,否则会一下子被打死(慢启动的时间根据实际情况合理定义)                                           
            
               对nginx开源版,本身不支持slow_start参数
                实现类似慢启动的方案:
                    1、在在流量不高的情况,提前新增机器
            
                    2、手动控制,每隔一段时间加一点权重 weight
                    
            或者用haproxy:
                提供了slow_start的功能 

                   
        
        
upstream模块的健康检查:

 
                1、下述参数只能针对端口没有响应
                server 192.168.43.100:8080 max_fails=3 fail_timeout=5s         
                2、而我们有可能遇到端口是可以正常响应,但是因为该端口对应的软件有bug
                    而导致有响应,但是是错误的响应,max_fails、fail_timeout无法检测出来                  
                    如何应对?
                      

 proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_403 http_404;                                 #认为此台服务器挂掉,跳过此台服务器去下一台返回给客户端正常的响应

                    

负载均衡调度算法

问题出现后的弥补措施

nginx原生——rr   weight  ip_hash  least_conn   

nginx本身不支持——url_hash  fair

轮询(默认算法)    按时间按顺序逐一分配到不同的后端服务器(默认)

weight                  加权轮询,weight值越大,分配到的概率越高

least_conn           最少链接数,哪个机器链接数少就往哪发(但每条链接的所用时间无法判断)

fair                        公平调度算法—-基于加载时间的长短进行负载均衡(比最小连接调度更智能)

 ip_hash               保持客户端访问的web服务器不变,打破了负载均衡的功能,但是对于不启用共                               享存储使用本地保存的会话session来说起到了保持会话的作用——-但基本不用

url_hash               与ip_hash相同,根据访问url的hash结果分配,每个url定向到同一个后端服务器

提前进行健康检查

负载均衡的健康检查(拓展,了解即可)——原生不支持

 必须要源码安装对应版本的nginx,下载第三方模块,进入nginx目录打补丁,最后进行make&&make install

haproxy内部支持健康检查

                    
十四、动静分离与资源分离
        

1、动静分离(*****)

 区分动态与静态的前提:软件的版本尚未更新,软件处于正常运行状态
静态请求:
    请求的结果基本不会变化,每个人来请求拿到的结果都一样
    例如图片、js、css
    
动态请求
    请求的结果会跟你提交的信息而发生变化,每个来请求结果都不一样
    
    例如:转账、添加购物车、付款、登录
    

为何分离?
    分离也好、分层也好,都是一种优化的思想
    只要遇到一些集群中性能或者管理上的问题,解决思路:
        1、能不能抽离出来
        2、只要能抽离出来,就可以单独有针对性的进行优化
    

动静分离有三大类方案
    1、后端在返回前端代码时,静态文件就配置好了cdn地址
    
    
    2、web服务器
        nginx ——-》php-fpm
        
        ===> 不是所有的静态请求都走cdn
            一些静态请求还是会打到我们自己的web服务器上
            此时web服务器上的动静分离依然是有收益的(cdn溯源的时候依然会在站点上用到动静分离)

            更精细化的管理(缓存到本地,比cdn更快)
                expires 30d;
    
            安全加固
            
    
    3、七层负载均衡
        方案1:(不推荐
            静态文件也用共享存储挂载给七层负载均衡
            七层负载均衡=负载均衡(只派活不干活)+静态资源服务器(响应静态请求)                                        (响应部分指定的静态请求)
      
            强调:最好是专业人干专业的事情,符合分层的思想

               

    
    
        方案2
            动静抽离出不同的服务器集群
                1、应用集群(动态请求)
                2、静态资源服务器(静态请求)                
            七层负载均衡将动、静请求分发给不同的集群来处理

    
    
    

2、资源分离(****)

     if判断:实现满足条件,发往特定的集群

负载均衡层

[root@lb01 ~]# vim /etc/nginx/conf.d/linux.sj.com.conf
upstream android {

    server 10.0.0.7;
}
 
upstream iphone {

    server 10.0.0.8;
}
 
upstream pc {

    server 10.0.0.9;
}
 
server {

    listen 80;
    server_name linux.sj.com;
 
    location / {

        if ($http_user_agent ~* “Android”) { #判断如果是安卓端
            proxy_pass http://android;       #代理到android虚拟主机池
        }
        if ($http_user_agent ~* “iPhone”) {    #判断如果是苹果端
            proxy_pass http://iphone;       #代理到iphone虚拟主机池
        }
        if ($http_user_agent ~* “WOW64”) {    #判断如果是IE浏览器
            return 403;                    #直接返回403
        }
        proxy_pass http://pc;               #如果没有匹配到以上内容,默认都代理到pc虚拟主机池
        include proxy_params;
    }
}

十五、重写rewrite(****)

定义

  什么是重写:
    rewrite是ngx_http_rewrite_module模块提供的一个功能
    可以把请求url地址中的uri路径部分进行改写
        
    http://egonlin.com/a/b/c?page=13  重写 https://egonlin.com/a/b/c/page/13
    
为何要用重写
    1、伪静态,方便浏览器收录(最常用的场景)
    2、协议或端口的更换
    http协议来请求,重写为https
    端口重写
    3、网站换新域名后,让旧的域名的访问跳转到信息的域名上
    
    
如何用重写
    强调重点:
        1、重写指令是以配置的形式写入配置文件中的,它是配置而不是代码
        
        2、代码是在nginx的进程内的,进程内有很多功能模块,负责重写功能的是重写模块
        
        
        总结:
            重写模块的代码会去配置文件中读取与重写有关的规则配置来执行
            其他功能的配置不归重写功能管理            
            配置文件不是代码,配置的文件没有执行顺序,配置的顺序无法完全代表代码的执行顺序

            配置文件是代码运行的原材料

            
            
        3、与重写有关的规则可以放在配置的哪些地方呢?
            server块
            location块
            if块    if( ) { }

            
            
    

ngx_http_rewrite_module模块提供4种配置指令
            
        break:终止重写逻辑的循环,所有与重写有关的指令都不会运行了,不影响其余模块运行
        last(等同于continue):终止本次循环,直接进入下一次        
        if        
        return:整体结束        
        rewrite:把url路径重写为一个新路径(但凡重新成功,一定会触发新一轮的location匹配)
            补充说明:
                rewrite 正则 /test1                # 触发新一轮的location匹配
                rewrite 正则 http://egonlin.com    # 直接跳转到新网址

                
   
模块运行逻辑(伪代码) 

    ngx_http_rewrite_module(代码)模块的运行逻辑:
        两大步骤:
        1、从配置文件的三个地方server块、location块、if块读取重写规则到内存中
        
        2、执行重写规则
        (1)先执行server块中的重写规则 ,如果重写为一个完整的url地址带着域名,那会直接跳转
            如果重写失败、或者重写为一个新路径,那进入下一个阶段
            
          (2) 进入一个loop循环—–伪代码      (break停止的是整个循环)

### 综上,配置文件中无论何处出现的重写指令,最终都会被nginx收纳到ngx_http_rewrite_module这个模块的运行逻辑中去,这个模块内部的运行逻辑包含了一个大循环(最多循环十次

 
先执行server块内的重写指令集 
while True:                                  # 再进入一个loop内
    #第一个location 
    判断请求的uri路径 == location指定的:
        if (条件) {

            重写指令1
            重写指令2
            重写指令3
        }
        重写指令4
        重写指令5
        重写指令n
        当前location内的所有重写指令执行完毕后会自动continue进入下一次loop
 
    #第2个location 
    判断请求的uri路径 == location指定的:
        if (条件) {

            重写指令1
            重写指令2
            重写指令3
        }
        重写指令4
        重写指令5
        重写指令n
        当前location内的所有重写指令执行完毕后会自动continue进入下一次loop
 
    #第3个location 
    判断请求的uri路径 == location指定的:
        if (条件) {

            重写指令1
            重写指令2
            重写指令3
        }
        重写指令4
        重写指令5
        重写指令n
        当前location内的所有重写指令执行完毕后会自动continue进入下一次loop

指令

 break

break指令指的是跳出整个重写模块代码的循环loop,即会终止所有后续的ngx_http_rewrite_module模块相关的所有重写相关指令的执行,
注意是所有的,意味着任何块里任何位置的rewrite相关的指令都不会再执行,但是非重写相关指令不受影响

if

if (conditon) {

   # 代表条件为真时的nginx操作,可以是反向代理,也可以是URL重写
}

可以在server、location内使用

# 如果要禁止掉一些访问,进行条件匹配后直接返回403状态码即可

return(详解见return指令)

可以在server、location、if内使用

rewrite

rewrite_log   仅在测试的时候开启,会增加日志的io量导致性能降低

通常在http、server、location中设置

server {

    listen 80;
    server_name domain.com; 
    rewrite_log on;
    # Rest of the configuration
}

[root@web01 ~]# vim /etc/nginx/nginx.conf
… …
error_log  /var/log/nginx/error.log notice;    # notice必须设置(日志等级)
… …
http {

    … …
    rewrite_log on;
    … …
}

语法
rewrite regex replacement [flag]; 
regex            #用于匹配uri路径的正则表达式
replacement     #替换的新路径
[flag];         #标记位,后面有详解案例
 
###
1、rewrite只能放在server{}, location{}, if{}中
2、regex正则部分只匹配uri路径部分
例如 http://seanlook.com/a/we/index.php?id=1&u=str 只对/a/we/index.php重写。
3、replacement可以是一个不带域名的uri路径(默认当前域名),也可以是一个带着新域名的完整url地址

# regex正则表达式的运用需要pcre库的支持—-默认会安装(rpm -qa | grep pcre) 

# flag标记

1、last: 相当于continue指令,会结束当前location内的重写指令,然后进入下一次loop
拿着改写后的新uri,从头开始匹配location,从第一次之后,即从第二次算起,最多不能超过10次loop
即不在rewrite指令所在的当前级别查找新的uri路径,而是从头开始在server块中查找location 
2、break: break掉重写模块的loop,所有重写模块相关的指令整体结束掉无论你在何处,但肯定不会
影响其他模块,所以结论就是会在本location内继续执行其他非重写模块相关指令 
3、redirect:  返回302临时重定向,浏览器地址会显示跳转后的URL地址. 
4、permanent:  返回301永久重定向,浏览器地址会显示跳转后URL地址.

rewrite regex replacement [flag];
rewrite regex replacement break;
rewrite regex replacement last;
rewrite regex replacement redirect;  # 302
rewrite regex replacement permanent; # 301

set

定义变量—–内层定义的覆盖外层定义的

server {

    listen 8080;
    set $my_name “linhaifeng”;  # server块内定义
    location / {

        set $my_key “p”;        # locatin块内定义
        if ($http_user_agent ~* (MSIE|Opera|Google|Bing|Yahoo|Firefox)) {

            set $my_page “7278389.html”;  # if块内定义
            rewrite .* https://www.cnblogs.com/$my_name/$my_key/$my_page;
        }
    }
}

案例

http——》https 

#Nginx跳转配置
server {

        listen 80;
        server_name linux.rewrite.com; # 可用$server_name获取该域名
        rewrite ^(.*) https://$server_name$1 redirect;
        #return 302 https://$server_name$request_uri;
}

伪静态

——指将动态网页(一般为带有查询字符串的 URL)转化为看起来像静态网页的 URL 的技术
                  例如,将/product.php?id=123改写成/product-123.html。

为了对网站进行seo优化,提升站点在搜索引擎中的排名(搜索引擎更倾向于将统一且结构简单的静态 HTML 页面排在更高的位置),对前端代码进行修改动态地址伪装成静态地址,但是后端读不懂伪装的地址所以需要重写成以前后端能读懂的代码此外;

伪静态 URL 也更加具有可阅读性,让用户能够更好地理解页面的内容。

/product-123.html—–(重写)—->/product.php?id=123

server {

    listen  80;
    server_name  www.example.com;
    location / {

        rewrite ^/product-([0-9]+).html$  /product.php?id=$1  last;
    }
}
前端请求用的是静态地址/product-123.html,这个地址本质上是不可用的,是一个假的
伪装的地址,所以到后台后需要location匹配并用rewrite将其重写为真正的可以执行的
动态请求

                
十六、其他模块(***)

使用模块时先用 nginx -V 看是否有这个模块

目录索引

### 点击链接直接就能进行下载

ngx_http_autoindex_module

语法

Syntax: autoindex on | off;
Default:    autoindex off;
Context:    http, server, location

配置

[root@web01 ~]# cat /etc/nginx/conf.d/www.autoindex.com.conf 
server {

    listen 80;
    server_name www.autoindex.com;
    charset utf8;
 
    location / {

    root /code/autoindex;
    index index.html;
    }
 
    location /download {

    root /code/autoindex;
    autoindex on;
    autoindex_exact_size off;

    #显示文件字节大小,默认是显示字节大小,配置为off之后,显示具体大小 M/G/K

    autoindex_localtime on;

    #显示文件的修改的具体时间,默认显示的时间与真实时间相差8小时,所以配置 on
    }
}

实例

[root@web01 ~]# vim /etc/nginx/conf.d/www.autoindex.com.conf 
server {

    listen 80;
    server_name www.autoindex.com;
    charset utf8;
 
    location / {

        root /code/autoindex;
        index index.html;
    }
 
    location /download {

        root /code/autoindex;
        autoindex on;

    }

#创建站点目录
[root@web01 ~]# mkdir /code/autoindex/download -p     #将数据放入此文件中提供下载
[root@web01 ~]# echo “测试autoindex模块” > /code/autoindex/index.html 
#访问
http://www.autoindex.com/       为主站
http://www.autoindex.com/download/      为下载文件的目录 

访问控制

 # ngx_http_access_module

语法

#允许访问的语法
Syntax: allow address | all;
Default:    —
Context:    http, server, location, limit_except
 
#拒绝访问的语法
Syntax: deny address | all;
Default:    —
Context:    http, server, location, limit_except
 
#如果配置允许,则也要配置拒绝;配置拒绝可以单独配置

实例(继续上个模板的实例)

# 拒绝指定IP

location /download {

        root /code/autoindex;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        deny 10.0.0.1;
        allow all;

#只允许指定IP访问

location /download {

        root /code/autoindex;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        allow 10.0.0.1;
        #如果使用all,一定放在最后面
        deny all;

#只允许指定IP访问拒绝该网段其他IP

allow 10.0.0.1;
        #如果使用all,一定放在最后面
deny 10.0.0.0/24;

访问认证

#访问网页时要先输入账号密码才能进行访问

# ngx_http_auth_basic_module

实例

#创建密码文件需要用到 htpasswd
[root@web01 ~]# htpasswd -c /etc/nginx/auth_basic lhd    # -c创建
New password: 
Re-type new password: 
Adding password for user lhd
 
#添加一个登录用户(追加)
[root@web01 ~]# htpasswd /etc/nginx/auth_basic egon # 不加-c即添加
New password: 
Re-type new password: 
Adding password for user egon
 
#密码文件内容
[root@web01 ~]# cat /etc/nginx/auth_basic
lhd:$apr1$A7d4BWYe$HzlIA7pjdMHBDJPuLBkvd/
egon:$apr1$psp0M3A5$601t7Am1BG3uINvuBVbFV0

#开启配置 
    location /download {

        root /code/autoindex;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        auth_basic “egon say hello!”;  # 用谷歌浏览器验证,不要用火狐抓不到401的包
        auth_basic_user_file /etc/nginx/auth_basic;   #拿到信息后会在文件中进行比对
    }
}   

状态监控

配置

location = /basic_status {     # 直接添加
        stub_status;
    }

访问

#访问 http://www.autoindex.com/basic_status
 

#nginx七种状态
Active connections: 2 
server accepts handled requests
 4 4 21 
Reading: 0 Writing: 1 Waiting: 1 
 
# 累计值
Active connections      #当前活跃的连接数
[root@web01 /usr/share/nginx/html]# netstat -ant |grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 
tcp 0 0 192.168.71.112:80 192.168.71.7:65491 ESTABLISHED
tcp 0 0 192.168.71.112:80 192.168.71.7:65492 ESTABLISHED
 
accepts                 #nginx启动开始算,累计接收的TCP连接总数
handled                 #累计成功的TCP连接数
requests                #累计成功的请求数
Reading                 #当前0个链接正在读请求
Writing                 #当前1个链接正在响应数据给客户端
Waiting                 #当前等待的请求数,即当前处于keep-alive状态的连接数
 
# 注意, 一次TCP的连接,可以发起多次http的请求, 如下参数可配置进行验证
keepalive_timeout  0;   # 类似于关闭长连接
keepalive_timeout  65;  # 65s没有活动则断开连接

连接限制   

请求限制

十七、nginx的优化(******)

对于优化来说,主要是针对i/o的优化

1、整体的优化思路(******)

 整套架构追求:高性能、高可用、高一致性,还有安全性

(1)先摸清楚情况
        I: 了解整套架构的链路与分层—》画出架构图/链路图

        II:了解整套架构承载的业务特点
        电商—-》峰值流量特别大
        toB—–>业务逻辑复杂性更高。代码bug率更高

(2)再发现瓶颈
        针对慢的问题          
            用户请求—–》负载均衡—–》应用—–》数据库与数据库缓存层
                                                                    —–》文件服务器层
     排查方法:
        1、有些慢可以直接计算出来
            峰值qps/应用服务压测的qps = 需要几台机器
            
            机器数不够就扩容
            
            
        2、无法直接计算出来的
            2.1、查看沿途的访问日志,例如mysql的慢查询日志
            2.2、top命令、netstat、或或ngx_http_stub_status_module查看链接数
    来确认资源使用情况,是否有超负载、内存用完、连接过多的情况

                                解决—-更改权重,最小链接调度算法等

                                           

(3)有针对性的进行优化

  2、架构维度优化方案

  2.1、架构高性能优化思路

         优化思路:(io优化
             (1)高频读:就少读、就近读、读缓存 
             (2)高频写:就少写、数据拆分、漏斗写,buffer写 
        优化步骤:
             把问题细分—》分出单独的层—》单独处理
             
        优化效果:例如动静分离、冷热分离,即分流了压力又做到了隔离保护,从而达到高性能的目的

  

   

     架构维度,每一层该如何优化举例
        1、io问题—》数据库层
        数据库慢查询—–》优化sql、索引、引入数据库缓存层
        2、web层:
            web集群机器数不够用(峰值qps/单机极限qps=机器数)–》扩机器            
            查看web服务的负载、内存使用率 —–》降权重,比较闲的机器应该增加权重            
        3、负载均衡(内存、cpu)—》多级负载均衡,买硬件F5
                
        4、文件服务器层
                       —–》分布式存储
                        
        5、网络问题
            丢包、延迟—–》优化网络环境、升级网络设备
            
            带宽不够——-》加带宽(网速)
            
            访问距离远——》CDN、静态资源缓存在用户浏览器中
                        
        6、其他棘手的问题—–》 考虑分离出来,单独处理
            动静分离
            冷热分离(访问频率)
      

2.2、单机通用优化点

            硬件
            负载均衡(内存大一些,cpu核多一些)#对于lvs的情况,包的返回直接发送给客户端不经                                                                                lvs,所以对cpu的性能而言要求要更高
            
            应用层:无特殊要求,因为有很多应用服务器,性能低可以设置的权重低一些
            
            文件服务器:(普通文件服务器例如nfs,内存磁盘大一些)#如果是分布式存储,对cpu也                                                                                                               有性能要求
            
            数据库: 内存、磁盘(可以考虑固态)
            
            数据库缓存:内存
            
        
        
        系统
            内核优化参数:
                (1)ipv4: /proc/sys/net/ipv4
                (2)tcp连接池:半连接池、全连接池
                
        
        软件
            服务
                nginx优化
            应用
                每个程序都有自己环境(编写语言)相关的优化参数
        
                    

3、系统优化(******)

内核优化

ulimit -u 3     #打开的最大进程数

ulimit -n 12     # 这个值默认最大可以设置为1048576,文件描述符
                                    ——临时生效

在/etc/security/limits.d/下放配置文件优先级更高,并且无需重启系统,退出当前终端重新进入即可生效
cat > /etc/security/limits.d/k8s.conf <<'EOF' 
* soft nofile 65535 
* hard nofile 131070 
EOF 
ulimit -Sn    #查询文件描述符软限制数量
ulimit -Hn    #硬限制

#设置
[root@egon ~]# cat >>/etc/sysctl.conf<<EOF
net.ipv4.tcp_fin_timeout = 2
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1    #开启后用来防止syn洪水攻击
net.ipv4.tcp_keepalive_time = 600
net.ipv4.ip_local_port_range = 4000    65000
net.ipv4.tcp_max_syn_backlog = 16384———-半连接队列
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384———–全连接队列
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 16384
net.ipv4.ip_forward = 1
EOF
 
#生效
[root@egon ~]# sysctl  -p

4、nginx优化(*****)

### 系统内核优化与nginx优化配合调整

通用nginx优化

#  调大连接数—–提高并发,文件描述符也跟着调大

全局配置优化

worker_processes  4; # 通常设置为auto就行,有几个核就设置为几
worker_rlimit_nofile 65535;  # 配合着要把文件描述符调大

events块

events {

    use epoll;  # 使用epoll网络io模型
    worker_connections 1024;  # 调大连接数
}

http块—-详情见nginx基础配置

server块—-线程池与独享全连接队列

#  全局新增
thread_pool egon_pool threads=3 max_queue=1024; # 定义线程池
 
http {

    #aio threads;
    aio threads=egon_pool; # 启用线程池
 
    # 启用线程池与reuseport并不冲突
    server {

        listen 8089 reuseport backlog=10240;

nginx作为代理服务器的优化 

负载均衡代理—-web(长连接)

 [root@lb01 ~]# vim /etc/nginx/conf.d/linux.keep.com.conf
upstream tomcat {

    server 172.16.1.7:8080;
    keepalive 8;                #配置开启长连接
}
 
server {

    listen 80;
    server_name linux.keep.com;
 
    location / {

        proxy_pass http://tomcat;
        proxy_http_version 1.1;         #代理带后端的http版本
        proxy_set_header Connection “”;    #清除请求头字段
        include proxy_params;
    }
}

web代理—-php(长连接)

 [root@web01 ~]# vim /etc/nginx/conf.d/linux.wp.com.conf 
upstream php_server {

    server 127.0.0.1:9000;
}
 
server {

    listen 80;
    server_name linux.wp.com;
 
    location / {

        root /code/wordpress;
        index index.php;
    }
 
    location ~* .php$ {

        fastcgi_pass php_server;
        fastcgi_param SCRIPT_FILENAME /code/wordpress/$fastcgi_script_name;
        fastcgi_param HTTPS on;
        fastcgi_keep_conn on;  # 开启长连接
        include fastcgi_params;
    }
}

代理优化配置

[root@lb01 ~]# cat /etc/nginx/proxy_params 

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;

proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;

proxy_next_upstream http_500 http_502 http_503 http_504;
 
然后在文件中引入
    location / {

        proxy_pass http://tomcat;
        include proxy_params; # —–》引入上面的文件
    }

### 总结 ###

cat nginx.conf

1、CPU亲和、worker进程数、调整nginx进程打开的文件句柄数
2、使用Epool网络模型、调整每个worker进程的最大连接数
3、文件的高效读取sendfile、nopush
4、文件的传输实时性、nodealy
5、开启tcp长连接,以及长连接超时时间keepalive_timeout
6、开启文件传输压缩gzip
7、开启静态文件expires缓存
8、隐藏nginx版本号
9、禁止通过ip地址访问,禁止恶意域名解析,只允许域名访问
10、配置防盗链、以及跨域访问
11、防DDOS、cc攻击,限制单IP并发连接,以及http请求
12、优雅显示nginx错误页面
13、nginx加密传输https优化
14、nginx proxy_cache、fastcgi_cache、uwsgi_cache 代理缓存,第三方工具(squid、varnish)

5、静态资源

                                   

http响应头

cache_control  #缓存控制

expires  #资源过期时间

last-modified  #标记资源最后被修改时间

etag  #为资源提供的一个特定的标识符

http请求头

If-None-Match

If-Modified-Since

浏览器缓存流程(了解)

1、浏览器优先去查看响应头部的 cache-control 
2、如果cache-control设置了缓存时间,并且未过期,则直接使用浏览器缓存的内容
3、如果cache-control设置为 no-cache,那么浏览器会继续去读取 expires
4.如果expires设置了,并且未达到过期时间,那么浏览器会读取缓存
5.如果 cache-control 和 expires 都没有设置
6.浏览器会去查看之前响应的 ETag值,然后放到请求头 If-None-Match中发往服务端进行验证,服务端比对之后
发现值相同,则代表资源未被修改,服务端将返回 304 Not Modified 状态码,浏览器随即从缓存中加载资源
注意:ETag 可以解决仅使用 Last-Modified 时因时间精度问题无法判断内容微小修改的问题,因此优先被检测
如果发现值不同,浏览器会读取之前响应的last-modified时间,放入请求头 If-Modified-Since 到服务端对比,如果值相同,那么走缓存
否则,需要重新到服务器上获取数据并返回

6、静态资源的访问优化

缓存到用户浏览器(本地硬盘)
 expires 7d;

#配置
[root@web01 conf.d]# vim linux.cache.com.conf
server {

    listen 80;
 
    location ~* .(png|jpg|gif)$ {

        root /code/cache;
        expires 7d;
    }
}

配置不走缓存

1.使用无痕模式
2.开启浏览器上面的 Disable cache
3.配置nginx关闭缓存
[root@web01 conf.d]# vim linux.cache.com.conf
server {

    listen 80;
 
    location ~* .(png|jpg|gif)$ {

        root /code/cache;
        etag off;
        add_header Cache-Control no-cache;
        if_modified_since off;

    }
}

        
静态资源压缩
gzip on;  
补充:压缩数据会提供io效率,但是压缩算法会消耗cpu

#压缩配置

[root@web01 cache]# vim /etc/nginx/conf.d/linux.gzip.com.conf 
server {

    listen 80;
    server_name linux.gzip.com;
 
    location ~* .(png|jpg|gif)$ {

        root /code/cache;
        gzip on;
        gzip_types image/jpeg image/gif image/png;
        gzip_comp_level 9;

    }
 
    location ~* .txt$ {

        root /code/cache;
        gzip on;
        gzip_types text/plain;
        gzip_comp_level 5;

    }
}

    
十八、防盗链(功能)

“Referer”HTTP请求头的一个字段,当你点击一个链接或者提交一个表单跳转到另一个页面时,
浏览器会自动添加这个Referer字段,用来告诉服务器你是从哪个页面跳转过来的。 

valid_referers是Nginx中用于检查HTTP Referer请求头部字段的指令,主要用于防止资源被其他站点盗用(用于server,location)

配置防盗链

[root@web01 conf.d]# vim linux.beidaolian.com.conf 
server {

    listen 8080;
    server_name linux.beidaolian.com 192.168.71.15;
 
    location ~* .(png|jpg|gif)$ {

        root /usr/share/nginx/html/;
 
        valid_referers none blocked server_names; # server_names默认只包含我们自己的域名
        if ($invalid_referer) {

           return 500;
        }
    }
}

补充: valid_referers none blocked server_names *.baidu.com; # 多加个*.baidu.com允许某些域名盗链

    
    
十九、cpu亲和(*****)—-》面试

# 绑定每一个worker进程到一个具体的cpu核心 

    好处:

      对于i/o密集型任务(对于cpu的消耗不高)
        减少进程的切换开销
        一个worker始终使用一个cpu,意味着可以有效率地利用cpu的缓存,减少内存的访问延迟        
        —》提升整体性能
    
    坏处:
        服务器运行着计算密集型的任务,会对某个cpu造成非常大的消耗与占用
        
        此时因为绑定,会到某个worker进程长期得不到cpu,效率反而 会低

配置

[root@lb ~]# vi /etc/nginx/nginx.conf
worker_processes auto;
worker_cpu_affinity auto;  #  为了很好的看到效果,所有worker都分配到一个cpu上
[root@lb ~]# systemctl restart nginx

查看

cat /etc/nginx/nginx.conf |grep -i work

ps -eo pid,args,psr | grep [n]ginx

补充说明:命令ps -eo pid,args,psr 是用来显示进程ID(pid)、命令行参数(args)以及进程运行的处理器ID(psr)

二十、同源策略(****)

1、浏览器的安全策略:同源策略(****)
    什么域?
        一个网站就是一个域
        域 = 协议://域名:端口

                  图片[1] - nginx详解 - 宋马
    
    什么是跨域?
        在域中发起了访问另外一个域的请求—-这就叫跨域        
        
    浏览器有一个安全策略:同源策略—-》跨域访问限制,不限制请求
        同源策略:
            同源指的是访问请求来自于同一个域
    
            非同源的请求浏览器会做限制,限制什么呢?
                限制响应,不限制请求
    
            总结同源策略是想要规避一件事:
                不允许你跨域去拿内容
                一个域里只能拿自己域里的数据,不能拿别的    
    
            补充:
                对于img、js、css文件的请求是可以跨域的
    

    
  二十一、web程序的两种开发模式

        

前后端分离开发

            前端是一个单独的项目,后端也是一个单独的项目        
            两者之间基于网络对接
        
            缺点:
                部署麻烦,两套2套程序
                
                前端程序要单独部署,单独监听一个:ip+端口
                
                后端程序要单独部署,单独监听一个:ip+端口
                
            优点:
                解开了耦合,前后端交给不同人单独开发,适用于大型项目、兼容多个前端

                
前后端不分离开发

            软件包整体就一份(前后端代码混在一起,强耦合在一起)
            部署时部署一份,对外暴漏用一个端口即可
            
            缺点:
                1、前后端一把抓,都需要自己开发
                2、因为是混合的
                所以一套后端,只能服务于唯一的一套前端,而前端是有很多种的:例如浏览器、微信小程序                
                即前后端混合在一起的程序,无法兼容多套前端
                
            优点:
                部署简单,只需部署一套程序,对外暴漏一个端口
                                                

结论
        针对前后端分离的软件,设计到跨域拿结果的问题        
        需要被跨域访问的那个后端程序主动告诉浏览器我允许被跨域拿结果

跨域访问

              ——-配置nginx告诉浏览器允许跨域访问

# 直接用nginx来响应接口请求return返回json数据
[root@web01 ~]# cat /etc/nginx/vhosts/www.egonlin.com.conf 
server {

    listen 8080;
    server_name www.backend.com 192.168.71.15;
 
    location /userinfo {

        #以下为解决跨域问题(增加响应头)
        add_header 'Access-Control-Allow-Origin' '*';   #表示服务器可以接受所有的请求源
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET,PUT,POST,DELETE,OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type,*';

 
        default_type application/json;
        return 200 '{“name”:”egon”,”age”:18}';
    }
}

补充:csrf攻击:跨站 请求伪造(***)
                 登录着正常的站点没有退出的情况下(比如登录后的cookie信息),

                 点击一个攻击者提供的链接,完成了一个正常的请求

                 跨站请求伪造,用户在登录正常的站点没有退出的情况下,点击了攻击者制造的恶意网站链接,此链接是对用户还未退出的网站进行的一些恶意操作请求,由于用户登录的正常网站未退出,浏览器会带着用户在正常网站的身份认证凭证去请求操作,从而导致恶意的请求成功操作。

         同源策略对于防止CSRF帮助不大,因为同源策略并不能阻止恶意网站发起跨站请求只是限制响应包。 
    

    
二十二、负载均衡—-会话保持(****)

     http协议特点

     1、无连接
        在完成http响应的情况下,http协议默认不会让tcp协议保持链接        
        
        问题:高并发场景下,同一个客户端可能在短时间内会重复多次请求服务,无连接会导致大量开销都浪费在重复创建与断开tcp连接上
        
        解决:开启keepalive长连接
            在请求与响应头里加上:connection:keep-alive            
            http1.1默认请求头里就加上了connection:keep-alive
                
        
    2、无状态
        http协议无法保存上一次访问的状态(用户登录信息、权限)
        
        问题:如果后续处理需要前面信息,那必须重传 

                
解决方案:cookie  session  jwt

             cookie:由服务端产生,存入客户端浏览器
              问题:
                    1、cookie存的是明文,容易泄露
                    2、cookie是可以被客户自己篡改
              总结:cookie本身没问题,但是单用cookie就有问题,问题如上
        
        
            session:由服务端产生,存在服务端称之为session(会话)

                             然后服务端会将该session做一个加密,得到一串加密字符,这串加密字符与                                   session信息相对应,我们将这串加密字符称之为session id
                             key-value                             key–session id         value–session
                             然后服务端会把这个session id存入客户端浏览器的cookie中
        
                优点:
                    1、客户端无法篡改,更安全
                
                问题:
                    1、在负载均衡的场景下,需要做会话共享(session存到哪由应用程序代码决定)     
                    2、需要把会话共享的组件例如redis做成集群
                    增加了管理成本                    
                    3、应程序都要依赖redis,意味着redis的性能
                    会限制整个集群的规模
                    
                    
            能不能有一种方案,即能防篡改,也能保持状态、会话———-于是诞生了jwt方案
               
              

 
                jwt:由服务端产生,存入客户端——json web token(令牌)
            jwt=header+payload+signatrue

            header:指定hash算法与类型—-经过base64url算法转换的字符串

            payload:状态信息—-经过base64url算法转换的字符串

            signature:存放”header+payload+口令”通过hash算法的hash值

            # 防篡改—-口令内容只有服务端才知道,所以一旦hash值对不上,一定是前两部分发生了篡改
            # base64url不是加密算法,可以进行反解
            
                                                                                    
补充:1、hash算法的特点(文件校验):
                    1、只要源内容一样、相同hash算法算出来的结果一定一样,反之亦然
                    
                    2、不能通过hash值反推出内容
           2、cookie是与域有关的,不能跨域,每个域都有自己的cookie,但是jwt可以跨域         

        使用方式

                    1、存储到cookies中

                    2、存储在localstorage,下次与服务端通信的时候从中取出来放到http请求头的authorization字段中,或者放在post请求的请求体里
                  

        优点与缺点

                          优点—-支持无状态认证与跨域认证,以及比较容易实现的分布式系统认证

                          缺点—-无法在使用的过程中废止某个token,jwt一旦发出在到期前都会生效
                                      客户端的存储容易受到xss(跨站脚本攻击)的攻击 

了解—-XSS

图片[2] - nginx详解 - 宋马      
        
负载均衡与会话保持案例

1、nfs共享存储(太慢):把多台后端服务器session文件目录挂载到NFS同一目录
2、mysql(也慢):通过程序将session存储到mysql数据库,需要程序本身支持
3、redis(块):通过程序将session存储到redis缓存,需要程序本身支持

1、机器规划
    负载均衡:192.168.71.116:9090

    web01: 192.168.71.112:8888
    web02: 192.168.71.113:8888                
    mysql数据库:192.168.71.116:3306    

2、环境准备
    关selinux、firewalld
    配置静态ip
    时间同步

3、安装数据库
    yum remove mysql* mariadb* -y      
    wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
    yum -y install mysql57-community-release-el7-10.noarch.rpm # 安装     
    yum -y install mysql-community-server –nogpgcheck        
    rm -rf /var/lib/mysql/*(仅测试环境使用)
    systemctl restart mysqld
    grep 'temporary password' /var/log/mysqld.log

    [root@db ~]# mysql -uroot -p'+eg31Fdhd/Ft'
    mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'Egon@666';
    Query OK, 0 rows affected (0.00 sec)

    mysql> flush privileges;
    Query OK, 0 rows affected (0.00 sec)

4、部署两台web:nginx+php-fpm
    yum -y install epel-release
    yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm #      

    yum -y install yum-utils     

    yum -y install php74-php-gd php74-php-pdo php74-php-mbstring php74-php-cli php74-php-fpm php74-php-mysqlnd

# 配置信息(如果是centos9默认以socket方式启动,想用端口方式,需要改listen=127.0.0.1:9000)
cat /etc/opt/remi/php74/php-fpm.d/www.conf |grep -v '^;' |grep -v '^$'

    systemctl start php74-php-fpm
    systemctl enable php74-php-fpm
    systemctl status php74-php-fpm

5、安装nginx对接php
    yum install nginx -y

    cat > /etc/nginx/conf.d/web.conf << “EOF”
        server {

            listen       8888;

        location / {

            root   /usr/share/nginx/html;
            index index.php index.html index.htm a.txt;
        }
     
        location ~ .php$ {

            fastcgi_pass   127.0.0.1:9000;
            fastcgi_param  SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
    EOF
    systemctl restart nginx

6、在两台web上部署应用程序
    wget https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-all-languages.zip

    unzip phpMyAdmin-5.2.1-all-languages.zip

    mv phpMyAdmin-5.2.1-all-languages /usr/share/nginx/html/php

    cd /usr/share/nginx/html/php
    cp config.sample.inc.php config.inc.php

    vi config.inc.php # 修改连接数据库的代码
    $cfg['Servers'][$i]['host'] = '192.168.71.16';
  

     chown -R nginx.nginx /usr/share/nginx/html/php
       

7、数据库中创建登录账号密码
    create user 'root'@'192.168.71.%' identified by 'Egon@666';
    grant all on *.* to 'root'@'192.168.71.%';
    flush privileges;

8、用nginx做七层负载均衡
yum install nginx -y
[root@web03 ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {

    worker_connections 1024;
}
http {

    upstream webserver {

    server 192.168.71.112:8888 max_fails=3 fail_timeout=5s;
    server 192.168.71.113:8888 max_fails=3 fail_timeout=5s;
    }
    server {

        listen       9090;
        location / {

           proxy_pass  http://webserver;
           
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header Host $http_host;
           proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_403 http_404;
        }
    }
}

    
        
9、会话共享方案
    不做会话共享的方案:
            ip_hash算法(违背了负载均衡的初衷)         
    

    会话共享的方案:

(1)nfs共享存储

# 1、nfs服务器
yum -y install nfs* -y
[root@lb ~]# cat /etc/exports 
/data 192.168.71.0/24(rw,sync,no_root_squash)
 
[root@lb ~]# mkdir /data
[root@lb ~]# exportfs -a ;systemctl restart nfs
 
# 2、所有web
yum install nfs* -y
 
# 3、web01挂载
[root@web01 ~]# mount -t nfs 192.168.71.11:/data/ /var/opt/remi/php74/lib/php/session
[root@web01 ~]# chmod o+rwx /var/opt/remi/php74/lib/php/session
 
[root@web02 ~]# mount -t nfs 192.168.71.11:/data/ /var/opt/remi/php74/lib/php/session
[root@web02 ~]# chmod o+rwx /var/opt/remi/php74/lib/php/session
        
        
 (2)redis

yum install -y redis

vim /etc/redis.conf

找到配置项 bind 127.0.0.1,然后将 127.0.0.1 修改为 0.0.0.0 或者你想让其绑定的具体IP,以允许远程访问。
找到protected-mode yes,并将其更改为 protected-mode no 这样可以允许非本地客户端连接。
增加设置密码:requirepass 123

systemctl restart redis # 端口默认6379—-重启redis,并用客户端命令测试
# 我们用redis-cli客户端命令测试,redis-cli并部署php程序要使用的客户端,php程序中有自己的客户端模块,需要在程序运行环境为php语言准备好相应的模块
[root@lb ~]# redis-cli -h 192.168.71.11 -p 6379 -a 123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.71.11:6379> keys *
(empty array)
192.168.71.11:6379> set name egon
OK
192.168.71.11:6379> get name
“egon”
192.168.71.11:6379> keys *
1) “name”
192.168.71.11:6379> 

#修改web上的php配置文件
[root@localhost session]# cat /etc/opt/remi/php74/php-fpm.d/www.conf 
…………..
php_value[session.save_handler] = redis
php_value[session.save_path]    = “tcp://192.168.71.11:6379?auth=123”
 
;php_value[session.save_path]   = “tcp://192.168.2.11:6379”  # 如果redis不带密码,则使用这种配置
;php_value[session.save_handler] = files
;php_value[session.save_path]    = /var/opt/remi/php74/lib/php/session
…………..
  
#重启
systemctl restart php74-php-fpm    

#在web服务器上安装php程序依赖的连接redis的模块

systemctl list-unit-files|grep php
 
wget http://pecl.php.net/get/redis-5.3.5.tgz
tar -zxvf redis-5.3.5.tgz
cd redis-5.3.5
# 1、必须下面命令
yum -y install php74-php-devel
/opt/remi/php74/root/usr/bin/phpize  
 
—-查找php-config的位置
#find / -name php-config
/opt/remi/php74/root/usr/bin/php-config
 
—-运行configure
./configure –with-php-config=/opt/remi/php74/root/usr/bin/php-config –enable-redis
 
—-编译
make
—-编译安装:提示安装后的目标目录
[root@web01 ~/redis-5.3.5]# make install
Installing shared extensions:     /opt/remi/php74/root/usr/lib64/php/modules/
[root@web01 ~/redis-5.3.5]# ls /opt/remi/php74/root/usr/lib64/php/modules/ |grep redis
redis.so
 
—增加配置加载redis.so
[root@web01 ~/redis-5.3.5]# cat /etc/opt/remi/php74/php.d/redis.ini
;redis
extension=redis.so
 
—重启
systemctl restart php74-php-fpm
—查看
[root@web01 ~/redis-5.3.5]# php74 -m |grep redis
redis

进行测试   http://192.168.71.12:9090/php

二十三、nginx的常见问题(了解) 

多server的优先级

在开始处理一个http请求时,nginx会取出header头中的Host变量,与nginx.conf中的每个server_name进行匹配,以此决定到底由哪一个server来处理这个请求,但nginx如何配置多个相同的server_name,会导致server_name出现优先级访问冲突。

1.首先选择所有的字符串完全匹配的server_name。(完全匹配  www.mumusir.com)
2.选择通配符在前面的server_name,如 *.mumusir.com
3.选择通配符在后面的server_name,如 www.mumusir.*
4.最后选择使用正则表达式匹配的server_name,如:~^www.(.*).com$
5.如果全部都没有匹配到,那么将选择在listen配置项后加入[default_server]的server块
6.如果没写,那么就找到匹配listen端口的第一个Server块的配置文件

禁止IP访问

当用户通过访问IP或者未知域名访问你得网站的时候,你希望禁止显示任何有效内容,可以给他返回500,目前国内很多机房都要求网站关闭空主机头,防止未备案的域名指向过来造成麻烦

1、禁止IP访问直接返回错误

[root@web01 conf.d]# vim a.conf 
server {

    listen 80 default_server;
    server_name localhost;
    return 500;

2、引流到其他网站

[root@web01 conf.d]# vim a.conf 
server {

    listen 80 default_server;
    server_name localhost;
    return 302 http://www.baidu.com;
}

3、返回指定内容

[root@web01 conf.d]# vim a.conf 
server {

    listen 80 default_server;
    server_name localhost;
    default_type text/plain;
    return 200 “请使用域名访问正规网站!!!”;
}

4、跳转到指定文件

[root@web01 ~]# vim /etc/nginx/conf.d/a.conf 
server {

    listen 80 default_server;
    server_name localhost;
    root /code;
    rewrite (.*) /1.jpg;
}

include上下线服务

一台服务器配置多个网站,如果配置都写在nginx.conf主配置文件中,会导致nginx.conf主配置文件变得非常庞大而且可读性非常的差。那么后期的维护就变得麻烦。 
 
假设现在希望快速的关闭一个站点,该怎么办? 
    1.如果是写在nginx.conf中,则需要手动注释,比较麻烦 
    2.如果是include的方式,那么仅需修改配置文件的扩展名,即可完成注释 
    Include包含的作用是为了简化主配置文件,便于人类可读。
 
inlcude /etc/nginx/online/*.conf    #线上使用的配置
 
/etc/nginx/offline                  #保留配置,不启用(下次使用在移动到online中)

调整上传文件大小

在nginx使用上传文件的过程中,通常需要设置文件大小限制,避免出现413 Request Entity Too Large

配置

(http  server  location)

#也可以放入http层,全局生效
server {

    listen 80;
    server_name _;
    client_max_body_size 200m;  #默认1m
}

try_files路径匹配

 try_files 指令用于按顺序检查文件或目录是否存在,并根据检查结果进行相应的处理。它可以用来处理静态文件请求、实现伪静态、处理单页面应用(SPA)等场景。

当第一个参数指定的文件或目录不存在时,Nginx 会尝试下一个参数,直到找到存在的文件或目录,或者执行最后一个参数指定的操作(如返回错误页或重定向)。

例如:

server {

    listen 80;
    server_name example.com;
    root /var/www/html;
    location / {

        try_files $uri $uri/ /index.html;
    }
}

当用户请求一个资源时,Nginx 会先检查 /var/www/html 目录下是否存在与请求 URI 对应的文件($uri);如果不存在,则检查是否存在对应的目录($uri/);如果仍然不存在,则返回 /var/www/html/index.html 文件。这在单页面应用中非常有用,可以确保用户在刷新页面时仍然能够正常访问应用。

index与try_files

index 主要用于处理目录请求,指定默认的索引文件;而 try_files 更侧重于文件或目录的存在性检查,并根据检查结果进行灵活的处理

index 适用于简单的静态网站,确保用户访问目录时能正确显示默认页面;try_files 适用于需要更复杂的文件查找和处理逻辑的场景,如单页面应用、伪静态等。

index 的参数是文件名,用于指定默认索引文件;try_files 的参数可以是文件、目录或 URI,用于指定查找顺序和最终处理方式。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容