目录
  • 待补充
    • Nginx安装
      • Nginx yum安装
        • 检查安装
        • 查看帮助
        • 验证Nginx
        • Nginx启动脚本
        • 配置Nginx
        • 启动Nginx
      • Nginx 编译安装
        • 安装Nginx
        • 验证版本及编译参数
        • 访问编译安装的nginx web界?
        • 创建Nginx?启动脚本
          • Nginx 1.18.0
        • 配置Nginx
        • 默认配置?件
  • Nginx 核?配置详解
    • 全局配置
      • 启动Nginx?作进程的数量
      • 错误?志记录配置
      • pid?件保存路径
      • ?作进程nice值,客户端的连接数
      • 开发调试配置
      • 事件模型配置参数
    • 核?配置示例
      • 新建?个PC web站点
      • 新建?个Mobile web站点
      • root与alias
      • location的详细使?
        • 匹配案例-精确匹配
        • 匹配案例-区分??写
        • 匹配案例-不区分??写
        • 匹配案例-URI开始
        • 匹配案例-?件名后缀
        • 匹配案例-优先级
        • ?产使?案例
      • Nginx 四层访问控制
      • Nginx账户认证功能
      • ?定义错误??
      • ?定义访问?志
      • 检测?件是否存在
      • ?连接配置
      • 作为下载服务器配置
      • 作为上传服务器
      • 其他配置
        • 指定对哪种浏览器禁??连接,比如ie浏览器
        • 限制客户端使?除了指定的请求?法之外的其它?法
        • 启用或禁用在 FreeBSD 和 Linux 上使用异步文件 I/O (AIO)
        • 否缓存打开过的?件信息
        • 隐藏Nginx server版本,1.18啥的
  • Nginx ?级配置
    • Nginx 状态?
    • Nginx 第三?模块
    • Nginx 变量使?
      • 内置变量
      • ?定义变量
    • Nginx ?定义访问?志
      • ?定义默认格式?志
      • json格式的?志访问统计
    • Nginx 压缩功能
    • ssl 配置参数
    • ?签名 证书
    • Nginx证书配置
    • 关于favicon.ico
    • 安全选项
      • 隐藏Nginx版本号
      • 升级OpenSSL版本
  • Nginx Rewrite相关功能
    • if指令
      • 示例
    • set指令
    • break指令
    • return指令
    • rewrite_log指令
    • rewrite指令
      • rewrite flag使?介绍
      • rewrite案例-域名永久与临时重定向
        • 临时重定向
      • 永久重定向
      • rewrite案例--brak与last
        • break案例
        • last案例
      • rewrite案例-判断?件是否存在
    • Nginx防盗链
      • 实现web盗链
      • 实现防盗链
  • Nginx 反向代理功能
    • 部署后端Apache服务器
    • 反向代理配置参数
    • nginx反向代理示例--单台web服务器
      • 隐藏后端服务相应头部的信息(Server默认已隐藏,显示的是nginx的Server)
      • 显示后端服务相应头部的信息
      • 把客户端的ip地址proxy给后端服务器
    • 反向代理示例--指定location
    • 反向代理示例--缓存功能
      • ?缓存场景压测
      • 准备缓存配置
      • 访问并验证缓存?件
    • 添加头部报?信息
      • Nginx配置
      • 验证头部信息
  • 反向代理示例--多台web服务器
  • 反向代理示例--客户端IP透传
  • 实现动静分离
  • 实现Nginx tcp负载均衡
    • tcp负载均衡配置参数(nginx的tcp负载均衡性能不如HAproxy更不如lvs,所以tcp的负载一般使用HAproxy)
    • tcp负载均衡实例:MySQL
    • tpc负载均衡实例--Redis
  • 实现FastCGI
    • FastCGI配置指令
      • 定义缓存
    • FastCGI示例--Nginx与php-fpm在同?服务器
      • php环境准备
      • php相关配置优化
      • 准备php测试??
      • Nginx配置转发
      • php-fpm 的运?状态??
    • FastCGI示例--Nginx与php不在同?个服务器
      • yum安装较新版本php-fpm (注意php和nginx不在同一个主机)
      • 修改php-fpm监听配置
      • 创建账号
      • 启动并验证php-fpm
      • php准备php测试??
      • Nginx配置转发
  • tengine使?
    • 动态模块
  • 系统参数优化
    • 系统参数优化
  • 待补充

    Nginx安装

    	Nginx的安装版本分为Mainline version(主要开发版本,其实就是还处于开发版)、Stable version(当前最新稳定版)和Legacy versions(旧的稳定版), Nginx安装可以使?yum或源码安装,但是推荐使?源码,?是yulog_not_foundm的版本?较旧,?是编译安装可以更?便?定义相关路径,三是使?源码编译可以?定义相关功能,更?便业务的上的使?,源码安装需要提前准备标准的编译器,GCC的全称是(GNU Compiler collection),其有GNU开发,并以GPL即LGPL许可,是?由的类UNIX即苹果电脑Mac OS X操作系统的标准编译器,因为GCC原本只能处理C语?,所以原名为GNU C语?编译器,后来得到快速发展,可以处理C++,Fortran,pascal,objective-C,java以及Ada等其他语?,此外还需要Automake?具,以完成?动创建Makefile的?作,Nginx的?些模块需要依赖第三?库,?如pcre(?持rewrite),zlib(?持gzip模块)和openssl(?持ssl模块)等。
    

    Nginx yum安装

    # 安装epel源,需要提前配置好epel源
    [root@localhost ~]# yum -y install epel-release
    
    # 安装nginx
    [root@localhost ~]# yum -y install nginx
    
    # 查看nginx包中文件
    [root@localhost ~]# rpm -ql nginx
    ## -q 查询/验证一个软件包
    ## -l 列出软件包中的文件
    
    

    检查安装

    [root@localhost ~]# rpm -qi nginx
    Name(名称)        : nginx
    Epoch(纪元)       : 1
    Version(版本)     : 1.16.1
    Release(发行)     : 3.el7
    Architecture(架构): x86_64
    Install Date(安装日期): 2021年03月23日 星期二 10时51分37秒
    Group(组)       : Unspecified(未指定)
    Size(大小)        : 1694049
    License(执照)     : BSD
    Signature(签名)   : RSA/SHA256, 2020年11月01日 星期日 10时58分48秒, Key ID 6a2faea2352c64e5
    Source RPM(源RPM)  : nginx-1.16.1-3.el7.src.rpm
    Build Date(建立日期)  : 2020年11月01日 星期日 10时02分58秒
    Build Host(构建主机)  : buildhw-x86-09.iad2.fedoraproject.org
    Relocations(搬迁) : (not relocatable)
    Packager(打包程序)    : Fedora Project
    Vendor(供应商)      : Fedora Project
    URL(网址)         : http://nginx.org/
    Bug URL(错误网址)     : https://bugz.fedoraproject.org/nginx
    Summary(摘要)     : A high performance web server and reverse proxy server
    Description(描述) :Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and IMAP protocols, with a strong focus on high concurrency, performance and low memory usage.
    (Nginx是用于HTTP,SMTP,POP3和IMAP协议的Web服务器和反向代理服务器,非常注重高并发性,性能和低内存使用率。 )
    

    查看帮助

    [root@localhost ~]# nginx -h
    -v : show version and exit	# 显示版本并退出 
    -V : show version and configure options then exit #显示版本并配置选项,然后退出 。显示版本和编译参数
    -t : test configuration and exit #测试配置并退出 。测试配置?件是否异常
    -T : test configuration, dump it and exit #测试配置,将其转储并退出 。测试并打印
    -q : suppress non-error messages during configuration testing #在配置测试期间抑制非错误消息 。静默模式
    -s signal : send signal to a master process: stop, quit, reopen,reload #signal:向主进程发送信号:停止,退出,重新打开,重新加载 。发送信号
    -p prefix : set prefix path (default: /usr/share/nginx/) #prefix:设置前缀路径(默认值:/ usr / share / nginx /) 。指定Nginx ?录
    -c filename : set configuration file (default: /etc/nginx/nginx.conf) #filename:设置配置文件(默认值:/etc/nginx/nginx.conf) 。配置?件路径
    -g directives : set global directives out of configuration file #指令:设置全局指令超出配置文件 。设置全局指令
    

    验证Nginx

    # 测试配置文件是否有错误
    [root@localhost ~]# nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
    # 显示nginx版本
    [root@localhost ~]# nginx -v
    nginx version: nginx/1.16.1
    
    # 显示nginx版本,并把配置项显示出来
    [root@localhost ~]# nginx -V
    nginx version: nginx/1.16.1
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.1.1c FIPS  28 May 2019 (running with OpenSSL 1.1.1g FIPS  21 Apr 2020)
    TLS SNI support enabled
    configure arguments: --prefix=/usr/share/nginx 
    					 --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf 
    					 --error-log-path=/var/log/nginx/error.log 
    					 --http-log-path=/var/log/nginx/access.log 
    					 --http-client-body-temp-path=/var/lib/nginx/tmp/client_body 
    					 --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi 
    					 --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi 
    					 --http-scgi-temp-path=/var/lib/nginx/tmp/scgi 
    					 --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx 
    					 --with-file-aio 
    					 --with-ipv6 
    					 --with-http_ssl_module 
    					 --with-http_v2_module 
    					 --with-http_realip_module 
    					 --with-stream_ssl_preread_module 
    					 --with-http_addition_module 
    					 --with-http_xslt_module=dynamic 
    					 --with-http_image_filter_module=dynamic 
    					 --with-http_sub_module 
    					 --with-http_dav_module 
    					 --with-http_flv_module 
    					 --with-http_mp4_module 
    					 --with-http_gunzip_module 
    					 --with-http_gzip_static_module 
    					 --with-http_random_index_module 
    					 --with-http_secure_link_module 
    					 --with-http_degradation_module 
    					 --with-http_slice_module 
    					 --with-http_stub_status_module 
    					 --with-http_perl_module=dynamic 
    					 --with-http_auth_request_module 
    					 --with-mail=dynamic 
    					 --with-mail_ssl_module 
    					 --with-pcre 
    					 --with-pcre-jit 
    					 --with-stream=dynamic 
    					 --with-stream_ssl_module 
    					 --with-google_perftools_module 
    					 --with-debug 
    					 --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' 
    					 --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
    
    

    Nginx启动脚本

    # 查看systemctl的nginx启动脚本
    [root@localhost ~]# cat /usr/lib/systemd/system/nginx.service
    [Unit]
    Description=The nginx HTTP and reverse proxy server
    After=network.target remote-fs.target nss-lookup.target
    
    [Service]
    Type=forking
    PIDFile=/run/nginx.pid
    # Nginx will fail to start if /run/nginx.pid already exists but has the wrong
    # SELinux context. This might happen when running `nginx -t` from the cmdline.
    # https://bugzilla.redhat.com/show_bug.cgi?id=1268621
    ExecStartPre=/usr/bin/rm -f /run/nginx.pid
    ExecStartPre=/usr/sbin/nginx -t
    ExecStart=/usr/sbin/nginx
    ExecReload=/bin/kill -s HUP $MAINPID
    KillSignal=SIGQUIT
    TimeoutStopSec=5
    KillMode=process
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    
    ##  CentOS 7的服务systemctl脚本存放在:/usr/lib/systemd/,有系统(system)和用户(user)之分,即:/usr/lib/systemd/system ,/usr/lib/systemd/user
    ## 每一个服务以.service结尾,一般会分为3部分:[Unit]、[Service]和[Install],就以nginx为例吧,具体内容如下:
    		[Unit]
    			Description : 服务的简单描述
    			Documentation : 服务文档
    			After= : 依赖,仅当依赖的服务启动之后再启动自定义的服务单元
    			Wants字段:表示sshd.service与sshd-keygen.service之间存在"弱依赖"关系,即如果"sshd-keygen.service"启动失败或停止运行,不影响sshd.service继续执行。
    			
    		[Service]
    			Type : 启动类型simple、forking、oneshot、notify、dbus
    					Type=simple(默认值):systemd认为该服务将立即启动。服务进程不会fork。如果该服务要启动其他服务,不要使用此类型启动,除非该服务是socket激活型。 
    					Type=forking:systemd认为当该服务进程fork,且父进程退出后服务启动成功。对于常规的守护进程(daemon),除非你确定此启动方式无法满足需求,使用此类型启动即可。使用此启动类型应同时指定 PIDFile=,以便systemd能够跟踪服务的主进程。
    					Type=oneshot:这一选项适用于只执行一项任务、随后立即退出的服务。可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。 
    					Type=notify:与 Type=simple 相同,但约定服务会在就绪后向 systemd 发送一个信号。这一通知的实现由 libsystemd-daemon.so 提供。 Type=dbus:若以此方式启动,当指定的 BusName 出现在DBus系统总线上时,systemd认为服务就绪。
    			PIDFile : pid文件路径 
    			ExecStartPre :启动前要做什么,上文中是测试配置文件 -t  
    			ExecStart:启动 
    			ExecReload:重载 
    			ExecStop:停止 
    			PrivateTmp:True表示给服务分配独立的临时空间
    		[Install]
    			WantedBy:服务安装的用户模式,从字面上看,就是想要使用这个服务的有是谁?上文中使用的是:multi-user.target ,就是指想要使用这个服务的目录是多用户。「以上全是个人理解,瞎猜的,如有不当,请大家多多指教」每一个.target实际上是链接到我们单位文件的集合,当我们执行:
    
    

    配置Nginx

    默认配置?件:/etc/nginx/nginx.conf,默认配置如下

    [root@localhost ~]#  grep -v "#" /etc/nginx/nginx.conf | grep -v "^$"
    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 {
        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  /var/log/nginx/access.log  main;
        sendfile            on;
        tcp_nopush          on;
        tcp_nodelay         on;
        keepalive_timeout   65;
        types_hash_max_size 2048;
        include             /etc/nginx/mime.types;
        default_type        application/octet-stream;
        include /etc/nginx/conf.d/*.conf;
        server {
            listen       80 default_server;
            listen       [::]:80 default_server;
            server_name  _;
            root         /usr/share/nginx/html;
            include /etc/nginx/default.d/*.conf;
            location / {
            }
            error_page 404 /404.html;
            location = /404.html {
            }
            error_page 500 502 503 504 /50x.html;
            location = /50x.html {
            }
        }
    }
    
    

    启动Nginx

    # 启动服务
    [root@localhost ~]# systemctl start nginx
    
    # 查看服务
    [root@localhost ~]# systemctl status nginx
    ● nginx.service - The nginx HTTP and reverse proxy server
       Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
       Active: active (running) since 二 2021-03-23 15:11:45 CST; 1s ago
      Process: 8450 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
      Process: 8447 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
      Process: 8446 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
     Main PID: 8453 (nginx)
       CGroup: /system.slice/nginx.service
               ├─8453 nginx: master process /usr/sbin/nginx
               └─8454 nginx: worker process
    
    3月 23 15:11:45 localhost.localdomain systemd[1]: Starting The nginx HTTP and reverse proxy server...
    3月 23 15:11:45 localhost.localdomain nginx[8447]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    3月 23 15:11:45 localhost.localdomain nginx[8447]: nginx: configuration file /etc/nginx/nginx.conf test is successful
    3月 23 15:11:45 localhost.localdomain systemd[1]: Failed to read PID from file /run/nginx.pid: Invalid argument
    3月 23 15:11:45 localhost.localdomain systemd[1]: Started The nginx HTTP and reverse proxy server.
    
    # 查看进程(可以看到80端口已开启)
    [root@localhost ~]# ss -tnl
    State      Recv-Q Send-Q               Local Address:Port                              Peer Address:Port              
    LISTEN     0      128                              *:80                                           *:*                  
    LISTEN     0      128                              *:22                                           *:*                  
    LISTEN     0      100                      127.0.0.1:25                                           *:*                  
    LISTEN     0      128                             :::80                                          :::*                  
    LISTEN     0      128                             :::22                                          :::*                  
    LISTEN     0      100                            ::1:25                                          :::*      
    
    # 关闭防火墙
    [root@localhost ~]# systemctl stop firewalld 
    [root@localhost ~]# setenforce 0
    
    
    # 访问nginx
    http://192.168.127.128/
    

    Nginx 编译安装

    准备编译安装的基础环境:

    centos 编译安装的基础环境

    [root@localhost html]# yum install -y vim lrzsz tree screen psmisc lsof tcpdump wget ntpdate gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools iotop bc zip unzip zlib-devel bash-completion nfs utils automake libxml2 libxml2-devel libxslt libxslt-devel perl perl ExtUtils-Embed
    
    # 或
    yum install -y  vim \
    				lrzsz \
                    tree \
                    screen \
                    psmisc \
                    lsof \
                    tcpdump \
                    wget \
                    ntpdate \
                    gcc \
                    gcc-c++ \
                    glibc \
                    glibc-devel \
                    pcre \
                    pcre-devel \
                    openssl \
                    openssl-devel \
                    systemd-devel \
                    net-tools \
                    iotop \
                    bc \
                    zip \
                    unzip \
                    zlib-devel \
                    bash-completion \
                    nfs \
                    utils \
                    automake \
                    libxml2 \
                    libxml2-devel \
                    libxslt \
                    libxslt-devel \
                    perl \
                    perl \
                    ExtUtils-Embed
    
    
    
    	gcc为GNU Compiler Collection的缩写,可以编译C和C++源代码等,它是GNU开发的C和C++以及其他很多种语?的编译器(最早的时候只能编译C,后来很快进化成?个编译多种语?的集合,如Fortran、Pascal、Objective-C、Java、Ada、 Go等。)
    
      	gcc 在编译C++源代码的阶段,只能编译 C++ 源?件,?不能?动和 C++ 程序使?的库链接(编译过程分为编译、链接两个阶段,注意不要和可执??件这个概念搞混,相对可执??件来说有三个重要的概念:编译(compile)、链接(link)、加载(load)。源程序?件被编译成?标?件,多个?标?件连同库被链接成?个最终的可执??件,可执??件被加载到内存中运?)。因此,通常使? g++ 命令来完成 C++ 程序的编译和连接,该程序会?动调? gcc 实现编译。
      
      	gcc-c++ 也能编译C源代码,只不过把会把它当成C++源代码,后缀为.c的,gcc把它当作是C程序,?g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的。
      
      	automake 是?个从Makefile.am?件?动?成Makefile.in的?具。为了?成Makefile.in,automake还需?到perl,由于automake创建的发布完全遵循GNU标准,所以在创建中不需要perl。libtool是?款?便?成各种程序库的?具。
    
      pcre pcre-devel:在Nginx编译需要 PCRE(Perl Compatible Regular Expression),因为Nginx 的Rewrite模块和HTTP 核?模块会使?到PCRE正则表达式语法。
    
      zlip zlib-devel:nginx启?压缩功能的时候,需要此模块的?持。
      
      openssl openssl-devel:开启SSL的时候需要此模块的?持。
      
    

    ubuntu 编译安装的基础环境

    root@jenkins-master:/usr/local/src/nginx-1.16.1# apt -y install gcc libpcre3 libpcre3-dev   zlib1g-dev openssl libssl-dev make
    
    (1)PCRE库
    
    PCRE库支持正则表达式。如果我们在配置文件nginx.conf中使用了正则表达式,那么在编译Nginx时就必须把PCRE库编译进Nginx,因为Nginx的HTTP模块需要靠它来解析正则表达式。另外,pcre-devel是使用PCRE做二次开发时所需要的开发库,包括头文件等,这也是编译Nginx所必须使用的。
    
    
    (2)zlib库
    zlib库用于对HTTP包的内容做gzip格式的压缩,如果我们在nginx.conf中配置了gzip on,并指定对于某些类型(content-type)的HTTP响应使用gzip来进行压缩以减少网络传输量,则在编译时就必须把zlib编译进Nginx。zlib-devel是二次开发所需要的库
    
    
    (3)OpenSSL库
    如果服务器不只是要支持HTTP,还需要在更安全的SSL协议上传输HTTP,那么需要拥有OpenSSL。另外,如果我们想使用MD5、SHA1等散列函数,那么也需要安装它。
    

    安装Nginx

    官?源码包下载地址:https://nginx.org/en/download.html

    # 切换目录,下载到/usr/local/src/
    [root@localhost ~]# cd /usr/local/src
    [root@localhost src]# ls
    
    # 下载二进制包,这里下载的1.18版本的,可以下载最新版本。(二进制包的意思是已经从源码编译到linux平台了)
    [root@localhost nginx-1.18.0]#  wget https://nginx.org/download/nginx-1.18.0.tar.gz
    
    # 解压
    [root@localhost src]# tar xf nginx-1.18.0.tar.gz
    
    # 切换进nginx-1.18.0目录,准备编译
    [root@localhost src]# ls
    nginx-1.18.0  nginx-1.18.0.tar.gz
    
    [root@localhost src]# cd nginx-1.18.0
    [root@localhost nginx-1.18.0]# ls
    auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  man  README  src
    
    
    # 编译
    ## 编译是为了检查系统环境是否符合编译安装的要求,?如是否有gcc编译?具,是否?持编译参数当中的模块,并根据开启的参数等?成Makefile?件为下?步做准备:
    [root@localhost nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && make && make install
    
    # 或
    ./configure --prefix=/apps/nginx \
    			--user=nginx \
    			--group=nginx \
    			--with-http_ssl_module \
    			--with-http_v2_module \
    			--with-http_realip_module \
    			--with-http_stub_status_module \
    			--with-http_gzip_static_module \
    			--with-pcre \
    			--with-stream \
    			--with-stream_ssl_module \
    			--with-stream_realip_module
    
    # --prefix=/apps/nginx # 程序存放的路径,make install时会自动创建
    # make #编译步骤,根据Makefile?件?成相应的模块
    # make install #创建?录,并将?成的模块和?件复制到相应的?录:
    
    # 创建用户,(以普通?户启动nginx)
    [root@localhost nginx-1.18.0]# useradd nginx -s /sbin/nologin -u 2000
    
    
    # 给目录nginx用户权限
    [root@localhost nginx-1.18.0]# chown nginx:nginx -R /apps/nginx/
    
    ################################## 备注:nginx完成安装以后,有四个主要的?录
    ###		conf:该?录中保存了nginx所有的配置?件,其中nginx.conf是nginx服务器的最核?最主要的配置?件,其他的.conf则是?来配置nginx相关的功能的,例如fastcgi功能使?的是fastcgi.conf和fastcgi_params两个?件,配置?件?般都有个样板配置?件,是?件名.default结尾,使?的使?将其复制为并将default去掉即可。
    
    ### 	html:该?录中保存了nginx服务器的web?件,但是可以更改为其他?录保存web?件,另外还有?个50x的web?件是默认的错误??提示??。
    
    ### 	logs:该?录?来保存nginx服务器的访问?志错误?志等?志,logs?录可以放在其他路径,?如/var/logs/nginx??。
    
    ### 	logs:该?录?来保存nginx服务器的访问?志错误?志等?志,logs?录可以放在其他路径,?如/var/logs/nginx??。
    

    验证版本及编译参数

    # 编译安装进了/apps/nginx/目录,在这个目录下找到执行程序
    [root@localhost nginx-1.18.0]# cd /apps/nginx/
    [root@localhost nginx]# ls
    conf  html  logs  sbin
    
    [root@localhost nginx]# ./sbin/nginx -V
    nginx version: nginx/1.18.0
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.0.2k-fips  26 Jan 2017
    TLS SNI support enabled
    configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
    
    

    访问编译安装的nginx web界?

    # 启动nginx
    [root@localhost ~]# cd /apps/nginx/sbin/
    [root@localhost sbin]# ls
    nginx
    
    [root@localhost sbin]# ./nginx
    [root@localhost sbin]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128            *:80                         *:*                  
    LISTEN     0      128            *:22                         *:*                  
    LISTEN     0      100    127.0.0.1:25                         *:*                  
    LISTEN     0      128           :::22                        :::*                  
    LISTEN     0      100          ::1:25                        :::*                  
    
    # 关闭防火墙
    [root@localhost nginx]# systemctl stop firewalld
    [root@localhost nginx]# setenforce 0
    
    # 访问测试
    http://192.168.127.130/
    

    创建Nginx?启动脚本

    Nginx 1.18.0
    # 创建service文件
    [root@localhost sbin]# vi /usr/lib/systemd/system/nginx.service
    [Unit]
    Description=The nginx HTTP and reverse proxy server
    After=network.target remote-fs.target nss-lookup.target
    
    [Service]
    Type=forking
    PIDFile=/apps/nginx/nginx.pid		(修改pid文件路径)
    # Nginx will fail to start if /run/nginx.pid already exists but has the wrong
    # SELinux context. This might happen when running `nginx -t` from the cmdline.
    # https://bugzilla.redhat.com/show_bug.cgi?id=1268621
    ExecStartPre=/usr/bin/rm -f /apps/nginx/nginx.pid	(删除指定的pid路径也要改,否者找不到pid文件)
    ExecStartPre=/apps/nginx/sbin/nginx -t	(测试配置文件格式是否正确)
    ExecStart=/apps/nginx/sbin/nginx	(启动命令的路径)
    ExecReload=/bin/kill -s HUP $MAINPID	(发一个信号)
    KillSignal=SIGQUIT
    TimeoutStopSec=5
    KillMode=process
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    
    # 可以看到pid文件在/apps/nginx/logs下
    [root@localhost ~]# ls /apps/nginx/logs/
    access.log  error.log  nginx.pid
    
    
    # 如果nginx启动了,停止它
    [root@localhost sbin]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128            *:80                         *:*                  
    LISTEN     0      128            *:22                         *:*                  
    LISTEN     0      100    127.0.0.1:25                         *:*                  
    LISTEN     0      128           :::22                        :::*                  
    LISTEN     0      100          ::1:25                        :::*                  
    [root@localhost sbin]# ./nginx -s stop
    [root@localhost sbin]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128            *:22                         *:*                  
    LISTEN     0      100    127.0.0.1:25                         *:*                  
    LISTEN     0      128           :::22                        :::*                  
    LISTEN     0      100          ::1:25                        :::*                  
    # 使用systemctl 启动,验证Nginx?启动脚本
    [root@localhost sbin]# systemctl start nginx
    ## 或
    [root@localhost sbin]#systemctl enable --now nginx
    
    # 查看状态
    [root@localhost sbin]# systemctl status nginx
    ● nginx.service - The nginx HTTP and reverse proxy server
       Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
       Active: active (running) since 二 2021-03-23 16:38:58 CST; 7s ago
      Process: 108061 ExecStart=/apps/nginx/sbin/nginx (code=exited, status=0/SUCCESS)
      Process: 108058 ExecStartPre=/apps/nginx/sbin/nginx -t (code=exited, status=0/SUCCESS)
      Process: 108057 ExecStartPre=/usr/bin/rm -f /apps/nginx/logs/nginx.pid (code=exited, status=0/SUCCESS)
     Main PID: 108063 (nginx)
       CGroup: /system.slice/nginx.service
               ├─108063 nginx: master process /apps/nginx/sbin/nginx
               └─108065 nginx: worker process
    
    3月 23 16:38:58 localhost.localdomain systemd[1]: Starting The nginx HTTP and r....
    3月 23 16:38:58 localhost.localdomain nginx[108058]: nginx: the configuration fi...
    3月 23 16:38:58 localhost.localdomain nginx[108058]: nginx: configuration file /...
    3月 23 16:38:58 localhost.localdomain systemd[1]: Failed to parse PID from file...t
    3月 23 16:38:58 localhost.localdomain systemd[1]: Started The nginx HTTP and re....
    Hint: Some lines were ellipsized, use -l to show in full.
    
    # 启动正常,service文件生效
    [root@localhost sbin]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128            *:80                         *:*                  
    LISTEN     0      128            *:22                         *:*                  
    LISTEN     0      100    127.0.0.1:25                         *:*                  
    LISTEN     0      128           :::22                        :::*                  
    LISTEN     0      100          ::1:25                        :::*                  
    

    配置Nginx

    	Nginx的配置?件的组成部分:
    		主配置?件:nginx.conf,?配置?件 include conf.d/*.conf
    		
    		fastcgi, uwsgi,scgi等协议相关的配置?件
    		
    		mime.types:?持的mime类型,MIME(Multipurpose Internet Mail Extensions)多?途互联?邮件扩展类型,MIME消息能包含?本、图像、?频、视频以及其他应?程序专?的数据,是设定某种扩展名的?件??种应?程序来打开的?式类型,当该扩展名?件被访问的时候,浏览器会?动使?指定应?程序来打开。多?于指定?些客户端?定义的?件名,以及?些媒体?件打开?式。
    	
    		Nginx主配置?件的配置指令?式:
    			directive value [value2 ...];
    		注意:
    			(1) 指令必须以分号结尾
    			(2) ?持使?配置变量
    			    内建变量:由Nginx模块引?,可直接引?
    				?定义变量:由?户使?set命令定义
    				set variable_name value;
    				引?变量:$variable_name
    

    MIME参考?档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_Types

    默认配置?件

    [root@localhost sbin]# grep -v "#" /apps/nginx/conf/nginx.conf | grep -v "^$"
    # 全局配置端,对全局?效,主要设置nginx的启动?户/组,启动的?作进程数量,?作模式,Nginx的PID路径,?志路径等。
    
    #user  nobody;		# 启动nginx的用户,可以有多个选项,前一个为用户,后一个为组。实例:user nginx nginx;
    
    worker_processes  1;	# 启动?作进程数数量
    
    events {	 # events设置块,主要影响nginx服务器与?户的?络连接,?如是否允许同时接受多个?络连接,使?哪种事件驱动模型处理请求,每个?作进程可以同时?持的最?连接数,是否开启对多?作进程下的?络连接进?序列化等。
        worker_connections  1024;	# 设置单个nginx?作进程可以接受的最?并发,作为web服务器的时候最?并发数为worker_connections * worker_processes,作为反向代理的时候为(worker_connections * worker_processes)/2,默认1024太少了,可以调到100000
    }
    
    http {	# http块是Nginx服务器配置中的重要部分,缓存、代理和?志格式定义等绝?多数功能和第三?模块都可以在这设置,http块可以包含多个server块,??个server块中?可以包含多个location块,server块可以配置?件引?、MIME-Type定义、?志?定义、是否启?sendfile、连接超时时间和单个链接的请求上限等。
    
        include       mime.types;	# 导??持的?件类型,在/apps/nginx/conf/mime.types这里可以查看,里面是常见的音频,视频等,比如.conf的配置文件没有定义,这种没有定义的会走default_type进行下载
        
        default_type  application/octet-stream;		# 设置默认的类型,会提示下载不匹配的类型?件,遇到mime.types没有定义的文件,这里下载
        
        sendfile        on;		# 常见的优化选项,一般nginx默认就是打开的,打开是作为静态服务器的时候,提升性能的一种参数,把nginx服务器上的某些文件(纯静态文件)直接返回给用户,不是通过后端服务器响应的,直接在内存中进行拷贝到用户空间缓冲区,不需要进入内核缓冲区拷贝了,而directio直接从磁盘进行拷贝
        
        						#作为web服务器的时候打开sendfile加快静态?件传输,指定是否使?sendfile系统调?来传输?件,sendfile通过DMA(直接内存访问)?式直接访问?件数据,并通过传输协议发送,从?避免了数据在内核缓冲区和?户缓冲区之间的拷?,操作效率很?,被称之为零拷?,硬盘>> kernel buffer (快速拷?到kernel socket buffer) >>协议栈。
        						# DMA(Direct Memory Access)即直接内存访问,DMA是?种完全由硬件执?I/O交换的?作?式,?个处理器可以包含多个DMA控制器,每个控制器有多个DMA通道,以及多条直接与存储器站(memorybank)和外设连接的总线,在很多?性能处理器中集成了两种类型的DMA控制器,第?类通常称为“系统DMA控制器”,可以实现对任何资源(外设和存储器)的访问,第?类称为内部存储器DMA控制器,专??于内部存储器所处位置之间的相互存取操作,即数据交换不经过CPU在不同的内存空间进?拷?可以节省资源copy带来的上线?切换,可以直接在内存和I/O设备之间进?,可以?幅提?CPU性能。
        
        keepalive_timeout  65;	# 一个用户在三次握手,打开网页后,如果不操作等待多长时间释放连接,长连接避免与用户持续的进行三次握手建立连接,但是时间太长也不好,一直连接等待它操作,会影响别的用户的访问。?连接超时时间,单位是秒。后面加一个值会在浏览器端显示等待时长,在页面头文件中可以看到。例如:keepalive_timeout  65 75;
        
        server {	# 设置?个虚拟机主机,可以包含??的全局快,同时也可以包含多个location模块。?如本虚拟机监听的端?、本虚拟机的名称和IP配置,多个server 可以使??个端?,?如都使?80端?提供web服务
        
            listen       80;	# 配置server监听的端?
            
            server_name  localhost;		# 本server的名称,当访问此名称的时候nginx会调?当前serevr内部的配置进程匹配。
            
            location / {	# location其实是server的?个指令,为nginx服务器提供?较多?且灵活的指令,都是在location中体现的,主要是基于nginx接受到的请求字符串,对?户请求的UIL进?匹配,并对特定的指令进?处理,包括地址重定向、数据缓存和应答控制等功能都是在这部分实现,另外很多第三?模块的配置也是在location模块中配置。
            
                root   html;	# 相当于默认??的?录名称,默认是相对路径,可以使?绝对路径配置。
                
                index  index.html index.htm;	# 默认的???件名称
            }
            
            error_page   500 502 503 504  /50x.html;	# 错误??的?件名称
            
            location = /50x.html {		 # location处理对应的不同错误码的??定义到/50x.html,这个跟对应其server中定义的?录下。
                root   html;	# 定义默认??所在的?录
            }
        }
        
    
    # mail {		# 和邮件相关的配置
    #		 ...
    # 		}	# mail 协议相关配置段
    
    
    # stream {		# tcp代理配置,1.9版本以上?持
    # 			...
    # 		} 		# stream 服务器相关配置段
    
    
    #include /apps/nginx/conf.d/*.conf		# 导?其他路径的配置?件,子配置文件
    }
    
    

    Nginx 核?配置详解

    全局配置

    启动Nginx?作进程的数量

    # 修改配置文件,nginx优化
    [root@localhost sbin]# vi /apps/nginx/conf/nginx.conf
    user nginx nginx; #启动Nginx?作进程的?户和组
    
    worker_processes [number | auto]; #启动Nginx?作进程的数量,比如worker_processes 4; 或者worker_processes auto;
    
    worker_cpu_affinity 0001 0010 0100 1000; 	# 将Nginx?作进程绑定到指定的CPU核?,默认Nginx是不进?进程绑定的,绑定并不是意味着当前nginx进程独占以?核?CPU,但是可以保证此进程不会运?在其他核?上,这就极?减少了nginx的?作进程在不同的cpu核?上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务器的性能。
    	# 2核cpu,开启2个进程
    	#	worker_processes     2;
    	#	worker_cpu_affinity 01 10;
    	# 		解释:01表示启用第一个CPU内核,10表示启用第二个CPU内核
    	
    	# 2核cpu,开启4个进程
    	#	worker_processes     2;
    	#	worker_cpu_affinity 01 10;
    	# 		解释:开启了四个进程,它们分别对应着开启2个CPU内核
    	
    	# 4个cpu,开启4个进程
    	# worker_processes     4;
    	# worker_cpu_affinity 0001 0010 0100 1000;
    	# 		解释:0001表示启用第一个CPU内核,0010表示启用第二个CPU内核,依此类推
    	
    	# 4核cpu,开启2个进程
    	# worker_processes     2;
    	# worker_cpu_affinity 0101 1010;
    	# 		解释:0101表示开启第一个和第三个内核,1010表示开启第二个和第四个内核;2个进程对应着四个内核;worker_cpu_affinity配置是写在/etc/nginx/nginx.conf里面的;2核是 01,四核是0001,8核是00000001,有多少个核,就有几位数,1表示该内核开启,0表示该内核关闭。
    	
    	# 8核cpu,开启8个进程
    	# worker_processes     8;
    	# worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
    	# 		解释:0001表示启用第一个CPU内核,0010表示启用第二个CPU内核,依此类推;worker_processes最多开启8个,8个以上性能提升不会再提升了,而且稳定性变得更低,所以8个进程够用了。
    	
    	# 或者 worker_cpu_affinity auto自动绑定
    	
    	# 配置完之后可以重启nginx,用ab工具或者wrk工具,可以进行性能测试,在服务器上执行top,然后按1,就可以看到cpu工作情况,如果多个cpu内核的利用率差不多,就证明nginx已经成功利用了多核cpu,测试结束后,cpu内核的负载都同时降低。
    
    	,
    
    # 启动nginx
    [root@localhost sbin]# systemctl start nginx
    [root@localhost sbin]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
    LISTEN     0      128            *:80                         *:*                  
    LISTEN     0      128            *:22                         *:*                  
    LISTEN     0      100    127.0.0.1:25                         *:*                  
    LISTEN     0      128           :::22                        :::*                  
    LISTEN     0      100          ::1:25                        :::*                  
    
    # 验证,虚拟机开启2个cpu,2个内核,或者1个cpu,4个内核,(可以看到一个工作进程在一个内核中工作,如果没有绑定,在客户端访问nginx的时候,进程和内核会不停的切换,增加cpu调度压力,绑定下来)
    [root@localhost sbin]# ps axo pid,cmd,psr,user | grep nginx
      5001 nginx: master process /apps   0 root
      5002 nginx: worker process         0 nginx
      5003 nginx: worker process         1 nginx
      5004 nginx: worker process         2 nginx
      5005 nginx: worker process         3 nginx
      5629 grep --color=auto nginx       1 root
    
    ## 进程管理ps aux中显示的信息比较详细,但是很多时候我们只想了解其中几项信息,这时候,我们可以使用自定义显示字段
    
    

    错误?志记录配置

    debug 调试
    info 信息,仅是一些基本的讯息说明而已;
    notice 公告,比 info 还需要被注意到的一些信息内容;
    warn warning 或 warn警告,警示讯息,可能有问题,但是还不至于影响到某个 daemon 运作。
    error err 或 error错误, 一些重大的错误讯息,这就要去找原因了。
    crit 暴击,比 error 还要严重的错误信息,crit 是临界点 (critical) 的缩写,已经很严重了!
    alert 警报,警告警告,已经很有问题的等级,比 crit 还要严重!
    emerg emerg 或 panic:疼痛等级,意指系统已经几乎要当机的状态! 很严重的错误信息了。
    
    # 修改配置文件
    [root@localhost sbin]# vi /apps/nginx/conf/nginx.conf
    
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    error_log  logs/error.log  info;
    
    	   # error_log    <FILE>    <LEVEL>;
       	      #  关键字        日志文件   错误日志级别
    
    	   # 关键字:其中关键字error_log不能改变
    	   # 日志文件:可以指定任意存放日志的目录
    	   #  错误日志级别:常见的错误日志级别有[debug | info | notice | warn | error | crit | alert | emerg],级别越高记录的信息越少。
    
    	   #  生产场景一般是 warn | error | crit 这三个级别之一
    	   
    	  # 注意:不要配置info等级较低的级别,会带来大量的磁盘I/O消耗。
    

    pid?件保存路径

    # 修改配置文件
    [root@localhost sbin]# vi /apps/nginx/conf/nginx.conf
    #pid        logs/nginx.pid;
    
    ## 刚安装的时候就是没有,其实在启动 nginx 时自动生成的 里面存放的是 当前 nginx 住进程的 ID 号, pid文件就是一个纯文本文件,里面记录的是进程的pid号
    
    ## 在Linux/Unix下,很多程序比如nginx会启动多个进程,而发信号的时候需要知道要向哪个进程发信号。不同的进程有不同的pid(process id)。将pid写进文件可以使得在发信号时比较简单。比如要重新加载nginx的配置可以这样写:kill -HUP `cat /path/to/nginx.pid`
    
    ## (1) pid文件的内容:pid文件为文本文件,内容只有一行, 记录了该进程的ID。用cat命令可以看到。(2) pid文件的作用:防止进程启动多个副本。只有获得pid文件(固定路径固定文件名)写入权限(F_WRLCK)的进程才能正常启动并把自身的PID写入该文件中。其它同一个程序的多余进程则自动退出。
    
    ### 根据PID文件的内容,准确判断进程是否正在运行,防止意外启动多个进程实例
    
    

    ?作进程nice值,客户端的连接数

    # 修改配置文件
    [root@localhost sbin]# vi /apps/nginx/conf/nginx.conf
    
    # 这两项需要在全局配置中手动添加,可以写在pid下面
    worker_priority 0; #?作进程nice值,-20~19,这个值越低优先值越高,这个值一般不用动,通常我们的服务器要么nginx自己一个服务器,大不了搭个php混合使用,他的程序不会太多,除非你这个服务器上跑了很多很多服务,就希望我的nginx优先级高点可以把这个值改 低点。
    ## 验证进程的优先级
    [root@localhost nginx]# watch -n1 'ps -axo pid,cmd,nice | grep nginx'
    
    
    worker_rlimit_nofile 65536; #这个数字包括Nginx的所有连接(例如与代理服务器的连接等,后端),?不仅仅是与客户端的连接,另?个考虑因素是实际的并发连接数不能超过系统级别的最?打开?件数的限制。这个需要改的多点,默认的65535是有点少了,如果访问量比较大,这个值都是以十万,一百万的改,高了没事,少了不行
    ## 查看同一时间最多可开启的文件数,(-n表示查看同一时间最多可开启的文件数)
    [root@localhost nginx]# ulimit -n
    1024
    
    ### 最大可以开启的文件数是2的20次方1048576,超过这个值是修改不了的,会报错
    [root@localhost nginx]# vi /etc/security/limits.conf 
    [root@localhost ~]# bc
    bc 1.06.95
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
    This is free software with ABSOLUTELY NO WARRANTY.
    For details type `warranty'. 
    2^20
    1048576
    
    ## 修改最大文件数
    ### 临时方式
    [root@localhost ~]# ulimit -n 65536
    
    ### 永久有效,修改配置文件,ulimit -n 65536 追加到/etc/profile这个文件中
    [root@localhost ~]# echo ulimit -n 65536 >> /etc/profile
    # source 不重启立即生效
    [root@localhost ~]# source /etc/profile
    # 验证
    [root@localhost ~]# ulimit -n
    65536
    
    ### 还有一种就是修改配置文件的方法
    # /etc/security/limits.conf
    # 在文件尾部添加如下代码: 
    # 	* soft nofile 65565
    # 	* hard nofile 65565
    
    

    开发调试配置

    # 修改配置文件 
    [root@localhost sbin]# vi /apps/nginx/conf/nginx.conf 
      
    # 下面这两项需要手动添加
    daemon off; # 开启就是off,默认是on,占据当前终端,一直阻塞,前台运?Nginx服务?于测试、docker等环境。
    master_process off|on; # 是否开启Nginx的master-woker?作模式,仅?于开发调试场景。不要上生产,如果off会只有一个主进程,直接响应客户端请求,可以访问但是性能很差。默认是on
    

    事件模型配置参数

    # 修改配置文件 
    [root@localhost sbin]# vi /apps/nginx/conf/nginx.conf 
    
    events { # 事件模型配置参数
     worker_connections 65536; #设置单个?作进程的最?并发连接数,这个需要调高点,除了客户端连接,和后端通信也需要连接,所以一个请求,消耗两个连接。
     
     use epoll; #使?epoll事件驱动,Nginx?持众多的事件驱动,?如select、poll、epoll,只能设置在events模块中设置。有些事件驱动如果想使用,需要在编译的时候添加选项
     
     accept_mutex on; #优化同?时刻只有?个请求?避免多个睡眠进程被唤醒的设置,on为防?被同时唤醒,默认为off,全部唤醒的过程也成为"惊群",因此nginx刚安装完以后要进?适当的优化。
     
     multi_accept on; #Nginx服务器的每个?作进程可以同时接受多个新的?络连接,但是需要在配置?件中配置,此指令默认为关闭,即默认为?个?作进程只能?次接受?个新的?络连接,打开后?个同 时接受多个。这样的话对性能也有些提升。
    }
    

    http详细配置

    # 修改配置文件 
    [root@localhost sbin]# vi /apps/nginx/conf/nginx.conf 
    
    http {
     	include mime.types; #导??持的?件类型
     	default_type application/octet-stream; #设置默认的类型,会提示下载不匹配的类型?件
     
    
    #?志配置部分
    	 #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    	 # '$status $body_bytes_sent "$http_referer" '
    	 # '"$http_user_agent" "$http_x_forwarded_for"';
     	#access_log logs/access.log main;
     
     
    #?定义优化参数
    	 sendfile on; #实现?件零拷?
    	 #tcp_nopush on; #在开启了sendfile的情况下,合并请求后统?发送给客户端。因为一些文件很小,只有几个字节,或者很小很小的文件,这些请求,nginx会把他合并成一个报文,统一向客户端响应,这个可以打开,这个有好处也有坏处,好处就是节约带宽,可以在一个响应中封装多个报文.坏处就是它有延迟,如果他这个文件没有返回过来,那这个时候只能等一会,等文件从磁盘拷过来在向客户端返回,,所以可能会导致客户端体验变得不好,这就需要看怎么衡量了
    	 #tcp_nodelay off; #在开启了keepalived模式下的连接是否启?TCP_NODELAY选项,当为off时,延迟0.2s发送,默认On时,不延迟发送,?即发送?户相应报?。在keepalived模式下建议打开,没有延迟,客户端方面会体验比较好,这种访问量不是很大没什么事,但是一旦到上万的并发的时候,那就问题出来了,这个问题
     
     	#keepalive_timeout 0;
    	 keepalive_timeout 65 65; #设置会话保持时间
    	 #gzip on; #开启?件压缩
      
     server {
    	 listen 80; #设置监听地址和端?
     
    	 server_name localhost; #设置server name(域名),可以以空格隔开写多个,并?持正则表达式,如*.helloworld.com www.helloworld.* www.(site\d+)\helloworld\.com$ default_server,其中default_server表示默认域名,也就是说当你访问nginx之后,如果说nginx所有的域名都不匹配,就会显示default_server当中的字段了,他就相当于默认域名一样了
    	 
     charset koi8-r; 	# 设置编码格式,默认是俄语格式,可以改为utf-8,否者中文会乱码 
     
     #access_log logs/host.access.log main;
     location / {
     root html;
     index index.html index.htm;
     }
     #error_page 404 /404.html;
     # redirect server error pages to the static page /50x.html
     #
     error_page 500 502 503 504 /50x.html; #定义错误??
     location = /50x.html {
     root html;
     }
     # proxy the PHP scripts to Apache listening on 127.0.0.1:80
     #
     #location ~ \.php$ { #以http的?式转发php请求到指定web服务器
     # proxy_pass http://127.0.0.1;
     #}
     # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
     #
     #location ~ \.php$ { #以fastcgi的?式转发php请求到php处理
     # root html;
     # fastcgi_pass 127.0.0.1:9000;
     # fastcgi_index index.php;
     # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
     # include fastcgi_params;
     #}
     # deny access to .htaccess files, if Apache's document root
     # concurs with nginx's one
     #
     #location ~ /\.ht { #拒绝web形式访问指定?件,如很多的?站都是通过.htaccess?
    件来改变??的重定向等功能。
     # deny all;
     #}
     location ~ /passwd.html {
     deny all;
     }
     }
     # another virtual host using mix of IP-, name-, and port-based
    configuration
     #
     
     #server { #?定义虚拟server
     # listen 8000;
     # listen somename:8080;
     # server_name somename alias another.alias;
     # location / {
     # root html;
     # index index.html index.htm; #指定默认???件,此指令由
    ngx_http_index_module模块提供
     # }
     #}
     # HTTPS server
     #
     #server { #https服务器配置
     # listen 443 ssl;
     # server_name localhost;
     # 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;
     # index index.html index.htm;
     # }
     location /linux38/passwd.ht {
     deny all;
     }
     #}
    

    核?配置示例

    基于不同的IP、不同的端?以及不?得域名实现不同的虚拟主机,依赖于核?模块
    ngx_http_core_module实现。

    新建?个PC web站点

    # 创建目录
    [root@localhost nginx]# mkdir /apps/nginx/conf/conf.d
    
    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    	listen 80;
    	 server_name www.helloworld.net;
    	 
     	location / {
     	     index index.html;
     		 root /data/nginx/html/pc;
     }
    }
    
    # 创建pc测试页目录
    [root@localhost sbin]# mkdir -pv /data/nginx/html/pc
    mkdir: 已创建目录 "/data"
    mkdir: 已创建目录 "/data/nginx"
    mkdir: 已创建目录 "/data/nginx/html"
    mkdir: 已创建目录 "/data/nginx/html/pc"
    
    # 创建测试页
    [root@localhost nginx]# echo "pc web" > /data/nginx/html/pc/index.html
    [root@localhost nginx]# cat /data/nginx/html/pc/index.html 
    pc web
    
    # 修改全局配置项,导?其他路径的配置?件,添加此项,可以写在最后
    [root@localhost nginx]# vi /apps/nginx/conf/nginx.conf
    http{
    	server{
    	
    	...
    	
    	}
    include /apps/nginx/conf/conf.d/*.conf;
    }
    
    
    # 重载nginx配置文件
    [root@s2 ~]# systemctl reload nginx
    
    #客户端编辑host文件,访问测试(访问成功,客户端已关闭防火墙)
    [root@localhost ~]# vi /etc/hosts
    192.168.127.130  www.helloworld.net
    
    [root@localhost ~]# curl www.helloworld.net
    pc web
    
    

    新建?个Mobile web站点

    # 编写配置文件
    [root@localhost sbin]# vi /apps/nginx/conf/conf.d/mobile.conf
    server {
            listen 80;
            server_name mobile.helloworld.net;
            location / {
                    root /data/nginx/html/mobile;
            }
    }
    
    # 创建mobile测试页目录
    [root@localhost sbin]# mkdir -pv /data/nginx/html/mobile
    mkdir: 已创建目录 "/data/nginx/html/mobile"
    
    
    # 创建测试页
    [root@localhost sbin]# echo "mobile web" >> /data/nginx/html/mobile/index.html
    [root@localhost sbin]# cat /data/nginx/html/mobile/index.html
    mobile web
    
    # 重载nginx配置文件
    [root@localhost sbin]# systemctl reload nginx
    
    #客户端编辑host文件,访问测试(访问成功,客户端已关闭防火墙)
    [root@localhost ~]# vi /etc/hosts
    192.168.127.130  www.helloworld.net
    192.168.127.130  mobile.helloworld.net
    
    [root@localhost ~]# curl mobile.helloworld.net
    mobile web
    

    root与alias

    root:指定web的家?录,在定义location的时候,?件的绝对路径等于 root+location,如:

    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    	listen 80;
    	 server_name www.helloworld.net;
    	 
     	location / {
     		root /data/nginx/html/pc;
    		 }
     
    
            location /linux {
                    root /data/nginx/html/pc;	# 必须要在html?录中创建?个about?录才可以访问,否则报错。访问时root+location的意思就是www.helloworld.net/linux/,如果location /linux这里是location /linux/访问的时候就不用加www.helloworld.net/linux最后的斜杠
                    index index.html;
          	  }
    
    }
    
    # 创建测试页目录
    [root@localhost sbin]# mkdir -pv /data/nginx/html/pc/linux
    mkdir: 已创建目录 "/data/nginx/html/pc/linux"
    
    # 创建测试页
    [root@localhost sbin]# cat /data/nginx/html/pc/linux/index.html
    linux
    
    # 重载nginx配置文件
    [root@localhost sbin]# systemctl reload nginx
    
    # 访问测试
    [root@localhost sbin]# curl www.helloworld.net/linux/
    linux
    
    

    alias:定义路径别名,会把访问的路径重新定义到其指定的路径,如:

    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
            }
            location /linux {
                    alias /data/nginx/html/pc;
                    # root /data/nginx/html/pc;
                    index index.html;
            }
    }
    
    # 重载nginx配置文件
    [root@localhost sbin]# systemctl reload nginx
    
    # 检测配置文件
    [root@localhost sbin]# cat /data/nginx/html/pc/linux/index.html 
    linux
    [root@localhost sbin]# cat /data/nginx/html/pc/index.html 
    pc web
    
    
    # 访问测试(可以看到我们加了/linux下的index.html它以然访问的是pc web)
    [root@localhost sbin]# curl www.helloworld.net/linux/index.html
    pc web
    
    

    location的详细使?

    	在没有使?正则表达式的时候,nginx会先在server中的多个location选取匹配度最?的?个uri,uri是?户请求的字符串,即域名后?的web?件路径,然后使?该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使?此location处理此请求。
    	
    		语法规则: location [=|~|~*|^~] /uri/ { … }
    		
    		= #?于标准uri前,需要请求字串与uri精确匹配,如果匹配成功就停?向下匹配并?即处理请求(只有请求的url路径与后面的字符串完全相等时,才会命中。)。
    		~ #?于标准uri前,表示包含正则表达式并且区分??写,并且匹配
    		!~ #?于标准uri前,表示包含正则表达式并且区分??写,并且不匹配
    		~* #?于标准uri前,表示包含正则表达式并且不区分?写,并且匹配
    		!~* #?于标准uri前,表示包含正则表达式并且不区分??写,并且不匹配
    		^~ #?于标准uri前,表示包含正则表达式并且匹配以什么开头
    		$ #?于标准uri前,表示包含正则表达式并且匹配以什么结尾
    		\ #?于标准uri前,表示包含正则表达式并且转义字符。可以转. * ?等
    		* #?于标准uri前,表示包含正则表达式并且代表任意?度的任意字符
    

    匹配案例-精确匹配

    在普通匹配模式中,还可以细分出一种叫精准匹配模式,也就是通过等于号直接来匹配的(只有请求的url路径与后面的字符串完全相等时,才会命中。)

    参考:https://cloud.tencent.com/developer/article/1631087
    
    location =/demo {
        root  html; 
        index gp.html;
    }
    location /demo {
       root   html;
       index  demo.html;
    }
    
    我们继续沿着上面的案例来添加一个基于 location =/demo的匹配规则,那么这个时候的匹配就是精准匹配。精准匹配和普通匹配的差异在哪里呢?以及匹配顺序是什么样的?
     http://localhost/demo √
     http://localhost/demo/demo.html √
     http://localhost/demo/gp.html √ (精准匹配)
     但是在此处并不能证明此处是精准匹配
     
     #################################################
     
     #location =/demo {
     #   root  html; 
      #  index gp.html;
    #}
    location /demo {
       root   html;
       index  demo.html;
    }
    
    把精准匹配注释掉
     http://localhost/demo √
     http://localhost/demo/demo.html √
     http://localhost/demo/gp.html √ (普通匹配)
     
    #################################################
     
    location =/demo {
        root  html; 
        index gp.html;
    }
    #location /demo {
     #  root   html;
      # index  demo.html;
    #}
    
    我们把普通匹配注释掉发现:
     http://localhost/demo ×
     http://localhost/demo/demo.html √
     http://localhost/demo/gp.html √
     第一种方式访问不了。但这也证明不了精准匹配的优先级比普通匹配高,这时我们可以这样设置
     
    #################################################
    
    location =/index.html {  # 精准匹配
        root  html/gp1;
        index index.html;
    }
    location /index.html {  # 普通匹配
        root html/gp2;
        index index.html;
    }
    
    然后我们再访问:
    www.helloworld.net/index.html
    gp1111
    访问到的是gp1目录中的,说明普通匹配没起作用。
    
    #########################################下面是示例
    
    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            
            location / {
                    root /data/nginx/html/pc;
            }
    
            location = /1.gif {
                    root /var/www/nginx/images;
                    index index.html;
            }
    }
    
    # 创建图片目录
    [root@localhost sbin]# mkdir -pv /var/www/nginx/images
    mkdir: 已创建目录 "/var/www"
    mkdir: 已创建目录 "/var/www/nginx"
    mkdir: 已创建目录 "/var/www/nginx/images"
    
    
    # 上传图片到/var/www/nginx/images
    [root@localhost sbin]# wget -P /var/www/nginx/images/  http://wx3.sinaimg.cn/large/ceeb653ely1foavre7v77g209q070n43.gif
    
    # 图片改一下名字
    [root@localhost sbin]# mv  /var/www/nginx/images/ceeb653ely1foavre7v77g209q070n43.gif /var/www/nginx/images/1.gif
    
    [root@localhost sbin]# ls  /var/www/nginx/images/
    1.gif
    
    
    # 重载nginx
    [root@localhost sbin]# systemctl reload nginx
    
    
    # 访问测试(精确匹配到了1.gif的location显示图片)
    http://www.helloworld.net/1.gif
    

    匹配案例-区分??写

    如果uri中包含?写字?,则以下location匹配Ax.jpg条件不成功,因为~为区分??写,那么当?户的请求被执?匹配时发现location中定义的是?写的A,则匹配失败,即要么继续往下匹配其他的location(如果有),要么报错给客户端。

    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location ~ /A.?\.gif {		# ~表示区分大小写,匹配大写A开头的图片,?表示0个字符或1个字
                    root /var/www/nginx/images;
                    index index.html;
            }
    }
    
    
    # 修改图片文件名
    [root@www ~]# mv /var/www/nginx/images/1.gif /var/www/nginx/images/Ab.gif
    [root@www ~]# ls /var/www/nginx/images/
    Ab.gif
    
    
    # 重载nginx
    [root@localhost sbin]# systemctl reload nginx
    
    # 访问测试(访问正常)
    http://www.helloworld.net/Ab.gif
    
    # 访问测试(换成小写的a就找不到了,看一下日志,可以看到他去找/data/nginx/html/pc/ab.gif这个文件,没有这个文件)
    http://www.helloworld.net/ab.gif
    
    [root@www ~]# cat /apps/nginx/logs/error.log 
    2021/03/23 22:07:07 [error] 4083#0: *43 open() "/data/nginx/html/pc/ab.gif" failed (2: No such file or directory), client: 192.168.127.1, server: www.helloworld.net, request: "GET /ab.gif HTTP/1.1", host: "www.helloworld.net"
    
    

    匹配案例-不区分??写

    对?户请求的uri做模糊匹配,也就是uri中?论都是?写、都是?写或者??写混合,此模式也都会匹配,通常使?此模式匹配?户request中的静态资源并继续做下?步操作。

    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
            }
    
    #       location ~ /A.?\.gif {
    #               root /var/www/nginx/images;
    #               index index.html;
    #       }
    
            location ~* /A.?\.gif {
                    root /var/www/nginx/images;
                    index index.html;
            }
    
    
    }
    
    # 创建大写的Ab.gif和小写的ab.gif,在nginx上做匹配但是需要有这个文件,他只是在uri匹配中不区分大小写了,文件还是要有的
    [root@www sbin]# cp /var/www/nginx/images/Ab.gif  /var/www/nginx/images/ab.gif 
    
    
    # 查看图片名
    [root@www sbin]# ls  /var/www/nginx/images
    ab.gif  Ab.gif
    
    
    # 重载nginx
    [root@localhost sbin]# systemctl reload nginx
    
    # 访问测试(他只是在url匹配中不区分大小写了,访问正常)
    http://www.helloworld.net/Ab.gif
    http://www.helloworld.net/ab.gif
    
    
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~~~~
    精确匹配指定名称:
    # location ~ /aa.jpg {
    # index index.html;
    # root /opt/nginx/html/image;
    # }
     location ~* /aa.jpg {
     index index.html;
     root /opt/nginx/html/image;
     }
     
     # 重启Nginx并访问测试
    
     	# 注意:对于不区分??写的location,则可以访问任意??写结尾的图??件,如区分??写则只能访问aa.jpg,不区分??写则可以访问aa.jpg以外的资源?如Aa.JPG、aA.jPG这样的混合名称?件,但是要求nginx服务器的资源?录有相应的?件,?如有Aa.JPG有aA.jPG。
     	
     	# 重点:
    		# Nginx匹配?次?件名是否区分??写
    		# Nginx可以在服务器找到指定的资源
    

    匹配案例-URI开始

    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
    
    
            location ^~ /images {
                    root /data/nginx;
                    index index.html;
            }
    
    #        location  /images1/ {		# 这个没有什么意思,在/data/nginx/html/pc这个目录下创建一个images1文件,下面有一个index.html文件就可以了。前面做过
    #                root /data/nginx/html/pc;
    #                index index.html;
    #        }
    
    # 创建文件
    ## /images1/ 这个下的目录可以不创建
    # [root@www ~]#  mkdir /data/nginx/html/pc/images1
    # [root@www ~]# echo  /data/nginx/html/pc/images1 > /data/nginx/html/pc/images1/index.html
    # [root@www ~]# cat /data/nginx/html/pc/images1/index.html
    
    [root@www ~]# mkdir -pv /data/nginx/images/
    [root@www ~]# echo  /data/nginx/images/ > /data/nginx/images/index.html
    [root@www ~]# cat /data/nginx/images/index.html
    /data/nginx/images/
    
    
            
    # 重载nginx
    [root@localhost sbin]# systemctl reload nginx
    
    # 访问测试
    [root@www ~]# curl www.helloworld.net/images/
    /data/nginx/images/
    
    [root@www ~]# curl www.helloworld.net/images1/
    /data/nginx/html/pc/images1
    
    

    匹配案例-?件名后缀

    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js)$ {		# 前面的~*表示匹配不区分大小写的uri,	\. 转义表示一点开始(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js)$表示文件名
                    root /data/nginx/images1;
                    index index.html;
            }
    }
    
    
    # 创建文件,每一个后缀对应一个文件
    [root@www ~]# mkdir -pv /data/nginx/images1
    [root@www ~]# ls /var/www/nginx/images/
    ab.gif  Ab.gif  
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.jpg
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.jpeg
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.bmp
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.png
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.tiff
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.tif
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.ico
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.wmf
    [root@www ~]# cp /var/www/nginx/images/ab.gif /data/nginx/images1/ab.js
    
    
    # 重载nginx
    [root@localhost sbin]# systemctl reload nginx
    
    # 访问测试
    http://www.helloworld.net/Ab.gif
    http://www.helloworld.net/ab.jpg
    http://www.helloworld.net/ab.jpeg
    http://www.helloworld.net/ab.bmp	(会下载文件)
    http://www.helloworld.net/ab.tiff	(会下载文件)
    http://www.helloworld.net/ab.ico
    http://www.helloworld.net/ab.wmf	(会下载文件)
    http://www.helloworld.net/ab.js		(会识别成js文件显示,如果是图片会显示乱码)
    
    

    匹配案例-优先级

    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location ~* /A.gif {
                    root /data/nginx/pc/html/linux38/images;
                    index index.html;
            }
    
            location = /A.gif {	# 等于号用于精确匹配
                    index index.html;
                    root /data/nginx/pc/html/python/images;
            }
    }
    
    ## 匹配优先级:=, ^~, ~/~*,/
    
    ## location优先级:(location =) > (location 完整路径) > (location ^~ 路径) >
    (location ~,~* 正则顺序) > (location 部分起始路径) > (/)
    
    # 创建目录
    [root@www ~]# mkdir -pv /data/nginx/pc/html/linux38/images
    mkdir: 已创建目录 "/data/nginx/pc"
    mkdir: 已创建目录 "/data/nginx/pc/html"
    mkdir: 已创建目录 "/data/nginx/pc/html/linux38"
    mkdir: 已创建目录 "/data/nginx/pc/html/linux38/images"
    [root@www ~]# mkdir -pv /data/nginx/pc/html/python/images
    mkdir: 已创建目录 "/data/nginx/pc/html/python"
    mkdir: 已创建目录 "/data/nginx/pc/html/python/images"
    
    
    # 创建测试页,两个路径下的测试页不一致,区分出效果
    wget -P /data/nginx/pc/html/linux38/images  http://wx3.sinaimg.cn/large/ceeb653ely1foavre7v77g209q070n43.gif
    
    wget -P /data/nginx/pc/html/python/images https://img.fun48.com/201809/25/15379167735l8RB0Qm.gif.webp
    
    # 改一下名字
     mv /data/nginx/pc/html/python/images/15379167735l8RB0Qm.gif.webp /data/nginx/pc/html/python/images/A.gif
    
    mv /data/nginx/pc/html/linux38/images/ceeb653ely1foavre7v77g209q070n43.gif /data/nginx/pc/html/linux38/images/A.gif
    
    
    [root@www ~]# ls /data/nginx/pc/html/linux38/images/
    A.gif
    [root@www ~]# ls /data/nginx/pc/html/python/images/
    A.gif
    
    
    # 重载nginx
    [root@localhost sbin]# systemctl reload nginx
    
    
    # 访问测试(可以看到访问的是/data/nginx/pc/html/python/images/
    下的A.gif,可以看到“=”等于号精确匹配的优先级要大于“~*”正则匹配的优先级)
    http://www.helloworld.net/A.gif
    
    

    ?产使?案例

    直接匹配?站根会加速Nginx访问处理:
    location = /index.html {	#精确匹配首页
     ......;
    }
    location / {
     ......;
    }
    
    
    静态资源配置:
    location ^~ /static/ {
     ......;
    }
    
    # 或者
    location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
     ......;
    }
    
    
    多应?配置
    location ~* /app1 {
     ......;
    }
    location ~* /app2 {
     ......;
    }
    

    Nginx 四层访问控制

    访问控制基于模块ngx_http_access_module实现,可以通过匹配客户端源IP地址进?限制。

    # 查看nginx默认安装的模块	(文件在解压缩的文件夹下)
    
    [root@www ~]# cat /usr/local/src/nginx-1.18.0/auto/options  | grep YES
    HTTP=YES
    HTTP_CACHE=YES
    HTTP_CHARSET=YES
    HTTP_GZIP=YES
    HTTP_SSI=YES
    HTTP_ACCESS=YES
    HTTP_AUTH_BASIC=YES
    HTTP_MIRROR=YES
    HTTP_USERID=YES
    HTTP_AUTOINDEX=YES
    HTTP_GEO=YES
    HTTP_MAP=YES
    HTTP_SPLIT_CLIENTS=YES
    HTTP_REFERER=YES
    HTTP_REWRITE=YES
    HTTP_PROXY=YES
    HTTP_FASTCGI=YES
    HTTP_UWSGI=YES
    HTTP_SCGI=YES
    HTTP_GRPC=YES
    HTTP_MEMCACHED=YES
    HTTP_LIMIT_CONN=YES
    HTTP_LIMIT_REQ=YES
    HTTP_EMPTY_GIF=YES
    HTTP_BROWSER=YES
    HTTP_UPSTREAM_HASH=YES
    HTTP_UPSTREAM_IP_HASH=YES
    HTTP_UPSTREAM_LEAST_CONN=YES
    HTTP_UPSTREAM_RANDOM=YES
    HTTP_UPSTREAM_KEEPALIVE=YES
    HTTP_UPSTREAM_ZONE=YES
    MAIL_POP3=YES
    MAIL_IMAP=YES
    MAIL_SMTP=YES
    STREAM_LIMIT_CONN=YES
    STREAM_ACCESS=YES
    STREAM_GEO=YES
    STREAM_MAP=YES
    STREAM_SPLIT_CLIENTS=YES
    STREAM_RETURN=YES
    STREAM_UPSTREAM_HASH=YES
    STREAM_UPSTREAM_LEAST_CONN=YES
    STREAM_UPSTREAM_RANDOM=YES
    STREAM_UPSTREAM_ZONE=YES
            --with-select_module)            EVENT_SELECT=YES           ;;
            --with-poll_module)              EVENT_POLL=YES             ;;
            --with-threads)                  USE_THREADS=YES            ;;
            --with-file-aio)                 NGX_FILE_AIO=YES           ;;
            --with-http_ssl_module)          HTTP_SSL=YES               ;;
            --with-http_v2_module)           HTTP_V2=YES                ;;
            --with-http_realip_module)       HTTP_REALIP=YES            ;;
            --with-http_addition_module)     HTTP_ADDITION=YES          ;;
            --with-http_xslt_module)         HTTP_XSLT=YES              ;;
            --with-http_image_filter_module) HTTP_IMAGE_FILTER=YES      ;;
            --with-http_geoip_module)        HTTP_GEOIP=YES             ;;
            --with-http_sub_module)          HTTP_SUB=YES               ;;
            --with-http_dav_module)          HTTP_DAV=YES               ;;
            --with-http_flv_module)          HTTP_FLV=YES               ;;
            --with-http_mp4_module)          HTTP_MP4=YES               ;;
            --with-http_gunzip_module)       HTTP_GUNZIP=YES            ;;
            --with-http_gzip_static_module)  HTTP_GZIP_STATIC=YES       ;;
            --with-http_auth_request_module) HTTP_AUTH_REQUEST=YES      ;;
            --with-http_random_index_module) HTTP_RANDOM_INDEX=YES      ;;
            --with-http_secure_link_module)  HTTP_SECURE_LINK=YES       ;;
            --with-http_degradation_module)  HTTP_DEGRADATION=YES       ;;
            --with-http_slice_module)        HTTP_SLICE=YES             ;;
            --with-http_perl_module)         HTTP_PERL=YES              ;;
            --with-http_stub_status_module)  HTTP_STUB_STATUS=YES       ;;
            --with-mail)                     MAIL=YES                   ;;
            --with-mail_ssl_module)          MAIL_SSL=YES               ;;
                MAIL=YES
                MAIL_SSL=YES
            --with-stream)                   STREAM=YES                 ;;
            --with-stream_ssl_module)        STREAM_SSL=YES             ;;
            --with-stream_realip_module)     STREAM_REALIP=YES          ;;
            --with-stream_geoip_module)      STREAM_GEOIP=YES           ;;
                                             STREAM_SSL_PREREAD=YES     ;;
            --with-google_perftools_module)  NGX_GOOGLE_PERFTOOLS=YES   ;;
            --with-cpp_test_module)          NGX_CPP_TEST=YES           ;;
            --with-compat)                   NGX_COMPAT=YES             ;;
            --with-debug)                    NGX_DEBUG=YES              ;;
            --with-pcre)                     USE_PCRE=YES               ;;
            --with-pcre-jit)                 PCRE_JIT=YES               ;;
            --with-libatomic)                NGX_LIBATOMIC=YES          ;;
            --test-build-devpoll)            NGX_TEST_BUILD_DEVPOLL=YES ;;
            --test-build-eventport)          NGX_TEST_BUILD_EVENTPORT=YES ;;
            --test-build-epoll)              NGX_TEST_BUILD_EPOLL=YES   ;;
            --test-build-solaris-sendfilev)  NGX_TEST_BUILD_SOLARIS_SENDFILEV=YES ;;
    
    
    # 查看自己添加的模块、编译时附带的可选模块或三方模块
    
    [root@www ~]# /apps/nginx/sbin/nginx -V
    nginx version: nginx/1.18.0
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.0.2k-fips  26 Jan 2017
    TLS SNI support enabled
    configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
    
    
    # 可以看到--without-http_access_module次功能没有开启(通过测试发现不用开启)
    [root@www ~]# cat /usr/local/src/nginx-1.18.0/auto/options | grep 'without-http_access_module)    HTTP_ACCESS='
            --without-http_access_module)    HTTP_ACCESS=NO             ;;
    
    
    # 编写配置文件
    [root@localhost nginx]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location ~* /A.gif {
                    root /data/nginx/pc/html/python/images;
                    index index.html;
            }
    
            location = /A.gif {
                    index index.html;
                    root /data/nginx/pc/html/linux38/images;
                    deny    192.168.127.128;	# 拒绝一个地址访问
                    allow   192.168.127.0/24;	# 允许这个地址段访问
                    allow   10.1.1.0/16;	# 允许这个地址段访问
                    allow   2001:0db8::/32;	# 允许ipv6的这个地址段访问
                    deny all;	# 白名单,先允许一小部分,在拒绝一大部分
            }
    }
    
    # 重载nginx
    [root@www ~]# systemctl reload nginx
    
    # 测试
    http://www.helloworld.net/A.gif
    
    ## 查看日志(可以看到192.168.127.1这个ip通过了allow   192.168.127.0/24;这条访问控制。可以访问)
    [root@www ~]# cat /apps/nginx/logs/access.log 
    192.168.127.1 - - [24/Mar/2021:13:38:47 +0800] "GET /A.gif HTTP/1.1" 200 265893 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.57"
    
    # 测试
    [root@localhost ~]# curl www.helloworld.net/A.gif
    <html>
    <head><title>403 Forbidden</title></head>
    <body>
    <center><h1>403 Forbidden</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    
    ## 查看日志(可以看到access forbidden by rule, client客户端禁止访问,192.168.127.128这个ip没有通过deny    192.168.127.128这条访问控制,拒绝了这个ip访问)
    [root@www ~]# cat /apps/nginx/logs/error.log 
    2021/03/24 13:41:26 [error] 25301#0: *5 access forbidden by rule, client: 192.168.127.128, server: www.helloworld.net, request: "GET /A.gif HTTP/1.1", host: "www.helloworld.net"
    
    

    Nginx账户认证功能

    # 安装htpasswd命令 是Apache的Web服务器内置工具,用于创建和更新储存用户名、域和用户基本认证的密码文件。
    ## centos安装
    [root@www ~]# yum -y install httpd-tools
    
    ## ubuntu安装
    [root@www ~]# apt install apache2-utils
    
    
    # 用htpasswd命令创建用户,在/apps/nginx/conf/创建一个隐藏文件.htpasswd,给上用户名和密码,进行加密保存
    [root@www ~]# htpasswd -cbm /apps/nginx/conf/.htpasswd user1 123456
    Adding password for user user1
    
    [root@www ~]# htpasswd -bm /apps/nginx/conf/.htpasswd user2 123456
    Adding password for user user2
    
    ## -c:创建一个加密文件
    ## -b:使用命令行中的密码而不是提示输入密码
    ## -m:默认采用MD5算法对密码进行加密,默认的所以不添加-m也行
    
    
    # 查看生成的密码
    [root@www ~]# tail /apps/nginx/conf/.htpasswd 
    user1:$apr1$8/XJHL5B$/vcdooOQUKELQISMzm929.
    user2:$apr1$vdtEMh1U$WDQVRhENNkw5lLIN6In/01
    
    # 编辑配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
            listen 80;
            server_name www.helloworld.net;
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location ~* /A.gif {
                    root /data/nginx/pc/html/python/images;
                    index index.html;
            }
    
            location = /A.gif {
                    index index.html;
                    root /data/nginx/pc/html/linux38/images;
                    deny    192.168.127.128;
                    allow   192.168.127.0/24;
                    allow   2001:0db8::/32;
                    deny all;
            }
            location = /login/ {	# 等于号精准匹配,可以加和可以不加,优先级会高
                    root /data/nginx/html/pc;
                    index index.html;
                    auth_basic      "login password";
                    auth_basic_user_file    /apps/nginx/conf/.htpasswd;
            }
    }
    
    
    
    ## auth_basic		允许通过使用“HTTP 基本身份验证”(HTTP Basic Authentication)协议验证用户名和密码来限制对资源的访问。auth_basic string这个string表示认证提示字符串,表示解释说明的字符串  auth_basic off特殊值off取消了auth_basic从先前配置级别继承的指令的效果(也就是表示关闭登入校验)。
    
    ## auth_basic_user_file		指定保存用户名密码的文件,这个文件权限最好是600,或者仅允许某些用户访问,由于保存的是密码不要让别的用户查看,不是600也没关系不影响使用
    
    
    # 创建目录,创建测试页
    [root@www ~]# mkdir -pv  /data/nginx/html/pc/login/
    mkdir: 已创建目录 "/data/nginx/html/pc/login/"
    
    [root@www ~]# echo  /data/nginx/html/pc/login/ > /data/nginx/html/pc/login/index.html
    [root@www ~]# cat /data/nginx/html/pc/login/index.html
    /data/nginx/html/pc/login/
    
    
    
    # 重载nginx
    [root@www ~]# systemctl reload nginx
    
    # 访问测试,登陆用户名,密码
    http://www.helloworld.net/login/
    

    ?定义错误??

    # 编辑配置文件,自定义错误页面定义在server中
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
            listen 80;
            server_name www.helloworld.net;
            error_page 500 502 503 504 404 /error.html;		# error_page指令的作用是当发生错误的时候,这些错误状态码可以自己定义,能够显示一个预定义的uri的内容,这里是/error.html,它会找到/error.html的location,显示这个location中定义的信息,比如错误页面。
    
             location = /error.html {
                    root html;	# 查看日志可以看到它的绝对路径是/apps/nginx/html下,需要在这个路径下创建一个error.html
            }
    
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location ~* /A.gif {
                    root /data/nginx/pc/html/python/images;
                    index index.html;
            }
    
            location = /A.gif {
                    index index.html;
                    root /data/nginx/pc/html/linux38/images;
                    deny    192.168.127.128;
                    allow   192.168.127.0/24;
                    allow   2001:0db8::/32;
                    deny all;
            }
            location = /login/ {
                    root /data/nginx/html/pc;
                    index index.html;
                    auth_basic      "login password";
                    auth_basic_user_file    /apps/nginx/conf/.htpasswd;
            }
    }
    
    # 创建自定义测试错误页面
    [root@www ~]# echo "错错错" > /apps/nginx/html/error.html
    [root@www ~]# cat /apps/nginx/html/error.html
    错错错
    
    
    # 重载nginx
    [root@www ~]# systemctl reload nginx
    
    # 访问测试(访问一个不存在的页面,状态码404,被测试成功,浏览器没有调到utf-8,显示的乱码,但是访问成功)
    http://www.helloworld.net/123.html
    

    ?定义访问?志

    access_log off中的off,表示不记录访问日志

    server段不指定access_log时,并且http段中也未指定任何access_log参数时,它会默认写到logs/access.log这个文件,也就是access_log默认值就是logs/access.log,而且是所有server的访问日志。

    如果我们不需要,在http段中加一行access_log off;然后在特定的server中配置自己想写入的日志。

    # 编辑配置文件,?定义访问和错误?志定义在这个server中作用域中
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
            listen 80;
            server_name www.helloworld.net;
            error_page 500 502 503 504 404 /error.html;
            
            
            access_log /apps/nginx/logs/www-helloworld-net_access.log;		# 定义访问日志路径和文件,重载会自动创建文件,不会创建目录,事先保证目录存在
            error_log /apps/nginx/logs/www-helloworld-net_error.log warn;
            # 定义错误日志,路径和文件,重载会自动创建文件,不会创建目录,事先保证目录存在,定义错误日志记录级别
    	
    
             location = /error.html {
                    root html;
            }
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location ~* /A.gif {
                    root /data/nginx/pc/html/python/images;
                    index index.html;
            }
    
            location = /A.gif {
                    index index.html;
                    root /data/nginx/pc/html/linux38/images;
                    deny    192.168.127.128;
                    allow   192.168.127.0/24;
                    allow   2001:0db8::/32;
                    deny all;
            }
            
            location = /login/ {
                    root /data/nginx/html/pc;
                    index index.html;
                    auth_basic      "login password";
                    auth_basic_user_file    /apps/nginx/conf/.htpasswd;
            }
    }
    
    
    # 重载nginx
    [root@www ~]# systemctl reload nginx
    
    # 查看创建的日志文件
    [root@www ~]# ls /apps/nginx/logs/
    access.log                     www-helloworld-net_access.log
    error.log                      www-helloworld-net_error.log
    nginx.pid        
    
    
    # 访问测试,访问成功
    http://www.helloworld.net/login/
    
    # 查看记录的访问日志
    [root@www ~]# cat /apps/nginx/logs/www-helloworld-net_access.log 
    192.168.127.1 - user1 [24/Mar/2021:19:33:49 +0800] "GET /login/ HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.57"
    
    
    # 访问测试,访问失败
    http://www.helloworld.net/123.html
    
    # 查看记录的错误日志
    [root@www ~]# cat /apps/nginx/logs/www-helloworld-net_error.log 
    2021/03/24 19:35:02 [error] 62130#0: *3 open() "/data/nginx/html/pc/123.html" failed (2: No such file or directory), client: 192.168.127.1, server: www.helloworld.net, request: "GET /123.html HTTP/1.1", host: "www.helloworld.net"  
     
    

    检测?件是否存在

    try_files会按我们写好的顺序逐个在服务器的指定路径,判断检查用户请求的资源?件是否存在(所以说try_files指令后面我们可以写多个文件,如果第一个不存在,就检查第二个,直到检查最后一个),返回第?个找到的?件或?件夹(结尾加斜线表示为?件夹),如果所有?件或?件夹都找不到,会进??个内部重定向到最后?个参数。只有最后?个参数可以引起?个内部重定向,之前的参数只设置内部URI的指向。最后?个参数是回退URI且必须存在,否则会出现内部500错误。

    (接收到用户请求报文之后,就判断文件是否存在,如果在就直接响应,如果不在就给他跳到首页,try_files指令就是测试,测试这个文件是否存在)

    # 编辑配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            error_page 500 502 503 504 404 /error.html;
    
            access_log /apps/nginx/logs/www-helloworld-net_access.log;
            error_log /apps/nginx/logs/www-helloworld-net_error.log warn;
    
             location = /error.html {
                    root html;
            }
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location /about {
                    root /data/nginx/html/pc;
                    index index.html;
                    try_files $uri $uri/index.html /default/index.html $uri.html =489;		# 先判断$url,这是nginx内置的变量。这个变量会获取用户请求的uri就是域名后面的
                    #用户请求这个$uri的时候这个/data/nginx/html/pc/$uri没有,用户输入的可能是个目录,往下走$uri/index.html到/data/nginx/html/pc/$uri/index.html这个再看有没有页面,如果有返回,如果没有往下走/default/index.html,看看/data/nginx/html/pc//default/index.html有没有,如果还没有返回一个状态码 = 489
            }
    }
    
    
    # 创建目录和测试页
    [root@www ~]# mkdir -pv /data/nginx/html/pc/{about,default}
    
    
    [root@www ~]# echo "/data/nginx/html/pc/about/" > /data/nginx/html/pc/about/index.html
    [root@www ~]# echo "/data/nginx/html/pc/default/" > /data/nginx/html/pc/default/index.html
    
    
    [root@www ~]# cat /data/nginx/html/pc/about/index.html
    /data/nginx/html/pc/about/
    [root@www ~]# cat /data/nginx/html/pc/default/index.html
    /data/nginx/html/pc/default/
    
    
    
    # 访问测试,正常
    [root@localhost ~]# curl www.helloworld.net/about/
    /data/nginx/html/pc/about/
    
    # 删掉/data/nginx/html/pc/about/下的index.html在测试
    [root@www ~]# rm -rf /data/nginx/html/pc/about/index.html 
    # 在访问(可以看到转跳到/data/nginx/html/pc/default/index.html下了,测试成功)
    [root@localhost ~]# curl www.helloworld.net/about/
    /data/nginx/html/pc/default/
    
    # # 删掉/data/nginx/html/pc/default/下的index.html在测试
    [root@www ~]# rm -rf /data/nginx/html/pc/default/index.html 
    # 在访问(可以看到第一次访问没有任何信息,第二次显示响应头,发现返回的状态是我们定义的489,测试成功)
    [root@localhost ~]# curl www.helloworld.net/about/
    [root@localhost ~]# curl www.helloworld.net/about/ -I
    HTTP/1.1 489 
    Server: nginx/1.18.0
    Date: Wed, 24 Mar 2021 12:51:01 GMT
    Content-Length: 0
    Connection: keep-alive
    
    

    ?连接配置

    keepalive_timeout number; #设定保持连接超时时?,0表示禁??连接,默认为75s,通常配置在http字段作为站点全局配置

    keepalive_timeout number; #设定保持连接超时时?,0表示禁??连接,默认为75s,通常配置在http字段作为站点全局配置
    
    keepalive_requests number; #在?次?连接上所允许请求的资源的最?数量,默认为100次
    
    ?```sh
    # 编辑配置文件,在nginx.conf主配置文件中设置在http字段中
    [root@www ~]# vi /apps/nginx/conf/nginx.conf
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;		# 这里显示默认是65,keepalive_timeout  65 70;这样写,会在请求头中显示长连接时长70,时间到后断开,如果在连接会三次握手
        keepalive_requests = 3;  	# 这里调3次测试用。这个值一般在公司中都改大,比如200或300,
    								# 指令用于设置一个keep-alive连接上可以服务的请求的最大数量,当最大请求数量达到时,连接被关闭。默认是100。这个参数的真实含义,是指一个keep alive建立之后,nginx就会为这个连接设置一个计数器,记录这个keep alive的长连接上已经接收并处理的客户端请求的数量。如果达到这个参数设置的最大值时,则nginx会强行关闭这个长连接,逼迫客户端不得不重新建立新的长连接。
    								#大多数情况下当QPS(每秒请求数)不是很高时,默认值100凑合够用。但是,对于一些QPS比较高(比如超过10000QPS,甚至达到30000,50000甚至更高) 的场景,默认的100就显得太低。
    								#简单计算一下,QPS=10000时,客户端每秒发送10000个请求(通常建立有多个长连接),每个连接只能最多跑100次请求,意味着平均每秒钟就会有100个长连接因此被nginx关闭。同样意味着为了保持QPS,客户端不得不每秒中重新新建100个连接。因此,就会发现有大量的TIME_WAIT的socket连接(即使此时keep alive已经在client和nginx之间生效)。因此对于QPS较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛弃的情况,减少TIME_WAIT。
    
    # 重载nginx
    [root@www ~]# systemctl reload nginx
    
    # 使用telnet访问测试
    [root@localhost ~]# telnet www.helloworld.net 80
    Trying 192.168.127.130...
    Connected to www.helloworld.net.
    Escape character is '^]'.
    GET / HTTP/1.1
    HOST:www.helloworld.net		# 这里需要回车
    
    HTTP/1.1 200 OK		# 第一次连接
    Server: nginx/1.18.0
    Date: Wed, 24 Mar 2021 14:29:06 GMT
    Content-Type: text/html
    Content-Length: 21
    Last-Modified: Wed, 24 Mar 2021 12:24:22 GMT
    Connection: keep-alive
    ETag: "605b2f76-15"
    Accept-Ranges: bytes
    
    /data/nginx/html/pc/
    GET / HTTP/1.1
    HOST:www.helloworld.net		# 这里需要回车
    
    HTTP/1.1 200 OK		# 第二次连接
    Server: nginx/1.18.0
    Date: Wed, 24 Mar 2021 14:29:17 GMT
    Content-Type: text/html
    Content-Length: 21
    Last-Modified: Wed, 24 Mar 2021 12:24:22 GMT
    Connection: keep-alive
    ETag: "605b2f76-15"
    Accept-Ranges: bytes
    
    /data/nginx/html/pc/
    GET / HTTP/1.1
    HOST:www.helloworld.net		# 这里需要回车
    
    HTTP/1.1 200 OK		# 第三次连接
    Server: nginx/1.18.0
    Date: Wed, 24 Mar 2021 14:29:26 GMT
    Content-Type: text/html
    Content-Length: 21
    Last-Modified: Wed, 24 Mar 2021 12:24:22 GMT
    Connection: close
    ETag: "605b2f76-15"
    Accept-Ranges: bytes
    
    /data/nginx/html/pc/
    Connection closed by foreign host. #(外部主机关闭连接。)三次连接后关闭连接
    [root@localhost ~]# 
    
    

    作为下载服务器配置

    # 创建download目录(download不需要index.html?件)
    [root@www ~]# mkdir -pv /data/nginx/pc/html/download
    mkdir: 已创建目录 "/data/nginx/pc/html/download"
    
    # 编辑配置文件(添加loadtion /download)
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
            listen 80;
            server_name www.helloworld.net;
            error_page 500 502 503 504 404 /error.html;
    
            access_log /apps/nginx/logs/www-helloworld-net_access.log;
            error_log /apps/nginx/logs/www-helloworld-net_error.log warn;
    
             location = /error.html {
                    root html;
            }
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location /about {
                    root /data/nginx/html/pc;
                    index index.html;
                    try_files $uri $uri/index.html /default/index.html  $uri.html =489;
            }
    
            location /download {
                    autoindex on;   # ?动索引功能,列出download目录下的的所有文件
                    autoindex_exact_size on;	 # 计算?件确切??(单位bytes),off只显示?概??(单位kb、mb、gb)
                    autoindex_localtime on;		 #显示本机时间??GMT(格林威治)时间
                     limit_rate 10k;	#限制响应给客户端的传输速率,单位是bytes/second,默认值0表示?限制 ,限速与不限速的对?:(如果不限制传输速率可以不加这条参数,默认不限速)
                            root /data/nginx/pc/html;
            }
    }
    
    # 复制测试文件
    [root@www ~]#  cp /etc/hosts /data/nginx/pc/html/download/
    [root@www ~]# cp /usr/local/src/nginx-1.18.0.tar.gz /data/nginx/pc/html/download/
    
    # 访问测试(测试成功,可以看到hosts文件和nginx-1.18.0.tar.gz,可以下载一个测试一下限速)
    [root@localhost ~]# curl www.helloworld.net/download/
    <html>
    <head><title>Index of /download/</title></head>
    <body>
    <h1>Index of /download/</h1><hr><pre><a href="../">../</a>
    <a href="hosts">hosts</a>                                              24-Mar-2021 22:06                 234
    <a href="nginx-1.18.0.tar.gz">nginx-1.18.0.tar.gz</a>                                24-Mar-2021 22:12             1039530
    </pre><hr></body>
    </html>
    
    

    作为上传服务器

    
    server {
        client_max_body_size 100m;
        listen       80;
    
        # Upload form should be submitted to this location(上传表格应提交到此位置 )
        location /upload {
            # Pass altered request body to this location #(将更改的请求正文传递到此位置 )
            upload_pass   @test;	#(指定要将请求主体传递到的位置。文件字段将被剥离并替换为字段,包含处理上传文件所需的信息。)
    
            # Store files to this directory		#(将文件存储到此目录 )
            # The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist		#(该目录已散列,子目录0 1 2 3 4 5 6 7 8 9应该存在)
            upload_store /tmp 1;	#(指定将保存输出文件的目录。目录可以哈希。在这种情况下,所有子目录应在开始nginx之前存在)
            
            # Allow uploaded files to be read only by user	#(允许上传的文件仅由用户读取 )
            upload_store_access user:r;		#(指定用于创建输出文件的访问模式。)
    
            # Set specified fields in request body		#(在请求正文中设置指定的字段 	upload_set_form_field:指定一个表单字段(s),用于生成请求机构传递到后端的每个上传文件。名称和值都包含以下特殊变量	$upload_file_name	-	原始文件字段的名称		$upload_content_type - 上传的文件的内容类型		$upload_file_name - 正在上传的文件的原始名称与 DOS 和 UNIX 符号中的主要路径元素被剥离。即"D:[文档和设置]我的直流\我的图片]图片.jpg"将转换为"图片.jpg","/等/通过"将转换为"通过"。		$upload_tmp_path - 原始文件内容存储到的路径。输出文件名称由 10 位数字组成,使用与proxy_temp_path指令相同的算法生成。)
            upload_set_form_field $upload_field_name.name 	"$upload_file_name";
            upload_set_form_field $upload_field_name.content_type "$upload_content_type";
            upload_set_form_field $upload_field_name.path "$upload_tmp_path";
    
            # Inform backend about hash and size of a file
            upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
            upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";
    
            upload_pass_form_field "^submit$|^description$";
    
            upload_cleanup 400 404 499 500-505;
        }
    
    
    # 引用:https://blog.csdn.net/bigtree_3721/article/details/79870937
    
    # 参考网址:http://www.grid.net.ru/nginx/upload.en.html
    # 参考网址:https://github.com/hongzhidao/nginx-upload-module/blob/master/README.md
    
    
    
    #########################################下面的不会使
    # 编辑配置文件,写在nginx.conf主配置文件中
    [root@www ~]# vi  /apps/nginx/conf/nginx.conf
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
        keepalive_requests 3;
    
        client_max_body_size 10m;	# 设置允许客户端上传单个?件的最?值,默认值为1m
        client_body_buffer_size 16k;	#?于接收每个客户端请求报?的body部分的缓冲区??;默认16k;超出此??时,其将被暂存到磁盘上的由下?client_body_temp_path指令所定义的位置,缓存在内存中性能当然好,但是内存不是持久存储,万一服务器挂了,内存里的数据就没了,没有硬盘安全。
        client_body_temp_path /apps/nginx/temp 1 2 2;	#设定存储客户端请求报?的body部分的临时存储路径及??录结构和数量,?录名为16进制的数字,使?
    hash之后的值从后往前截取1位、2位、2位作为?件名。	/apps/nginx/temp此目录在重启nginx后会自动创建,“1”是一级目录会有16个目录0-F16进值,第二级目录是“2”有两个0-F,交叉创建0-F乘0-F是256个目录,第三级我们写的“2”如果写“3”会更多,	16*256=4096	16*256*256=1048576,分类是为了避免很多文件放在一个目录下,会照成寻址时间会很长,比如ll的时候会把一个目录下的文件全部加载到内存中,并且创建一个文件很小只有一个字节但是它还是会占用磁盘上的一个inodes(可以使用df -i查看),如果inodes一旦占完了就会创建不了文件,使用df -TH看磁盘上还有很多空间但是就是创建不了文件,也会报错磁盘文件用完了,这就是inodes用完的原因。
    
    
    # 重载nginx
    [root@www ~]# systemctl restart nginx
    
    

    其他配置

    指定对哪种浏览器禁??连接,比如ie浏览器

    # 编辑配置文件,写在nginx.conf主配置文件中
    [root@www ~]# vi  /apps/nginx/conf/nginx.conf
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
        keepalive_requests 3;
        keepalive_disable msie6;	# 可以使用管道符指定多个浏览器比如:keepalive_disable none | browser ...;
    
    
    ## MSIE 名词释义: Microsoft Internet Explorer,简称MSIE
    ## MSIE 是微软公司推出的一款网页浏览器,他们分为 IE4 IE5 IE6 IE7 IE8 IE9
    
    # 重载nginx
    [root@www ~]# systemctl reload nginx
    
    

    限制客户端使?除了指定的请求?法之外的其它?法

    # 使用limit_except method ... { ... },仅?于location
    
    # 编辑配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
            listen 80;
            server_name www.helloworld.net;
            error_page 500 502 503 504 404 /error.html;
    
            access_log /apps/nginx/logs/www-helloworld-net_access.log;
            error_log /apps/nginx/logs/www-helloworld-net_error.log warn;
    
             location = /error.html {
                    root html;
            }
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location /download {
                    autoindex on;
                    autoindex_exact_size on;
                    autoindex_localtime on;
                    limit_rate 10k;
                            root /data/nginx/pc/html;
            }
    
            location /upload {
                    root /data/pc;
                    index index.html;
                    limit_except GET {		# 只允许GET方法,拒绝GET以外的所有方法
                            allow 192.168.127.128;		# 单纯的访问控制,别想limit_except GET那么多,允许192.168.127.128主机访问/data/pc/upload/index.html,这个主机可以GET但是不能使用别的请求方法比如POST
                            deny all;
                    }
            }
    }
    
    ## 请求方法: method:GET, HEAD, POST, PUT, DELETE,MKCOL, COPY, MOVE, OPTIONS, PROPFIND,PROPPATCH, LOCK, UNLOCK, PATCH
    
    
    # 修改nginx为上传服务器,修改主配置文件,
    [root@www ~]# vi  /apps/nginx/conf/nginx.conf
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
        keepalive_requests 3;
    
        client_max_body_size 10m;	# 添加
        client_body_buffer_size 16k;	# 添加
        client_body_temp_path /apps/nginx/temp 1 2 2;	# 添加
    
    
    
    # 创建目录,给权限,nginx使用的是nginx用户无法对root用户的文件操作
    [root@www ~]# mkdir -pv /data/pc/upload
    [root@www ~]# chown -R nginx:nginx /data/
    [root@www ~]# ll /data
    总用量 0
    drwxr-xr-x. 6 nginx nginx 57 3月  24 12:50 nginx
    drwxr-xr-x. 2 nginx nginx  6 3月  25 19:40 pc
    
    # 创建测试页
    [root@www nginx-1.18.0]# echo /data/pc/upload > /data/pc/upload/index.html
    [root@www nginx-1.18.0]# cat /data/pc/upload/index.html 
    /data/pc/upload
    
    
    
    
    # 重载nginx
    [root@www ~]# systemctl reload nginx
    
    
    # 测试上传文件
    [root@localhost ~]# curl -XPUT /etc/issue http://www.helloworld.net/download/
    curl: (3) <url> malformed
    <html>
    <head><title>405 Not Allowed</title></head>		# 405 Nginx已经允许但是程序未?持上传功能
    <body>
    <center><h1>405 Not Allowed</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    
    
    [root@localhost ~]# curl -XPUT /etc/issue http://www.helloworld.net/upload
    curl: (3) <url> malformed
    <html>
    <head><title>403 Forbidden</title></head>	# allow 192.168.127.128允许这个地址GET访问,但是拒绝使用除GET以外的方法,这里使用的POST上传,nginx直接拒绝
    <body>
    <center><h1>403 Forbidden</h1></center>
    <hr><center>nginx/1.18.0</center>
    </body>
    </html>
    
    
    

    启用或禁用在 FreeBSD 和 Linux 上使用异步文件 I/O (AIO)

    什么场合适合sendfile 	什么场合适合 aio
    启用aio时会自动启用directio,小于directio定义的大小的文件则采用sendfile进行发送,超过或等于directio定义的大小的文件,将采用aio线程池进行发送,也就是说aio和directio适合大文件下载。因为大文件不适合进入操作系统的buffers/cache(缓冲区/缓存 ),这样会浪费内存,而且Linux AIO(异步磁盘IO)也要求使用directio的形式。
    
    sendfile_max_chunk可以减少阻塞调用sendfile()所花费的最长时间。因为Nginx不会尝试一次将整个文件发送出去,而是每次发送大小为256KB的块数据。
    
    注意,Nginx从1.7.11开始为AIO引入了线程池支持,能够使用多线程读取和发送文件,以免工人进程被阻塞。要启用多线程支持,configure时需要显式加入–with-threads选项。
    
    aio on | off # 默认是off,是否启?asynchronous file I/O(AIO)功能,需要编译开启
    linux 2.6以上内核提供以下?个系统调?来?持aio:
    1、SYS_io_setup:建?aio 的context
    2、SYS_io_submit: 提交I/O操作请求
    3、SYS_io_getevents:获取已完成的I/O事件
    4、SYS_io_cancel:取消I/O操作请求
    5、SYS_io_destroy:毁销aio的context
    
    
    
    directio size | off; # directio是直接磁盘IO,默认为关闭,directio的设计初衷,它具备sendfile的基本原理,只是不使?内核cache,?是直接使?DMA,当某个?件?于等于给定??时会?效,?于此值会使?sendfile,例如directio 4m,直接I/O最?的优点就是减少操作系统缓冲区和?户地址空间的拷?次数,降低了CPU的开销和内存带宽,主要使?在磁盘上有较??件的场合,?如视频、?频等。
    
    directio_alignment 512; #设置directio的对??式,在?多数情况下,?个512字节的对?就?够了,但是,在Linux下使?XFS时,需要将其增加到4K。
    
    #directio可以和sebdfile结合使?不冲突,在Linux上同时启? AIO和sendfile时,AIO?于?于或等于directio指令中指定的??的?件,?sendfile?于较?的?件或禁?directio的?件,directio需要nginx开启aio,如:
    location /video {
     root /data/video;
     index index.html;
     sendfile on;
     aio on;
     directio 8m;
     directio_alignment 512;
     }
    
    
    官方文档
    http://nginx.org/en/docs/ngx_core_module.html#thread_pool	 #开启多线程,定义多线程读取和发送?件?不会阻塞
    
    官方文档
    http://nginx.org/en/docs/http/ngx_http_core_module.html#aio		 #Syntax: aio on | off | threads[=pool]; #directio
    Default:
    aio off;		# nginx默认是没有开的,所以说nginx安装完之后很多地方需要优化
    Context: http, server, location
    This directive appeared in version 0.8.11.
    
    
    
    参考引用:https://blog.csdn.net/qq_34556414/article/details/106804472
    什么是缓存 I/O (Buffered I/O)
    1,缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O。在 Linux 2,的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。写的过程就是数据流反方向。缓存 I/O 有以下这些优点:
    
    缓存 I/O 使用了操作系统内核缓冲区,在一定程度上分离了应用程序空间和实际的物理设备。
    缓存 I/O 可以减少读盘的次数,从而提高性能。
    对于读操作:当应用程序要去读取某块数据的时候,如果这块数据已经在页缓存中,那就返回之。而不需要经过硬盘的读取操作了。如果这块数据不在页缓存中,就需要从硬盘中读取数据到页缓存。
    
    对于写操作:应用程序会将数据先写到页缓存中,数据是否会被立即写到磁盘,这取决于所采用的写操作机制:
    
    同步机制:数据会立即被写到磁盘中,直到数据写完,写接口才返回;
    延迟机制:写接口立即返回,操作系统会定期地将页缓存中的数据刷到硬盘。所以这个机制会存在丢失数据的风险。想象下写接口返回的时候,页缓存的数据还没刷到硬盘,正好断电。对于应用程序来说,认为数据已经在硬盘中。
    
    缓存 I/O 的缺点
    在缓存I/O的机制中,以写操作为例,数据先从用户态拷贝到内核态中的页缓存中,然后又会从页缓存中写到磁盘中,这些拷贝操作带来的CPU以及内存的开销是非常大的。对于某些特殊的应用程序来说,能够绕开内核缓冲区能够获取更好的性能,这就是直接I/O出现的意义。
    
    直接IO绕开磁盘高速缓存
    凡是通过直接I/O方式进行数据传输,数据直接从用户态地址空间写入到磁盘中,直接跳过内核缓冲区。对于一些应用程序,例如:数据库。他们更倾向于自己的缓存机制,这样可以提供更好的缓冲机制提高数据库的读写性能。
    
    顾名思义直接落盘
    
    直接io,绕开磁盘高速缓存
    
    1,正常情况下没有开启直接I/O,用户进程调用read方法,先从磁盘读取出到内核的缓冲区即磁盘高速缓存,然后读到用户存储空间缓冲区,这里其实是读了2次哦(先到磁盘高速缓存再到用户缓冲区),写和读一样也是两次。直接I/O让我们绕开了内核缓冲区,即磁盘高速缓存,当我们读的时候直接从磁盘读进来,写的时候从用户缓冲区直接写入磁盘。总结:我们可以让读写操作绕过内核缓冲区,直接读写用户缓冲去,提高速度,避免磁盘缓存页的拷贝
    2,传统走缓冲区未开启直接I/O方式好处是每次读取到缓冲区了,下次再读的话,命中到同一个缓冲区的内容就不需要读磁盘了,好处也是挺明显的,缺点是有两次拷贝
    3,高速缓冲区作用,某些文件存入高速缓冲区,可以复用,大文件直接读取,
    
    直接I/O 优点
    最大的优点就是减少操作系统缓冲区和用户地址空间的拷贝次数。降低了CPU的开销,和内存带宽。对于某些应用程序来说简直是福音,将会大大提高性能。
    
    直接I/O 缺点
    直接IO并不总能让人如意。直接IO的开销也很大,应用程序没有控制好读写,将会导致磁盘读写的效率低下。磁盘的读写是通过磁头的切换到不同的磁道上读取和写入数据,如果需要写入数据在磁盘位置相隔比较远,就会导致寻道的时间大大增加,写入读取的效率大大降低。
    
    具体应用场景
    当我们的磁盘上有大量的大文件的时候,对于大文件很难拷贝到内存当中,即磁盘缓冲是无效的,如果每次拷贝一次没意义!比如每个文件都有几个G大小,压根不太可能在内存当中缓存住的,那么你每次读都是一个浪费,所以大文件都是直接启用直接I/O,这样就避免了两次拷贝。(当磁盘上的文件大小超过size后,启用directIO功能,避免Buffered IO模式下磁盘页缓存中的拷贝消耗)
    
    操作系统内核通常尝试优化和缓存任何读/写请求。 由于数据在内核中缓存,对同一位置的任何后续读取请求将更快,因为不需要再从磁盘读取信息。
    
    直接I/O是文件系统的一个功能,其从应用程序到磁盘直接读取和写入,从而绕过所有操作系统缓存。 这使得更好地利用CPU周期和提高缓存效率。
    
    该方法用于数据具有较差命中率的地方。 这样的数据不需要在任何高速缓存中,并且可以在需要时加载。 它可以用于提供大文件。 directio指令启用该功能。 该指令可用于http,server和location区块:
    
    location /video/ {
         directio 4m;
    }
    
    任何大于指令中指定的文件将由直接I/O加载。 其它情况下禁用此参数。
    直接I/O取决于执行数据传输时的块大小。 nginx有directio_alignment指令来设置块大小。 该指令可用于http,server和location区块:
    
    location /video/ {
         directio 4m;
         directio_alignment 512;
    }
    
    除了XFS文件系统,默认值512字节在所有Linux版本运行良好。在此文件系统下,大小应增加到4KB。
    
    默认直接I/O功能是关闭的,如果要使用需要配置size,比如size 200M,超过200M的内容才启用。
    
    #nginx.conf配置线程池:
    events {
     	worker_connections 1024;
     	use epoll;		# 事件驱动模型,内核的,只能设置在events模块中设置
     	accept_mutex on;
     	multi_accept on;
    }
    
    # 定义线程池,需要定义到全局配置,线程池可以定义多个这里有pool1和pool2两个线程池,分别在pool1中开启了16个线程和在pool2中开启了32个线程,max_queue定义线程队列的值。	可以看到进程开启的线程数是16+32在+默认的1个=49个
    thread_pool pool1 threads=16 max_queue=65536;
    thread_pool pool2 threads=32 max_queue=65535;
    
    #server调?线程池:
     location /video {
     	root /data/video;
     	index index.html;
     	sendfile on;
     	aio threads=pool1;		# 在location中调用线程池,在这里开启aio,这个aio调用的是pool1这个线程池定义的是16个线程
     	directio 8m;	# 开启directio当常过8M的文件,就跟磁盘直接io
     	directio_alignment 4096;	# 直接I/O取决于执行数据传输时的块大小。 nginx有directio_alignment指令来设置块大小,这里测试4096(4k)一个块
     }
    
    
    ##################################下面示例
    
    # 关闭nginx,编译之后才能启动aio
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s stop
    [root@www nginx-1.18.0]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port                Peer Address:Port              
    LISTEN     0      128                *:22                             *:*                  
    LISTEN     0      100        127.0.0.1:25                             *:*                  
    LISTEN     0      128               :::22                            :::*                  
    LISTEN     0      100              ::1:25                            :::*   
    
    
    #拿到aio的编译参数
    [root@www nginx-1.18.0]# ./configure  --help | grep aio
      --with-file-aio                    enable file AIO support(启用文件AIO支持 )
      
    # 拿到多线程的编译参数,ningx多线程默认也是没有开的,我们可以在线程池里指定nginx使用多少线程
    [root@www nginx-1.18.0]# ./configure  --help | grep threads
      --with-threads                     enable thread pool support
    
    
    
    # 重新编译安装nginx,开启aio和线程池功能
    [root@www nginx-1.18.0]# pwd
    /usr/local/src/nginx-1.18.0
    [root@www nginx-1.18.0]# ls
    auto     CHANGES.ru  configure  html     Makefile  objs    src
    CHANGES  conf        contrib    LICENSE  man       README
    
    
    [root@www nginx-1.18.0]#./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads && make && make install
     
    # 修改主配置文件,开启线程池
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/nginx.conf
    
    events {
        worker_connections  1024;
    }
    
    thread_pool pool1 threads=16 max_queue=65536;	# 添加
    thread_pool pool2 threads=32 max_queue=65535;	# 添加
    
    # 修改子配置文件,开启aio
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
            listen 80;
            server_name www.helloworld.net;
            error_page 500 502 503 504 404 /error.html;
    
            access_log /apps/nginx/logs/www-helloworld-net_access.log;
            error_log /apps/nginx/logs/www-helloworld-net_error.log warn;
    
             location = /error.html {
                    root html;
            }
    
            location / {
                    root /data/nginx/html/pc;
            }
    
            location /download {
                    autoindex on;
                    autoindex_exact_size on;
                    autoindex_localtime on;
                    limit_rate 10k;
                            root /data/nginx/pc/html;
            }
    
            location /upload {
                    root /data/pc;
                    index index.html;
                    sendfile     on;		# 添加
                    aio  threads=pool1;		# 添加
                    directio     8m;		# 添加
                    directio_alignment 4096;		# 添加
                    limit_except GET {
                            allow 192.168.127.128;
                            deny all;
                    }
            }
    }
    
    
    
    # 重启nginx并验证:
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    
    # 启动报错(说的是无效的PID号在这个pid文件中)
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    nginx: [error] invalid PID number "" in "/apps/nginx/logs/nginx.pid"
    ## 解决方法:
    ###需要先执行
    nginx -c /etc/nginx/nginx.conf
    ### nginx.conf文件的路径可以从nginx -t的返回中找到。
    nginx -s reload
    
    ###如果以上没用,则直接kill调nginx里面的进程
    ### 例如:sudo kill -quit 28504
    
    ### 然后重启nginx
    
    # 启动nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    [root@www nginx-1.18.0]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port                Peer Address:Port              
    LISTEN     0      128                *:80                             *:*                  
    LISTEN     0      128                *:22                             *:*                  
    LISTEN     0      100        127.0.0.1:25                             *:*                  
    LISTEN     0      128               :::22                            :::*                  
    LISTEN     0      100              ::1:25                            :::*              
    
    
    # 验证线程是否开启
    [root@www nginx-1.18.0]# ps -ef | grep nginx
    root      49788      1  0 22:31 ?        00:00:00 nginx: master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
    nginx     73727  49788  0 22:41 ?        00:00:00 nginx: worker process
    nginx     73728  49788  0 22:41 ?        00:00:00 nginx: worker process
    nginx     73729  49788  0 22:41 ?        00:00:00 nginx: worker process
    nginx     73730  49788  0 22:41 ?        00:00:00 nginx: worker process
    root      77758 113177  0 22:43 pts/0    00:00:00 grep --color=auto nginx
    [root@www nginx-1.18.0]# cat /proc/73727/status
    Name:   nginx
    Umask:  0000
    State:  S (sleeping)
    Tgid:   73727
    Ngid:   0
    Pid:    73727
    PPid:   49788
    TracerPid:      0
    Uid:    2000    2000    2000    2000
    Gid:    2000    2000    2000    2000
    FDSize: 64
    Groups: 2000 
    VmPeak:   440420 kB
    VmSize:   440420 kB
    VmLck:         0 kB
    VmPin:         0 kB
    VmHWM:      2268 kB
    VmRSS:      2268 kB
    RssAnon:            1648 kB
    RssFile:             620 kB
    RssShmem:              0 kB
    VmData:   395056 kB
    VmStk:       132 kB
    VmExe:       904 kB
    VmLib:      6948 kB
    VmPTE:       288 kB
    VmSwap:        0 kB
    Threads:        49				### 看这里,49个线程数,开启成功
    
    

    否缓存打开过的?件信息

    如果一个文件不断打开,就在nginx缓存下来

    # open_file_cache off; #是否缓存打开过的?件信息
    
    #	open_file_cache max=N [inactive=time];
    #		nginx可以缓存以下三种信息:
    #		(1) ?件元数据:?件的描述符、?件??和最近?次的修改时间
    #		(2) 打开的?录结构
    #		(3) 没有找到的或者没有权限访问的?件的相关信息
    #		max=N:可缓存的缓存项上限数量;达到上限后会使?LRU(Least recently used,最近最少使?)算法实现管理
    #		inactive=time:缓存项的?活动时?,在此处指定的时?内未被命中的或命中的次数少于open_file_cache_min_uses指令所指定的次数的缓存项即为?活动项,将被删除
    
    
    # open_file_cache_errors on | off;
    	 是否缓存查找时发?错误的?件?类的信息
    	 默认值为off
    	 
    
    # open_file_cache_min_uses number;
    # 	 open_file_cache指令的inactive参数指定的时?内,?少被命中此处指定的次数?可被归类为活动项
    # 	 默认值为1
    
    # open_file_cache_valid time;
    #    缓存项有效性的检查验证频率,默认值为60s
    
    
    ##################################下面示例
    # 修改主配置文件
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/nginx.conf
    http {
    	...
    	
        open_file_cache max=10000 inactive=60s; 	# 最?缓存10000个?件,这个需要调高点,缓存几十个意义不大,?活动数据超时时?60s,(在60秒内是否被访问了5次,每隔60秒检查一次)
        open_file_cache_valid 60s; 		# 每间隔60s检查?下缓存数据有效性
        open_file_cache_min_uses 5; 	# 60秒内?少被命中访问5次才被标记为活动数据
        open_file_cache_errors on; 		# 缓存错误信息,比如404信息,但是这个不要缓存很长时间,毕竟我们下一刻就修复了,如果缓存时间太长,他就一直报404了
    
        server {
    
    # 重载nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    

    隐藏Nginx server版本,1.18啥的

    避免有版本bug被别人利用漏洞攻击

    # 语法:	server_tokens on | off | build | string;
    
    # 修改主配置文件
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/nginx.conf
    http {
    	...
    	
        open_file_cache max=10000 inactive=60s;
        open_file_cache_valid 60s;
        open_file_cache_min_uses 5;
        open_file_cache_errors on;
        
        server_tokens off;		# #隐藏Nginx server版本
        
        server {
        
    # 重载nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    # 访问验证
    [root@localhost ~]# curl -I  http://www.helloworld.net/upload/ 
    HTTP/1.1 200 OK
    Server: nginx/1.18.0		# 原来显示的格式
    
    
    [root@localhost ~]# curl -I  http://www.helloworld.net/upload/
    HTTP/1.1 200 OK
    Server: nginx		# 禁用后显示的格式
    Date: Thu, 25 Mar 2021 15:11:39 GMT
    Content-Type: text/html
    Content-Length: 16
    Last-Modified: Thu, 25 Mar 2021 13:07:30 GMT
    Connection: keep-alive
    ETag: "605c8b12-10"
    Accept-Ranges: bytes
    
    
    

    Nginx ?级配置

    Nginx 状态?

    # 基于nginx模块ngx_http_stub_status_module实现,在编译安装nginx的时候需要添加编译参数--withhttp_stub_status_module,否则配置完成之后监测会是提示语法错误。
    
    # 配置示例:
    # location /nginx_status {		# 当访问/nginx_status这个uri的时候显示它的状态页,这个状态页是可以授权的,账号认证
    # 	 stub_status;
    #    allow 192.168.0.0/16;
    #    allow 127.0.0.1;
    # 	 deny all;
     }
     
    # 状态??于输出nginx的基本状态信息:
    
    #    输出信息示例:
    # Active connections: 291
    # server accepts handled requests
    # 	 16630948 16630948 31070465
    
    #  上?三个数字分别对应accepts,handled,requests三个值
    # Reading: 6 Writing: 179 Waiting: 106
    
    
    # Active connections: 当前处于活动状态的客户端连接数,包括连接等待空闲连接数。
    # accepts:统计总值,Nginx?启动后已经接受的客户端请求的总数。
    # handled:统计总值,Nginx?启动后已经处理完成的客户端请求的总数,通常等于accepts,除?有因
    # worker_connections限制等被拒绝的连接。
    # requests:统计总值,Nginx?启动后客户端发来的总的请求数。
    # Reading:当前状态,正在读取客户端请求报??部的连接的连接数。比如正在解析用户的url
    # Writing:当前状态,正在向客户端发送响应报?过程中的连接数。正在给用户发送数据
    # Waiting:当前状态,正在等待客户端发出请求的空闲连接数,开启 keep-alive的情况下,这个值等于。用户打开网页后没有操作,一直在保持连接,还没有跟服务器断开,可能是在看首页
    # active – (reading+writing),
    
    
    
    
    ##################################下面示例
    # 拿到状态?的编译参数
    [root@www nginx-1.18.0]# ./configure --help  | grep status_module
      --with-http_stub_status_module     enable ngx_http_stub_status_module
    
    
    # 编译
    [root@www nginx-1.18.0]# pwd
    /usr/local/src/nginx-1.18.0
    
    [root@www nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads --with-http_stub_status_module && make && make install
    
    
    # 修改子配置文件
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    
    		...
    		
            location /nginx_status {
                    stub_status;	# 当访问这个uri的时候显示这个状态页
                    allow 192.168.0.0/16;
                    allow 192.168.127.128;
                    deny all;
            }
    }
    
    
    # 重载nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    
    #访问测试
    http://www.helloworld.net/nginx_status
    Active connections(活动连接): 2		# 这个值是最重要的
    server(服务器) accepts(接受) handled(处理) requests(要求)
     				4 				4 				3 		# 这三个是统计值,是nginx致启动后统计的数据,accepts和handled如果没有些拒绝的话一般这两个值是一样的
    Reading(读 ): 0 Writing(写): 1 Waiting(等待): 1 	# 这三个值比较重要
    

    Nginx 第三?模块

    第三模块是对nginx 的功能扩展,第三?模块需要在编译安装Nginx 的时候使?参数--addmodule=PATH指定路径添加,有的模块是由公司的开发?员针对业务需求定制开发的,有的模块是开源爱好者开发好之后上传到github进?开源的模块,nginx?持第三?模块需要从源码重新编译?持,?如开源的echo模块 https://github.com/openresty/echo-nginx-module.git echo这个模块类似于shell中echo可以显示变量信息,很适用于调试,这个模块在github中,可以克隆下来

    #关掉nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s stop
    
    
    # 查看开启扩展模块的插件
    [root@www nginx-1.18.0]# ./configure --help | grep add
      --add-module=PATH                  enable external module		# 把第三方模块编译到nginx中
    
    # 安装git
    [root@www nginx-1.18.0]# yum -y install git
    
    # 切换目录,不要和nginx放在一个目录,分开存放
    [root@www nginx-1.18.0]# cd /usr/local/src/
    [root@www src]# pwd
    /usr/local/src
    
    # 把模块克隆下来(如果克隆不下来,想办法适用浏览器下载压缩包,下载下来,传到服务器中)
    [root@www src]# git clone https://github.com/openresty/echo-nginx-module.git
    
    
    # 查看一下(这个包是用c写的)
    [root@www src]# ls
    echo-nginx-module-master  nginx-1.18.0  nginx-1.18.0.tar.gz
    [root@www src]# cd echo-nginx-module-master/
    [root@www echo-nginx-module-master]# pwd
    /usr/local/src/echo-nginx-module-master
    
    
    # 编译,指定第三方模块编译进nginx
    [root@www nginx-1.18.0]# pwd
    /usr/local/src/nginx-1.18.0
    [root@www nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads --add-module=/usr/local/src/echo-nginx-module-master && make && make install
    
    # 编辑子配置文件测试一下echo指令好不好用
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    
    		
    		...
    		
            location /main {		# 当访问/main的时候
                    index index.html;
                    default_type text/html;
                    echo "hello world,main-->";		# 访问一下hello world,main-->,如果显示echo的话,它就不显示index.html里面的内容了
                    echo_reset_timer;
                    echo_location /sub1;	# 调用的下面的location /sub1
                    echo_location /sub2;	# 调用的下面的location /sub2
                    echo "took $echo_timer_elapsed sec for total.";		# 最后echo了一个$echo_timer_elapsed总耗时
                    }
            
            location /sub1 { 
                    echo_sleep 1;		# echo_sleep 1 睡一秒钟
                    echo sub1;
            }       
     
            location /sub2 {
                    echo_sleep 1;
                    echo sub2;
                    
            }
                    
            location /sub3 {
            		default_type text/html;		# 如果直接访问/sub3,让它以文本的方式显示,否者找不到文件,它会下载
            		echo "helloworld";
            		echo $remote_addr;		# echo一个变量,显示源地址
            		# echo $msie;		# 判断是不是ie浏览器
            		echo $scheme;				# 打印用户的请求协议
            }
    
    }
    
    
    # 重载一下nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] still could not bind()
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    
    
    # 访问测试(测试成功echo生效)
    [root@localhost ~]# curl  http://www.helloworld.net/main/
    hello world,main-->
    sub1
    sub2
    took 2.003 sec for total.
    
    
    [root@localhost ~]# curl  http://www.helloworld.net/sub3
    helloworld 192.168.127.1 http
    
    

    Nginx 变量使?

    nginx的变量可以在配置?件中引?,作为功能判断或者?志等场景使?,变量可以分为内置变量和?定义变量,内置变量是由nginx模块?带,通过变量可以获取到众多的与客户端访问相关的值。

    内置变量

    $remote_addr;
    #存放了客户端的地址,注意是客户端的公?IP,也就是?家?访问?个?站,则会显示为路由器的公?IP。
    
    $args;
    #变量中存放了URL中的指令,例如http://www.magedu.net/main/index.do?
    id=20190221&partner=search中的id=20190221&partner=search
    
    
    $document_root;
    #保存了针对当前资源的请求的系统根?录,如/apps/nginx/html。
    
    
    $document_uri;
     #保存了当前请求中不包含指令的URI,注意是不包含请求的指令,?如 http://www.magedu.net/main/index.do?id=20190221&partner=search会被定义为/main/index.do 
     
     
    $host;
    #存放了请求的host名称。
    
    
    $http_user_agent;
    #客户端浏览器的详细信息
    
    
    limit_rate 10240;
    echo $limit_rate;
    #如果nginx服务器使?limit_rate配置了显示?络速率,则会显示,如果没有设置, 则显示0。
    
    
    $remote_port;
    #客户端请求Nginx服务器时随机打开的端?,这是每个客户端??的端?。
    
    $http_cookie;
    #客户端的cookie信息。
    
    
    $remote_user;
    #已经经过Auth Basic Module验证的?户名。
    
    
    $request_body_file;
    #做反向代理时发给后端服务器的本地资源的名称。
    
    
    $request_method;
    #请求资源的?式,GET/PUT/DELETE等
    
    
    $request_filename;
    #当前请求的资源?件的路径名称,由root或alias指令与URI请求?成的?件绝对路径,
    如/apps/nginx/html/main/index.html
    
    
    $request_uri;
    #包含请求参数的原始URI,不包含主机名,如:/main/index.do?id=20190221&partner=search
    
    
    $scheme;
    #请求的协议,如ftp,https,http等。
    
    
    $server_protocol;
    #保存了客户端请求资源使?的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等。
    
    
    $server_addr;
    #保存了服务器的IP地址。
    
    $server_name;
    #请求的服务器的主机名。
    
    
    $server_port;
    #请求的服务器的端?号
    
    
    ##################################下面示例
    
    # 编辑子配置文件
    server {
    
    		...
    
            location /sub3 {
                    default_type text/html;
                    echo "helloworld";
                    echo "remote_addr-->" $remote_addr;
                    #echo $msie;
                    echo "scheme-->" $scheme;
                    echo "args-->" $args;
                    echo "document_root-->" $document_root; 
                    echo "document_uri-->" $document_uri;
                    echo "host-->" $host;
                    echo "http_user_agent-->" $http_user_agent;
                    echo "http_cookie-->" $http_cookie;
                    limit_rate 10240;
                    echo "limit_rate-->" $limit_rate;
                    echo "remote_port-->" $remote_port;
                    echo "remote_user-->" $remote_user;
                    echo "request_body_file-->" $request_body_file;
                    echo "request_method-->" $request_method;
                    echo "request_filename-->" $request_filename;
                    echo "request_uri-->" $request_uri;
                    echo "server_protocol-->" $server_protocol;
                    echo "server_addr-->" $server_addr;
                    echo "server_name-->" $server_name;
                    echo "server_port-->" $server_port;
            }
    }
    
    
    # 重载nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    
    # 访问测试
    [root@localhost ~]# curl  http://www.helloworld.net/sub3
    helloworld
    remote_addr--> 192.168.127.128
    scheme--> http
    remote_addr--> 192.168.127.128
    args--> 
    document_root--> /apps/nginx/html
    document_uri--> /sub3
    host--> www.helloworld.net
    http_user_agent--> curl/7.29.0
    http_cookie--> 
    limit_rate--> 0
    remote_port--> 36096
    remote_user--> 
    request_body_file--> 
    request_method--> GET
    request_filename--> /apps/nginx/html/sub3
    request_uri--> /sub3
    server_protocol--> HTTP/1.1
    server_addr--> 192.168.127.130
    server_name--> www.helloworld.net
    server_port--> 80
    
    

    ?定义变量

    # 假如需要?定义变量名称和值,使?指令set $variable value;,则?法如下
    # Syntax: set $variable value;		# set设置变量名,value值
    # Default: —
    # Context: server, location, if
    
    #  set $name magedu;
    #  echo $name;
    #  set $my_port $server_port;		# 可以将$server_port变量的信息赋值给$my_port它
    #  echo $my_port;
    #  echo "$server_name:$server_port";	# 也可以组合变量(格式化变量输出信息)
    
    
    ##################################下面示例
    
    # 编辑子配置文件
    server {
    
    		...
    
            location /sub3 {
            		
            		...
            		
                    set  $zhe_shi_yi_ge_zi_ding_yi_bian_liang zhe_shi_yi_ge_zi_ding_yi_bian_liang;      
                    echo "zhe_shi_yi_ge_zi_ding_yi_bian_liang-->" $zhe_shi_yi_ge_zi_ding_yi_bian_liang;
            }
    }
    
    
    # 重载nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    
    # 访问测试
    [root@localhost ~]# curl  http://www.helloworld.net/sub3
    zhe_shi_yi_ge_zi_ding_yi_bian_liang--> zhe_shi_yi_ge_zi_ding_yi_bian_liang
    
    

    Nginx ?定义访问?志

    访问?志是记录客户端即?户的具体请求内容信息,全局配置模块中的error_log是记录nginx服务器运?时的?志保存路径和记录?志的level,因此有着本质的区别,?且Nginx的错误?志?般只有?个,但是访问?志可以在不同server中定义多个,定义?个?志需要使?access_log指定?志的保存路径,使?log_format指定?志的格式,格式中定义要保存的具体?志内容。

    ?定义默认格式?志

    # 如果是要保留?志的源格式,只是添加相应的?志内容,使?log_format指定?志的格式,则配置如下:
    # log_format nginx_format1 '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"' '$server_name:$server_port'; 
    
    # log_format 含义是配置了一个名为nginx_format1的日志格式化的规则,应用在了access_log的日志上。
    
    # access_log logs/access.log nginx_format1;
    
    
    #重启nginx并访问测试?志格式
    ==> /apps/nginx/logs/access.log <==
    192.168.0.1 - - [22/Feb/2019:08:44:14 +0800] "GET /favicon.ico HTTP/1.1" 404
    162 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/2
    0100101 Firefox/65.0" "-"www.magedu.net:80
    
    
    
    ##################################下面示例
    
    # 修改主配置文件(自定义日志,在http字段定义,可以在不同的server中调用)
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/nginx.conf
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
    
        #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;
    
    
    
    ########## 下面是添加的自定义日志(用的都是nginx的变量,定义在主配置文件的http中)
    
         log_format nginx_format1 '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"' '$server_name:$server_port';
    
    
         log_format access_json '{"@timestamp":"$time_iso8601",'		# json格式的日志,"@timestamp"键,"$time_iso8601"值。加起来的键值对就是json格式
             '"host":"$server_addr",'
             '"clientip":"$remote_addr",'
             '"size":$body_bytes_sent,'
             '"responsetime":$request_time,'
             '"upstreamtime":"$upstream_response_time",'
             '"upstreamhost":"$upstream_addr",'
             '"http_host":"$host",'
             '"uri":"$uri",'
             '"domain":"$host",'
             '"xff":"$http_x_forwarded_for",'
             '"referer":"$http_referer",'
             '"tcp_xff":"$proxy_protocol_addr",'
             '"http_user_agent":"$http_user_agent",'
             '"status":"$status"}';
    
    
    # 修改子配置文件(server中定义了多个访问日志,这些日志都会创建并记录)
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    
    server {
            listen 80;
            server_name www.helloworld.net;
            error_page 500 502 503 504 404 /error.html;
    
            #access_log /apps/nginx/logs/www-helloworld-net_access.log;
            access_log /apps/nginx/logs/$server_name-now_access.log ;	# 适用变量获取主机名试试,会生成一个新的配置文件,需要给配置文件权限,因为我们的nginx是用的普通用户启动的,不改会没有写权限
            error_log /apps/nginx/logs/www-helloworld-net_error.log warn;
    
    		# 引用主配置文件中log_format自定义的日志(调用规则名,可以在主配置文件中定义,子配置文件中引用)
    		access_log /apps/nginx/logs/access_json.log access_json;
    		access_log /apps/nginx/logs/helloworld.log nginx_format1;	
    
    
    # 给文件权限
    [root@www nginx-1.18.0]# chown -R nginx:nginx /apps/nginx/logs
    
    # 重载nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    # 访问测试(可以看到nginx生成了一些新日志)
    [root@localhost ~]# curl  http://www.helloworld.net/sub3
    
    [root@www nginx-1.18.0]# ll /apps/nginx/logs/
    总用量 88
    -rw-r--r--. 1 root  root    329 3月  26 02:07 access_json.log
    -rw-r--r--. 1 nginx nginx 27319 3月  24 22:28 access.log
    -rw-r--r--. 1 nginx nginx 20019 3月  26 02:07 error.log
    -rw-r--r--. 1 root  root    121 3月  26 02:07 helloworld.log
    -rw-r--r--. 1 nginx nginx     6 3月  26 01:28 nginx.pid
    -rw-r--r--. 1 nginx nginx 15436 3月  26 01:13 www-helloworld-net_access.log
    -rw-r--r--. 1 nginx nginx  6180 3月  26 00:44 www-helloworld-net_error.log
    -rw-r--r--. 1 nginx nginx   192 3月  26 02:07 www.helloworld.net-now_access.log
    
    
    # 查看一下日志(这是json格式的日志)
    [root@www nginx-1.18.0]# cat  /apps/nginx/logs/access_json.log 
    {"@timestamp":"2021-03-26T02:07:45+08:00","host":"192.168.127.130","clientip":"192.168.127.128","size":707,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.helloworld.net","uri":"/sub3","domain":"www.helloworld.net","xff":"-","referer":"-","tcp_xff":"-","http_user_agent":"curl/7.29.0","status":"200"}
    
    

    json格式的?志访问统计

    # 一个python脚本对json日志进行统计
    
    #coding:utf-8
    #Author:Zhang ShiJie
    status_200= []
    status_404= []
    with open("/apps/nginx/logs/access_json.log") as f:
            for line in f.readlines():
                    line = eval(line)
                    if line.get("status") == "200":
                            status_200.append(line.get)
                    elif line.get("status") == "404":
                            status_404.append(line.get)
                    else:
                            print("状态码 ERROR")
    f.close()
    
    print "状态码200的有--:",len(status_200)
    print "状态码404的有--:",len(status_404)
    
    # 运行一下
    [root@www nginx-1.18.0]# python /apps/nginx/logs/pythonjsonlog.py
    状态码200的有--: 1
    状态码404的有--: 0
    
    

    Nginx 压缩功能

    Nginx?持对指定类型的?件进?压缩然后再传输给客户端,?且压缩还可以设置压缩?例,压缩后的?件??将?源?件显著变?,这样有助于降低出?带宽的利?率,降低企业的IT?出,不过会占?相应的CPU资源。

    Nginx对?件的压缩功能是依赖于模块ngx_http_gzip_module,不需要编译时指定,官??档: https://nginx.org/en/docs/http/ngx_http_gzip_module.html, 配置指令如下:

    Syntax:	gzip on | off;
    Default:	
    gzip off;
    Context:	http, server, location, if in location		# 可以放在http字段,server字段,location字段,甚至if中
    
    #启?或禁?gzip压缩,默认关闭
    gzip on | off;
    
    #压缩?由低到?从1到9,默认为1,指定压缩比,值越高,压缩的文件就越小,但是越消耗cpu,一般配置折中的值,比如5,或者4,3
    gzip_comp_level level;
    
    #禁?IE6 gzip功能,因为早期的IE6不支持,7以后支持,所以对这些浏览器禁用压缩功能
    gzip_disable "MSIE [1-6]\.";
    
    #gzip压缩的最??件,?于设置值的?件将不会压缩,小于1k的文件不压缩,超过的就压缩,这些小文件没必要压缩了
    gzip_min_length 1k;
    
    #启?压缩功能时,协议的最?版本,默认HTTP/1.1,所以说这个值可以配,也可以不配
    gzip_http_version 1.0 | 1.1;
    
    #指定Nginx服务需要向服务器申请的缓存空间的个数*??,默认32 4k|16 8k;
    gzip_buffers number size;
    
    
    #指明仅对哪些类型的资源执?压缩操作;默认为gzip_types text/html,不?显示指定,否则出错,这些压缩类型需要自己指定,常见的主要是文本,图片等,但是像视频压缩几乎没有太大效果
    gzip_types mime-type ...;
    
    #如果启?压缩,是否在响应报??部插?“Vary: Accept-Encoding”,这是字段插入Accept-Encoding也就是告诉客户端已经压缩了
    gzip_vary on | off;
    
    
    ##################################下面示例
    
    # 创建测试页,大于1k大小,/data/nginx/html/pc此路径location以定义
    [root@www ~]# cp /apps/nginx/logs/access.log  /data/nginx/html/pc/test.html
    
    # 创建一个小于1k大小的测试页,检测gzip_min_length效果
    [root@www ~]# echo "test1" > /data/nginx/html/pc/test1.html 
    
    # location配置
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    
    		...
    		
            location / {
                    root /data/nginx/html/pc;
            }
    
    
    
    # 修改主配置文件
    [root@www ~]# vi /apps/nginx/conf/nginx.conf
    http {
    
    	...
    	
        #gzip  on;
    
        gzip on;	# 开启gzip压缩
        gzip_comp_level 5;		# 压缩?为5
        gzip_min_length 1k;		# ?于设置值的?件将不会压缩
        gzip_types text/plain application/javascript application/x-javascript text/cssapplication/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;		# 对这些类型的资源执?压缩操作
        gzip_vary on;		# 告诉客户端已经开启压缩了
    
    
    # 重启nginx
    [root@www ~]# /apps/nginx/sbin/nginx -t
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    # 访问测试
    ## --compressed 采用压缩方式接收返回数据
    ## --head参数等同于-I向服务器发出 HEAD 请求,然会将服务器返回的 HTTP 标头打印出来
    
    [root@localhost ~]# curl --head --compressed http://www.helloworld.net/
    HTTP/1.1 200 OK
    Server: nginx
    Date: Fri, 26 Mar 2021 11:40:35 GMT
    Content-Type: text/html
    Content-Length: 21		# 指示出报文实体主体的字节大小
    Last-Modified: Wed, 24 Mar 2021 12:24:22 GMT
    Connection: keep-alive
    ETag: "605b2f76-15"
    Accept-Ranges: bytes
    
    
    [root@localhost ~]# curl --head --compressed http://www.helloworld.net/test.html
    HTTP/1.1 200 OK
    Server: nginx
    Date: Fri, 26 Mar 2021 11:44:12 GMT
    Content-Type: text/html
    Last-Modified: Fri, 26 Mar 2021 11:28:32 GMT
    Connection: keep-alive
    Vary: Accept-Encoding
    ETag: W/"605dc560-6ab7"
    Content-Encoding: gzip		 # 压缩传输,用浏览器f12调试模式可以看到压缩的文件大小
    
    [root@localhost ~]# curl --head --compressed http://www.helloworld.net/test1.html
    HTTP/1.1 200 OK
    Server: nginx
    Date: Fri, 26 Mar 2021 11:52:29 GMT
    Content-Type: text/html
    Content-Length: 6	# 指示出报文实体主体的字节大小
    Last-Modified: Fri, 26 Mar 2021 11:30:46 GMT
    Connection: keep-alive
    ETag: "605dc5e6-6"
    Accept-Ranges: bytes	# test1.html文件小于1k没有压缩
    
    

    https 功能

    Web?站的登录??都是使?https加密传输的,加密数据以保障数据的安全,HTTPS能够加密信息,以免敏感信息被第三?获取,所以很多银??站或电?邮箱等等安全级别较?的服务都会采?HTTPS协议,HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上?加了?层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进?加密,所以传输的数据都是加密后的数据。

    https 实现过程如下:
    1.客户端发起HTTPS请求:
    客户端访问某个web端的https地址,?般都是443端?

    2.服务端的配置:
    采?https协议的服务器必须要有?套证书,可以通过?些组织申请,也可以??制作,?前国内很多?站都??做的,当你访问?个?站的时候提示证书不可信任就表示证书是??做的,证书就是?个公钥和私钥匙,就像?把锁和钥匙,正常情况下只有你的钥匙可以打开你的锁,你可以把这个送给别?让他锁住?个箱?,??放满了钱或秘密,别?不知道??放了什么?且别?也打不开,只有你的钥匙是可以打开的。

    3.传送证书:
    服务端给客户端传递证书,其实就是公钥,??包含了很多信息,例如证书得到颁发机构、过期时间等等。

    4.客户端解析证书:
    这部分?作是有客户端完成的,?先回验证公钥的有效性,?如颁发机构、过期时间等等,如果发现异常则会弹出?个警告框提示证书可能存在问题,如果证书没有问题就?成?个随机值,然后?证书对该随机值进?加密,就像2步骤所说把随机值锁起来,不让别?看到。(随机数,以后服务器和客户端在通信就用随机数,这个随机数可以理解为客户端的私钥,只有客户端能解)

    5.传送4步骤的加密数据:
    就是将?证书加密后的随机值传递给服务器,?的就是为了让服务器得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值进?加密解密了。(只有服务器端有私钥,可以解密公钥,拿到随机数)

    6.服务端解密信息:
    服务端?私钥解密5步骤加密后的随机值之后,得到了客户端传过来的随机值

    7.传输加密后的信息:
    服务端将?随机值加密后的数据传递给客户端,在客户端可以被还原出原数据内容(客户端也有随机值,客户端使用客户端的随机值进行解密)。

    8.客户端解密信息:
    客户端?之前?成的随机值获解密服务端传递过来的数据,由于数据?直是加密的,因此即使第三?获取到数据也?法知道其详细内容。

    ssl 配置参数

    nginx 的https 功能基于模块ngx_http_ssl_module实现,因此如果是编译安装的nginx要使?参数ngx_http_ssl_module开启ssl功能,但是作为nginx的核?功能,yum安装的nginx默认就是开启的,编译安装的nginx需要指定编译参数--with-http_ssl_module开启,官??档: https://nginx.org/en/docs/http/ngx_http_ssl_module.html,配置参数如下:

    
     # 查看ssl模块(--with-http_ssl_module)
    [root@www ~]# /apps/nginx/sbin/nginx -V
    nginx version: nginx/1.18.0
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.0.2k-fips  26 Jan 2017
    TLS SNI support enabled
    configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads --add-module=/usr/local/src/echo-nginx-module-master
    
    
    ssl on | off;
    #为指定的虚拟主机配置是否启?ssl功能,此功能在1.15.0废弃,使?listen [ssl]替代。
    
    listen [ssl];
    # 1.15.0之后的版本使用listen开启ssl,示例:listen 443 ssl这样写,表示这是个ssl端口
    
    ssl_certificate /path/to/file;
    #当前虚拟主机使?使?的公钥?件,?般是crt?件
    
    ssl_certificate_key /path/to/file;
    #当前虚拟主机使?的私钥?件,?般是key?件
    
    ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
    #?持ssl协议版本,早期为ssl,现在是TSL,默认为后三个
    
    ssl_session_cache off | none | [builtin[:size]] [shared:name:size]; # 配置ssl缓存(是否要缓存已经建立过连接的ssl会话,建立会话可以在一定程度上减轻服务器的压力,如果不缓存每次三次握手都要重新建立公钥传输,然后传输key文件,服务器在解密,解密完之后在通过https传输会话,如果我们缓存下来,只要这个sesstion(连接)没过期,我们可以复用这个ssl。)
    
    	# off: 关闭缓存
    	# none: 通知客户端?持ssl session cache,但实际不?持
    	# builtin[:size]:使?OpenSSL内建缓存,为每worker进程私有(每一个worker进程都有缓存,但是进程有很多,需要每一个都有缓存所以这个不用)
       # [shared:name:size]:在各worker之间使??个共享的缓存(缓存是在内存),需要定义?个缓存名称(就是name)和缓存空间??(就是size),?兆可以存储4000个会话信息,多个虚拟主机可以使?相同的缓存名称。
       
    ssl_session_timeout time;#客户端连接可以复?ssl session cache中缓存的有效时?,默认5m
    
    

    ?签名 证书

    # 创建certs(certs是用来保存当前这个服务的证书的,nginx的证书就在nginx的certs,Apache的证书就在Apache的certs),一般在nginx下创建这个目录
    [root@www ~]# cd /apps/nginx/
    [root@www nginx]# pwd
    /apps/nginx
    [root@www nginx]# ll
    总用量 4
    drwx------. 2 nginx root     6 3月  23 16:18 client_body_temp
    drwxr-xr-x. 3 nginx nginx 4096 3月  26 19:39 conf
    drwx------. 2 nginx root     6 3月  23 16:18 fastcgi_temp
    drwxr-xr-x. 2 nginx nginx   58 3月  24 19:17 html
    drwxr-xr-x. 2 nginx nginx  241 3月  26 02:18 logs
    drwx------. 2 nginx root     6 3月  23 16:18 proxy_temp
    drwxr-xr-x. 2 nginx nginx   36 3月  26 00:14 sbin
    drwx------. 2 nginx root     6 3月  23 16:18 scgi_temp
    drwx------. 2 nginx root     6 3月  25 16:50 temp
    drwx------. 2 nginx root     6 3月  23 16:18 uwsgi_temp
    
    
    [root@www nginx]# mkdir certs
    [root@www nginx]# cd certs/
    
    # 自签名CA证书(正常情况下,ca证书是向机构购买的,把你的域名发给他,它会自动给你发证书的,但是要钱,一般是运维提需求,有公司的商务走流程,但是也有例外,运维自己跟机构联系,后在走商务付款)
    [root@s2 certs]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout www.helloworld.net.key -out www.helloworld.net.csr
    
    # 或(证书的文件名可以自制,在实现多域名https的时候会根据请求的域名,发送合适的证书)
    
    [root@www certs]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt
    Generating a 4096 bit RSA private key
    ...................................................................................................................................................................................................................................++
    ...............................................++
    writing new private key to 'ca.key'
    -----
    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) []:BeiJing 		# 省份
    Locality Name (eg, city) [Default City]:BeiJing 	# 城市名称
    Organization Name (eg, company) [Default Company Ltd]:helloworld	# 公司名称
    Organizational Unit Name (eg, section) []:IT	# 部?
    Common Name (eg, your name or your server's hostname) []:helloworld.ca	# 通用名称(例如,您的名称或服务器的主机名) 
    Email Address []:123456789@qq.com	# 邮箱
    
    
    
    # 查看证书文件
    [root@www certs]# ll
    总用量 16
    -rw-r--r--. 1 root root 2114 3月  26 21:13 ca.crt
    -rw-r--r--. 1 root root 3272 3月  26 21:13 ca.key
    -rw-r--r--. 1 root root 1756 3月  26 21:19 www.helloworld.net.csr
    -rw-r--r--. 1 root root 3272 3月  26 21:19 www.helloworld.net.key
    
    
    # 签发证书
    [root@www certs]#  openssl x509 -req -days 3650 -in www.helloworld.net.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out www.helloworld.net.crt
    Signature ok	(签名 ok)
    subject=/C=CN/ST=BeiJing/L=BeiJing/O=helloworld.net/OU=IT/CN=helloworld.net/emailAddress=123456789@qq.com
    Getting CA Private Key
    
    
    # 验证证书内容
    [root@www certs]# openssl x509 -in www.helloworld.net.crt -noout -text
    Certificate:
        Data:
            Version: 1 (0x0)
            Serial Number:
                c8:26:cd:52:d9:6d:ec:37
        Signature Algorithm: sha256WithRSAEncryption
            Issuer: C=CN, ST=BeiJing, L=BeiJing, O=helloworld, OU=IT, CN=helloworld.ca/emailAddress=123456789@qq.com
            Validity
                Not Before: Mar 26 13:20:39 2021 GMT
                Not After : Mar 24 13:20:39 2031 GMT
            Subject: C=CN, ST=BeiJing, L=BeiJing, O=helloworld.net, OU=IT, CN=helloworld.net/emailAddress=123456789@qq.com
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    Public-Key: (4096 bit)
    
    
    

    Nginx证书配置

    # 编辑主配置文件(正常需要在写一个配置文件的,这里https只有这个server下的loation生效)
    [root@www certs]# vi /apps/nginx/conf/nginx.conf
       server {
           listen       80;
    
           listen 443 ssl;	# 无论访问我的80还是443这些location还是一致的
           ssl_certificate /apps/nginx/certs/www.helloworld.net.crt;	# 公钥位置
           ssl_certificate_key /apps/nginx/certs/www.helloworld.net.key;	# 私钥位置
           ssl_session_cache shared:sslcache:20m;	# 缓存是shared然后是sslcache这个名称,大小是20m
           ssl_session_timeout 5m;	# 超时时间是5分钟
           
    # 启动nginx验证证书(这个时候就可以通过https访问我们的网站,但是这时候使用http访问也没问题,因为我们还没有做全站https,所以访问的时候需要自己指定https协议,浏览器会提示不信任)
    [root@www certs]# /apps/nginx/sbin/nginx -t
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    https://www.helloworld.net/
    
    

    实现多域名HTTPS

    Nginx?持基于单个IP实现多域名的功能,并且还?持单IP多域名的基础之上实现HTTPS,其实是基于Nginx的SNI(Server Name Indication)功能实现,SNI是为了解决?个Nginx服务器内使??个IP绑定多个域名和证书的功能,其具体功能是客户端在连接到服务器建?SSL链接之前先发送要访问站点的域名(Hostname),这样服务器再根据这个域名返回给客户端?个合适的证书。

    # 这里TLS SNI support enabled可以看到SNI功能已经开启了
    [root@www certs]# /apps/nginx/sbin/nginx -V
    nginx version: nginx/1.18.0
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.0.2k-fips  26 Jan 2017
    TLS SNI support enabled
    
    
    # 制作key和csr?件
    [root@www certs]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout mobile.helloworld.net.key -out mobile.helloworld.net.csr
    Generating a 4096 bit RSA private key
    ........................................................................................++
    .............................................................++
    writing new private key to 'mobile.helloworld.net.key'
    -----
    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) []:BeiJing
    Locality Name (eg, city) [Default City]:BeiJing
    Organization Name (eg, company) [Default Company Ltd]:helloworld
    Organizational Unit Name (eg, section) []:IT
    Common Name (eg, your name or your server's hostname) []::mobile.magedu.net
    Email Address []:123456789@qq.com
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    
    
    # 签名证书
    [root@www certs]# openssl x509 -req -days 3650 -in mobile.helloworld.net.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out mobile.helloworld.net.crt
    Signature ok	(证书 ok)
    subject=/C=CN/ST=BeiJing/L=BeiJing/O=helloworld/OU=IT/CN=helloworld.com/emailAddress=123456789@qq.com
    Getting CA Private Key
    
    # 验证证书内容
    [root@s2 certs]# openssl x509 -in mobile.helloworld.net.crt -noout -text
    
    
    # #Nginx 配置(配置一个单独的文件,mobile.helloworld.net表示移动端,当访问移动端的时候,也可以使用ssl)
    [root@www certs]# vi /apps/nginx/conf/conf.d/mobile.conf
    server {
            listen 80;
                    server_name mobile.helloworld.net;
                    location / {
                            root html;
                            index index.html index.htm;
                    }
    
                    location /linux38 {
                            root /data/nginx/mobile/html;
                            index index.html index.htm;
                    }
    
                    location /python {
                            root /data/nginx/mobile/html;
                            index index.html index.htm;
                    }
    
    }
    
    server {
            listen 443 ssl;
                    server_name mobile.helloworld.net;
                    ssl_certificate /apps/nginx/certs/mobile.helloworld.net.crt;
                    ssl_certificate_key /apps/nginx/certs/mobile.helloworld.net.key;
                    ssl_session_cache shared:sslcache:20m;
                    ssl_session_timeout 10m;
    
                    location / {
                            root html;
                            index index.html index.htm;
                    }
    
                    location /linux38 {
                            root /data/nginx/mobile/html;
                            index index.html index.htm;
                    }
    
                    location /python {
                            root /data/nginx/mobile/html;
                            index index.html index.htm;
                    }
    }
    
    # 创建测试文件
    [root@www certs]# mkdir -pv /data/nginx/mobile/html/{linux38,python}
    mkdir: 已创建目录 "/data/nginx/mobile"
    mkdir: 已创建目录 "/data/nginx/mobile/html"
    mkdir: 已创建目录 "/data/nginx/mobile/html/linux38"
    mkdir: 已创建目录 "/data/nginx/mobile/html/python"
    [root@www certs]# echo  /data/nginx/mobile/html/linux38 > /data/nginx/mobile/html/linux38/index.html
    [root@www certs]# mkdir -pv /data/nginx/mobile/html/python > /data/nginx/mobile/html/python/index.html
    
    
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -t
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
    # hosts文件添加主机名
    192.168.127.130 www.helloworld.net
    192.168.127.130 mobile.helloworld.net
    
    # 访问测试(我可以使用http协议访问,也可以使用https协议访问)
    http://www.helloworld.net
    https://mobile.helloworld.net/
    

    关于favicon.ico

    favicon.ico ?件是浏览器收藏?址时显示的图标,当客户端使?浏览器问??时,浏览器会??主动发起请求获取??的favicon.ico?件,但是当浏览器请求的favicon.ico?件不存在时,服务器会记录404?志,?且浏览器也会显示404报错。

    #?:服务器不记录访问?志:
     #location = /favicon.ico {
     # 	log_not_found off;
     #	access_log off;
     #}
    
    ## favicon.ico占用 error_log日志大量信息,把我们真正需要查看的日志给覆盖。因此这里,我们通过 log_not_found off 关闭它。
    
    ## log_not_found on|off,默认为on。
    ### 启用或禁用404错误日志,这个指令可以用来禁止nginx记录找不到rebots.txt或favicon.ico这类文件的错误信息
    
     
    #?:将图标保存到指定?录访问:
     #location ~ ^/favicon\.ico$ {
     	location = /favicon.ico {
     	root /data/nginx/html/pc/images;
     	expires 90d; #设置?件过期时间
     	}
     }
    ##################################下面示例
    
    # 创建目录
    [root@www ~]# mkdir -pv /data/nginx/static
    mkdir: 已创建目录 "/data/nginx/static"
    
    
    # 找一个图标(就是一个小Logo)
    [root@www ~]# cd /data/nginx/static/
    [root@www static]# wget https://www.baidu.com/favicon.ico
    --2021-03-26 22:15:11--  https://www.baidu.com/favicon.ico
    正在解析主机 www.baidu.com (www.baidu.com)... 110.242.68.4, 110.242.68.3
    正在连接 www.baidu.com (www.baidu.com)|110.242.68.4|:443... 已连接。
    已发出 HTTP 请求,正在等待回应... 200 OK
    长度:16958 (17K) [image/x-icon]
    正在保存至: “favicon.ico”
    
    100%[==================================================>] 16,958      --.-K/s 用时 0s      
    
    2021-03-26 22:15:11 (211 MB/s) - 已保存 “favicon.ico” [16958/16958])
    
    [root@www static]# ls
    favicon.ico
    
    
    
    # 编辑配置文件(在子配置文件中配置)
    [root@www certs]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
            listen 80;
            server_name www.helloworld.net;
    
    		...
    		
            location = /favicon.ico {		# 写一个location 请求的资源是否精确等于favicon.ico(utl需要些www.helloworld.net/favicon.ico/index.html否者有可能访问不到)如果是,就直接显示了,等于号的优先级是最高的
                    root /data/nginx/static;		# 指定路径
            }
    }
    
    
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
    # 访问测试(浏览器调试页面就不会报/favicon.ico找不到了,这个类型是x-icon的是一个很特殊的格式)
    www.helloworld.net
    

    安全选项

    隐藏Nginx版本号

    # 更改nginx源码信息并重新编译Nginx(响应报文的Server服务名是定义在nginx源码中的,可需要更改源码,自定义名字,然后重新编译,在启动)
    [root@www certs]# vi + 49 /usr/local/src/nginx-1.18.0/src/http/ngx_http_header_filter_module.c 
    49 static u_char ngx_http_server_string[] = "Server: helloworld" CRLF;	# 定义响应报?中的server字段信息为helloworld
    
    
    
    # 关闭nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s stop
    
    # 切换目录
    echo-nginx-module-master/ nginx-1.18.0/             
    [root@www certs]# cd /usr/local/src/nginx-1.18.0/
    
    # 编译
    [root@www nginx-1.18.0]# pwd
    /usr/local/src/nginx-1.18.0
    [root@www nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads --add-module=/usr/local/src/echo-nginx-module-master&& make && make install
    
    
    # 启动nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    [root@www certs]# /apps/nginx/sbin/nginx
    
    [root@www nginx-1.18.0]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port                Peer Address:Port              
    LISTEN     0      128                *:80                             *:*                  
    LISTEN     0      128                *:22                             *:*                  
    LISTEN     0      100        127.0.0.1:25                             *:*                  
    LISTEN     0      128                *:443                            *:*                  
    LISTEN     0      128               :::22                            :::*                  
    LISTEN     0      100              ::1:25                            :::* 
    
    
    # 验证
    [root@localhost ~]# curl -I www.helloworld.net
    HTTP/1.1 200 OK
    Server: helloworld		# 修改成功,显示为我们自定义的名字
    Date: Sat, 27 Mar 2021 05:17:48 GMT
    Content-Type: text/html
    Content-Length: 21
    Last-Modified: Wed, 24 Mar 2021 12:24:22 GMT
    Connection: keep-alive
    ETag: "605b2f76-15"
    Accept-Ranges: bytes
    
    
    

    升级OpenSSL版本

    ?脏出?(英语:Heartbleed),也简称为??漏洞,是?个出现在加密程序库OpenSSL的安全漏洞,该程序库?泛?于实现互联?的传输层安全(TLS)协议。它于2012年被引?了软件中,2014年4??次向公众披露。只要使?的是存在缺陷的OpenSSL实例,?论是服务器还是客户端,都可能因此?受到攻击。此问题的原因是在实现TLS的?跳扩展时没有对输?进?适当验证(缺少边界检查),因此漏洞的名称来源于“?跳”(heartbeat),该程序错误属于缓冲区过读,即可以读取的数据?应该允许读取的还多。

    OpenSSL官网:https://www.openssl.org/

    # 准备OpenSSL源码包
    [root@www nginx-1.18.0]# wget -P /usr/local/src/ https://www.openssl.org/source/openssl-1.1.1k.tar.gz
    
    [root@www src]# ls
    echo-nginx-module-master  nginx-1.18.0  nginx-1.18.0.tar.gz  openssl-1.1.1k.tar.gz
    
    # 解压
    [root@www ~]# tar xvf /usr/local/src/openssl-1.1.1k.tar.gz -C /usr/local/src/
    
    [root@www ~]# ls /usr/local/src/
    echo-nginx-module-master  nginx-1.18.0.tar.gz  openssl-1.1.1k.tar.gz
    nginx-1.18.0              openssl-1.1.1k
    
    
    # 停止nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s stop 
    
    
    # 编译安装Nginx并制定新版本OpenSSL路径
    
    [root@www nginx-1.18.0]# ./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads --add-module=/usr/local/src/echo-nginx-module-master --with-openssl=/usr/local/src/openssl-1.1.1k && make && make install
    
    
    # 验证并启动Nginx(--with-openssl=/usr/local/src/openssl-1.1.1k可以看到openssl的版本已经是1.1.1k了)
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -t
    [root@www certs]# /apps/nginx/sbin/nginx
    
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -V
    nginx version: nginx/1.18.0
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.1.1k  25 Mar 2021
    TLS SNI support enabled
    configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads --add-module=/usr/local/src/echo-nginx-module-master --with-openssl=/usr/local/src/openssl-1.1.1k
    
    
    

    Nginx Rewrite相关功能

    Nginx服务器利?ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(PerlCompatible Regular Expressions),因此编译之前要安装PCRE库(编译安装需要安装,开启pcre,编译前先安装好nginx的依赖包,yum安装nginx默认已经安装),rewrite是nginx服务器的重要功能之?,?于实现URL的重写,URL的重写是?常有?的功能,?如它可以在我们改变?站结构之后,不需要客户端修改原来的书签(用户可能收藏网址直接点击打开,但是我们的域名和路径可能发生了变化,但是不能让用户访问不了吧,所以这个方式就是不改变用户的访问方式,改变用户的访问结果,将域名重定向),也?需其他?站修改我们的链接,就可以设置为访问,另外还可以在?定程度上提??站的安全性。

    http://www.pcre.org/ # PCRE官?站点

    # 查看ngx_http_rewrite_module模块是否安装
    

    ngx_http_rewrite_module模块指令

    https://nginx.org/en/docs/http/ngx_http_rewrite_module.html

    if指令

    ?于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进?配置,Nginx的if语法仅能使?if做单次判断,不?持使?if else或者if elif这样的多重判断,?法如下:

    	if (条件匹配) {
    		action
    	}
    

    使?正则表达式对变量进?匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使?以下符号链接(!感叹号标识取反):

    	=: #?较变量和字符串是否相等,相等时if指令认为该条件为true,反之为false。
    	
    	!=: #?较变量和字符串是否不相等,不相等时if指令认为条件为true,反之为false。
    	
    	~: #表示在匹配过程中区分??写字符,(可以通过正则表达式匹配),满?匹配条件为真,不满?为假。
    	
    	!~:#为区分??写字符且匹配结果不匹配,不满?为真,满?为假。
    	
    	~*: #表示在匹配过程中不区分??写字符,(可以通过正则表达式匹配),满?匹配条件为真,不满?为假。
    	
    	!~*: #为不区分??字符且匹配结果不匹配,满?为假,不满?为真。
    	
    	-f 和 !-f: #判断请求的?件是否存在和!-f是否不存在
    	
    	-d 和 !-d: #判断请求的?录是否存在和!-d是否不存在
    	
    	-x 和 !-x: #判断?件是否可执?和!-x是否不可执?。
    	
    	-e 和 !-e: #判断请求的?件或?录是否存在和!-e是否不存在(包括?件、?录、软链接)。
    	
    	注: 如果$变量的值为空字符串或是以0开头的任意字符串,则if指令认为该条件为false,其他条件为true,?且在nginx 1.0.1版本之前$变量的值为0还会是false。
    

    示例

    # 编辑子配置文件
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    					# 配置证书,写在server中指定域名server_name www..helloworld.net :对所有location生效,否者https无法验证
    		listen 443 ssl;
    		server_name www..helloworld.net;
    		ssl_certificate /apps/nginx/certs/mobile.helloworld.net.crt;
    		ssl_certificate_key /apps/nginx/certs/mobile.helloworld.net.key;
    		ssl_session_cache shared:sslcache:20m;
    		ssl_session_timeout 10m;
    
    
    		...
    		
            location /main {		
                    index index.html;
                    default_type text/html;
                    echo "hello world,main-->";
                    echo_reset_timer;
                    echo_location /sub1;
                    echo_location /sub2;
                    echo "took $echo_timer_elapsed sec for total.";
    
    				# 判断变量$scheme是什么协议并输出,判断变量 $request_filename当前请求的资源?件的路径名称,!-f文件是否不存在,如果不存在就echo
                    if ( $scheme = http){
                            echo "if -----> $scheme";
                    }
    
                    if ($scheme = https){
                            echo "if -----> $scheme";
                    }
    
                    # if (!-f $request_filename) {			# 这个如果要使用,要把上面的两个if注释掉,上面的等于号优先级高,不会执行下面的if,上面的执行完下面的的就不执行了
                    #         echo " $request_filename -----> file is not exist";
                    # }
            }
    
    }
    
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
    # 测试(http测试成功)
    [root@localhost ~]# curl http://www.helloworld.net/main
    eif -----> http
    
    # 测试(-k 忽略证书,https测试成功)
    [root@localhost ~]# curl -k  https://www.helloworld.net/main
    if -----> https
    
    
    
    # 测试(在上面的if语句注释掉的情况下,测试网页文件是否存在,网页不存在成功)
    [root@localhost ~]# curl -k  https://www.helloworld.net/main/index2.html
    echo  /apps/nginx/html/main/index2.html -----> file is not exist"
    
    
    

    set指令

    指定key,并给其定义?个变量,变量可以调?Nginx内置变量赋值给key,另外set定义格式为set $key$value,及?论是key还是value都要加$符号。(set指令,变量赋值)

    # 修改子配置文件
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    
    			...
    			
            location /main {
                    set $Annotation "-----> file is not exist(thi is a set)";
    
                    if ( !-f $request_filename) {
                            echo  " $request_filename $Annotation";
                    }
            }
            
    # 重载nginx
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    
    # 检测(测试成功)
    [root@localhost ~]# curl -k  https://www.helloworld.net/main/index2.html
    /apps/nginx/html/main/index2.html -----> file is not exist(thi is a set)"
    
    

    break指令

    ?于中断当前相同作?域(location)中的其他Nginx配置,与该指令处于同?作?域的Nginx配置中,位于它前?的配置?效,位于后?的指令配置就不再?效了,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上?层作?域继续向下读取配置,该指令可以在server块和location块以及if块中使?,使?语法如下:

    server {
    
    			...
    			
            location /main {
                    set $Annotation "-----> file is not exist(thi is a set)";
                    echo $Annotation;
    
                    break;	# (此break打断下面的set语句,不在执行,在这个location中这个break一下的除了echo指令,别的都不执行,if也不执行)
                    set $my_port $server_port;
    
            #       break;	# (break对echo不生效)
                    echo $my_port "thi is break";
    
            #       if ( !-f $request_filename) {
            #                echo "echo " $request_filename $Annotation";
            #        }
            }
            
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
            
    # 测试(正常注释掉break,状态码会被赋值打印出来)
    set $Annotation "-----> file is not exist(thi is a set)";
    echo $Annotation;
    # break;
    set $my_port $server_port;
    break;	#(此break对echo不生效,echo照样执行,$my_port已被赋值443)
    echo $my_port "thi is break";
    
    [root@localhost ~]# curl -k  https://www.helloworld.net/main
    -----> file is not exist(thi is a set)
    443 thi is break
    
    
    # 测试(break打断执行的情况,echo照样执行了)
    set $Annotation "-----> file is not exist(thi is a set)";
    echo $Annotation;
    break;
    set $my_port $server_port;
    break;
    echo $my_port "thi is break";
    
    [root@localhost ~]# curl -k  https://www.helloworld.net/main/index2.html
    -----> file is not exist(thi is a set)
     thi is break
    
    

    return指令

    从nginx版本0.8.42开始?持,return?于完成对请求的处理,并直接向客户端返回响应状态码,?如其可以指定重定向URL(对于特殊重定向状态码,301/302等) 或者是指定提示?本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执?,return可以在server、if和location块进?配置,?法如下:

    # return code; #返回给客户端指定的HTTP状态码
    # return code (text); #返回给客户端的状态码及响应体内容,可以调?变量
    # return code URL; #返回给客户端的URL地址
    
    
    # 修改子配置文件
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    
    			...
    			
            location /main {
    
                    if ( $scheme = http ){
                    		# return 301 https://www.helloworld.net
                            return 500 "service error";
                            echo "if ------> $scheme";
                    }
    
                    if ( $scheme = https ){
                            echo "if ----> $scheme";
                    }
            }
            
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
    
    # 访问测试(https测试成功)
    [root@localhost ~]# curl -k  https://www.helloworld.net/main
    if ----> https
    
    # 访问测试(http测试,我们自己return回来的,返回值,状态码500)
    [root@localhost ~]# curl  http://www.helloworld.net/main
    service error
    [root@localhost ~]# curl  -I http://www.helloworld.net/main/
    HTTP/1.1 500 Internal Server Error
    Server: helloworld
    Date: Sat, 27 Mar 2021 13:41:34 GMT
    Content-Type: text/html
    Content-Length: 13
    Connection: keep-alive
    
    
    # 测试return一个URL
    if ( $scheme = http ){
    	return 301 https://www.helloworld.net
    	# return 500 "service error";
    	echo "if ------> $scheme";
    }
    
    [root@www nginx-1.18.0]# /apps/nginx/sbin/nginx -s reload
    
    # -L参数会让 HTTP 请求跟随服务器的重定向。curl 默认不跟随重定向。
    # -k参数指定跳过 SSL 检测。
    #-I参数向服务器发出 HEAD 请求,然会将服务器返回的 HTTP 标头打印出来。
    [root@localhost ~]# curl -L -k  http://www.helloworld.net/main 
    /data/nginx/html/pc/	# 正常显示我们return的url地址内容
    
    [root@localhost ~]# curl -L -k  -I http://www.helloworld.net/main 
    HTTP/1.1 301 Moved Permanently
    Server: helloworld
    Date: Sat, 27 Mar 2021 14:12:23 GMT
    Content-Type: text/html
    Content-Length: 162
    Connection: keep-alive
    Location: https://www.helloworld.net	# 可以看到http请求被301重定向到https地址
    
    HTTP/1.1 200 OK
    Server: helloworld
    Date: Sat, 27 Mar 2021 14:12:23 GMT
    Content-Type: text/html
    Content-Length: 21
    Last-Modified: Wed, 24 Mar 2021 12:24:22 GMT
    Connection: keep-alive
    ETag: "605b2f76-15"
    Accept-Ranges: bytes
    
    

    rewrite_log指令

    可以通过 rewrite_log on; 记录rewrite(是否记录重定向进错误日志)

    设置是否开启记录ngx_http_rewrite_module模块?志记录到error_log?志?件当中,可以配置在http、server、location或if当中,需要?志级别为notice (notice 公告,比 info 还需要被注意到的一些信息内容;) 用来记录重写日志的。对于调试重写规则建议开启。

    默认情况下,"rewrite_log on;"只有在配置文件"error_log logs/error.log notice;"已经标记需要记录哪些非默认事件级别时才会起作用。

    “设置某个日志级别会导致记录指定的和更严重的日志级别的所有消息。”

    所以,第一"error_log logs/error.log notice;",然后"rewrite_log on;"和error.log开始接收改写记录

    # 修改子配置文件,修改错误日志级别为notice(我们在这个server中定义了错误日志,所以使用的是这个server的日志,所以访问这个server的时候,使用过的是这个server的错误日志地址,而不是主配置文件错误日志地址)
    [root@www nginx-1.18.0]# vi /apps/nginx/conf/conf.d/pc.conf 
    
    server {
            listen 80;
            listen 443 ssl;
    
            error_page 500 502 503 504 404 /error.html;
            
            error_log /apps/nginx/logs/www-helloworld-net_error.log notice;		# 开启notice,比 info 还需要被注意到的一些信息内容
            #error_log /apps/nginx/logs/www-helloworld-net_error.log error;
    
    
    
    			...
    			
            location /main {
                    index index.html;
                    default_type text/html;
    
                    set $name helloworld;
                    echo $name;
    
                    rewrite_log on;		# 开启rewrite_log会将重定向日志记录在/apps/nginx/logs/www-helloworld-net_error.log
    
                    if ( $scheme = http ){
                            rewrite / https://www.cnblogs.com/hao-ran/ permanent;		# rewrite_log on进对rewrite重定向生效
                            #return 301 https://www.helloworld.net;		# return的ur虽然也实现了重定向的功能,但是此操作默认记录在错误日志中
                            #return 500 "service error";
                            echo "if ------> $scheme";
                    }
    
                    }
    
            }
    }
    
    
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
    # 测试(注释#rewrite_log on,正常情况下,不会对rewrite进行记录进错误日志,但不管是否都开都会记录在访问日志中,访问日志中可能不会定义重定向的地址,而显示状态码301)
    location /main {
    	index index.html;
    	default_type text/html;
    	set $name helloworld;
    	echo $name;
    	#rewrite_log on;
    if ( $scheme = http ){
    	rewrite / https://www.cnblogs.com/hao-ran/ permanent;
    	#return 301 https://www.helloworld.net;
    	#return 500 "service error";
    	echo "if ------> $scheme";
    	}
    
    
    [root@www ~]# date
    2021年 03月 28日 星期日 12:14:03 CST
    
    [root@localhost ~]# curl -k -L -I  http://www.helloworld.net/main
    HTTP/1.1 301 Moved Permanently
    Server: helloworld
    Date: Sun, 28 Mar 2021 04:14:15 GMT
    Content-Type: text/html
    Content-Length: 162
    Connection: keep-alive
    Location: https://www.cnblogs.com/hao-ran/		# 重定向到这个地址
    
    HTTP/1.1 200 OK		# 重定向成功
    Date: Sun, 28 Mar 2021 04:14:15 GMT
    Content-Type: text/html; charset=utf-8
    Connection: keep-alive
    Vary: Accept-Encoding
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Set-Cookie: .AspNetCore.Antiforgery.b8-pDmTq1XM=CfDJ8EklyHYHyB5Oj4onWtxTnxYmXuj6n5DLyz8zRz138ArjUzkgVKTeSVvR5Ur3uVlcxUM1XV1wwlBE19ELcWkEc8VFg9vy-NBu9O3JRngisdPEVxeqS9B_Hc0AVWMbuNGtdBCRCdDS2HsqL6jM4_k5VHI; path=/; httponly
    Strict-Transport-Security: max-age=2592000; includeSubDomains; preload
    X-Frame-Options: SAMEORIGIN
    
    [root@www ~]# tail -f /apps/nginx/logs/www-helloworld-net_error.log 
    2021/03/28 12:11:02 [notice] 36905#36905: *254 rewritten redirect: "https://www.cnblogs.com/hao-ran/", client: 192.168.127.128, server: www.helloworld.net, request: "HEAD / HTTP/1.1", host: "www.helloworld.net"		# 日志中未有12:14:03的日志
    
    
    # 测试(rewrite_log on,打开)
    location /main {
    	index index.html;
    	default_type text/html;
    	set $name helloworld;
    	echo $name;
    	rewrite_log on;
    if ( $scheme = http ){
    	rewrite / https://www.cnblogs.com/hao-ran/ permanent;
    	#return 301 https://www.helloworld.net;
    	#return 500 "service error";
    	echo "if ------> $scheme";
    	}
    
    # 重载nginx
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    [root@www ~]# date
    2021年 03月 28日 星期日 12:24:01 CST
    
    [root@localhost ~]# curl -k -L -I  http://www.helloworld.net/main
    HTTP/1.1 301 Moved Permanently
    Server: helloworld
    Date: Sun, 28 Mar 2021 04:24:24 GMT
    Content-Type: text/html
    Content-Length: 162
    Connection: keep-alive
    Location: https://www.cnblogs.com/hao-ran/
    
    HTTP/1.1 200 OK
    Date: Sun, 28 Mar 2021 04:24:24 GMT
    Content-Type: text/html; charset=utf-8
    Connection: keep-alive
    Vary: Accept-Encoding
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Set-Cookie: .AspNetCore.Antiforgery.b8-pDmTq1XM=CfDJ8EklyHYHyB5Oj4onWtxTnxbFm0AMcSEuUTEv1f7Hj5J1TEKb-8vwJGxA_Bii7thTm2FCDYPVz3RJWmHZ2XJGdx3NLv1b1tICQSFx-7sSVvp53OqJg4bbcD1gI_YWgX1d4Xf2OAfoWdIptTRfpzJuONY; path=/; httponly
    Strict-Transport-Security: max-age=2592000; includeSubDomains; preload
    X-Frame-Options: SAMEORIGIN
    
    
    # 监视错误日志
    [root@www ~]# tail -f /apps/nginx/logs/www-helloworld-net_error.log 
    2021/03/28 12:24:24 [notice] 53449#53449: *256 "/" matches "/main", client: 192.168.127.128, server: www.helloworld.net, request: "HEAD /main HTTP/1.1", host: "www.helloworld.net"
    2021/03/28 12:24:24 [notice] 53449#53449: *256 rewritten redirect: "https://www.cnblogs.com/hao-ran/", client: 192.168.127.128, server: www.helloworld.net, request: "HEAD /main HTTP/1.1", host: "www.helloworld.net"		# 错误日志中记录成功
    
    

    rewrite指令

    通过正则表达式的匹配来改变URI,可以同时存在?个或多个指令,按照顺序依次对URI进?匹配,
    rewrite主要是针对?户请求的URL或者是URI做具体处理,以下是URL和URI的具体介绍:

    	URI(universal resource identifier):通?资源标识符,标识?个资源的路径,可以不带协议。
    	
    	URL(uniform resource location):统?资源定位符,是?于在Internet中描述资源的字符串,是URI的?集,主要包括传输协议(scheme)、主机(IP、端?号或者域名)和资源具体地址(?录和?件名)等三部分,?般格式为 scheme://主机名[:端?号][/资源路径],如:http://www.a.com:8080/path/file/index.html就是?个URL路径,URL必须带访问协议。
    
    	每个URL都是?个URI,但是URI不都是URL。
    	例如:
    		http://example.org:8080/path/to/resource.txt #URI/URL(是一个url也是一个uri)
    		ftp://example.org/resource.txt #URI/URL(是一个url也是一个uri)
    		/absolute/path/to/resource.txt #URI(这种不带协议,不带主机地址的,在服务器上路径,他只是一个uri)
    

    rewrite的官?介绍地址:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite,
    rewrite可以配置在server、location、if,其具体使??式为:

    	rewrite regex replacement [flag];
    	rewrite 正则匹配客户端请求 修改后的请求 标记位;
    	(正则匹配客户端请求:通过某种方式来匹配用户的请求,对那些请求做处理,并不是对所有请求都要做处理,一定是对不符合要求的请求才做处理)
    	
    	示例;
    	        root html/file/;
    	        location /first {	
    	        	rewrite ^/first(.*) /second$1 last;		# ^表示以什么开头,这里以first开头,把/first的路径重写成/second,(.*)表示分组,这个分组是/first下面的一个路径,这个路径很可能是文件名,但是这个请求的文件名我不知道是什么,所以说把他分组,分组之后/second下的$1就是对(.*)这个分组的引用,用户亲求的是什么这个$1就是什么,last表示结束符
    	        	return 200 'first';
    	        }
    	        
    	        location /second {
    	        	rewrite /second(.*) /third$1 break;
    	        	return 200 'second';
    	        }
    	        
    	        location /third {
    	        	return 200 'third';
    	        }
    

    rewrite将?户请求的URI基于regex所描述的模式进?检查,匹配到时将其替换为表达式指定的新的URI。

    注意:如果在同?级配置块中存在多个rewrite规则,那么会?下?下逐个检查;被某条件规则替换完成后,会重新?轮的替换检查,隐含有循环机制,但不超过10次;如果超过,提示500响应码,[flag]所表示的标志位?于控制此循环机制,如果替换后的URL是以http://或https://开头,则替换结果会直接以重向返回给客户端, 即永久重定向301

    rewrite flag使?介绍

    利?nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是redirect(临时重定向,状态码302)、permanent(永久重定向,状态码301)、break和last。其中前两种是跳转型的flag,后两种是代理型,跳转型是指有客户端浏览器重新对新地址进?请求,代理型是在WEB服务器内部实现跳转的。

    Syntax: rewrite regex replacement [flag]; #通过正则表达式处理?户请求并返回替换后的数据包。
    Default: —
    Context: server, location, if (作用域)

    	redirect;
    	#临时重定向,重写完成后以临时重定向?式直接返回重写后?成的新URL给客户端,由客户端重新发起请求;使?相对路径,或者http://或https://开头,状态码:302
    	
    	permanent;
    	#重写完成后以永久重定向?式直接返回重写后?成的新URL给客户端,由客户端重新发起请求,状态码:301
    	
    	last;
    	#重写完成后停?对当前URI在当前location中后续的其它重写操作,?后对新的URL启动新?轮重写检查,不建议在多location配置环境中使?
    	
    	break;
    	#重写完成后停?对当前URL在当前location中后续的其它重写操作,?后直接将匹配结果返还给客户端即结束循环并返回数据给客户端,建议在多location配置环境中使?
    

    rewrite案例-域名永久与临时重定向

    要求:因业务需要,将访问源域名 www.helloworld.net 的请求永久重定向到www.helloworld.com 。
    临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存(浏览器缓存重定向的结果,当以后再次访问同一个域名的时候,会通过缓存访问重定向之后的路径,所以浏览器就不需要在去服务器请求了,会直接访问缓存中的重定向的新的路径)。

    临时重定向

    域名临时重定向(temporarily moved)状态码为302,告诉浏览器域名不是固定重定向到当前?标域名,后期可能随时会更改,因此浏览器不会缓存当前域名的解析记录,?浏览器会缓存永久重定向的DNS解析记录,这也是临时重定向与永久重定向最?的本质区别。

    # 编辑子配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    
    		...
    
            location / {
                    root /data/nginx/html/pc;
                    index index.html
                    rewrite / https://www.cnblogs.com/hao-ran/ redirect;		# 匹配/,匹配到后重定向到https://www.cnblogs.com/hao-ran/
            }
    }
    
    
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
    
    # 测试
    root@localhost ~]# curl -k -L -I  www.helloworld.net
    HTTP/1.1 302 Moved Temporarily		# 状态码302临时重定向,不会缓存域名解析记录(A记录)
    Server: helloworld
    Date: Sun, 28 Mar 2021 03:34:21 GMT
    Content-Type: text/html
    Content-Length: 138
    Connection: keep-alive
    Location: https://www.cnblogs.com/hao-ran/		# 重定向到https://www.cnblogs.com/hao-ran/
    
    HTTP/1.1 200 OK		# 访问https://www.cnblogs.com/hao-ran/	状态码200成功,重定向成功
    Date: Sun, 28 Mar 2021 03:34:21 GMT
    Content-Type: text/html; charset=utf-8
    Connection: keep-alive
    Vary: Accept-Encoding
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Set-Cookie: .AspNetCore.Antiforgery.b8-pDmTq1XM=CfDJ8EklyHYHyB5Oj4onWtxTnxYZtnf_Zr3RHwKH2vL0PsWr-s9YTtf9M-OmGU5HLHYW_fKcLAdDHpvwvEDOOJpUMcGzxdRRCfb5JPg9S02JW8nLcafyY66ADDtiUr7xzKE_-YcntAK9jUt8Ipmy7JOKTf4; path=/; httponly
    Strict-Transport-Security: max-age=2592000; includeSubDomains; preload
    X-Frame-Options: SAMEORIGIN
    
    

    永久重定向

    域名永久重定向(permanent redirect)状态码为301,例如京东早期的域名 www.360buy.com 由于与360公司类似,容易引起误解,于是京东光后期将域名www.360buy.com 永久重定向到了
    www.jd.com,永久重定向浏览器会缓存DNS解析记录。

    # 编辑子配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    
    		...
    
            location / {
                    root /data/nginx/html/pc;
                    index index.html
                    rewrite / https://www.cnblogs.com/hao-ran/ permanent;	# 匹配/,匹配到后permanent永久重定向到https://www.cnblogs.com/hao-ran/	,缓存DNS
            }
    }
    
    
    # 重载nginx
    [root@www certs]# /apps/nginx/sbin/nginx -s reload
    
    
    # 测试
    [root@localhost ~]# curl -k -L -I  www.helloworld.net
    HTTP/1.1 301 Moved Permanently		# 状态码301永久重定向,会缓存域名解析记录(A记录)
    Server: helloworld
    Date: Sun, 28 Mar 2021 03:46:01 GMT
    Content-Type: text/html
    Content-Length: 162
    Connection: keep-alive
    Location: https://www.cnblogs.com/hao-ran/		# 重定向到https://www.cnblogs.com/hao-ran/
    
    HTTP/1.1 200 OK		# 访问https://www.cnblogs.com/hao-ran/	状态码200成功,重定向成功
    Date: Sun, 28 Mar 2021 03:46:01 GMT
    Content-Type: text/html; charset=utf-8
    Connection: keep-alive
    Vary: Accept-Encoding
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Set-Cookie: .AspNetCore.Antiforgery.b8-pDmTq1XM=CfDJ8EklyHYHyB5Oj4onWtxTnxYWiNiF61cVBvo74rmtSbHnT0QWxxjpH6XFdMMfX_S1weVmCaCT4czOzSwokTsJVbIFICCbVE8sYqcMh_P0fVoZAMClDCoV3wLLc63oqYA-PqdiuOOP21nACWzghmTTauk; path=/; httponly
    Strict-Transport-Security: max-age=2592000; includeSubDomains; preload
    X-Frame-Options: SAMEORIGIN
    
    

    rewrite案例--brak与last

    测试:访问/break的请求被rewrite重定向?test1,?访问test1传递请求再次被rewrite重定向?test2,以此测试last和break分别有什么区别:

    break案例

    break适?于不改变客户端访问?式,但是要将访问的?的URL做单次重写的场景,?如有个?站前端??访问路径发?变化,旧版本的?站数据已经保存到了statics不能丢失,但是要将访问新版本的资源重写到新的静态资源路径到新的?录static:
    location /statics { #旧版本程序中的请求路径需要重写请求路径后再响应给客户端,不需要在跳转?其他location(旧版本程序就是旧网页)
    	root /data/nginx;
    	index index.html;
    	rewrite ^/statics/(.*) /static/pool1/$1 break;
     }
    
    location /static/pool { #新版本程序的请求路径直接响应请求(新版本程序就是新网页)
    	root /data/nginx;
    	index index.html;
     }
    
    ##################################下面示例
    
    # 备用一下文件(之前的优先级太乱了,容易冲突)
    [root@www ~]# cp /apps/nginx/conf/conf.d/pc.conf /apps/nginx/conf/conf.d/pc.conf.bak
    
    # 编译子配置文件(避免冲突全删)
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    
            location /break {
                    # return 666 "break";
                    index index.html;
                    root /data/nginx;
                    rewrite ^/break(.*) /test1/$1 break;
                    rewrite ^/test1(.*) /test2/$1 break;
            }
    
            location = /test1/index.html {		# 为了避免index index.html与主配置文件中匹配有冲突,填写绝对路径
                    #return 999 "new test1";		# 返回状态码
                    #index index.html;
                    root /data/nginx;
            }
    
            location = /test2/index.html {
                    #return 666 "new test2";		# 返回状态码
                     root /data/nginx;
                     #index index.html;
            }
    }
    
    # 创建资源路径
    [root@www ~]# mkdir -pv /data/nginx/{break,test1,test2}
    mkdir: 已创建目录 "/data/nginx/break"
    mkdir: 已创建目录 "/data/nginx/test1"
    mkdir: 已创建目录 "/data/nginx/test2"
    [root@www ~]# echo break > /data/nginx/break/index.html
    [root@www ~]# echo test1 > /data/nginx/test1/index.html
    [root@www ~]# echo test2 > /data/nginx/test2/index.html
    [root@www ~]# cat  /data/nginx/break/index.html
    break
    [root@www ~]# cat  /data/nginx/test1/index.html
    test1
    [root@www ~]# cat  /data/nginx/test2/index.html
    test2
    
    # 给页面权限
    [root@www ~]# chown -R nginx:nginx /data
    
    
    
    # 重载nginx
    [root@www ~]# /apps/nginx/sbin/nginx -t
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    
    # 测试break(访问test1和test2,他会转跳掉/test1的location,显示其中的内容)
    location /break {
    	# return 666 "break";
    	index index.html;
    	root /data/nginx;
    	rewrite ^/break(.*) /test1/$1 break;	# 把下面的注释掉,测试这个rewrite是否会重定向
    	rewrite ^/test1(.*) /test2/$1 break;	# 这个rewrite把test1转跳到test2,会后显示的因为是test2中的内容,但是这个rewrite不会执行,因为break只要匹配一次会跳出循环,不在往下执行
    	
    [root@localhost ~]# curl  -L  www.helloworld.net/break/index.html
    test1	# 测试成功,转跳掉test1的location中
    
    

    last案例

    last:对某个location的URL匹配成功后会停?当前location的后续rewrite规则,并结束当前location,然后将匹配?成的新URL跳转?其他location继续匹配,直到没有location可匹配后将最后?次location的数据返回给客户端。
    
    location /last {
    	root /data/nginx;
    	index index.html;
    	rewrite ^/last/(.*) /test1/$1 last;
    	#rewrite ^/test1/(.*) /test2/$1 last; #如果第?条rewrite规则匹配成功则不执?本条,否则执?本条rewrite规则。
    }
    
    
    location = /test1/index.html {
    	return 999 "new test1";
    	#root /opt/nginx;
    	#index index.html;
    }
    
    location = /test2/index.html {
    	return 666 "new test2";
    	#root /opt/nginx;
    	#index index.html;
    }
    
    last访问测试:
    [root@s3 ~]# curl -L http://www.hellowrld.net/last/index.html
    new test2 #会匹配多个location,直到最终全部匹配完成,返回最后?个location的匹配结果给客户端。
    
    last适?于要不改变客户端访问?式但是需做多次?的URL重写的场景,场景不是很多。
    
    ##################################下面示例
    
    # 备用一下文件(之前的优先级太乱了,容易冲突)
    [root@www ~]# cp /apps/nginx/conf/conf.d/pc.conf /apps/nginx/conf/conf.d/pc.conf.bak
    
    # 编译子配置文件(避免冲突全删)
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    
            location /last {
                    # return 666 "break";
                    index index.html;
                    root /data/nginx;
                    rewrite ^/last(.*) /test1/$1 last;		# 匹配到test的url后last会把这个url返回给浏览器,让浏览器在用这个url在请求一次,看看能不能匹配上这个url的locatlon如果有就显示这个location中的内容,如果没有就干嘛干嘛,改报错报错
                   # rewrite ^/last(.*) /test2/$1 last;		# 两个rewrite都打开last也不会重写到test2,显示的还是test1,除非把上一条注释掉
            }
    
            location = /test1/index.html {		# 为了避免index index.html与主配置文件中匹配有冲突,填写绝对路径
                    #return 999 "new test1";		# 返回状态码
            #       index index.html;
                    root /data/nginx;
            }
    
            location = /test2/index.html {
                    #return 666 "new test2";		# 返回状态码
                     root /data/nginx;
            #        index index.html;
            }
    }
    
    
    

    rewrite案例-?动跳转https

    要求:基于通信安全考虑公司?站要求全站https,因此要求将在不影响?户请求的情况下将http请求全部?动跳转?https,另外也可以实现部分location跳转。

    编辑子配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    	listen 443 ssl;
    	listen 80;
    	ssl_certificate /apps/nginx/certs/www.helloworld.net.crt;
    	ssl_certificate_key /apps/nginx/certs/www.helloworld.net.key;
    	ssl_session_cache shared:sslcache:20m;
    	ssl_session_timeout 10m;
    	server_name www.helloworld.net;
    	
    	location / {
    		root /data/nginx/html/pc;
    		index index.html;
    		if ($scheme = http ){ #未加条件判断,会导致死循环
    		rewrite / https://www.cnblogs.com/hao-ran/ permanent;
      		}
          # rewrite / https://www.helloworld.net permanent;		# 死循环写法,
    
     	}
    }
    
    # 重载nginx
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    
    # 访问测试
    [root@localhost ~]# curl  -L -k -I  www.helloworld.net
    HTTP/1.1 301 Moved Permanently
    Server: helloworld
    Date: Sun, 28 Mar 2021 08:50:51 GMT
    Content-Type: text/html
    Content-Length: 162
    Connection: keep-alive
    Location: https://www.cnblogs.com/hao-ran/		# 重定向到此地址
    
    HTTP/1.1 200 OK		# 重定向成功
    Date: Sun, 28 Mar 2021 08:50:51 GMT
    Content-Type: text/html; charset=utf-8
    Connection: keep-alive
    Vary: Accept-Encoding
    Cache-Control: no-cache, no-store
    Pragma: no-cache
    Set-Cookie: .AspNetCore.Antiforgery.b8-pDmTq1XM=CfDJ8EklyHYHyB5Oj4onWtxTnxYdL5F2O6TUPYCpLPa66OUX1UrK4Ydp2rbwZdV6_q12vyrcoM1NU5tAP0aB3mORqto3p9X67Rq6xPKq4iRGUaKf7cHjqb9JYLeov6mcCJHhmAaHaziVvoK1HeR4iDasJP0; path=/; httponly
    Strict-Transport-Security: max-age=2592000; includeSubDomains; preload
    X-Frame-Options: SAMEORIGIN
    
    
    注意:如果是因为规则匹配问题导致的陷?死循环,则报错如下:
    
    浏览器:
    	该网页无法正常运作
    	www.helloworld.net将你重定向的次数多。
    	
    curl:
    	curl: (47) Maximum (50) redirects followed
    	(curl:(47)最多(50)个重定向)
    

    rewrite案例-判断?件是否存在

    要求:当?户访问到公司?站的时输?了?个错误的URL,可以将?户重定向?官???。

    编辑子配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf 
    server {
    	listen 443 ssl;
    	listen 80;
    	ssl_certificate /apps/nginx/certs/www.helloworld.net.crt;
    	ssl_certificate_key /apps/nginx/certs/www.helloworld.net.key;
    	ssl_session_cache shared:sslcache:20m;
    	ssl_session_timeout 10m;
    	server_name www.helloworld.net;
    	
    	location / {
    		root /data/nginx/html/pc;
    		index index.html;
    #       if ($scheme = http) {
    #	       rewrite / https://www.cnblogs.com/hao-ran/ permanent;
    #	       }
    
    #       rewrite / https://www.helloworld.net permanent;
    #}
    
            if (!-f $request_filename) {
    	        # return 404 "linux35";
    	        rewrite (.*) http://www.helloworld.net/index.html;		# (.*)表示分组.点表示匹配任意一位*表示匹配任意多个.匹配任意长度字符
            }
    }
    
    # 重载nginx
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    # 访问测试(正常的主页页面)
    [root@localhost ~]# curl  -L  -k www.helloworld.net/index.html
    /data/nginx/html/pc/
    
    # 访问测试(错误的主页页面,判断不存在,转跳(重定向)到主页页面)
    [root@localhost ~]# curl -L -k  www.helloworld.net/hh.html
    /data/nginx/html/pc/
    
    

    Nginx防盗链

    防盗链基于客户端携带的referer(https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referer)实现(referer就是你在访问我们的浏览器之前,从哪个地方跳过来的,淘宝,拼多多分享一个商品链接,口令什么的,那就是一个referer,别人已复制,然后打开拼多多,他就会跳到那个商品上去,在比如我们做了推广之后,怎么看到成功,就看referer怎么转跳过来的),referer是记录打开?个??之前记录是从哪个??跳转过来的标记信息,如果别?只链接了???站图?或某个单独的资源,?不是打开了?站的整个??,这就是盗链,referer就是之前的那个?站域名,正常的referer信息有以下?种(只有知道那些是正常的referer才能知道那些是不正常的referer,如果要做防盗链的话,才能给他把不正常的referer封掉,其实就是先允许这些正常的,在把这之外的给他拒绝):

    	none:请求报??部没有referer?部,?如?户直接在浏览器输?域名访问web?站,就没有referer信息(直接在浏览器输入域名,或者收藏的直接访问的)。
    	
    	blocked:请求报?有referer?部,但?有效值,?如为空访问日志中记录的("referer":"-"显示横杠,或者为空,也就是none其实也是自己访问的所以没有信息,这个信息如果禁用了,自己都访问不了)。
    	
    	server_names:referer?部中包含本主机名及即nginx 监听的server_name。
    	
    	arbitrary_string:?定义指定字符串,但可使?*作通配符(这种是搜索引擎呀什么的跳转过来,不管做不做推广也要允许)。
    	
    	regular expression:被指定的正则表达式模式匹配到的字符串,要使?~开头,例如:~.*\.helloworld\.com。(正则的,匹配的域名,比如有的网址有很多域名,要用正则匹配,这个也不要禁用)
    

    正常通过搜索引擎搜索web ?站并访问该?站的referer信息如下:

    	#通过搜索引擎访问web?站的referer信息:
    	==> /apps/nginx/logs/access_json.log <==
    	{"@timestamp":"2019-02-28T13:58:46+08:00","host":"192.168.7.102","clientip":"192.168.0.1","size":0,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.helloworld.net","uri":"/index.html","domain":"www.helloworld.net","xff":"-","referer":"https://www.baidu.com/s?ie=utf8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=www.helloworld.net&oq=www.helloworld.net&rsv_pq=d63060680002eb69&rsv_t=de01TWnmyTdcJqph7SfI1hXgXLJxSSfUPcQ3QkWdJk%2FLNrN95ih3XOhbRs4&rqlang=cn&rsv_enter=1&inputT=321&rsv_sug3=41&rsv_sug2=0&rsv_sug4=1626","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36","status":"304"}
    

    实现web盗链

    在?个web 站点盗链另?个站点的资源信息,?如图?、视频等(web A 盗链web B需要两台服务器)

    # wab A
    ## 编辑配置文件
    [root@localhost sbin]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            
            location / {
                    root /data/nginx/html/pc/referer;
                    index index.html;
                    access_log /apps/nginx/logs/access_json.log access_json;
            }
    
    # 准备一个图片(盗链自己,用于查看日志,盗链方和被盗链方都可以看到)
    [root@www ~]# wget -P /data/nginx/images/ https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png
    
    # 改一下文件名
    [root@www ~]# mv /data/nginx/images/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png /data/nginx/images/1.png
    
    # 编辑子配置文件,填写一个location
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    
    		...
    
            location = /images/1.png {
                    root /data/nginx;
            }
    }
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 访问测试(测试成功,可以访问)
    http://www.helloworld.net/images/1.png
    
    
    # web B的nginx服务准备盗链web A图片
    ## 编辑配置文件
    [root@localhost sbin]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name daolian.helloworld.com; 	(测试用web B的域名,访问web A 的图片)
    
            location / {
                    root /data/nginx/html/pc/referer;
                    index index.html;
                    access_log /apps/nginx/logs/access_json.log access_json;	(定义日志,方便查看)
    
            }
    }
    
    
    # 创建测试页面目录
    [root@www ~]# mkdir -pv /data/nginx/html/pc/referer
    mkdir: 已创建目录 "/data/nginx/html/pc/referer"
    [root@www ~]# vi /data/nginx/html/pc/referer/index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
            <meta charset="UTF-8">
            <title>盗链页面</title>
    </head>
    
    <body>
    <a href="daolian.helloworld.con">测试盗链</a>
    <img src="http://www.helloworld.net/images/1.png">
    
    </body>
    </html>
    
    
    # 重载nginx
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    # 客户端添加hosts
    192.168.127.132 daolian.helloworld.con
    
    # 访问测试(浏览器会显示百度标志)
    http://daolian.helloworld.com/
    
    # 查看web A日志(被盗链方"http_host":"www.helloworld.net"	$host:请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名。	表示请求的服务器名 )	(盗链方"referer":"http://daolian.helloworld.com/"		$http_referer :表示当前请求上一次页面访问的地址,	表示你是访问了http://daolian.helloworld.com/后访问的www.helloworld.net我,或者是从http://daolian.helloworld.com/转跳到我,请求www.helloworld.net的主页,或者一个图片,"uri":"/images/1.png"这里只访问了我一个图片)
    [root@www ~]# tail -f /apps/nginx/logs/access_json.log 
    {"@timestamp":"2021-03-29T13:44:16+08:00","host":"192.168.127.130","clientip":"192.168.127.1","size":13908,"responsetime":0.000,"upstreamtime":"-","upstreamhost":"-","http_host":"www.helloworld.net","uri":"/images/1.png","domain":"www.helloworld.net","xff":"-","referer":"http://daolian.helloworld.com/","tcp_xff":"-","http_user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36","status":"200","baseanme":"/data/nginx/images/1.png"}
    
    
    

    实现防盗链

    基于访问安全考虑,nginx?持通过ungx_http_referer_module模块 https://nginx.org/en/docs/http/ngx_http_referer_module.html#valid_referers 检查访问请求的referer信息是否有效实现防盗链功能,定义?式如下:

    [root@s2 ~]# vim /apps/nginx/conf/conf.d/pc.conf
    location /images {
    	root /data/nginx/html/pc;
    	index index.html;
    	valid_referers none blocked server_names		# valid_referers表示有效的referer,把有效的(允许的referer放进来就行),比如none为空的,blocked没有值的,server_names把你自己的允许
    		*.example.com example.* www.example.org/galleries/		# 把一些正则匹配的其他域名,就是那些搜索引擎,比如*.example.com芯匹配的三级域名,这个example.*用芯去匹配一,二级域名,或者www.example.org/galleries/绝对域名,绝对路径
    		~\.google\.;	# 比如google等等
    
    	if ($invalid_referer) {		# 这个if意思就是除了上面允许以外的都是无效的
    		return 403;		# 那无效的怎么办,就返回一个403
     	}
    

    定义防盗链

    # web A 编辑配置文件
    [root@www conf.d]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    
    			...
    
                    location = /images/1.png {
                           root /data/nginx;
                           access_log /apps/nginx/logs/access_json.log access_json;
                           valid_referers none blocked server_name *.helloworld.net www.helloworld.*  www.helloworld.net/images  ~\.google\.  ~\.baidu\.;
            
                            if ($invalid_referer) {
                                    return 403;
                            }
    
                    }
    
    }
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # web B盗链访问测试(访问成功,但是可以浏览器调试可以看到图片没有打开,并且状态码是403,测试成功)
    http://daolian.helloworld.com/
    

    Nginx 反向代理功能

    反向代理:反向代理也叫reverse proxy,指的是代理外??户的请求到内部的指定web服务器,并将数据返回给?户的?种?式,这是?的?较多的?种?式。

    Nginx除了可以在企业提供?性能的web服务之外,另外还可以将本身不具备的请求通过某种预定义的协议转发?其它服务器处理,不同的协议就是Nginx服务器与其他服务器进?通信的?种规范,主要在不同的场景使?以下模块实现不同的功能:

    	ngx_http_proxy_module: 将客户端的请求以http协议转发?指定服务器进?处理。
    	
    	ngx_stream_proxy_module:将客户端的请求以tcp协议转发?指定服务器处理。
    	
    	ngx_http_fastcgi_module:将客户端对php的请求以fastcgi协议转发?指定服务器处理。
    	
    	ngx_http_uwsgi_module:将客户端对Python的请求以uwsgi协议转发?指定服务器处理。
    

    实现http反向代理

    要求:将?户对域 www.helloworld.net 的请求转发值后端服务器处理,官??档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html

    环境准备:

    	192.168.7.102 #Nginx 代理服务器
    
    	192.168.7.103 #后端web A,Apache部署
    
    	192.168.7.104 #后端web B,Apache部署
    
    graph TD A[用户请求] --> B(nginx) B --> |同构代理| C[后端服务器,nginx,apache,tomcat,mysql,redis] B --> |异步代理| D[php,python]

    部署后端Apache服务器

    # web A
    ## 安装httpd
    [root@localhost ~]# yum -y install httpd
    
    ## 制作测试页
    [root@localhost ~]# echo "web a" > /var/www/html/index.html
    [root@localhost ~]# cat /var/www/html/index.html 
    web A
    
    ## 启动,开机自启httpd
    [root@localhost ~]# systemctl start httpd && systemctl enable httpd
    Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
    [root@localhost ~]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port                Peer Address:Port              
    LISTEN     0      128                *:22                             *:*                  
    LISTEN     0      100        127.0.0.1:25                             *:*                  
    LISTEN     0      128               :::80                            :::*                  
    LISTEN     0      128               :::22                            :::*                  
    LISTEN     0      100              ::1:25                            :::*  
    
    ## 关闭防火墙
    [root@localhost ~]# systemctl stop firewalld
    [root@localhost ~]# setenforce 0
    
    
    
    
    
    
    # web B
    ## 安装httpd
    [root@localhost ~]# yum -y install httpd
    
    ## 制作测试页
    [root@localhost ~]# echo "web B" > /var/www/html/index.html
    [root@localhost ~]# cat /var/www/html/index.html 
    web B
    
    ## 启动,开机自启httpd
    [root@localhost ~]# systemctl start httpd && systemctl enable httpd
    Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
    [root@localhost ~]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port                Peer Address:Port              
    LISTEN     0      128                *:22                             *:*                  
    LISTEN     0      100        127.0.0.1:25                             *:*                  
    LISTEN     0      128               :::80                            :::*                  
    LISTEN     0      128               :::22                            :::*                  
    LISTEN     0      100              ::1:25                            :::*     
    
    ## 关闭防火墙
    [root@localhost ~]# systemctl stop firewalld
    [root@localhost ~]# setenforce 0
    
    
    
    
    # 客户端访问测试
    [root@localhost ~]# curl http://192.168.127.129
    web A
    [root@localhost ~]# curl http://192.168.127.131
    web B
    
    

    Nginx http 反向代理??

    官??档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

    反向代理配置参数

    proxy_pass;
    #?来设置将客户端请求转发给的后端服务器的主机,可以是主机名、IP地址:端?的?式,也可以代理到预先设置的主机群组,需要模块ngx_http_upstream_module?持。
    	location /web {
    		index index.html;
    		proxy_pass http://192.168.7.103:80;
    		#不带斜线将访问的/web(把这个/web转递给后端服务器,斜线也传递过去),等于访问后端服务器http://192.168.7.103:80/web/index.html,即后端服务器配置的站点根?录要有web?录才可以被访问,这是?个追加/web到后端服务器 http://servername:port/WEB/INDEX.HTML的操作
    		
    		proxy_pass http://192.168.7.103:80/;
     		#带斜线,等于访问后端服务器的http://192.168.7.103:80/index.html 内容返回给客户端(如果加上斜线可能是http://192.168.7.103:80//这样,他可能把第二个斜线当根了,就找后端服务器的根页面)
    	}
    	
    #重启Nginx测试访问效果:
    # curl -L http://www.magedu.net/web/index.html
    
    
    	proxy_hide_header field;
    	#?于nginx作为反向代理的时候,在返回给客户端http响应的时候,隐藏后端服务版本相应头部的信息,可以设置在http/server或location块,(fastcgi_hide_header 和proxy_hide_header的都可以用来隐藏主机信息,fastcgi_hide_header 在fastcgi模式下起作用,proxy_hide_header在proxy模式下起作用)	(默认nginx不会将响应中的Date、Server、X-Pad、X-Accel-...等响应头发送给客户端。而proxy_hide_header指令则是继续设置不需要发送的其他的响应头)
    	location /web {
    		index index.html;
    		proxy_pass http://192.168.7.103:80/;
    		proxy_hide_header ETag;
    		#proxy_hide_header Server;	# 这条指令没有意义,客户端显示的是nginx的Server头部,不是后端服务器的,后端服务器的默认已经隐藏,如果要隐藏nginx的,就用nginx的隐藏方法
    	}
    
    
    	proxy_pass_header field;
    	#默认nginx在响应报?中不传递后端服务器的?部字段Date, Server, X-Pad, X-Accel等参数,如果要传递的话则要使? proxy_pass_header field声明将后端服务器返回的值传递给客户端。
    	
    	proxy_pass_request_body on | off;
    	#是否向后端服务器发送HTTP包体部分,可以设置在http/server或location块,默认即为(on,不加也可以,可以加上显得专业,参数多)开启(这个一定要发,如果不发给服务器端,服务器端就不知道用户请求的什么)
    	
    	proxy_pass_request_headers on | off;
    	#是否将客户端的请求头部转发给后端服务器,可以设置在http/server或location块,默认即为开启(可以加上显得专业,参数多)(发给服务器端Request Headers,让服务器端知道客户使用的浏览器类型什么的)
    	
    	proxy_set_header;
    	#可以更改或添加客户端的请求头部信息内容并转发?后端服务器,?如在后端服务器想要获取客户端的真实IP的时候,就要更改每?个报?的头部,如下:
    	
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;		# $proxy_add_x_forwarded_for这个变量也可以获得
    		# proxy_set_header X-Forwarded-For $remote_addr;	($remote_addr这个变量没测试成功)
    		#添加HOST到报?头部,如果客户端为NAT上?那么其值为客户端的共?的公?IP地址,常?于在日志中记录客户端的真实IP地址。(这个值需要加,尤其是后端服务器要对客户端ip地址要做一些处理的时候,客户端服务器通过X-Forwarded-For来获取客户的IP地址,如果不加客户端的源地址会被替换成负载均衡nginx的源地址)
    	
    	proxy_connect_timeout time;
    	#配置nginx服务器与后端服务器尝试建?连接的超时时间,默认为60秒,?法如下:
    		proxy_connect_timeout 60s;
    		#60s为?定义nginx与后端服务器建?连接的超时时间((nginx服务器多长时间跟后端服务器没有建立成功就不在等待,对用户来将这个时间很长了,他只管能不能访问就行了))
    	
    	proxy_read_timeout time;
    	#配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60s	(这个意思是proxy_connect_timeout这个已经建立成功了,但是后端服务器并不能即使给客户端返回,因为他有可能需要查数据库什么的,这里有等待时间,这个时间可能会有点长,时间一到nginx就不在等待,这个时间需要高点,比如600秒,有的时候可能中间件什么负载高,)	(read读可以理解成"读"GET)
    	proxy_send_timeout time;
    	#配置nginx项后端服务器或服务器组发起write请求后,等待的超时时间,默认60s		(send写可以理解未POST,意思是如果我要传数据多久传完,这个时间也长点,有足够的等待时间)
    	
    	proxy_http_version 1.0 | 1.1;
    	#?于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0	(nginx代理服务器和后端服务器通信的协议,通常这段1.0版本够了,如果需要1.1也可以设置)
    	
    	proxy_ignore_client_abort off;
    	#当客户端?络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器会忽略客户端中断并?直等着代理服务执?返回,如果设置为off,则客户端中断后Nginx也会中断客户端请求并?即记录499?志,默认为off。	(当客户端中断请求了,有可能是客户端打开的是半天没有响应,他页面给他关了,或者是正访问呢,网络断了,这个请求已经发给nginx了,nginx可能已经转给后端服务器了,正在等待后端服务器响用,这时候客户端跟nginx端口,那nginx要不要跟后端服务器断开,一般是要断开的,就算后端服务器把响应发给ningx了,nginx也跟客户端断开连接了,tcp已经断了,响应不了,)
    	
    	proxy_headers_hash_bucket_size 128;
    	#当配置了 proxy_hide_header和proxy_set_header的时候,?于设置nginx保存HTTP报?头的hash表的上限。
    	proxy_headers_hash_max_size 512;
    	#设置proxy_headers_hash_bucket_size的最?可?空间
    
    	server_names_hash_bucket_size 512;
    	#server_name hash表申请空间??
    	server_names_hash_max_szie 512;
    	#设置服务器名称hash表的上限??
    	(只有访问量特别大的时候,这些值可能不够,不够久丢数据,或者响应的比较慢,正常这些空间够了,设置的比官方高点就行)
    

    nginx反向代理示例--单台web服务器

    # 备份nginx配置文件,从模板配置文件复制一份
    [root@www conf.d]# pwd
    /apps/nginx/conf/conf.d
    
    [root@www conf.d]# mv pc.conf pc.conf.bak0304
    
    [root@www conf.d]# ls
    mobile.conf  pc.conf.bak0304
    
    [root@www conf.d]# cp mobile.conf pc.conf
    [root@www conf.d]# ls
    mobile.conf  pc.conf pc.conf.bak0304
    
    # 修改配置文件
    [root@www conf.d]# vi pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            location / {
                    proxy_pass http://192.168.127.129:80;
                    proxy_hide_header ETag;
                    proxy_pass_header Server;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_pass_request_body on;
                    proxy_pass_request_headers on;
                    proxy_read_timeout 600s;
                    proxy_send_timeout 600s;
                    proxy_http_version 1.1;
                    proxy_ignore_client_abort off;
            }
    
    }
    
    
    # 重启nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    # 客户端修改hosts文件,指向nginx
    192.168.127.130  www.helloworld.net
    
    
    # 客户端测试(测试成功)
    [root@localhost ~]# curl -L http://www.helloworld.net
    web A
    
    
    隐藏后端服务相应头部的信息(Server默认已隐藏,显示的是nginx的Server)
    # 修改配置文件
    [root@www conf.d]# vi pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            location / {
                    proxy_pass http://192.168.127.129:80;
                    proxy_hide_header ETag;		# 隐藏ETag头
            }
    
    }
    
    
    # 重启nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 客户端测试(测试成功)
    [root@localhost ~]# curl -L http://www.helloworld.net -I
    HTTP/1.1 200 OK
    Server: helloworld
    Date: Mon, 29 Mar 2021 10:18:38 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Length: 6
    Connection: keep-alive
    Last-Modified: Mon, 29 Mar 2021 02:33:02 GMT
    ETag: "6-5bea3b3674691"		# 未隐藏
    Accept-Ranges: bytes
    
    
    
    [root@localhost ~]# curl -L http://www.helloworld.net -I		# 隐藏后效果
    HTTP/1.1 200 OK
    Server: helloworld
    Date: Mon, 29 Mar 2021 10:18:17 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Length: 6
    Connection: keep-alive
    Last-Modified: Mon, 29 Mar 2021 02:33:02 GMT
    Accept-Ranges: bytes
    
    
    
    
    显示后端服务相应头部的信息
    # 修改配置文件
    [root@www conf.d]# vi pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            location / {
                    proxy_pass http://192.168.127.129:80;
                    proxy_hide_header ETag;
                    proxy_pass_header Server;		# 显示后端服务器的Server
            }
    
    }
    
    
    
    # 重启nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 客户端测试(测试成功)
    [root@localhost ~]# curl -L http://www.helloworld.net -I
    [root@localhost ~]# curl -L http://www.helloworld.net -I
    HTTP/1.1 200 OK
    Date: Mon, 29 Mar 2021 10:22:48 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Length: 6
    Connection: keep-alive
    Server: Apache/2.4.6 (CentOS)		# 后端服务器Server
    Last-Modified: Mon, 29 Mar 2021 02:33:02 GMT
    Accept-Ranges: bytes
    
    把客户端的ip地址proxy给后端服务器

    proxy_set_header 修改用户的请求报文,发给服务器。通常这个我们用来透传ip地址的

    # 修改nginx配置文件
    [root@www conf.d]# vi pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            
            location /web {
                    access_log /apps/nginx/logs/access_json.log access_json;
                    default_type text/html;
                    
                    proxy_pass http://192.168.127.129:80/;
                    
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
            }
    
    
    }
    
    
    # 重启nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 定义后端服务器的日志添加X-Forwarded-For查看ip(这里使用的httpd)
    [root@localhost ~]# vi /etc/httpd/conf/httpd.conf 
        LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
        
        CustomLog "logs/access_log" combined	# 可以看到这里日志引用的是combined,定义这个
    
    # 重启httpd
    [root@localhost ~]# systemctl reload httpd
    
    # 客户端访问
    [root@localhost ~]# curl http://www.helloworld.net/
    web A
    
    
    # 在看日志(测试成功,客户端ip传过来了)
    [root@localhost ~]# cat /etc/httpd/logs/access_log 
    192.168.127.128 192.168.127.130 - - [29/Mar/2021:19:43:47 +0800] "GET / HTTP/1.0" 200 6 "-" "curl/7.29.0"
    
    
    
    
    
    # 重启nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    

    反向代理示例--指定location

    # 编辑nginx配置文件
    [root@www conf.d]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            location / {
                    index index.html index.php;
                    root /data/nginx/html/pc;
            }
    
            location /web {
                   #proxy_pass http://192.168.127.129:80/; # 注意有后面的/
                    proxy_pass http://192.168.127.129:80;
                    proxy_hide_header ETag;
                    proxy_pass_header Server;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_pass_request_body on;
                    proxy_pass_request_headers on;
                    proxy_read_timeout 600s;
                    proxy_send_timeout 600s;
                    proxy_http_version 1.1;
                    proxy_ignore_client_abort off;
            }
    
    }
    
    # nginx测试页面
    [root@www conf.d]# mkdir -pv  /data/nginx/html/pc
    mkdir: 已创建目录 "/data/nginx/html/pc"
    [root@www conf.d]# echo "/data/nginx/html/pc/" > /data/nginx/html/pc/index.html
    [root@www conf.d]# cat /data/nginx/html/pc/index.html 
    /data/nginx/html/pc/
    
    
    # 后端web服务器必须要有相对于的访问URL
    ## web A
    [root@localhost ~]# cat /var/www/html/index.html 
    web A
    
    ## web B
    [root@localhost ~]# cat /var/www/html/index.html 
    web B
    
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    # 客户端访问测试(测试成功)
    [root@localhost ~]# curl -L http://www.helloworld.net/web
    web B
    
    
    # Apache的访问?志(看日志可以看到是192.168.127.130访问的Apache,这个地址是nginx的ip,不是客户端的ip,客户端的请求,发送给nginx,nginx帮他去求情响应,然后在将结果转发给客户端)
    [root@localhost ~]# tail -f /var/log/httpd/access_log
    192.168.127.130 - - [29/Mar/2021:10:43:05 +0800] "GET // HTTP/1.0" 200 6 "-" "curl/7.29.0"
    
    # nginx的访问日志(nginx日志上可以看到客户端ip)
    [root@www conf.d]# tail -f /apps/nginx/logs/access.log 
    192.168.127.128 - - [29/Mar/2021:10:43:05 +0800] "GET /web/ HTTP/1.1" 200 6 "-" "curl/7.29.0
    
    

    反向代理示例--缓存功能

    缓存功能默认关闭状态
    (缓存功能在某些场合可以提高nginx并发能力,因为nginx需要把一些请求转给后端服务器,但是有些请求他是固定的静态文件,这个文件或者图片,我们可以让nginx临时缓存在nginx本身的磁盘上,当第一个人请求的时候,nginx没有,没有就向后端服务器读,读完之后,如果后期再有客户端访问同一个资源那么nginx就可以基于这个缓存直接给用户返回,但是他默认关掉的,需要给他开启)

    	proxy_cache zone | off; 默认off
    	#指明调?的缓存,或关闭缓存机制;Context:http, server, location(作用域)# 开启缓存,zone表示区域名字,后面调用,这个要配置在你的location里面,它默认是关闭的
    
    	proxy_cache_key string;
    	#缓存中?于“键”的内容(键就是key,这个key就是用户请求的url,一般不缓存域名,一般缓存用户请求的资源路径,其实就是把他的资源缓存下来),默认值:proxy_cache_key $scheme$proxy_host$request_uri;	#$scheme协议,$proxy_host主机,$request_uri资源路径,具体路径
    	
    	proxy_cache_valid [code ...] time;
    	#定义对特定响应码的响应内容的缓存时?,定义在http{...}中	(对响应成功的进行缓存,缓存多长时间)
    		示例:
    			proxy_cache_valid 200 302 10m;	# 这种缓存成功的,可以缓存时间长点
    			proxy_cache_valid 404 1m;	# 404就缓存断点,因为我们下一刻可能就修复了。
    			
    	proxy_cache_path;
    		定义可?于proxy功能的缓存;Context:http(作用域)
    		proxy_cache_path path [levels=levels] [use_temp_path=on|off]
    		
    	keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
    
    	示例:在http配置定义缓存信息
    		proxy_cache_path /var/cache/nginx/proxy_cache #定义缓存保存路径,proxy_cache会?动创建,只要nginx有权限创建缓存路径就行,路径随便
    		
    		levels=1:2:2 #定义缓存?录结构层次,1:2:2可以?成2^4x2^8x2^8=1048576个?录
    		
    		keys_zone=proxycache:20m #指内存中缓存的??,主要?于存放key和metadata(元数据)(如:使?次数)
    		
    		inactive=120s; #缓存有效时间(120秒后就删了)
    		
    		max_size=1g; #最?磁盘占?空间,磁盘存??件内容的缓存空间最?值(这个缓存的静态文件最终是存磁盘上的,这个磁盘占多大)
    		
    	#调?缓存功能,需要定义在相应的配置段,如server{...};或者location等(配置好要调用,不然定义他们干啥)
    		proxy_cache proxycache;
    		proxy_cache_key $request_uri;
    		proxy_cache_valid 200 302 301 10m; #指定的状态码返回的数据缓存多?时间
    		proxy_cache_valid any 1m;
    		
    	proxy_cache_use_stale error http_502 http_503;
    	#在被代理的后端服务器出现哪种情况下,可直接使?过期的缓存响应客户端,
    	proxy_cache_use_stale error(报错) | timeout(超时) | invalid_header(无效的头部) | updating(更新中) | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ; #(报这些错误,我们可以让nginx直接使用缓存)默认是off
    		
    	proxy_cache_methods GET | HEAD | POST ...;
    	#对哪些客户端请求?法对应的响应进?缓存,GET和HEAD?法总是被缓存
    
    ?缓存场景压测
    
    # httpd准备测试页,拷贝一个相对较大的文件,修改这个文件权限,起码能让别的用户能读
    [root@localhost ~]# chmod 644 /var/www/html/test.txt 
    [root@localhost ~]# ll -h /var/www/html/test.txt 
    -rw-r--r--. 1 root root 7.8M 3月  29 21:36 /var/www/html/test.txt
    
    
    # 客户端访问nginx测试(页面可以打开测试成功)
    http://www.helloworld.net/web/test.txt
    
    
    
    # 客户端使用压测工具,测试一下在没有nginx缓存的情况下怎么样		(Requests per second:    6.99 [#/sec] (mean)			 #每秒多少请求,这个是非常重要的参数数值,服务器的吞吐量)
    [root@localhost ~]# yum -y install httpd-tools
    [root@localhost ~]#  ab -n1000 -c100 http://www.helloworld.net/web/test.txt
    ## 名字ab		-n1000	(一共访问1000次) -c100	(并发量是100个)	 访问:http://www.helloworld.net/web/test.txt
    
    
    [root@localhost ~]# ab -n1000 -c100 http://www.helloworld.net/web/test.txt
    This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    Licensed to The Apache Software Foundation, http://www.apache.org/
    
    Benchmarking www.helloworld.net (be patient)
    Completed 100 requests
    Completed 200 requests
    Completed 300 requests
    Completed 400 requests
    Completed 500 requests
    Completed 600 requests
    Completed 700 requests
    Completed 800 requests
    Completed 900 requests
    Completed 1000 requests
    Finished 1000 requests
    
    
    Server Software:        Apache/2.4.6				#服务器软件
    Server Hostname:        www.helloworld.net				#域名
    Server Port:            80							#请求端口号
    
    Document Path:          /web/test.txt				#文件路径
    Document Length:        2314700 bytes				#页面字节数
    
    Concurrency Level:      100							#请求的并发数
    Time taken for tests:   143.122 seconds				#总访问时间
    Complete requests:      1000						#请求成功数量
    Failed requests:        0							#请求失败数量
    Write errors:           0
    Total transferred:      2314963000 bytes			#请求总数据大小(包括header头信息)
    HTML transferred:       2314700000 bytes			 #html页面实际总字节数
    Requests per second:    6.99 [#/sec] (mean)			 #每秒多少请求,这个是非常重要的参数数值,服务器的吞吐量
    Time per request:       14312.207 [ms] (mean)			 #用户平均请求等待时间 
    Time per request:       143.122 [ms] (mean, across all concurrent requests)			# 服务器平均处理时间,也就是服务器吞吐量的倒数 
    Transfer rate:          15795.65 [Kbytes/sec] received		#每秒获取的数据长度
    
    Connection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0  136 286.2     66    3086
    Processing:   380 13978 4597.2  13863   28480
    Waiting:        2  910 1519.8    337    6582
    Total:        396 14114 4601.0  14034   28483
    
    Percentage of the requests served within a certain time (ms)
      50%  14034		 #50%用户请求在14034ms内返回
      66%  15802
      75%  16798
      80%  17545
      90%  19431
      95%  21957
      98%  23704
      99%  24293
     100%  28483 (longest request)
    
    
    准备缓存配置
    # 把nginx缓存加上在测试(这种配置一般都是配在全局,/apps/nginx/proxy_cache此文件nginx自动创建,但是所在的目录nginx要有权限创建)
    [root@www conf.d]# vi /apps/nginx/conf/nginx.conf
    http {
    
    	...
    	
        #gzip  on;
    
       proxy_cache_path /apps/nginx/proxy_cache         levels=1:2:2    keys_zone=proxycache:20m        inactive=120s   max_size=1g;
    
       ...
    }
    
    
    # 在server子配置文件中调用(nginx本身他那些文件,是存在本身的就不用缓存了,他自己就可以调用,这种通过后端服务器发的静态文件,我们就把他缓存到本地,就不用每一次后端服务器在发一次了,在请求读缓存数据)
    [root@www conf.d]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            location /web {
                    access_log /apps/nginx/logs/access_json.log access_json;
    
                    proxy_cache proxycache;
                    proxy_cache_key $request_uri;
                    proxy_cache_valid 200 302 301 10m; 
                    proxy_cache_valid any 1m; 
                    
    				...
    		}
    }
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 给缓存保存路径权限,让他能写(不需要,页面访问以下就会自动创建目录)
    [root@www conf.d]# chown -R nginx:nginx /apps/nginx/
    
    
    # 查看一下缓存保存路径(这个文件nginx已经创建,现在是空的)
    [root@www conf.d]# ll /apps/nginx/proxy_cache/
    总用量 0
    
    
    
    访问并验证缓存?件
    # nginx添加缓存后客户端再次压测(可以看到服务器的吞吐量已经达到了30.27,之前是8点多,性能提升的不是一点半点,提升了很多)
    [root@localhost ~]# ab -n1000 -c100 http://www.helloworld.net/web/test.txt
    Requests per second:    30.27 [#/sec] (mean)
    
    
    
    # 查看nginx创建的缓存文件(他会遵循我们定义好的规则,定义三层文件,先取a717e7af484371af075b18fd2fc5e72d这个文件的最后一位数d,这个值hash过来的,最后一位数d命名第一级目录,然后在取两位数字72命名第二级目录,第三级5e是命名第三级的)
    [root@www conf.d]# ll /apps/nginx/proxy_cache/
    总用量 0
    drwx------. 3 nginx nginx 16 3月  29 22:50 d
    [root@www conf.d]# ll /apps/nginx/proxy_cache/d
    总用量 0
    drwx------. 3 nginx nginx 16 3月  29 22:50 72
    [root@www conf.d]# ll /apps/nginx/proxy_cache/d/72/
    总用量 0
    drwx------. 2 nginx nginx 46 3月  29 22:50 5e
    [root@www conf.d]# ll /apps/nginx/proxy_cache/d/72/5e/
    总用量 2264
    -rw-------. 1 nginx nginx 2315326 3月  29 22:50 a717e7af484371af075b18fd2fc5e72d
    
    

    添加头部报?信息

    nginx基于模块ngx_http_headers_module可以实现对头部报?添加指定的key与值, https://nginx.org/en/docs/http/ngx_http_headers_module.html,

    	Syntax: add_header name value [always];		(add_header加上某些字段,返回给客户端。通常是添加缓存,等想被客户端知道的信息,但是这些信息不能加太多,否者你的头部报文装不下)
    	Default: —
    	Context: http, server, location, if in location(作用域)
    	
    	#添加?定义?部(以下告诉客户端是否使用缓存了,比如客户端开发模式可以看到 X-Cache HIT fron xxx.xxxx.com,其中HIT表示命中,就是你之前访问过我,后面命中的地址有可能是cdn厂商的缓存,我们这里是nginx的缓存),如下:
    	add_header name value [always];
    		add_header X-Via $server_addr;
    		add_header X-Cache $upstream_cache_status;
    		add_header X-Accel $server_name;
    		
            #添加?定义响应信息的尾部, 1.13.2版后?持
    		add_trailer name value [always];
    
    Nginx配置
    # 编辑配置文件
    [root@www conf.d]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
            listen 80;
            server_name www.helloworld.net;
            location / {
                    index index.html index.php;
                    root /data/nginx/html/pc;
            }
    
            location /web {
                    proxy_pass http://192.168.127.131:80/;
                    proxy_set_header clientip $remote_addr;
    
                    add_header X-Via $server_addr;
                    add_header X-Cache $upstream_cache_status;
                    add_header X-Accel $server_name;
            }
    
    }
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    验证头部信息
    # 客户端访问测试(测试成功)
    [root@localhost ~]# curl www.helloworld.net/web -I
    HTTP/1.1 200 OK
    Date: Wed, 31 Mar 2021 01:28:53 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Length: 6
    Connection: keep-alive
    Server: Apache/2.4.6 (CentOS)
    Last-Modified: Mon, 29 Mar 2021 02:33:02 GMT
    X-Via: 192.168.127.130			(web服务器的下一跳地址,我们这里下一跳时nginx代理服务器)
    X-Cache: HIT			(是否命中缓存,HIT表示命中,	miss表示从来没有访问过,没有命中缓存,表示nginx没有缓存,rm -rf /apps/nginx/proxy_cache/*把这下面的缓存删掉就miss了)
    X-Accel: www.helloworld.net		(你的服务器地址)
    Accept-Ranges: bytes
    
    

    Nginx http 反向代理?级应?

    在上?个章节中Nginx可以将客户端的请求转发?单台后端服务器(单台指定的服务器)但是?法转发?特定的?组的服务器(无法写两个proxy_pass),?且不能对后端服务器提供相应的服务器状态监测(就是你的服务器挂了,你的nginx不知道),但是Nginx可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等?级功能,官??档: https://nginx.org/en/docs/http/ngx_http_upstream_module.html

    http upstream配置参数

    	upstream name {
    	
    	}
    	#?定义?组服务器,配置在http内(使用upstream指令,指定一个组,起一个组名name)
    	
    	server address [parameters];
    	#配置?个后端web服务器,配置在upstream内,?少要有?个server服务器配置。
    	
    	#server?持的parameters如下:
    		weight=number #设置权重,默认为1。
    		max_conns=number #给当前server设置最?活动链接数,默认为0表示没有限制。(这个值一般不设置,但是如果你这个服务器配置很低,你可以给他设置1000个连接,或者2000个连接,当后端服务器请求达到设定的值,nginx就不在往这个服务器转发连接了)
    		fail_timeout=time #对后端服务器的失败监测超时时间,默认为10秒。
    		max_fails=number #在fail_timeout时间对后端服务器连续监测失败多少次就标记为不可?。(fail_timeout这个时间写了10秒,max_fails这里写了3,也就是在这10秒之内连续3次都失败了,那nginx就把这台服务器标记为不可用,踢出去,这里nginx探测端口的方式比较初级,比如端口存在,但是你的服务器不一定是可用的,HAproxy可以用更高级的探测方式)
    		proxy_next_upstream=error timeout; #指定在哪种检测状态下将请求转发器其他服务器。
    		backup #设置为备份服务器,当所有服务器不可?时将重新启?次服务器。(比如server backup1.example.com:8080  backup)
    		down #标记为down状态。
    		resolve #当server定义的是主机名的时候,当A记录发?变化会?动应?新IP?不?重启Nginx。
            
    	# 算法
    	hash KEY consistent;
    		#基于指定key做hash计算,使?consistent参数,将使?ketama?致性hash算法,适?于后端是Cache服务器(如varnish)时使?(适用于后端服务器使用缓存的),consistent定义使??致性hash运算,?致性hash(?致性hash意思就是只要是同一个uri他的hash结果就是一样的)基于取模运算。
    
    		hash $request_uri consistent; #基于( $request_uri哪个用户停请求的uri做hash,就是凡是请求同一个uri的,我们就转发给同一个后端服务器)?户请求的uri做hash			
    	ip_hash;
    		#源地址hash调度?法,基于的客户端的remote_addr(源地址)做hash计算,以实现会话保持,
    
    	least_conn;
    		#最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器
    

    反向代理示例--多台web服务器

    # 编辑配置文件(weight=1权重一般没有特殊的要求,都写一样的就可以了
    fail_timeout=15s max_fails=3在15秒之内连续检测3次失败)	(upstream是记录在http中的,在server中proxy_pass调用就行)
    [root@www conf.d]# vi /apps/nginx/conf/conf.d/pc.conf
    
    upstream webserver {
    	#hash $request_uri consistent;		# 基于url做hash,访问这个url我就转发给那台服务器,访问那个url我就转发给哪个服务器,访问同一个页面,就转发给固定的服务器	# 指定的算法,如果任何算法都不指他回轮询,如果配置nginx缓存会影响轮询
    	#ip_hash;							# 使用基于ip的hash算法,不能使用backup,基于第一次访问ip做hash,如果这个ip再次访问就直接代理只上一次访问的服务器,就不在轮询。指定的算法,如果任何算法都不指他回轮询,如果配置nginx缓存会影响轮询
    	#least_conn;						# nginx和后端多个服务器建立连接,对用连接最少的服务器做转发。 指定的算法,如果任何算法都不指他回轮询,如果配置nginx缓存会影响轮询
            server 192.168.127.129:80 weight=1 fail_timeout=15s max_fails=3; 	#后端服务器状态监测
            server 192.168.127.131:80 weight=1 fail_timeout=15s max_fails=3;
            server 192.168.127.132:80 weight=1 fail_timeout=15s max_fails=3 backup;
    
    }
    
    server {
            listen 80;
            server_name www.helloworld.net;
            location / {
                    access_log /apps/nginx/logs/access_json.log access_json;
    
                    default_type text/html;
                    proxy_pass http://webserver;		# 它可以基于webserver找到upstream中的定义的服务器地址.(如果是location  /web,表示后端服务器/web目录下index.html. proxy_pass http://webserver/,注意这里webserver后面有斜杠,使用场景,比如访问www.helloworld.net进nginx,www.helloworld.net进tomcat)
                    
                    ...
                    
                    add_header X-Via $server_addr;
                    add_header X-Cache $upstream_cache_status;
                    add_header X-Accel $server_name;
            }
    }
    
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    
    # 客户端访问测试(可以看到是轮询)
    [root@localhost ~]# curl http://www.helloworld.net/
    web B
    [root@localhost ~]# curl http://www.helloworld.net/
    web A
    [root@localhost ~]# curl http://www.helloworld.net/
    web A
    [root@localhost ~]# curl http://www.helloworld.net/
    web B
    
    
    # 客户端访问测试backup备份服务器(测试成功)
    ## web A
    [root@localhost ~]# systemctl stop httpd
    ## web B
    [root@localhost ~]# systemctl stop httpd
    
    [root@localhost ~]# curl http://www.helloworld.net/
    thi is a backup
    # 或者
    
    ## 修改权重,每轮循环192.168.127.129访问2次,192.168.127.131访问1次
            server 192.168.127.129:80 weight=2 fail_timeout=15s max_fails=3;
            server 192.168.127.131:80 weight=1 fail_timeout=15s max_fails=3;
    
    [root@localhost ~]# while true;do curl http://www.helloworld.net/ 1;done
    
    
    ## 关闭192.168.7.103和192.168.7.104,测试nginx backup服务器可?性(如果服务关了,nginx状态检测就不在转发,如果服务又好了,nginx状态检测发现服务好了,就再次转发)
    [root@localhost ~]# while true;do curl http://www.helloworld.net/ 1;done
    

    反向代理示例--客户端IP透传

    1 Apache:
    把客户端的ip地址proxy给后端服务器

    2 nginx:

    [root@s1 conf.d]# cat /apps/nginx/conf/nginx.conf
    "$http_x_forwarded_for"' #默认?志格式就有此配置
    
    重启nginx访问web界?并验证?志格式:
    192.168.7.102 - - [04/Mar/2019:16:33:24 +0800] "GET // HTTP/1.0" 200 24 "-"
    "curl/7.29.0" "192.168.7.104"
    192.168.7.102 - - [04/Mar/2019:16:40:51 +0800] "GET / HTTP/1.0" 200 24 "-"
    "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/72.0.3626.119 Safari/537.36" "192.168.0.1"
    
    
    3 tomcat
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    	prefix="n50.access_log." suffix=".log"		# 这里可以该改名
    	pattern="%h %{X-Forwarded-For}i %l %u %t &quot;%r&quot; %s %b" />	# 添加%{X-Forwarded-For}i 这里面%{X-Forwarded-hhh}i名字可以更改
    
    

    实现动静分离

    # 编辑配置文件,我们将图片,文件什么的静态资源交给nginx去处理
    [root@www conf.d]# vi /apps/nginx/conf/conf.d/pc.conf
    upstream webserver {
            #hash $request_uri consistent;
            #ip_hash;
            #least_conn;
            server 192.168.127.131:80 weight=1 fail_timeout=15s max_fails=3;
            server 192.168.127.129:80 weight=1 fail_timeout=15s max_fails=3;
            server 192.168.127.132:80 weight=1 fail_timeout=15s max_fails=3 backup;
    }
    
    server {
    
    		...
    		
            location ~* \.(gif|jpg|jpeg|bmp|png|tiff|tif|ico|wmf|js)$ {		
                    root /data/nginx/images1;
                    index index.html;
    
                    }
    }
    
    # 创建测试路径和图片
    [root@www ~]# ls /data/nginx/images1/
    ab.bmp  ab.ico  ab.jpeg  ab.jpg  ab.js  ab.png  ab.tif  ab.tiff  ab.wmf
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 访问测试(直接访问ab.png文件,location匹配到就直接去nginx中去找,实现了静态文件和动态文件分离)
    http://www.helloworld.net/ab.png
    

    实现Nginx tcp负载均衡

    Nginx在1.9.0版本开始?持tcp模式的负载均衡,在1.9.13版本开始?持udp协议的负载,udp主要?于DNS的域名解析,其配置?式和指令和http 代理类似,其基于ngx_stream_proxy_module模块实现tcp负载,另外基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、调度算法等?级功能。(前面讲的都是http协议)

    官??档:https://nginx.org/en/docs/stream/ngx_stream_core_module.html

    tcp负载均衡配置参数(nginx的tcp负载均衡性能不如HAproxy更不如lvs,所以tcp的负载一般使用HAproxy)

    
    # 我们需要在upstream外面在包一层stream
    stream { #定义stream
    	upstream backend { #定义后端服务器
    		hash $remote_addr consistent; #定义调度算法
    		server backend1.example.com:12345 weight=5; #定义具体server
    		server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
    		server unix:/tmp/backend3;
    	}
    	
    	upstream dns { #定义后端服务器
    		server 192.168.0.1:53535; #定义具体server
    		server dns.example.com:53;
    	}
    	
    	server { #定义server
    		listen 12345; #监听IP:PORT(tcp不像http,http他通过一个80端口过来,他可以接收所有的请求,然后请求他们所有头部报文中的host字段,可以知道客户端请求哪一个主机,哪一个路径,但是tcp是只能指定端口了,他每一个tcp可能就是不同的服务了)
    		proxy_connect_timeout 1s; #连接超时时间
    		proxy_timeout 3s; #转发超时时间
    		proxy_pass backend; #转发到具体服务器组
    	}
    	
    	server {
    		listen 127.0.0.1:53 udp reuseport;
    		proxy_timeout 20s;
    		proxy_pass dns;
    	}
    	
    	server {
    		listen [::1]:12345;
    		proxy_pass unix:/tmp/stream.socket;
    	}
    }
    
    

    tcp负载均衡实例:MySQL

    服务器安装MySQL(基于tcp)

    # 找一个或者安装一个数据库(在访问数据库的时候,不是直接访问数据库,而是通过负载均衡器,直接通过ip地址也不是不行,但是以后数据库服务器地址发生变化,或者主机发生故障,相对服务器做迁移的话就很麻烦了)
    [root@localhost ~]# yum -y install mariadb-server
    
    # 关闭防火墙
    [root@localhost ~]# systemctl stop firewalld
    
    # 启动数据库
    [root@localhost ~]# systemctl start mariadb
    [root@localhost ~]# systemctl enable mariadb
    
    
    
    
    # ngixn代理查看是否编译安装--with-stream模块(这里已编译安装)
    [root@www conf.d]# /apps/nginx/sbin/nginx -V
    nginx version: nginx/1.18.0
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.1.1k  25 Mar 2021
    TLS SNI support enabled
    configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-file-aio --with-threads --add-module=/usr/local/src/echo-nginx-module-master --with-openssl=/usr/local/src/openssl-1.1.1k
    
    
    # 加一个配置,创建一个目录(把tcp的负载配置放在tcp目录,不要把tcp的负载配置跟http放一块,他们指定的生效范围是不一样的,如果直接配置在http里面服务就直接起不来了)
    [root@www conf.d]# mkdir -pv  /apps/nginx/conf/tcp
    mkdir: 已创建目录 "/apps/nginx/conf/tcp"
    
    # 编辑配置文件(mysql.conf主要用于命名区分)(我们需要在upstream和server外面在包一层stream,感觉和http没什么区别)
    [root@www conf.d]# vi /apps/nginx/conf/tcp/mysql.conf
    stream {
            upstream mysql_server {
                    #hash $remote_addr consistent;
                    server 192.168.127.134:3306 max_fails=3 fail_timeout=30s;		# 后端mysql的地址
            }
            
            server {
                    listen 192.168.127.130:3306;	# 监听在本机的地址的3306,他会给自己ip上绑定一个3306端口,可以接收基于3306端口的请求
                    proxy_connect_timeout 30s;		# 这个参数也http一样
                    proxy_timeout 300s;				# 这个参数也http一样
                    proxy_pass redis_server;		# 这前面要是使用的是http://redis_server 表示使用的http协议,但是mysql不支持使用的是http协议,所以不要加http
                    }
    }
    
    # 编辑主配置文件,指向mysql.conf的子配置文件路径(把tcp放在http字段是不行的,需要妨到外面来,否者服务器起不来)
    [root@www conf.d]# vi /apps/nginx/conf/nginx.conf
    include /apps/nginx/conf/conf.d/*.conf;
    # include /apps/nginx/conf/http/*.conf;
    }
    include /apps/nginx/conf/tcp/*.conf;
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 查看监听的地址(可以看到本机没有安装mysql但是也监听了3306端口,这个3306是访问mysql的,可以先对mysql进行授权)
    [root@www conf.d]# ss -tnl
    State      Recv-Q Send-Q Local Address:Port                Peer Address:Port              
    LISTEN     0      128                *:80                             *:*                  
    LISTEN     0      128                *:22                             *:*                  
    LISTEN     0      100        127.0.0.1:25                             *:*                  
    LISTEN     0      128                *:443                            *:*                  
    LISTEN     0      128    192.168.127.130:3306                           *:*                  
    LISTEN     0      128               :::22                            :::*                  
    LISTEN     0      100              ::1:25                            :::*      
    
    
    # 数据库创建用户授权远程登陆
    [root@localhost ~]# mysql
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MariaDB connection id is 2
    Server version: 5.5.68-MariaDB MariaDB Server
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MariaDB [(none)]> CREATE DATABASE mydata;
    Query OK, 1 row affected (0.00 sec)
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON mydata.* TO "mydata"@"192.168.%.%" IDENTIFIED BY "123456";
    Query OK, 0 rows affected (0.00 sec)
    
    
    # 客户端安装mysql命令
    [root@www conf.d]# yum -y install mariadb
    
    
    # 客户端登陆数据库测试(直连mysql登陆成功)
    [root@localhost ~]# mysql -umydata -h192.168.127.134 -p123456
    
    # 客户端通过nginx连接mysql登陆测试(通过nginx反向代理登陆mysql成功,当然我们正常是通过域名访问的,所有可以hosts文件上加上域名解析)
    [root@localhost ~]# mysql -umydata -h192.168.127.130 -p123456
    
    ## 修改hosts文件(公司中后端数据库域名可能是这样的格式,然后告诉开发,要是连接数据库就走这个域名)
    [root@localhost ~]# vi /etc/hosts
    192.168.127.130  mysql-vip-boss.helloworld.net.online
    
    ## 通过域名访问数据库
    [root@localhost ~]# mysql -umydata -hmysql-vip-boss.helloworld.net.online -p123456
    
    

    tpc负载均衡实例--Redis

    # 安装epel源
    [root@localhost ~]# yum -y install epel-release
    
    # 安装redis
    [root@localhost ~]# yum -y install redis
    
    # 启动前修改配置文件(改掉监听地址)
    [root@localhost ~]# vi /etc/redis.conf 
    bind 0.0.0.0
    
    
    # 启动redis(启动redis需要指定配置文件。启动后会监听在6379端口)
    [root@localhost ~]# redis-server /etc/redis.conf 
    
    
    
    # 在nginx负载均衡配置文件中添加一个server(一个server就是一个tcp对外提供的服务,地址可以复用,只要端口不冲突就行,redis端口号6379)
    [root@www conf.d]# vi /apps/nginx/conf/tcp/mysql.conf
    stream {
            upstream mysql_server {
                    #hash $remote_addr consistent;
                    server 192.168.127.134:3306 max_fails=3 fail_timeout=30s;
            }
    
            upstream redis_server {
                    #hash $remote_addr consistent;
                    server 192.168.127.134:6379 max_fails=3 fail_timeout=30s;		# 指定后端redis服务器地址和端口
            }
    
    
            server {
                    listen 192.168.127.130:3306;
                    proxy_connect_timeout 3s;
                    proxy_timeout 3s;
                    proxy_pass mysql_server;
                    }
    
            server {
                    listen 192.168.127.130:6379;		# 绑定本地的ip和6379端口
                    proxy_connect_timeout 3s;
                    proxy_timeout 3s;
                    proxy_pass redis_server;
                    }
    }
    
    # 重载nginx
    [root@www conf.d]# /apps/nginx/sbin/nginx -t
    [root@www conf.d]# /apps/nginx/sbin/nginx -s reload
    
    
    # 客户端安装redis(使用redis命令)
    [root@localhost ~]# yum -y install redis
    
    # 客户端通过nginx负载均衡器连接redis(192.168.127.130是nginx负载均衡地址)
    [root@localhost ~]# redis-cli -h 192.168.127.134
    192.168.127.134:6379> info
    
    

    实现FastCGI

    	CGI的由来:
    		最早的Web服务器只能简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML?件返回给浏览器,也就是静态html?件(http://www.zbbz.com/index.html),但是后期随着?站功能增多?站开发也越来越复杂,以?于出现动态技术,?如像php(1995年)、java(1995)、python(1991)语?开发的?站,但是nginx/apache服务器并不能直接运? php、java这样的?件,apache实现的?式是打补丁,但是nginx却通过与第三?基于协议实现,即通过某种特定协议将客户端请求转发给第三?服务处理,第三?服务器会新建新的进程处理?户的请求,处理完成后返回数据给Nginx并回收进程,最后nginx在返回给客户端,那这个约定就是通??关接?(common gateway interface,简称CGI),CGI(协议) 是web服务器和外部应?程序之间的接?标准,是cgi程序和web服务器之间传递信息的标准化接?。
    
    
    	为什么会有FastCGI?
    	
    		CGI协议虽然解决了语?解析器和web server之间通讯的问题,但是它的效率很低,因为web server每收到?个请求都会创建?个CGI进程,PHP解析器都会解析php.ini?件,初始化环境,请求结束的时候再关闭进程,对于每?个创建的CGI进程都会执?这些操作,所以效率很低,?FastCGI是?来提?CGI性能的,FastCGI每次处理完请求之后不会关闭掉进程,?是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不?再重新创建?个进程了,??提升了处理效率。
    		
    		FastCGI通信?式:
    		
    		什么是PHP-FPM?
    			PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是?个实现了Fastcgi的管理程序,并且提供进程管理的功能,进程包括master进程和worker进程,master进程只有?个,负责监听端?,接受来?web server的请求。worker进程?般会有多个,每个进程中会嵌??个PHP解析器,进?PHP代码的处理。
    

    FastCGI配置指令

    	Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发?php-fpm处理,其配置指令如下:
    
    proxy_pass http://		# tpc协议直接proxy_pass 后面主机,http协议需要指定协议在主机前面加上http://,比如proxy_pass http://
    fastcgi_pass 172.31.7.8:9000;		# fastcgi就是单独的配置参数fastcgi_pass,后面也不用写协议
    #转发请求到后端服务器,address为后端的fastcgi server的地址,可?位置:location, if in location
    
    
    fastcgi_index name;
    #fastcgi默认的主?资源,示例:fastcgi_index index.php;(通常是index.php这个参数一定要写,要告诉服务器你的默认首页,否者有可能用户在输入的时候没有加index.php,那就相当于没有页面,那就请求不到了)
    
    
    fastcgi_param parameter value [if_not_empty];
    #设置传递给FastCGI服务器的参数值,可以是?本,变量或组合,可?于将Nginx的内置变量赋值给?定义key(由于php和nginx是完全两个不同的语言开发的所以说他们的变量也不一样,比如nginx有很多变量,可以获取用户的源地址,但是php的变量跟他不一样,所以说需要通过fastcgi_param把这些变量名(变量值),重新给你的php传以下		默认情况下已经内置了很多变量了,我们也不用去配了,有一个文件就叫/apps/nginx/conf/fastcgi.conf,这个配置文件中就配置了很多和php很多相关的参数)
    fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
    fastcgi_param REMOTE_PORT $remote_port; #客户端源端?
    fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
    fastcgi_param SERVER_PORT $server_port; #请求的服务器端?
    fastcgi_param SERVER_NAME $server_name; #请求的server name
    
    
    Nginx默认配置示例(一旦访问点php文件就转给php去处理):
    	location ~ \.php$ {
    		root html;
    		fastcgi_pass 127.0.0.1:9000;
    		fastcgi_index index.php;
    		fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径,php会通过SCRIPT_FILENAME获取,用户当前的uri,/data/nginx/html/$fastcgi_script_name这地址可以写变量,也可以写绝对路径
    		include fastcgi_params;
    	}
    

    缓存定义指令:
    php也可以定义缓存,和nginx的proxy_pass一样,可以把某些后端服务器响应的文件,临时缓存到nginx服务器,来加速nginx的响应,只不过他是通过fastcgi_cache_path来定义指令

    fastcgi_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
    
    定义fastcgi的缓存;
    	path #缓存位置为磁盘上的?件系统路径
    	max_size=size #磁盘path路径中?于缓存数据的缓存空间上限
    	levels=levels:#?六进制的缓存?录的层级数量,以及每?级的?录数量,levels=ONE:TWO:THREE,示例:leves=1:2:2
    	keys_zone=name:size #设置缓存名称及k/v映射的内存空间的名称及??
    	inactive=time #缓存有效时间,默认10分钟,需要在指定时间满?fastcgi_cache_min_uses 次数被视为活动缓存。
    

    缓存调?指令:

    fastcgi_cache zone | off;
    #调?指定的缓存空间来缓存数据,可?位置:http, server, location(指定调用名称,这个名称就是keys_zone=name这个名称)
    
    
    fastcgi_cache_key string;
    #定义?作缓存项的key的字符串,示例:fastcgi_cache_key $request_uri;(我们基于哪个用户请求的哪个资源,做缓存,通常是缓存用户的请求uri)
    
    
    fastcgi_cache_methods GET | HEAD | POST ...;
    #为哪些请求?法使?缓存,比如说GET | HEAD | POST,一般是缓存那些GET的方法
    
    
    fastcgi_cache_min_uses number;
    #缓存空间中的缓存项在inactive定义的?活动时间内?少要被访问到此处所指定的次数?可被认作活动项(比如inactive=time定义了,缓存有效时间10分钟,那么在这10分钟之内,要被访问多少次才被认为活动项)
    
    
    fastcgi_keep_conn on | off;
    #收到后端服务器响应后,fastcgi服务器是否关闭连接,建议启??连接(如果nginx已经把当前这个用户的请求处理完以后,nginx是否还和后端的php建立连接,如果关掉就不连接了,建议开启,否者每次访问都要跟php建立三次握手,比较浪费资源)
    
    
    fastcgi_cache_valid [code ...] time;
    #不同的响应码各?的缓存时?(不同状态码的数据缓存时长)
    
    
    fastcgi_hide_header field; #隐藏响应头指定信息(比如隐藏php版本)
    fastcgi_pass_header field; #返回响应头指定信息,默认不会将Status、X-Accel-..返回客户端,如果要返回,就把这条添加上。
    
    
    

    定义缓存

    # 编辑配置文件(首先在全局配置文件中定义)
    [root@www ~]# vi /apps/nginx/conf/nginx.conf
    http {
    
    	...
    	
       proxy_cache_path /apps/nginx/proxy_cache     levels=1:2:2    keys_zone=proxycache:20m        inactive=120s   max_size=1g;
       fastcgi_cache_path  /apps/nginx/php_cache   levels=1:2:2    keys_zone=phpcache:20m  inactive=120s   max_size=1g;
    
    
    # 在子配置文件location中调用
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    
    		...
    		
            location ~ \.php$ {
                    root /data/nginx/php;
                    fastcgi_pass 127.0.0.1:9000;
                    fastcgi_index index.php;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    include fastcgi_params;
                    fastcgi_hide_header X-Powered-By;
                    fastcgi_pass_header X-Accel;
    
                    fastcgi_cache phpcache;		# 调用缓存
                    fastcgi_cache_key $request_uri;
                    fastcgi_cache_valid 200 302 301 10m;
                    fastcgi_cache_valid any 1m;
    
            }
    }
    
    # 重载nginx
    [root@www ~]# /apps/nginx/sbin/nginx -t
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    
    # 访问以下页面,查看以下缓存目录(缓存成功,代码升级需要把缓存清理)
    [root@www ~]# ll /apps/nginx/php_cache/
    1/ b/ e/ 
    [root@www ~]# ll /apps/nginx/php_cache/1/
    总用量 0
    drwx------. 3 nginx nginx 16 3月  31 20:14 af
    [root@www ~]# ll /apps/nginx/php_cache/1/af/
    总用量 0
    drwx------. 2 nginx nginx 46 3月  31 20:14 15
    [root@www ~]# ll /apps/nginx/php_cache/1/af/15/
    总用量 40
    -rw-------. 1 nginx nginx 40307 3月  31 20:14 e251273eb74a8ee3f661a7af00915af1
    
    
    

    FastCGI示例--Nginx与php-fpm在同?服务器

    这种最为常见,也是大多数公司惯用的方式,nginx和php通过127.0.0.1调用,数据是分开的,他们会分别调用内核去申请读写数据,读是nginx去读,写是php去写,比如博客上传图片,最后是php写到磁盘上的,这个php是谁启动的,那么这个文件的属组和宿主就是这个用户

    	php安装可以通过yum或者编译安装,使?yum安装相对?较简单,编译安装更?便?定义参数或选项。
    

    php环境准备

    使?base源?带的php版本,https://www.php.net/docs.php

    # 安装php-fpm(yum安装的版本较低,一般使用编译安装)
    [root@www ~]# yum -y install php-fpm
    
    # 修改php-fpm配置文件(把启动账号改成普通用户,我们是用nginx启动的,这里就改成nginx同一个账号启动)
    [root@www ~]# vi /etc/php-fpm.d/www.conf 
    user = nginx
    ; RPM: Keep a group allowed to write in log dir.
    group = nginx
    
    # 启动php-fpm(他会监听9000端口)
    [root@www ~]# systemctl restart php-fpm
    [root@www ~]# systemctl enable php-fpm
    [root@www ~]# ss -tnl
    LISTEN      0      128                               127.0.0.1:9000                                                  *:*      
    
    

    php相关配置优化

    [root@s2 ~]# grep "^[a-Z]" /etc/php-fpm.conf
    include=/etc/php-fpm.d/*.conf
    pid = /run/php-fpm/php-fpm.pid
    error_log = /var/log/php-fpm/error.log
    daemonize = yes #是否后台启动
    
    
    # 编辑配置文件
    [root@www ~]# vi /etc/php-fpm.d/www.conf
    
    [www]
    listen = 127.0.0.1:9000 #监听地址及IP
    listen.allowed_clients = 127.0.0.1 #允许客户端从哪个源IP地址访问,要允许所有??加 ;注释即可
    user = nginx #php-fpm启动的?户和组,会涉及到后期?件的权限问题
    group = nginx
    
    pm = dynamic #动态模式进程管理		(这个地方会优化以下,早期的php他是静态的,需要你去指定开启多少php的工作进程的,新版的php都是动态了,他会随着访问量自动调整,但是你要指定一个范围才行,比如pm.max_children定义的值和pm.start_servers定义的值)
    
    pm.max_children = 500 #静态?式下开启的php-fpm进程数量,在动态?式下他限定php-fpm的最?进程数
    pm.start_servers = 100 #动态模式下初始进程数,必须?于等于pm.min_spare_servers和?于等于pm.max_children的值。
    pm.min_spare_servers = 100 #最?空闲进程数(就算没有人访问php他也能空闲那么多进程)
    pm.max_spare_servers = 200 #最?空闲进程数(有些请求完了以后,他会把连接保留下来,但是最多保留200个,这个值不小,已经很大了)
    pm.max_requests = 500000 #进程累计请求回收值,会回收并重新?成新的?进程
    pm.status_path = /status #状态访问URL	(状态页,可以http://www.foo.bar/status?json 或 http://www.foo.bar/status?html,通常使用json,拿到之后在用python处理以下
    )
    ping.path = /ping #ping访问动地址	(相当于php的api一样,我们可以通过curl命令来访问这个/ping看看返回的值是不是200,如果是200就是正常)
    ping.response = pong #ping的返回值
    slowlog = /var/log/php-fpm/www-slow.log #慢?志路径
    php_admin_value[error_log] = /var/log/php-fpm/www-error.log #错误?志
    php_admin_flag[log_errors] = on
    php_value[session.save_handler] = files #phpsession保存?式及路径
    php_value[session.save_path] = /var/lib/php/session #当时使?file保存session的?件路径
    
    # 修改配置?件后记得重启php-fpm
    [root@s2 ~]# systemctl restart php-fpm
    
    # 查看php的启动账号
    [root@www ~]# ps -ef | grep nginx
    nginx     31362  31313  0 17:57 ?        00:00:00 php-fpm: pool www
    
    

    准备php测试??

    [root@s2 ~]# mkdir -pv /data/nginx/php
    [root@www ~]# vi /data/nginx/php/index.php 		#php测试??
    <?php
            phpinfo();
    ?>
    
    

    Nginx配置转发

    Nginx安装完成之后默认?成了与fastcgi的相关配置?件,?般保存在nginx的安装路径的conf?录当中,?如/apps/nginx/conf/fastcgi.conf、/apps/nginx/conf/fastcgi_params。

    # 在nginx负载均衡配置文件中加一个location(在主配置文件中有示例)
    [root@www ~]# cat /apps/nginx/conf/nginx.conf
            #location ~ \.php$ {
            #    root           html;
            #    fastcgi_pass   127.0.0.1:9000;
            #    fastcgi_index  index.php;
            #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #    include        fastcgi_params;		# 他会把/apps/nginx/conf/fastcgi_params
    这个文件中的变量导入进来
            #}
    
    
    
    [root@s2 ~]# vim /apps/nginx/conf/conf.d/pc.conf #在指定?件配置fastcgi
    server {
    
    	...
    	
    	location ~ \.php$ {
    		root /data/nginx/php; 				# $document_root调?root?录
    		fastcgi_pass 127.0.0.1:9000;
    		fastcgi_index index.php;
    		#fastcgi_param SCRIPT_FILENAME /data/nginx/php$fastcgi_script_name;			# 定义fastcgi_params的绝对路径
    		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 			#如果SCRIPT_FILENAME是绝对路径则可以省略root /data/nginx/php;	($document_root的值就是root定义的路径,他会去这个路径下去找)
    		include fastcgi_params;
    		fastcgi_hide_header X-Powered-By;		# 隐藏php版本信息
    		fastcgi_pass_header X-Accel;			# 透传上一跳信息(Vary: Accept-Encoding没有上一跳信息,他就不显示)
    	}	
    }
    
    #重启Nginx并访问web测试
    [root@www ~]# /apps/nginx/sbin/nginx -t
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    
    # 测试(测试成功,必须指定index.php,location / 中没有设置默认的index,有index.php)
    http://www.helloworld.net/index.php
    
    ## fastcgi_pass常?的错误:
    ## File not found. #路径不对
    ## 502: php-fpm处理超时、服务停?运?等原因导致的?法连接或请求超时
    
    

    php-fpm 的运?状态??

    访问配置?件??指定的路径,会返回php-fpm的当前运?状态。
    Nginx配置:

    [root@s2 ~]# vim /apps/nginx/conf/conf.d/pc.conf #在指定?件配置fastcgi
    server {
    
    	...
    	
    	location ~ ^/(status|ping)$ {		# 如果客户端访问status和ping的时候,就会被这个location匹配到
    		#access_log off;
    		#allow 127.0.0.1;
    		#deny all;
    		include fastcgi_params;
    		fastcgi_pass 127.0.0.1:9000;		# 匹配成功后就转给本地的9000
    		fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
    		fastcgi_keep_conn on;
    
    	}
    }
    
    # 重载nginx
    [root@www ~]# /apps/nginx/sbin/nginx -t
    [root@www ~]# /apps/nginx/sbin/nginx -s reload
    
    # 访问测试ping
    [root@localhost ~]# curl http://www.helloworld.net/ping
    pong		# pong表示php是正常的
    
    # 访问测试status(php的运行状态)
    pong[root@localhost ~]# curl http://www.helloworld.net/status
    pool:                 www
    process manager:      dynamic
    start time:           31/Mar/2021:17:57:16 +0800
    start since:          1662
    accepted conn:        7
    listen queue:         0			# 队列有多少
    max listen queue:     0
    listen queue len:     128
    idle processes:       49		# 空闲的进程数
    active processes:     1			# 当前活动的进程数(活动就是访问)
    total processes:      50
    max active processes: 2
    max children reached: 0
    slow requests:        0
    
    ## 或者
    [root@localhost ~]# curl http://www.helloworld.net/status?json
    {"pool":"www","process manager":"dynamic","start time":1617184636,"start since":1885,"accepted conn":8,"listen queue":0,"max listen queue":0,"listen queue len":128,"idle processes":49,"active processes":1,"total processes":50,"max active processes":2,"max children reached":0,"slow requests":0}
    
    [root@localhost ~]# curl http://www.magedu.net/pm_status?full
    
    [root@localhost ~]# curl http://www.magedu.net/pm_status?html
    
    

    FastCGI示例--Nginx与php不在同?个服务器

    nginx会处理静态请求,但是会转发动态请求到后端指定的php-fpm服务器,因此代码也需要放在后端的php-fpm服务器,即静态??放在Nginx上?动态??放在后端php-fpm服务器,正常情况下,?般都是采?6.3.2的部署?式。

    yum安装较新版本php-fpm (注意php和nginx不在同一个主机)

    # 使用清华的yum源,这里的php-fpm版本较新(包含较新的PHP等软件包)
    [root@www ~]# wget https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm
    
    # 查看包
    [root@www ~]# rpm -qpl remi-release-7.rpm
    警告:remi-release-7.rpm: 头V4 DSA/SHA1 Signature, 密钥 ID 00f97f56: NOKEY
    /etc/pki/rpm-gpg/RPM-GPG-KEY-remi
    /etc/pki/rpm-gpg/RPM-GPG-KEY-remi2017		# 生成一堆key文件
    /etc/pki/rpm-gpg/RPM-GPG-KEY-remi2018		# 生成一堆key文件
    /etc/pki/rpm-gpg/RPM-GPG-KEY-remi2019		# 生成一堆key文件
    /etc/pki/rpm-gpg/RPM-GPG-KEY-remi2020		# 生成一堆key文件
    /etc/pki/rpm-gpg/RPM-GPG-KEY-remi2021		# 生成一堆key文件
    /etc/yum.repos.d/remi-glpi91.repo
    /etc/yum.repos.d/remi-glpi92.repo
    /etc/yum.repos.d/remi-glpi93.repo
    /etc/yum.repos.d/remi-glpi94.repo
    /etc/yum.repos.d/remi-modular.repo
    /etc/yum.repos.d/remi-php54.repo		# 这堆repo文件当中包括php54
    /etc/yum.repos.d/remi-php70.repo		# 这堆repo文件当中包括php70
    /etc/yum.repos.d/remi-php71.repo		# 这堆repo文件当中包括php71
    /etc/yum.repos.d/remi-php72.repo		# 这堆repo文件当中包括php72
    /etc/yum.repos.d/remi-php73.repo		# 这堆repo文件当中包括php73
    /etc/yum.repos.d/remi-php74.repo		# 这堆repo文件当中包括php74
    /etc/yum.repos.d/remi-php80.repo		# 这堆repo文件当中包括php80
    /etc/yum.repos.d/remi-safe.repo
    /etc/yum.repos.d/remi.repo
    
    # 解决php安装的依赖关系
    [root@www ~]# yum -y localinstall remi-release-7.rpm
    
    # 查看php版本
    [root@www ~]# yum list php*
    
    
    # 安装php
    [root@www ~]# yum -y install php72-php-fpm php72-php-mysql
    [root@www ~]# rpm -ql php72-php-fpm
    
    # ?成php72配置?件
    [root@www ~]# cp /opt/remi/php72/root/usr/share/doc/php72-php-common-7.2.34/php.ini-production /opt/remi/php72/root/usr/etc/php.ini
    
    [root@www ~]# cp /opt/remi/php72/root/usr/share/doc/php72-php-fpm-7.2.34/php-fpm.conf.default /opt/remi/php72/root/usr/etc//php-fpm.conf
    
    

    修改php-fpm监听配置

    php-fpm默认监听在127.0.0.1的9000端?,也就是?法远程连接,因此要做相应的修改。

    #php56修改监听配置
    [root@s4 ~]# vim /opt/remi/php56/root/etc/php-fpm.d/www.conf
    39 listen = 192.168.7.104:9000 #指定监听IP
    65 #listen.allowed_clients = 127.0.0.1 #注释运?的客户端
    
    # php72修改监听配置(修改用户和组,同nginx一样)
    [root@www ~]#  vi /etc/opt/remi/php72/php-fpm.d/www.conf
    user = nginx
    ; RPM: Keep a group allowed to write in log dir.
    group = nginx
    
    ...
    
    listen = 192.168.127.130:9000		# 修改监听地址,127.0.0.1就不行了,使用本机地址让其能在远程访问
    
    ...
    
    ; listen.allowed_clients = 127.0.0.1		# 默认不允许别的主机访问,只允许本机访问,注释掉就能被远程访问了
    
    

    创建账号

    # 要与前端nginx账号和id一致(nginx账号id2000)
    [root@www ~]# id nginx
    uid=2000(nginx) gid=2000(nginx) 组=2000(nginx)
    
    # php创建账号,指定id
    [root@localhost ~]# useradd -u 2000 nginx
    
    ## 如果已创建,修改id
    [root@localhost ~]# usermod -u 2000 nginx		#修改用户id
    [root@localhost ~]# groupmod -g 2000 nginx		# 修改组id
    
    [root@localhost ~]# id nginx
    uid=2000(nginx) gid=2000(nginx) 组=2000(nginx)
    
    

    启动并验证php-fpm

    # 启动php-fpm56
    [root@s4 ~]# systemctl start php56-php-fpm
    [root@s4 ~]# systemctl enable php56-php-fpm
    
    # 启动php-fpm72
    [root@localhost ~]# systemctl start php72-php-fpm
    [root@localhost ~]# systemctl enable php72-php-fpm
    
    # 验证php-fpm进程及端?
    [root@localhost ~]# ps -ef | grep php-fpm
    root       7894      1  0 21:17 ?        00:00:00 php-fpm: master process (/etc/opt/remi/php72/php-fpm.conf)
    nginx      7895   7894  0 21:17 ?        00:00:00 php-fpm: pool www
    nginx      7896   7894  0 21:17 ?        00:00:00 php-fpm: pool www
    nginx      7897   7894  0 21:17 ?        00:00:00 php-fpm: pool www
    nginx      7898   7894  0 21:17 ?        00:00:00 php-fpm: pool www
    nginx      7899   7894  0 21:17 ?        00:00:00 php-fpm: pool www
    root       8925  65172  0 21:18 pts/0    00:00:00 grep --color=auto php-fpm
    
    
    [root@localhost ~]# ss -tnl | grep 9000
    LISTEN     0      128    192.168.127.128:9000                     *:*          
    [root@localhost ~]# netstat -tuanlp | grep 9000
    tcp        0      0 192.168.127.128:9000    0.0.0.0:*               LISTEN      7894/php-fpm: maste
    
    

    php准备php测试??

    # 准备php数据?录
    [root@www ~]# mkdir -p /data/nginx/php
    
    # 准备测试页
    [root@localhost ~]# vi /data/nginx/php/index.php
    <?php
            phpinfo();
    ?>
    
    
    

    Nginx配置转发

    # 修改子配置文件
    [root@www ~]# vi /apps/nginx/conf/conf.d/pc.conf
    server {
    
    		...
    
            location ~ \.php$ {
                    root /data/nginx/php;
                    fastcgi_pass 192.168.127.128:9000;		# php的地址
                    fastcgi_index index.php;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;		# 这里如果是绝对路径需要创建出来,否者会访问的时候会报错404找不到页面
                    include fastcgi_params;
                    fastcgi_hide_header X-Powered-By;
                    fastcgi_pass_header X-Accel;
    
             #       fastcgi_cache phpcache;		# 如果主配置文件中没有定义缓存,就注释掉
             #       fastcgi_cache_key $request_uri;
             #       fastcgi_cache_valid 200 302 301 10m;
             #       fastcgi_cache_valid any 1m;
            }
    }
    
    
    # 重载nginx
    [root@localhost tengine-2.1.2]# /apps/tengine-2.1.2/sbin/nginx -s reload
    
    
    # 访问测试(测试正常,版本是7.2,是我们刚才安装的)
    http://www.helloworld.net/index.php
    X-Powered-By: PHP/7.2.34
    
    

    tengine使?

    Tengine使?:http://tengine.taobao.org/
    关闭nginx,下载tengine源码并使?nginx参编译安装,tengine与nginx版本不?致会导致编译参数不通?。

    动态模块

    http://tengine.taobao.org/document_cn/dso_cn.html

    	这个模块主要是?来运?时动态加载模块,?不?每次都要重新编译Tengine.
    
    	如果你想要编译官?模块为动态模块,你需要在configure的时候加上类似这样的指令(--withhttp_xxx_module),./configure --help可以看到更多的细节.
    
    	如果只想要安装官?模块为动态模块(不重新安装tengine),那么就只需要configure之后,执? makedso_install命令.动态加载模块的个数限制为128个.
    
    	如果已经加载的动态模块有修改,那么必须重起Tengine才会?效.
    
    	只?持HTTP模块.
    
    	模块 在Linux/FreeeBSD/MacOS下测试成功.
    

    ?
    tengine v2.1.2(基于ginx/1.6.2)(v2.1.2是稳定版) centos 7.x

    # 解决依赖关系
    [root@localhost tengine-2.1.2]# yum install -y vim lrzsz tree screen psmisc lsof tcpdump wget ntpdate gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools iotop bc zip unzip zlib-devel bash-completion nfs utils automake libxml2 libxml2-devel libxslt libxslt-devel perl perl ExtUtils-Embed
    
    
    # 下载tengine源码包
    [root@localhost ~]# wget http://tengine.taobao.org/download/tengine-2.1.2.tar.gz
    
    # 解压包
    [root@localhost ~]# tar vxf tengine-2.1.2.tar.gz 
    
    # 切换目录
    [root@localhost ~]# cd tengine-2.1.2
    
    # 编译安装(如果你要替换nginx,找到当前nginx的编译参数nginx -V,但是有些模块tengine有可能不支持,tengine基于nginx的版本太低了)
    [root@localhost tengine-2.1.2]# ./configure --prefix=/apps/tengine-2.1.2 --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre && make && make install
    
    
    # 切换目录(他的目录基本上跟nginx是一样的)
    [root@localhost tengine-2.1.2]# cd /apps/tengine-2.1.2
    [root@localhost tengine-2.1.2]# ls
    conf  html  include  logs  modules  sbin
    
    
    # 修改配置文件
    [root@localhost tengine-2.1.2]# vi /apps/tengine-2.1.2/conf/nginx.conf
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
         log_format access_json '{"@timestamp":"$time_iso8601",'            
             '"host":"$server_addr",'
             '"clientip":"$remote_addr",'
             '"size":$body_bytes_sent,'
             '"responsetime":$request_time,'
             '"upstreamtime":"$upstream_response_time",'
             '"upstreamhost":"$upstream_addr",'
             '"http_host":"$host",'
             '"uri":"$uri",'
             '"domain":"$host",'
             '"xff":"$http_x_forwarded_for",'
             '"referer":"$http_referer",'
             '"tcp_xff":"$proxy_protocol_addr",'
             '"http_user_agent":"$http_user_agent",'
             '"status":"$status",'
             '"tengine-uri":"$request_filename"}';
    
    	server{
    	
    	...
    	
    	}
    include /apps/tengine-2.1.2/conf/conf.d/*.conf;
    }
    
    # 创建用户
    [root@localhost tengine-2.1.2]# useradd nginx -s /sbin/nologin -u 2000
    
    # 启动tingine
    [root@localhost tengine-2.1.2]# /apps/tengine-2.1.2/sbin/nginx -t
    the configuration file /apps/tengine-2.1.2/conf/nginx.conf syntax is ok
    configuration file /apps/tengine-2.1.2/conf/nginx.conf test is successful
    
    [root@localhost tengine-2.1.2]# /apps/tengine-2.1.2/sbin/nginx
    [root@localhost tengine-2.1.2]# ss -tnl
    State       Recv-Q Send-Q                                       Local Address:Port                                                      Peer Address:Port              
    LISTEN      0      128                                                      *:80                                                                   *:*                  
    LISTEN      0      128                                                      *:22                                                                   *:*                  
    LISTEN      0      100                                              127.0.0.1:25                                                                   *:*                  
    LISTEN      0      128                                                     :::22                                                                  :::*                  
    LISTEN      0      100                                                    ::1:25     
    
    # 关闭防火墙
    [root@localhost tengine-2.1.2]# systemctl stop firewalld
    [root@localhost tengine-2.1.2]# setenforce 0
    
    # 访问测试(测试成功)
    http://192.168.127.130/
    Welcome to tengine!
    
    # 创建目录
    [root@localhost tengine-2.1.2]# mkdir -pv  /apps/tengine-2.1.2/conf/conf.d
    mkdir: 已创建目录 "/apps/tengine-2.1.2/conf/conf.d"
    
    
    # 创建子配置文件
    [root@localhost tengine-2.1.2]# vi /apps/tengine-2.1.2/conf/conf.d/pc.conf
    server {
    
            listen 80;
            server_name www.helloworld.net;
    
            location ~ \.php$ {
                    root /data/tengine/php;
                    access_log /apps/tengine-2.1.2/logs/access_json.log access_json;
                    fastcgi_pass 192.168.127.128:9000;   	# 指定php地址           
                    fastcgi_index index.php;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 	# 指定页面路径                           
                    include fastcgi_params;
                    fastcgi_hide_header X-Powered-By;
                    fastcgi_pass_header X-Accel;
            }
    }
    
    
    # 重载nginx
    [root@localhost tengine-2.1.2]# /apps/tengine-2.1.2/sbin/nginx -t
    [root@localhost tengine-2.1.2]# /apps/tengine-2.1.2/sbin/nginx -s reload
    
    
    
    # 准备php数据?录(tingine对php分开部署,有问题访问不了)
    [root@localhost tengine-2.1.2]# mkdir -p /data/tengine/php
    
    
    # 准备测试页
    [root@localhost ~]# vi /data/tengine/php/index.php
    <?php
            phpinfo();
    ?>
    
    
    
    
    # 访问测试(测试正常,版本是7.2,是我们刚才安装的)
    [root@localhost ~]# curl http://www.helloworld.net/index.php
    File not found.
    
    

    系统参数优化

    系统参数优化

    默认的Linux内核参数考虑的是最通?场景,不符合?于?持?并发访问的Web服务器的定义,根据业务特点来进?调整,当Nginx作为静态web内容服务器、反向代理或者提供压缩服务器的服务器时,内核参数的调整都是不同的,此处针对最通?的、使Nginx?持更多并发请求的TCP?络参数做简单的配置,修改/etc/sysctl.conf来更改内核参数
    
    net.ipv4.ip_nonlocal_bind = 1 #允许?本地IP地址socket监听
    net.ipv4.ip_forward = 1 #开启IPv4转发
    net.ipv4.tcp_timestamps = 0 #是否开启数据包时间戳(不能打开)
    net.ipv4.tcp_tw_reuse = 0 #端?复?
    net.ipv4.tcp_tw_recycle = 0 #快速回收TIME_WAIT状态,?于?量TIME_OUT场景
    
    fs.file-max = 1000000
    #表示单个进程较?可以打开的句柄数
    
    net.ipv4.tcp_tw_reuse = 1
    #参数设置为 1 ,表示允许将TIME_WAIT状态的socket重新?于新的TCP链接,这对于服务器来说意义重?,因为总有?量TIME_WAIT状态的链接存在
    
    net.ipv4.tcp_keepalive_time = 600
    #当keepalive启动时,TCP发送keepalive消息的频度;默认是2?时,将其设置为10分钟,可更快的清理?效链接
    
    net.ipv4.tcp_fin_timeout = 30
    #当服务器主动关闭链接时,socket保持在FIN_WAIT_2状态的较?时间
    
    net.ipv4.tcp_max_tw_buckets = 5000
    #表示操作系统允许TIME_WAIT套接字数量的较?值,如超过此值,TIME_WAIT套接字将?刻被清除并打印警告信息,默认为8000,过多的TIME_WAIT套接字会使Web服务器变慢
    
    net.ipv4.ip_local_port_range = 1024 65000
    #定义UDP和TCP链接的本地端?的取值范围
    
    net.ipv4.tcp_rmem = 10240 87380 12582912
    #定义了TCP接受socket请求缓存的内存最?值、默认值、较?值
    
    net.ipv4.tcp_wmem = 10240 87380 12582912
    #定义TCP发送缓存的最?值、默认值、较?值
    
    net.core.netdev_max_backlog = 8096
    #当?卡接收数据包的速度?于内核处理速度时,会有?个列队保存这些数据包。这个参数表示该列队的较?值
    
    net.core.rmem_default = 6291456
    #表示内核套接字接受缓存区默认??
    
    net.core.wmem_default = 6291456
    #表示内核套接字发送缓存区默认??
    
    net.core.rmem_max = 12582912
    #表示内核套接字接受缓存区较???
    
    net.core.wmem_max = 12582912
    #表示内核套接字发送缓存区较???
    注意:以上的四个参数,需要根据业务逻辑和实际的硬件成本来综合考虑
    
    net.ipv4.tcp_syncookies = 1
    #与性能?关。?于解决TCP的SYN攻击
    
    net.ipv4.tcp_max_syn_backlog = 8192
    #这个参数表示TCP三次握?建?阶段接受SYN请求列队的较??度,默认1024,将其设置的??些可使出现Nginx繁忙来不及accept新连接时,Linux不?于丢失客户端发起的链接请求
    
    net.ipv4.tcp_tw_recycle = 1
    #这个参数?于设置启?timewait快速回收
    
    net.core.somaxconn=262114
    #选项默认值是128,这个参数?于调节系统同时发起的TCP连接数,在?并发的请求中,默认的值可能会导致链接超时或者重传,因此需要结合?并发请求数来调节此值。
    
    net.ipv4.tcp_max_orphans=262114
    #选项?于设定系统中最多有多少个TCP套接字不被关联到任何?个?户?件句柄上。如果超过这个数字,孤?链接将?即被复位并输出警告信息。这个限制指示为了防?简单的DOS攻击,不?过分依靠这个限制甚?认为的减?这个值,更多的情况是增加这个值
    

    标签智能推荐:

    docker挡板程序实现启动多个实例进程

    启动服务:docker-composerestart

    SpringCloudAlibaba--服务熔断--Sentinel服务熔断配置(Ribbon)

    Sentinel服务熔断-Ribbonorder80消费端:Sentinel服务熔断-exceptionsToLgnore

    SpringCloudAlibaba--服务降级--Sentinel的降级

    Sentinel服务降级--简介Sentinel服务降价--RT:Sentinel服务降级--异常比例:Sentinel服务降级--异常数:&nbsp;&nbsp;

    Mac上的Apache服务指令

    停止服务:sudo/usr/sbin/apachectlstop开启服务:sudo/usr/sbin/apachectlstart重启服务:sudo/usr/sbin/apachectlrestart

    OSP学习笔记--ESPService模型

    ESPService模型中的服务Key类型服务key加载服务保存服务单据单个:ESPBillProvider列表:BillFormEnumerESPBillResolver字典大数据:LargeDICTService普通:DICTServiceMDMResolver

    Linux服务文件位置

    systemctl服务所在位置:ls/usr/lib/systemd/systemservice服务位置:ls/etc/init.d/

    linux 7 关闭防火墙 开启sshd服务

    启动一个服务:systemctlstartfirewalld.service关闭一个服务:systemctlstopfirewalld.service重启一个服务:systemctlrestartfirewalld.service显示一个服务的状态:systemctlstatusfirewalld.service在开机时启用一个服务:systemctlenablefirewalld.service

    ORA-12541:tns:no listener

    &nbsp;打开任务管理器,查看服务,看箭头所指的三个服务是否开启即可

    查看docker服务状态

    root用户使用#查看docker服务状态:systemctlstatusdocker非root用户使用#查看docker服务:sudosystemctlstatusdocker