NGINX温故而知新

前言

本篇nginx温故而知新文章主要基于实际生产环境中所用到的知识总结出的一篇文章,主要包含ssl证书替换、平滑升级、nginx优化等知识点。同时这篇文章会不定期更新内容,将我自身遇到的一些实际问题及解决方法或者是nginx的新知识内容都会更新到此,希望对大家有用!

NGINX的优点

1、高并发
2、IO多路复用
3、epoll模型
4、异步非阻塞
5、多进程模型 主进程负责监听外部控制信号,通过频道机制将相关信号操作传递给工作进程,多个工作进程间通过共享内存来共享数据和信息,默认配置下,工作进程的数量与主机CPU核数相同,充分利用cpu和进程的亲缘性将工作进程与CPU绑定,从而最大限度发挥CPU的处理能力

NGINX信号

信号又称软中断信号,可以通过调用系统命令kill来发送信号实现进程通信

信号					命令行参数				功能
TERM或INT 			    stop 				快速关闭Nginx服务
QUIT					quit				安全关闭Nginx服务
HUP						reload				平滑重启,热加载配置文件
WINCH										从容关闭工作进程
USR1					reopen				 重新创建日志文件,主要用于日志文件切割
USR2										平滑更新Nginx执行文件

示例操作:
	使用kill命令向nginx发送信号指令
		kill -HUP 'cat nginx.pid'
	使用nginx -s 命令行参数实现信号指令发送	
		nginx -s reload

NGINX主配置文件分类

coreModule 核心模块 提供了进程管理、内存管理、配置文件解析、日志等功能
EventsModule 事件驱动模块 负责进行连接处理,提供对不同操作系统的I/O网络模型支持和自动根据系统平台选择最有效I/O网络模型的方法
HttpCoreModule http内核模块 提供HTTP处理的核心功能和部分功能模块
stream 模块 提供TCP、UDP会话支持

NGINX命令行参数

-v  nginx版本信息
-V  模块信息
-t  进行配置文件语法检查,测试配置文件的有效性
-T  进行配置文件语法检查,测试配置文件的有效性,同时输出所有有效配置内容(如果nginx的配置文件被误删除且nginx处于运行状态、没有reload加载过,则可以使用该命令恢复配置文件)
-q  在测试配置文件的有效性时,不输出非错误信息
-s  发送信号给nginx主进程,信号可以为以下4个:
	stop  快速关闭
    quit  正常关闭
    reopen  重新打开配置文件
    reload  重新加载配置文件 启动一个加载新配置文件的进程,正常关闭一个加载就配置文件的进程
-p  指定nginx的执行目录
-c  指定nginx.conf文件的位置
-g  外部指定配置文件中的全局指令

NGINX匹配

1、location前缀含义
    = 表示精确匹配,优先级也是最高的
    ^~ 表示url以某个常规字符串开头,理解为匹配url路径即可
    ~ 表示区分大小写的正则匹配
    ~* 表示不区分大小写的正则匹配
    !~ 表示区分大小写不匹配的正则(很少用)
    !~* 表示不区分大小写不匹配的正则(很少用)
    / 通用匹配,任何请求都会匹配到

2、多个location配置的情况下匹配顺序为:
	= (精确匹配)> ^~(字符开头匹配) > ~|~*|!~|!~*(按正则匹配) > 最后是通用匹配/

root与alias指令区别

root 
例如:
 location /abc {   #当匹配到/abc时,会去root定义的/home/www/nginx目录下的abc目录下(/home/www/nginx/abc/2.html)去找2.html
  root /home/www/nginx; 
  index 2.html index.html
 }
alias (访问重定向)
 location /abc {  #当收到的请求是 http://example.com/abc/2.html 时,Nginx 会查找文件系统中的 /home/www/nginx/2.html 并返回该文件
  alias /home/www/nginx/; #alias 定义的目录结尾必须以/根结尾
  index 2.html index.html
 }

地址重写rewrite

即URL重写,把传入web的请求重定向到其他URL的过程
应用环境,server和location
302临时重定向 redirect 在跳转时会查看哪个网址更直观,就跳转哪个
301永久重定向 permanent 
last:重写完成后, 停止对当前URL在当前location中后续的其他重写操作, 而后对新的URL启动新一轮重写检查, 不建议在location中使用
适用于一个URL多次重写, 要注意避免出现超过10次以及URL重写后返回错误的URL给用户
break:重写完成后, 停止对当前URL在当前location中后续的其他重写操作, 至于重写后的URL, 如果在其他location中有匹配, 那么也不会执行, break就是直接结束循环, 只要遇到了break, 那么就会结束匹配, 并且执行break前rewrite定义的操作, 建议在location中使用
适用于一个URL一次重写

permanent (301 重定向)添加与不添加的区别

permanent 会将地址显示为新的URL地址(重定向之后的URL)
	1、当rewrite *. /a/b/1.html 后添加 permanent时, url被替换,浏览器页面上通过F12检查会发现生成了两次请求,且页面url地址是新地址。
	2、当rewrite *. /a/b/1.html 后不添加 permanent时,url是老的,服务器内部转换请求,页面中的url地址不变

nginx优化

1.worker_processes 8; 工作进程数(一般为cpu的核数)
2.worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;(充分利用多核CPU)
3.worker_rlimit_nofile 102400; 最大文件打开数
4.events模块调优
events {
    use epoll;  事件驱动模型
    worker_connections  102400; 最大连接数
    #multi_accept on;
    multi_accept off;  批量建立连接
    accept_mutex on; nginx负载均衡锁(该锁可以让Nginx的多个worker进程轮流的、序列化的与新客户端建立TCP连接,以此实现worker进程间的请求数尽量接近。关闭可以让TCP建立连接更快,但不建议关闭)
}
5  sendfile on; 提高传输效率
   tcp_nopush  on; (当包累计到一定大小后就发送,与sendfile搭配使用,防止网络堵塞)
   server_tokens off;(隐藏版本号)
   autoindex off; 不允许列出整个目录
    gzip                on; 打开gzip压缩
    gzip_min_length     4k; 允许压缩的页面最小字节数
    gzip_buffers     4 16k; 设置缓存的单位,压缩的时候要分配的缓冲区,缓冲区以16K为单位,往缓冲区写入内容的时候超过16K的时候,那么就会按照4倍的大小创建新的缓冲区,也就是建立一个64K的存储,这样把压缩的内容倒进去
    #gzip_http_version    1.1;
    gzip_comp_level      3; 压缩级别1-9,比如level为1的话,压缩的比例比较低,但是效率比较高,官方推荐6
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttc font/ttf; 定义了压缩的类型
    gzip_vary          off; 关闭应答头"Vary: Accept-Encoding"
    # off IE6
    gzip_disable "MSIE [1-6]\."; IE5.5和IE6 SP1使用msie6参数来禁止gzip压缩 )指定哪些不需要gzip压缩的浏览器(将和User-Agents进行匹配),依赖于PCRE库
    include conf.d/*.conf;
}
6 上传的包大小 client_max_body_size 2000m;
7 请求行+请求头的标准大小为2m  client_header_buffer_size 2m;
8 请求行+请求头的最大大小为40m  large_client_header_buffers 4 10m;(如果超过这个值,会报414错误)
9 请求主体的缓冲区大小         client_body_buffer_size 4m;
10 表示upstream 的连接、读取、发送超时时间都是300秒
  proxy_connect_timeout 300;
  proxy_read_timeout 300;
  proxy_send_timeout 300;
11 一个http产生的tcp连接在传送完最后一个响应后,还需要hold住 keepalive_timeout秒后,才开始关闭这个连接   keepalive_timeout  300;

NGINX负载均衡策略(通过upstream模块实现)

1、rr 轮询
2、weight 加权(权重越高,被访问到的几率越大)
3、ip_hash (在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的。我们可以采用ip_hash指令解决这个问题,如果客户已经访问了某个服务器,当用户再次访问时,会将该请求通过哈希算法,自动定位到该服务器。可以解决session问题)
4、fair 第三方(按后端服务器的响应时间来分配请求)
5、url_hash 按访问url的hash结果来分配请求,使每个url定向到同一个(对应的)后端服务器,后端服务器为缓存时比较有效。

NGINX常用模块

Nginx访问控制
  1、基于用户的访问控制
		auth_basic认证模块
        只需要在server 或者location 或者http中增加如下两行
         auth_basic "Please input password";      ##输入用户名密码提示框
         auth_basic_user_file /etc/nginx/conf.d/auth_pwd;  ##配置用户名密码验证文件路径
        可以使用htpasswd或者openssl工具生成密码
        #安装工具
          yum -y install httpd-tools
	    #生成密码
          htpasswd -c ./passwd username
        #执行上命令后会要求输入两次密码,./passwd 是在当前目录下创建密码文件passwd ,username即为需要设置的账号
  2、基于主机的访问控制 (只允许某个ip地址访问)
		server {
          allow 10.18.45.65;
          allow 10.18.45.181;
          deny all;
        }
rewrite地址重写模块
server {
    listen 80;
    server_name www.aa.com;
    location /test {
        rewrite ^/test(.*)$ http://www.bb.com/test1$1 permanent;
    }
}
上述配置中,首先定义了一个server块,监听80端口,对应的域名是www.aa.com。然后在location块中,设置了一个rewrite规则,匹配以/test开头的请求,并将其重定向到www.bb.com/test1,同时保持原来的请求参数不变。最后使用permanent关键字,表示这是一个永久重定向,浏览器会自动缓存这个重定向结果,下次访问时直接跳转。
文件压缩模块
gzip on;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; 
gzip_static on;
防盗链模块
 valid_referers none blocked *.a.com;
       if ($invalid_referer) {
            return 403;
        }
状态检测模块 (展示用户和nginx连接数量)
location /nginx_status {	
stub_status;
access_log on;
}

NGINX平滑升级

1.下载需要更新得nginx版本,并解压,并执行nginx -V得到旧版nginx的configure参数
2.进入到解压目录,执行以下命令
	./configure --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --http-log-path=/var/log/nginx/access.log --with-http_ssl_module --with-http_v2_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-http_realip_module
  这些参数第一步获取到的.切记不要随意更改
  在执行make进行编译
3.进入到现有nginx的sbin/nginx下,进行备份 mv nginx nginx.bak
4.编译完成后可以看到一个objs文件夹,进入到objs文件夹
5.复制objs目录下的nginx到现有的nginx目录下
  cp xxx/xxx/objs/nginx  /export/server/nginx/sbin/
6.发送信号usr2给nginx老版本对应的进程
  kill -usr2 `cat /export/server/nginx/logs/nginx.pid`
7.发送信号winch信号平滑逐步的关闭旧的work进程
  kill -WINCH `cat /export/server/nginx/logs/nginx.pid.oldbin`
8.使用HUP重新加载配置文件,使用新的配置,并逐步关闭旧进程
  kill -HUP `cat /export/server/nginx/logs/nginx.pid.oldbin`
9.结束工作进程完成升级(QUIT等待请求处理结束后退出)
  kill -QUIT `cat /export/server/nginx/logs/nginx.pid.oldbin`
10.查看是否升级成功
  /export/server/nginx/sbin/nginx -v

NGINX添加新模块

背景:
	已经安装完成且正在使用的nginx,经过nginx -V检查缺失某个模块,需要新增加模块
步骤:
	1、检查当前nginx有哪些模块 nginx -V ,如下图1所示
	2、添加一个http/2模块
	3、下载当前nginx对应的二进制安装包,解压至指定位置找到configure文件位置
	4、重新配置configure参数,切记一定要带上现有的参数(通过nginx -V查出来有多少个必须指定多少个)
	5、当前示例执行以下命令 ./configure --prefix=/export/package/nginx-1.20.1/ --with-http_stub_status_module(现有模块) --with-http_ssl_module(现有模块) --wiht-http_v2_module(新增模块)
	6、上述命令执行完后再执行make命令,切记不要执行make install命令,不然会覆盖现有nginx目录
	7、进入现有nginx目录  cd /export/server/nginx/sbin/
	8、停止现有nginx并备份现有nginx文件 ./nginx stop && cp ./nginx ./nginx.bak_20240918
	9、将编译完成的nginx文件拷贝至现有nginx的sbin目录下 cp /export/package/nginx-1.20.1/objs/nginx  /export/server/nginx/sbin/nginx (按 y键确认覆盖)
	10、启动现有nginx /export/server/nginx/sbin/nginx
	11、检查现有nginx模块是否已存在http/2模块 /export/server/nginx/sbin/nginx -V

在这里插入图片描述

NGINX ssl证书替换

下载已申请完成的ssl证书文件,如下图所示

在这里插入图片描述

注意事项:
	CSR 文件是申请证书时由您上传或系统在线生成的,提供给 CA 机构。安装时可忽略该文件。

替换证书步骤:
	1.打开ssl证书的配置路径
	2.备份旧证书,上传新证书
		将已获取到的 yqzhfwxt.bda.gov.cn_bundle.crt 证书文件和 yqzhfwxt.bda.gov.cn.key 私钥文件从本地目录拷贝到 ssl目录下
	3.修改conf文件,指定ssl_certificate和ssl_certificate_key 对应的ssl证书文件位置及证书名,保存并重载nginx  执行该命令即可 nginx -t && nginx -s reload

NGINX proxy_pass url路径末尾带/与不带/的区别

在nginx中配置proxy_pass反向代理时,当在后面的url加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;如果没有/,则会把匹配的路径部分也给代理走
例子:
1、当nginx配置文件proxy_pass后边的url带"/"时,代理到后端的路径为:http://127.0.0.1:18081/bill.html,省略了匹配到的/pss/路径;
location /pss/ {
proxy_pass http://127.0.0.1:18081/;
}

2、当nginx配置文件proxy_pass后边的url不带"/"时,代理到后端的路径为:http://127.0.0.1:18081/pss/bill.html,连同匹配到的/pss/路径,一起进行反向代理;
location /pss/ {
proxy_pass http://127.0.0.1:18081;
}

location 带/与不带/的区别

1、当location与proxy_pass都带/,则真实地址不带location匹配目录
	location /api/ {
    	proxy_pass http://127.0.0.1:8080/;
	}
访问地址:www.test.com/api/upload–>http://127.0.0.1:8080/upload
2、当location不带/,proxy_pass带/,则真实地址会带/
	location /api {
    proxy_pass http://127.0.0.1:8080/;
	}
访问地址: www.test.com/api/upload–>http://127.0.0.1:8080//upload
3、location带/,proxy_pass不带/,则真实地址会带location的匹配目录
	location /api/ {
    proxy_pass http://127.0.0.1:8080;
	}
访问地址: www.test.com/api/upload–>http://127.0.0.1:8080/api/upload
4、location和proxy_pass都不带/,则真实地址会带location的匹配目录

NGINX隐藏版本号

1、对于已经安装的nginx,我们可以将它的版本号隐藏
vim /etc/nginx/nginx.conf
在http 模块里加入 server_tokens off;

NGINX正代和反代

正向代理
	隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都由代理服务器代替来请求
正向代理示例配置
 http {
    server {
        listen 80;
        server_name example.com;
        location / {
            proxy_pass http://192.168.1.100:8080;
            proxy_set_header Host $host;
            proxy_cache_bypass $http_cache_control;
            proxy_cache_valid 200 60m;
            proxy_cache_valid 404 1m;
            proxy_cache_revalidate on;
            proxy_cache_min_uses 3;
            proxy_cache_lock on;
        }
    }
}
proxy_pass指定了请求的转发地址,http_host和request_uri表示客户端请求的主机名和URI
反向代理
	是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端。
示例配置
http {
    upstream backend {
        server 127.0.0.1:8000;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

NGINX日志轮转(切割)

1、按日志大小进行切割(当日志文件达到"size=100M"时进行切割)
/export/server/nginx/logs/*.log {  
	# 指定要切割的日志文件路径。* 通配符表示匹配该目录下的所有文件,.log 表示以 .log 结尾的文件。
    create 0644 root root
	# 创建新的轮换日志文件,并设置权限位。
    compress
    # 压缩转储后的日志文件
    delaycompress
	# 当日志文件进行轮换时,延迟压缩到下一次轮换时进行。
    missingok
    # 如果日志文件不存在,则不报错。
    dateext
    # 可以方便地查看不同时间点的日志内容,也可以防止日志文件名字的冲突。
    dateformat %Y%m%d%s
	# 设置时间格式
    rotate 1000
    # 保留1000份旧日志文件,超过1000份的旧日志将被删除。
    notifempty
    # 仅在日志文件非空时才进行轮换。
    size 100M
    # 设置每个日志文件的最大大小为100M,超过此大小则会触发日志切割。
    postrotate
     if [ -f /export/server/nginx/logs/nginx.pid ]; then
        /export/server/nginx/sbin/nginx -s reopen
     fi
    endscript
    # 这是一个 shell 脚本,postrotate 标记指定开始运行 shell 命令的位置,endscript 标记指定结束位置。这里的命令 表示切割后重新打开日志文件以确保 Nginx 继续写入新的日志。
}
	/usr/sbin/logrotate /etc/logrotate.d/nginx.conf   加载执行logrotate的主配置文件
2、按时间切割(daily|week|month|yearly)
 /export/server/nginx/logs/*.log {
    create 0644 root root
	daily
    compress
    delaycompress
    missingok
    dateext
    dateformat %Y%m%d%s
    rotate 30
    notifempty
    postrotate
     if [ -f /export/server/nginx/logs/nginx.pid ]; then
        /export/server/nginx/sbin/nginx -s reopen
     fi
    endscript
}

正向代理配置


背景:
	192.168.1.191可以上外网,绑定了一个公网ip`223.234.56.45`,192.168.1.192不能上外网,使用nginx正向代理的方法实现192.168.1.192主机可以访问外网。
	实现步骤:
		1、191机器上安装nginx,且nginx必须要有正向模块ngx_http_proxy_connect_module。因为nginx默认支持正向代理http,不支持https。
		2、配置代理
vim conf/nginx.conf
	其余配置省略
    #正向代理转发http请求
    server {
    #指定DNS服务器IP地址
        resolver 自己服务器的DNS地址;
    #监听80端口,http默认端口80
        listen 80;
    #服务器IP或域名
            server_name  localhost;
    #正向代理转发http请求
    location / {
        proxy_pass                 http://$host$request_uri;
        proxy_set_header           HOST $host;
        proxy_buffers              256 4k;
        proxy_max_temp_file_size   0k;
        proxy_connect_timeout      30;
        proxy_send_timeout         60;
        proxy_read_timeout         60;
        proxy_next_upstream error  timeout invalid_header http_502;
    }
    }
    #正向代理转发https请求
    server {
        #指定DNS服务器IP地址
            resolver 自己服务器的DNS地址;
        #监听443端口,https默认端口443
        listen 443;
        #正向代理转发https请求
        proxy_connect;
        proxy_connect_allow            443 563;
        proxy_connect_connect_timeout  10s;
        proxy_connect_read_timeout     10s;
        proxy_connect_send_timeout     10s;
     location / {
             proxy_pass http://$host;
             proxy_set_header Host $host;
   }
   }
   	3、nginx服务所在服务器验证正向代理功能
   	  curl -I http://www.baidu.com/ -v -x 127.0.0.1:80
	 curl -I https://www.baidu.com/ -v -x 127.0.0.1:443
	4、内网服务器设置访问外网
	 	a、只配置使用yum时,能够使用正向代理访问外网
		vim /etc/yum.conf
            proxy=http://192.168.0.20:80		#nginx正向代理服务器的地址
            proxy=ftp://192.168.0.20:80			#nginx正向代理服务器的地址
		b、全局配置,所有访问请求都能使用正向代理访问外网
		#追加配置
         vim /etc/profile
            http_proxy=192.168.0.20:80
            https_proxy=192.168.0.20:443
            ftp_proxy=192.168.0.20:443
            export http_proxy
            export https_proxy
            export ftp_proxy
        # 加载配置
        source /etc/profile

nginx配置四层ssl证书

背景:
	用于设置一个基于TCP的反向代理
stream {
  upstream stream_backend {
      zone tcp_servers 512k;
      hash $remote_addr consistent;
      server emqx:1883 max_fails=2 fail_timeout=30s;
  }

  server {
      listen 1883 ssl;
      #status_zone tcp_server;
      proxy_pass stream_backend;
      proxy_buffer_size 4k;
      ssl_handshake_timeout 15s;
      ssl_certificate     /export/certs/ca.crt;
      ssl_certificate_key /export/certs/ca.key;
  }
}

常见的 2 种 Nginx 中 HTTP 跳转 HTTPS 场景

1. Nginx 上层无代理,用户直接访问
	这种方式比较简单。
我们对 http 和 https 都具有控权。且用户是直接访问 Nginx 服务器。

在这里插入图片描述

可以直接通过在 http server 上配置到 301 跳转 到 https 服务器即可。
# http server
server {
    listen 80;
    server_name _;
    return 301 https://$host$request_uri;
}

# https server
server {
    listen 443 ssl http2;
    server_name www.example.com;

    # ... other
}
2. Nginx 上层有代理
这种情况, 稍微麻烦一点。

1.最重要的, 用户并不直接访问我们的 Nginx Server, 而是通过上层代理 Proxy 代理。
2.实际提供 HTTPS 服务的其实是上层 Proxy, 且 我们并没有管理权限。
3.因此, Proxy 在访问 Nginx Server 的时候, 始终使用 HTTP 协议。

在这里插入图片描述

这种情况下, 我们直接使用 Nginx 提供的 内置变量 scheme 就行不通了
# 错误配置
server {
    listen 80;
    server_name _;

    if ($scheme = "http"){
        return 301 https://$host$request_uri; 
    }
}
使用上述配置,无论用户通过任何协议请求,Nginx Server 拿到的都是 http,即 条件恒等。结果就是永远在跳转, 直到重定向次数过多而报错。

解决方案就是 使用 Proxy 提供的 Header 进行判断。不同的 Proxy 提供的 Header 名称可能不一样,需要具体分析。
# 可用配置
server {
    listen 80;
    server_name _;

    # ... other

    if ($http_x_forward_scheme = "http"){
        return 301 https://$host$request_uri; 
    }
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值