Nginx 纵享丝滑

Nginx 纵享丝滑高可用 轻便式 可插拔的服务软件 推荐 赞赞赞 nixgix

大家好,欢迎来到IT知识分享网。

1.基本介绍

Nginx是由俄罗斯的设计师开发的。
Nginx不像Apache那样,不论功能是否常用,统统都给你 自带了,
虽然功能 很强大,但是也很消耗性能,而Nginx只是自带了常用的功能。

Nginx 是 开源、高性能、高可靠的 Web 和反向代理 服务器,
而且支持 热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。
性能 是 Nginx 最重要的考量,其占用内存少、并发能力强、能支持高达 5w 个并发连接数,最重要的是,Nginx 是免费的并可以商业化,配置使用也比较简单。

使用场景

  • 静态资源服务,通过本地文件系统提供服务;
  • 反向代理服务,延伸出包括缓存、负载均衡等;
  • API 服务,OpenResty ;

使用实例

1、vue 打包部署到 NGINX

server { 
    listen 80; server_name localhost; sendfile on; tcp_nodelay on; error_log /root/nginx_error_log/app_error.log; location / { 
    # allow 27.197.70.72; # allow 119.176.167.13; # allow 119.176.161.201; # deny all; root /home/tom/vue/dist/;
                index index.html; try_files $uri $uri/ /index.html; } location /test { 
    default_type text/plain; return 200 "hahahaha"; } # 前端 通过重定向 处理 前端 获取动态数据 的请求跨域 location /api_defaul{ 
    proxy_set_header Host $proxy_host; proxy_set_header Real-IP $remote_addr; proxy_set_header name bbb; rewrite ^/api_default/(.*)$ /$1 break; proxy_pass http://localhost:8033; } } 
try_files 说明:

try_files 作用是 检查文件是否存在,就是指 在每次匹配URL路径的时候,找不到 对应的 静态资源 的 时候 自动跳转 到index.html文件。

  • 不加 try_files 会出现的问题:

nginx部署完项目后,正常访问是没有问题的, 但是 只要在 非根目录 下的页面 只要 一刷新 就报 Nginx404页面

  • 原因解释:

因为web 单页面开发模式,只有一个index.html入口,其他路径 都是 前端路由 去跳转的,nginx 是不知道对应这个路径。
举例说明:如:http://127.0.0.1/user ,此时 刷新页面 之后,会 根据浏览器的url, 访问nginx上 对应的 静态资源,而nginx会根据localhost / 的 匹配规则 在 dist文件夹 中 查找 对应的静态文件user,肯定是找不到的,所以就会报错404。

  • 解决办法:
# 无 子目录 情况
location / {
   root /home/tom/vue/dist/;
   index index.html;
   try_files $uri $uri/ /index.html;
}


# 有子目录 的情况
server {
    listen 80;
    server_name 127.0.0.1;
    index index.html;
    root /www/h5;
    try_files $uri $uri/ /index.html;
    
	......
}

2、服务 的反向代理

server { 
    listen 80; server_name www.baidu.com; error_log /root/nginx_error_log/app_error.log; # 配置跨域 ===============> add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT'; add_header 'Access-Control-Allow-Headers' 'Origin, x-requested-with, Content-Type, Accept, Authorization'; add_header 'Access-Control-Expose-Headers' 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma'; if ($request_method = 'OPTIONS') { 
    add_header 'Access-Control-Max-Age' ; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } # 配置跨域 <=============== location / { 
    proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header proxyhost $proxy_host; proxy_set_header veryimportant $host$request_uri; proxy_pass http://0.0.0.0:8033; } # 静态资源 的 访问服务 location ~ .*\.(gif|jpg|jpeg|png|txt|html|ico|apk)$ { 
    default_type text/plain; root /data/static/; } } server { 
    listen 443 ssl; server_name www.baidu.com; ssl_certificate /root/nginx_cert/www.baidu.com_bundle.crt; ssl_certificate_key /root/nginx_cert/www.baidu.com.key; ssl_session_timeout 10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; add_header X-Frame-Options DENY; # 减少点击劫持 add_header X-Content-Type-Options nosniff; # 禁止服务器自动解析资源类型 add_header X-Xss-Protection 1; # 防XSS攻击 # 配置跨域 ===============> add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT'; add_header 'Access-Control-Allow-Headers' 'Origin, x-requested-with, Content-Type, Accept, Authorization'; add_header 'Access-Control-Expose-Headers' 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma'; if ($request_method = 'OPTIONS') { 
    add_header 'Access-Control-Max-Age' ; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } # 配置跨域 <=============== location / { 
    proxy_set_header veryimportant $host$request_uri; proxy_set_header Host $proxy_host; proxy_set_header Real-IP $remote_addr; proxy_pass http://localhost:8033; } location ~ .*\.(gif|jpg|jpeg|png|txt|html|ico|apk)$ { 
    add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT'; add_header 'Access-Control-Allow-Headers' 'Origin, x-requested-with, Content-Type, Accept, Authorization'; add_header 'Access-Control-Expose-Headers' 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma'; if ($request_method = 'OPTIONS') { 
    add_header 'Access-Control-Max-Age' ; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } default_type text/plain; root /data/static/; } } 

3、重定向处理跨域问题

 # 前端 通过重定向 处理 前端 获取动态数据 的请求跨域 # /wtt/aaa/bbb ====> /aaa/bbb ====> http://localhost:8082/aaa/bbb location /wtt{ 
    proxy_set_header Host $proxy_host; proxy_set_header Real-IP $remote_addr; proxy_set_header name bbb; rewrite ^/wtt/(.*)$ /$1 break; proxy_pass http://localhost:8082; } 

4、负载均衡

 http { 
    server { 
    listen 1234; server_name localhost; location /test { 
    default_type text/plain; return 200 "===> the server is test 1234"; } } server { 
    listen 1235; server_name localhost; location /test { 
    charset utf-8; default_type text/plain; return 200 "===> 哈哈哈哈"; } } upstream wtt { 
    server localhost:1234; # # 链接后面 一定不要带 请求路径 server localhost:1235; } # 访问 http://localhost:80/test 体验负责均衡 server { 
    listen 80; server_name localhost; location / { 
    proxy_pass http://wtt; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } 

安装

apt install nginx yum install nginx 

Nginx 操作常用命令

  • nginx -v

版本查看

  • nginx -s reload

重新加载配置文件,热重启

  • nginx -s reopen

重启nginx

  • nginx -s quit

等待工作进程处理完成后关闭

  • nginx -s stop

快速关闭

  • nginx -T

查看当前nginx最终的配置

  • nginx -t
  • -c <配置路径>
    检查 指定路径的配置文件 是否有问题
  • -q
    屏蔽 非错误 信息
  • 查看 配置文件 nginx.conf 位置
way1: 既可以检查 配置文件 , 又能找到配置文件的位置 nginx -t way2: 如果程序正在运行着 ps -ef | grep nginx >>> master process /www/server/nginx/sbin/nginx -c /www/server/nginx/conf/nginx.conf 
  • 通过 systemctl 命令 对 Nginx进行 启动、停止、重载、开启自启等管理

安装好的各文件位置:

配置文件(/etc/nginx/nginx.conf)

配置结构

#全局块 events { #events块,此处配置 可影响 服务器 和 用户的网络链接 } http { #http全局块,配置代理、缓存、日志等 upstream # 配置后端服务器的具体地址,负载均衡相关配置 server { #server块,配置虚拟主机相关参数,一个http可有多个server块 location { #location块,配置url的匹配,一个server可有多个location块 } } } 

配置文件的语法规则

  • 配置文件由指令与指令块构成;
  • 每条指令以;分号结尾,指令与参数间以空格符号分隔;
  • 指令块{}大括号将多条指令组织在一起;
  • include 语句允许组合多个配置文件以提升可维护性;
  • 使用 # 符号添加注释,提高可读性;
  • 使用$符号使用变量;
  • 部分指令的参数支持正则表达式

常见配置项说明

user nginx; # 用于配置worker进程的用户和用户组(如果指定的用户不存在,则报错),语法 user user[group], 默认值 nobody,位置 全局块。页面报403,往往是worker进程的用户 没有访问root用户文件的权限导致的。

master_process;	# 配置是否开启worker进程,on|off ,默认 on,位于 全局块。
worker_processes auto; # 配置 worker进程的个数,建议和 CPU 核数一样,默认1

daemon on; # 设定nginx是否已守卫进程的方式启动, on|off 默认on,位于 全局块。默认启动方式 相当于 用了screen命令,所以在开启的终端中 Ctrl + C 无法退出nginx服务,或者直接关闭开启的终端 也不会 终止退出 nginx服务。

pid /run/nginx.pid; # 配置 master进程 的 进程号 和 进程号ID的文件路径, 位于 全局块。

error_log  /var/log/nginx/error.log warn;   # 配置 错误日志 存放路径 [日志级别]。位于 全局块、http、server、location。

include /etc/nginx/modules-enabled/*.conf; # 引入 子配置文件 合并到此处, 使nginx的配置更加灵活,位置 any。

events {
	accept_mutex on; # 网络连接序列化,on|off, 默认on,位于 events块,该配置项主要解决“惊群”问题,比如:空闲状态下所有的worker进程都会休眠,当进来一个用户请求时,所有worker都会被惊醒(唤醒),抢着处理这个请求,最先抢到的进行处理,其他没抢到的继续休眠,一个请求唤醒全部worker进程明显是影响nginx性能的,所以开启此配置项后,worker进程就会被编号,一个一个来唤醒,一个请求 唤醒一个worker进程。
	multi_accept on; # 配置是否允许 一个worker进程用时接收多个网络请求,默认off,位于 events块,建议打开。如果为off,一个worker进程只能同时接收一个新的连接。
	
	worker_connections 768; # 每个worker进程允许最大并发数,默认512,位于 events块,注意:其值 不能大于操作系统支持打开的最大 文件句柄 的数量。

	use epoll; # 配置nginx服务器选择哪种 事件驱动 来处理网络消息。默认值:根据操作系统,位于 events块。此配置是nginx优化的重要内容,可选值: select/poll/epoll/kqueue等,linux 内核在2.6以上可以使用epoll函数来优化nginx。
}

# http服务器 的相关设置
http {

	
	# -----------------------------Basic Settings (基础设置)-----------------------------
	

	sendfile on; # 提高处理静态资源的性能,默认 off, 位于 http、server、location。 sendfile函数Linux系统内核中高效处理静态资源的函数,故Nginx作为静态资源服务器时,开启则能大大提高Nginx的性能,但作为反向代理来使用的时候,就没什么进益了。

	tcp_nopush on; # 减少网络报文段的数量,仅在使用sendfile的时候使用
	tcp_nodelay on;

	keepalive_timeout 65; # 配置 长连接超时时间,默认75s,位于 http、server、location
	keepalive_requests 120; # 配置 一个长连接 可以处理的请求的个数,超过这个个数就会断开该连接。默认100,位于 http、server、location

	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types; # 设定mime类型,类型由mime.types文件定义
	default_type application/octet-stream;

	
	# -----------------------------SSL Settings(安全设置)-----------------------------
	

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	
	# -----------------------------Logging Settings (日志设置)-----------------------------
	

	# nginx 中的日志分为 access.log (记录用户所有的请求) 和 error.log(记录nginx运行时的错误信息)
	# nginx支持对日志的格式、大小、输出等进行设置,需要用到一下两个命令:
	log_format wttformat 'this is my defined'; # 指定日志的输出格式,位于http, 凡是采用  wttformat 格式的日志,只会重复输出一句话:this is my defined

	access_log /var/log/nginx/access.log wttformat; # 指定access日志的文件路径等相关属性,语法:access_log path [formate [buffer=size]],位于http、server、location, 日志采用就近原则,location 先用自身块中的 日志路径下的文件,如果没有就到 server中找,如果还没有就到http中找配置信息。
	error_log /var/log/nginx/error.log; # 指定error日志的文件路径等相关属性,

	
	# -----------------------------Gzip Settings(压缩设置)-----------------------------
	

	gzip on;

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;


    
	# -----------------------------Server(配置 虚拟主机)-----------------------------
	

    server {
      listen  80; #虚拟主机监听的端口
      server_name localhost;  #虚拟主机使用的域名
  
  	
      # 单独 为该虚拟机定义一个 日志路径,而不是使用全局的
      # access_log /home/hero/log/wtt.access.log;
  
      
      charset utf-8;# 该虚拟机使用的字符编码
  
 	  location /get_text {
 		include mime.types;
 		default_type text/plain; # 配置nginx响应前端请求的默认mime类型,默认 text/plain,位于 http、server、location;告诉 浏览器 返回的资源类型
 		return 200 "<h1> hello </h1>"; # 普通字符串处理
 	  }
 	  location /get_html {
 		include mime.types;
 		default_type text/html; 
 		return 200 "<h1> hello </h1>"; # html文档处理
 	  }
  
      # 定义web的根路径
      location / {
        root  /usr/share/nginx/html; # 网站根目录
        index index.html; 	# 默认访问文件
  	  deny 172.168.22.11;   # 禁止访问的ip地址,可以为 all
        allow 172.168.33.44;  # 允许访问的ip地址,可以为 all
      }
  
      error_page 500 502 503 /50x.html # 根据错误代码,返回对应页面
  	  error_page 400 404 error.html;   # 同上
  
      # url 中可包含正则
      location [=|~|~*|^~]url {
        ...
      }
  	  # 1. = 精确匹配路径,用于不含正则表达式的 uri 前,如果匹配成功,不再进行后续的查找;
  	  # 2. ^~ 用于不含正则表达式的 uri 前,表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找;
  	  # 3. ~ 表示用该符号后面的正则去匹配路径,区分大小写;
  	  # 4. ~* 表示用该符号后面的正则去匹配路径,不区分大小写。跟 ~ 优先级都比较低,如有多个location的正则能匹配的话,则使用正则表达式最长的那个;
  	  # 5. 如果 uri 包含正则表达式,则必须要有 ~ 或 ~* 标志。
  
  	  # example:
  	  location ~ .*\.(gif|jpg|jpeg|png)$ {
  		root /root/wtt/rxw/static;
  	  }
    }
}

全局变量

Nginx 有一些常用的全局变量,你可以在配置的 任何位置 使用它们,如下表:

全局变量名称 功能
$host 请求头中的host的值,如果请求头中无该键值对,则为 设置的服务器域名
$request_method 客户端的请求方法
$remote_addr 客户端的IP地址
$args 这个变量等于GET请求中的参数。例如,foo=123&bar=blahblah;
$arg_PARAMETER GET请求中变量名为PARAMETER参数的值
$content_length 请求头中的Content-length字段
$http_user_agent 客户端agent信息
$http_cookie 客户端cookie信息
$remote_addr 客户端的ip地址
$remote_port 客户端的端口
$server_protocol 请求协议:HTTP/1.0、HTTP/1.1
$server_addr 服务器地址
$server_name 服务器名称
$server_port 服务器端口号
$scheme HPPT方法(http,https)

还有更多的内置预定义变量,可以直接搜索关键字「nginx内置预定义变量」

自定义变量

可以在sever,http,location等标签中使用set命令(非唯一)声明变量,语法如下:

set $变量名 变量值 location b/ { set $a hello nginx return 200 $a } 

变量拼接

 server { 
    listen 1234; location /aaa { 
    default_type text/plain; set $name tom return 200 "===> the host is $host , the name is $name"; # 以上方式 变量 和 字符 必须要有 间隔, 像 $hostaaa 是不可以的,如果非要 没有间隔,则使用如下方式: return 200 "===> the host is ${host}aaa"; } } 

案例代码(跨域): 反向代理 + 静态资源

server {
   listen 33333 ssl;
   server_name kaoji.cn;

   ssl_certificate /root/music_level/nginx/ssl/kaoji..cn.pem;   # 证书文件地址
   ssl_certificate_key /root/music_level/nginx/ssl/kaoji.cn.key;  # 私钥文件地址
   
   ssl_session_timeout 10m;

   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;      #请按照以下协议配置
   ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
   ssl_prefer_server_ciphers on;

    一般还可以加上下面几个增强安全性的命令:
   add_header X-Frame-Options DENY;           # 减少点击劫持
   add_header X-Content-Type-Options nosniff; # 禁止服务器自动解析资源类型
   add_header X-Xss-Protection 1;             # 防XSS攻击


   location / {
        proxy_pass http://0.0.0.0:33332;
        # proxy_set_header wttname WHO;
        proxy_set_header Host $proxy_host; # 修改转发请求头,让被代理的应用可以受到真实的请求
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   }

   location ~ .*\.(gif|jpg|jpeg|png|mp4|xls)$ {
           root /root/music_level/app/static/upload;
   }
   access_log  /root/music_level/nginx/logs/access.log;
   error_log  /root/music_level/nginx/logs/error_log.log;
}

server {
   listen 55555;
   server_name kaoji.cn;

   sendfile on;
   tcp_nodelay on;

   location / {
           root   /root/music_level/webpage/dist;
           index  index.html;
           try_files $uri $uri/ /index.html;
   }
   location ~ .*\.(gif|jpg|jpeg|png|mp4)$ {
   				# 允许跨域请求的“域” 这是 ==核心==
   				# 允许跨域的请求,可以自定义变量 $http_origin, *表示所有
                add_header 'Access-Control-Allow-Origin' *;
                # 允许携带Cookie请求
                add_header 'Access-Control-Allow-Credentials' 'true';
                # 允许跨域的请求方法
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
                # 允许请求时携带的头部信息,*表示所有
                add_header 'Access-Control-Allow-Headers' 'Origin, x-requested-with, Content-Type, Accept, Authorization';
                # 允许发送 按段获取资源的 请求
                add_header 'Access-Control-Expose-Headers' 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma';
                # 若没有下面的语句, 则 post方法 无法进行跨域,
                # 因为 在发送 post跨域请求之前,会以options方式发送 预检请求, 服务器 接受时 才会正式请求
                if ($request_method = 'OPTIONS') {
                        # 预检请求缓存时间
                        add_header 'Access-Control-Max-Age' 1728000;
                        add_header 'Content-Type' 'text/plain; charset=utf-8';
                        add_header 'Content-Length' 0;
                        return 204;
                }
           expires 1d;
           root /root/music_level/app/static/upload;
   }
}

2.静态资源部署

Nginx处理静态资源的内容,要考虑一下几个方面:

  1. 配置命令
  2. 配置优化
  3. 压缩配置指令
  4. 缓存处理
  5. 访问控制,包括跨域 和 防盗链问题

一、配置指令

1. listen

listen 配置比较灵活,常用方式如下:

  1. listen 120.0.0.1:8000; // 监听指定的IP和端口
  2. listen 120.0.0.1; // 不加端口,默认监听 80端口
  3. listen 8000; // 监听指定端口上的连接
  4. listen *:8000; // 监听指定端口上的连接

listen 的 default_server 配置参数项 是 标识符,用来将此虚拟机设置成为默认主机
所谓的默认主机: 如果所有的server都没有匹配到对应的 address:port(实际过程中,先匹配port,再匹配 address), 则默认执行该 server。
如果不手动指定,则默认第一个server 是 默认主机。

2. server_name

关于server_name 的配置方式有三种:

  1. 精确匹配
server { 
      listen 80; server_name www.baidu.com www.kaixin.com; } 
  1. 通配符匹配

通配符 * 只能出现在域名的 首 和 尾, 不能出现在中间位置!!!

server_name *.baidu.com; # 以下情况 为 语法错误 server_name www.*.com; server_name www.baidu.c*; # 正确为: www.baidu.*; 
  1. 正则匹配

若使用正则表达式,必须 使用 ~ 作为正则表达式 字符串 开始的标记。
强调: ~ 后面不能有空格,要紧挨着后面的 正则表达式 字符串。

server_name ~^www\.(/w+)\.com$; # 正则拆分:   ~: 正则表达式 字符串 开始的标记  ^www : 以三w开头  \. : 之后必须有个 点  (/w+): 至少得有一个字符,去掉括号也可以  com$ : 以com结尾 
匹配优先级 (重点)
  1. 精确匹配 的优先级最高
  2. 通配符 在 开始位置 的情况 次之
  3. 通配符 在 结尾位置 的情况 再次之
  4. 正则匹配 的优先级 再靠后
  5. 最后 被 默认的虚拟机 (default_server)处理
  6. 如果没有明确指定虚拟机,则被第一台 虚拟机 处理

3. location

location

  1. 头指定模式: 不带上述符号,则必须 以 指定模式 开始
location /abc { 
      default_type text/plain; return 200 "===> see you"; } 

说明:

location / { 
      default_type text/plain; return 200 "===> see you"; } 
  1. =: 精准匹配
location =/abc { 
      default_type text/plain; return 200 "===> see you"; } 
  1. ~: 正则匹配
location ~^/abc\w$ { 
      default_type text/plain; return 200 "===> see you"; } 
  • 例 图片的静态目录
location ~ .*\.(gif|jpg|jpeg|png)$ { 
      # default_type text/plain; root /root/test/static/; } 
  1. ~*: 正则无大小匹配
location ~*^/abc\w$ { 
      default_type text/plain; return 200 "===> see you"; } 
  1. ^~: 一见钟情匹配
location /abcd { 
      default_type text/plain; return 200 "===> 指定模式"; } location ~/abc\w$ { 
      default_type text/plain; return 200 "===> 正则匹配"; } 
location ^~/abcd { 
      default_type text/plain; return 200 "===> 一见钟情匹配"; } location ~/abc\w$ { 
      default_type text/plain; return 200 "===> 正则匹配"; } 

4. 请求资源的目录 root/alias

rootalias 都可以定义在location模块中,都是用来指定 请求静态资源文件路径 的。
但在使用过程中要注意两者的区别:

比如要 访问: /root/wtt/static/imgs/01.png 文件

  • root 的方式访问
location /imgs { root /root/wtt/static; } 

root的处理结果是: root路径 + location路径
所以图片文件的访问路径:/imgs/01.png

  • alias 的方式访问
location /imgs { alias /root/wtt/static; } 

alias的处理结果是: alias路径 替换 location路径
所以图片文件的访问路径:/imgs/imgs/01.png

还有一个小区别:
如果location路径是以 / 结尾,那么alias也必须以 / 结尾,如下:

location /imgs/ { alias /root/wtt/static/; } 

root则没有要求。

  • 该部分 常用语 静态资源 ,实例如下:
 location ~ .*\.(gif|jpg|jpeg|png|mp4)$ { 
       root /home/hero/static; } 

5.index

设置网站的 默认 首项(呵呵 谐音梗 首相)
语法: index file …;
默认值: index index.html;
位置; http、server、location


location /images/ { 
       alias html/images/; # index 后面可以跟多个 静态文件0, 会从左到右依次进行访问,直到找到为止。 # http://localhost/images 展示aaa.png图片,如果没有找到,则展示bbb.png index aaa.png bbb.png; } 

6.error_page

server { 
       # 当出现对应的 code 时:  case1:可以指定 具体的跳转地址 error_page 404 https://www.baidu.com;  case2: 可以指定 重定向地址 (重定向到 http://localhost/50x.html, 展示50x.html文件) error_page 500 501 /50x.html;  case3: 通过@定向到 location上 error_page 404 @wtt_say_hi; # 实例 location /img { 
       error_page 404 https://www.baidu.com; # 当找不到 对应的图片 就 跳到百度页面 alias /home/hero/Desktop/other; index a.jpg avatar.jpg; } } 
  • 说一下 可选性 [ = [response]] 的作用:
server { 
       error_page 404 =200 /a.html; location =/a.html { 
       default_type text/plain; return 404 "hi my friend"; } } 

二、静态资源优化指令

1. sendfile on;

底层原理解释:

为了保证操作安全,操作系统分为 用户区内核区
当用户区 需要 操作本地资源数据 or 对底层硬件进行操作时 都需要 向 内核区 申请(即 调用内核区的方法), 由 内核区 来完成。
nginx 运行在 用户区,当客户端过来一个请求客户端本地 aaa.png图片的请求时:

不启用sendfile的处理过程

  1. nginx 通过调用 系统的read()方法,向系统传递 要读取本地 aaa.png文件到 用户区(即 nginx应用程序缓冲区)
  2. 第一次复制操作:内核区 将 硬盘 上的 aaa.png 复制 到 内核缓冲区
  3. 第二次复制操作:内核缓存区 将 aaa.png 复制到 用户区的 nginx应用程序缓冲区
  4. nginx 通过调用 系统的write()方法,向系统传递 要将用户区的 aaa.png文件 写入到 内核区(具体为 socket 缓冲区)通过网卡将文件发送到客户端。
  5. 第三次复制操作: 用户区的nginx应用程序缓冲区 向 内核区的socket缓冲区 进行文件复制
  6. 第四次复制操作: 内核区的socket缓冲区 将文件 复制到 网卡 上,进行文件发送。

启用sendfile的处理过程

  1. nginx 通过调用 系统的 sendfile()方法,向系统表明要 发送 aaa.png文件的操作
  2. 第一次复制操作:内核区 将 硬盘 上的 aaa.png 复制 到 内核缓冲区
  3. 内核缓冲区 将aaa.png文件 直接移动到 socket缓冲区,(因为都在内核区)
  4. 第二次复制操作:内核区的socket缓冲区 将文件 复制到 网卡 上,进行文件发送。

2. tcp_nopush on;

该指令必须在sendfile打开的状态下才会生效,主要用来提升网络包的传输效率
语法: tcp_nopush on|off;
默认值: off
位置: http、server、location


底层原理解释:

3. tcp_nodelay on;

该指令必须在keep-alive(长连接)开启的时候才会生效,主要来提高网络包传输的实时性
语法: tcp_nodelay on|off;
默认值: on
位置: http、server、location


底层原理解释:

上面三个指令的配置建议

三、静态资源压缩

1 gzip off;

2 gzip_typys text/html;

http{ 
       gzip on; gzip_typys application/javascript; # 此时只有返回给前端js文件时,才对js文件启用压缩功能, } 

3 gzip_comp_level 1;

http{ 
       gzip on; gzip_typys application/javascript; # 此时只有返回给前端js文件时,才对js文件启用压缩功能, gzip_comp_level 6# 一般建议在6就可以了。级别再高,可以压缩的空间就很小了,反而会浪费很多CPU资源 } 

4 gzip_vary off;

5 gzip_disable

6 gzip_http_version 1.1;

7 gzip_min_length 20;

8 gzip_proxied off;

配置值说明:

  • off: 不压缩
  • expired:启用压缩,如果header中包含Expires的头信息
  • no-cache:启用压缩,如果header中包含 Cache-Control:no-cache 的头信息
  • no-store:启用压缩,如果header中包含 Cache-Control:no-store 的头信息
  • private:启用压缩,如果header中包含 Cache-Control:private 的头信息
  • no_last_modified:启用压缩,如果header中包含 Last-Modified 的头信息
  • no_tag:启用压缩,如果header中包含 Etag 的头信息
  • auth:启用压缩,如果header中包含 Authorization 的头信息
  • any:无条件启用压缩

思考: Gzip 和 sendfile 的共存问题

  • gzip_static on|off|always;

四、静态资源缓存

相关说明

http协议中缓存相关的字段:

Header 说明
Expires 缓存过期的时间
Cache-Control 设置缓存相关的配置信息
Last-Modified 请求资源最后修改的时间
Etag 请求变量的实体标签的当前值,比如文件的MD5值

浏览器使用缓存文件流程说明:

  1. 浏览器发送请求前, 先判断是否有缓存
  2. 如果没有 请求服务器
  3. 如果有,判断缓存是否已过期
  4. 如果没过期,则使用本地缓存的资源
  5. 如果过期,则将请求发送到服务器,验证Etag和Last-Modified
  6. 通过验证,决定 继续使用本地缓存 or 请求服务器资源

1 expires off;

参数说明:

  • time:
location ~ .*\.(html|js|css|png)$ { 
         expires 10d; #expires 3600; #3600s } 
  • epoch
  • max
location ~ .*\.(html|js|css|png)$ { 
         expires max; } 
  • off: 默认值,告诉浏览器不要缓存

2 add_header

add_header Token ; 
  • 此配置可用来解决跨域问题:
  • Access-Control-Allow-Orion

允许跨域访问该服务的 源地址,可以用逗号隔开配置多个,也可以使用 * 允许所有的请求地址 跨域访问该服务。

  • Access-Control-Allow-Methods

允许跨域访问的请求方法,可以用逗号隔开配置多个。

location /aaa { 
         ==================================== 跨域处理 ========================================== # 允许跨域请求的“域” 这是 ==核心== add_header 'Access-Control-Allow-Origin' $http_origin; # 允许客户端提交Cookie add_header 'Access-Control-Allow-Credentials' 'true'; # 允许客户端的请求方法 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT'; # 允许客户端提交的的请求头 add_header 'Access-Control-Allow-Headers' 'Origin, x-requested-with, Content-Type, Accept, Authorization'; # 允许客户端访问的响应头 add_header 'Access-Control-Expose-Headers' 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma'; # 处理 预检请求 if ($request_method = 'OPTIONS') { 
         # 预检请求缓存时间 add_header 'Access-Control-Max-Age' ; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } ===================================================================================== default_type applicaton/json; return 200 '{"code":0, "data":"请求成功"}'; } 

五、静态资源防盗链

资源盗链: 将他人服务器上的图片展示在自己的网站中。

nginx防盗链的实现原理:

具体实现

valid_referers none|blocked|server_names|string…
  • none: 如果Header中的Referer为空,允许访问。直接将图片链接 通过浏览器打开的时候,Referer便为空,也就是说允许浏览器直接打开。
  • blocked:如果Header中的Referer 不为空, 但是该值 被 防火墙 or 代理 进行伪装过,如不带 “http://”、“https://” 等协议头的资源 允许其进行访问。
  • server_names:指定具体的 域名 or IP
  • string:可以支持正则表达式 和 * 的字符串。 如果是正则表达式,需要以 ~ 开头进行标识。
location ~ .*\.(png|jpg|gif)$ { 
         valid_referers none blocked www.baidu.com 192.168.1.1 *.example.com ~\.google\.; if ($invalid_referer) { 
         return 403; } root /home/wtt/static/images; } 

扩展:如果图片有很多,该如何进行批量处理,也就是针对目录进行防盗链处理

location /images { 
         valid_referers none blocked www.baidu.com 192.168.1.1 *.example.com ~\.google\.; if ($invalid_referer) { 
         return 403; } root /home/wtt/static; } 

3.重定向(URL 重写)

在nginx中 重定向 有两个 指令 : returnrewrite
return 一般用于 域名 重写,rewrite 一般用于 路径 重写。

  • 转发重定向 的区别

转发 是 服务端 的 行为, 重定向 是 客户端 的 行为

  • 后面要讲的 proxy_pass 代理 属于 转发,转发 是 服务端 的 行为,所以 浏览器是无感知的,因此 浏览器的 访问输入的 地址 是不会发生变化的。
  • 重定向是 浏览器的 行为,所以 浏览器的 访问输入的 地址 是会发生变化的。

return:

服务端 停止处理 并 将状态码 status code 返回给客户端

语法 默认值 位置
return code [text]; return code URL; return URL server、location、if

说明:

  • code : 指定 返回给客户端的 HTTP状态码。可以返回的状态为0~999
  • text : 返回到客户端的内容信息
  • URL : url 的情况直接进行跳转(忽略此项)

例子

  • 域名迁移

从 aaa.com 和 bbb.com 迁移到 ccc.com

server { 
         listen 80; listen 8080 ssl; server_name aaa.com bbb.com; return 301 $scheme://ccc.com$request_uri; } 
  • 添加 www
server { 
         listen 80; server_name aaa.com; return 301 $scheme;//www.aaa.com$request_uri; } 

rewrite

语法 默认值 位置
rewrite regexp replacement [flag]; server、location、if

说明:

  • regexp : 用来匹配URI的正则表达式
  • replacement : 匹配成功后,用URI中被截取内容的字符串 对URI进行重写。
location /aaa { 
         # $1 是 正则的第一个()匹配的内容 rewrite ^/aaa/(bbb)\w*$ /$1; # 请求 /aaa/bbb 先被 /aaa 匹配,然后重定向 到 /bbb rewrite /aaa/ccc /ccc; # 请求 /aaa/ccc 先被 /aaa 匹配,然后重定向 到 /ccc } location /bbb { 
         default_type text/plain; return 200 bbbbbb; } location /ccc { 
         default_type text/plain; return 200 cccccc; }  效果 > 访问 http://localhost:8889/aaa/bbb ===> bbbbbb > 访问 http://localhost:8889/aaa/ccc ===> cccccc 

最佳实践:前后分离 的 跨域解决

server { 
         listen 80; server_name aaa.com; # 前端 vue静态服务 location / { 
         root /home/meng/;
                index index.html; try_files $uri $uri/ /index.html; } # 代理的 后端服务,  # 前端 请求加前缀 /api/* 代理到 后端服务, 实现 跨域处理 location /api{ 
         proxy_set_header Host $proxy_host; proxy_set_header Real-IP $remote_addr; rewrite ^/api_default/(.*)$ /$1 break; # /api/user/info ===url重写===> /user/info # 重定向之后 的 反向代理 的地址 不要有 请求路径, 即使 加上也 无效,这一点和 纯粹的 反向代理 差别很大 proxy_pass http://bbb.com; } } 

重定向 flag :last break redirect permanent

这里重点说明 last 和 break

# 例子 last ====================================================== server { 
         listen 80; location /ccc { 
         default_type text/plain; return 200 "===> this is proxy pass"; } } server { 
         listen 1234; location /aaa { 
         rewrite /aaa /ccc last; proxy_pass http://localhost; } location /ccc { 
         default_type text/plain; return 200 "===> this is location ccc"; } } 访问 localhost:1234/aaa 返回 ===> this is location ccc # 例子 break ====================================================== server { 
         listen 80; location /ccc { 
         default_type text/plain; return 200 "===> this is proxy pass"; } } server { 
         listen 1234; location /aaa { 
         rewrite /aaa /ccc break; proxy_pass http://localhost; } location /ccc { 
         default_type text/plain; return 200 "===> this is location ccc"; } } 访问 localhost:1234/aaa 返回 ===> this is proxy pass 
  • last: 终止 在 本location块 中继续 处理接收到的URI,
    并将 重写后的URI作为一个新的URI, 在 同 server 下 使用 各location块 进行继续处理。
  • break:将此处重写的URI作为一个新的URI,在 本location 块中 继续进行处理。
注意:

如果replacement是以 http 或 https开头的,则不会向下对URI进行处理,而是直接返回重写的URI给客户端, 例如: rewrite /aaa https://www/baidu.com;

  • redirect: 将重写后端的URI返回给客户端,状态码302,指明是临时重定向URI,只要用在replacement变量不是以 http 或 https 开头的情况。
  • permanent: 将重写后的URI返回给客户端, 状态码301,指明是临时重定向URI,只要用在replacement变量不是以 http 或 https 开头的情况。

rewrite_log

语法 默认值 位置
rewrite_log on off; off

说明:

Rewrite应用场景:

Rewrite 的相关指令

set:定义一个新的变量

语法 默认值 位置
set $key val; server、location、if
location /aaa { 
         set $name tom; set $age 12; default_type text/plain; return 200 'name is $name age is $age'; } 

自定义的 变量 和预设变量一样 也可以用在 日志文件中。

if:条件判断

语法 默认值 位置
if (condition){…} server、location

condition 作为判定条件,支持以下写法:

  1. 变量名: 如果变量名的值是 空字符串 or 0,都会被判定为 false
  2. 条件: 使用 = 和 != 进行条件判断:
location /test/methed { 
         if ($request_method = POST){ 
         return 200 'your request methods is $request_method'; } if ($request_method = GET){ 
         return 200 'your request methods is $request_method'; } if ($request_method = DELETE){ 
         return 200 'your request methods is $request_method'; } return 200 "===> defaule "; } 

注意:

  1. 正则: 变量 和 正则表达式 之间 用 、!、! 来连接
if ($http_user_agent ~ MSIE){ 
         # 若 $http_user_agent 的值中 包含 MSIE 字符串,则为true } 

注意:

  1. 文件存在:
if (-f $request_filename){ 
         # 判断请求的文件是否存在 } 

小案例:

server { 
         listen 8099; server_name wtt; set $subject test_rewrite; set $age 10; location / { 
         if ($age = 5) { 
         return 404; } if ($age = 6) { 
         return 405; } if ($age = 7) { 
         return 302 /abc; }
         
                default_type text/html; return 200 "<h1 style=\"color:red\">nihao </h1>"; } location /abc { 
         default_type text/plain; return 200 $subject; } error_page 404 @wtt_say_hi; location @wtt_say_hi { 
         default_type text/plain; return 404 "hi my friend 找不到阿"; } } 

说明:

4.反向代理

在客户端 和 服务端 交流的过程中,如果 代理服务器 充当的是 客户端的角色,则为 正向代理
若充当的是服务端 的角色,则为 反向代理
所以说 反向代理 是掩藏 真实 服务器地址 的好手段。

nginx 反向代理 模块的指令是由 ngx_http_proxy_module 模块进行解析的,该模块在安装nginx的时候已经自己加装到nginx中了。

1 相关指令介绍

proxy_pass

该指令用来设置 被代理服务器的地址,可以是主机名称、IP地址加端口的形式。

语法 默认值 位置
proxy_pass URL; location
proxy_pass http://www.baidu.com; proxy_pass http://198.168.1.1/; 
注意
  • 一个location 下 只能有一个 proxy_pass 多了就报错。
此节重点

代理地址 的端口之后 带不带 / 有很大的区别,
以下是 没带 的情况:

以下是 的情况:

proxy_pass http://www.123.com/;
proxy_pass http://www.123.com:1234/;
proxy_pass http://www.123.com:1234/abc/def;

1、没带 /

请求的匹配的 路径 就是 反向代理 收到的路径。

location /api/ { 
         proxy_pass http://localhost:8080; } 匹配的路径 ===> 反向代理收到的路径 /api/user ===> /api/user 

2、带 /

请求的匹配的 路径 后,以开头 第一个 / 基准,先将其后 匹配成功的 那部分 去除, 再将 剩余部分 直接 拼接到 反向代理 后的路径 之后 就是 反向代理 最终收到的 路径。

  • 举例说明
    location ^~ /api/ , 第一个 / 为基准, 其后 匹配的部分为 api/,如果请求的路径是 /api/user/info , 那么 去除 匹配部分之后 剩下的部分为: /user/info, 剩下的 这部分 会被 直接 拼接在 反向代理的 路径后面。
location / { 
         proxy_pass http://localhost/; } /api/user ==> /api/user location /api { 
         proxy_pass http://localhost/; } /api/user ==> //user location /api/ { 
         proxy_pass http://localhost/; } /api/user ==> /user location / { 
         proxy_pass http://localhost/haha; } /api/user ==> /hahaapi/user location / { 
         proxy_pass http://localhost/haha/; } /api/user ==> /haha/api/user location /api { 
         proxy_pass http://localhost/haha/; } /api/user ==> /haha//user # 以上都是 探索形态, 以下这个是 成果形态 location /api/ { 
         proxy_pass http://localhost/haha/; } /api/user ==> /haha/user 

proxy_set_header

语法 默认值 位置
proxy_set_header key val; Host $proxy_host http、server、location
proxy_set_header field value; Connection close http、server、location

代理服务器:

location /aaa { 
         # 设置一些密文 proxy_set_header wttname WHO; # 将 nginx 地址 赋值给 Host proxy_set_header Host $proxy_host; # 修改转发请求头,让被代理的应用可以受到真实的请求 # 将 真正请求IP 赋值给 Real-IP proxy_set_header Real-IP $remote_addr; proxy_pass http://192.168.1.1:8080/ping; } 

proxy_redirect

该指令用来 重置头信息中的 Location 和 Refresh 的值。

语法 默认值 位置
proxy_redirect redirect replacement; proxy_redirect default; http、server、location
proxy_redirect default; proxy_redirect default; http、server、location
proxy_redirect off; proxy_redirect default; http、server、location

说明:

  • proxy_redirect redirect replacement;
    redirect:目标, Location 的值
    replacement: 要替换的值

  • proxy_redirect default;
    将Location 块的URI 变量作为 replacement,
    将proxy_pass 变量作为 redirect进行替换

  • proxy_redirect off;
    关闭 proxy_set_header 功能。
具体用途说明

举例说明:

server { 
         listen 222.22.2.222:8081; server_name localhost; location / { 
         # 111.111.1.111 这个地址是不能暴露的 proxy_pass http://111.111.1.111:8081/; # proxy_redirect 待替换的地址(被保护的地址) 拿来替换的内容(暴露给用户的地址); # 真正服务器 的地址 代理服务器 的地址 proxy_redirect http://111.111.1.111 http://222.22.2.222; } } # 被nginx 所代理的服务 为 真实服务,以 gin框架举例: case1:重定向到 一个 链接 func Ping(c *gin.Context) { 
         c.Redirect(302, "http://www.baidu.com") } case2: 重定向到 一个 请求路径 func Ping(c *gin.Context) { 
         c.Redirect(302, "aaa/bbb/ccc") } 

说明:

  1. 在 不使用 proxy_redirect 的情况下:
    如果 被代理服务器 没有发生重定向,那么客户端 看到的地址是 代理服务器的 地址
    如果 被代理服务器 发生重定向,那么客户端 看到的地址是 被代理服务器的 地址
    .


  2. 在 使用 proxy_redirect 的情况下:
  • 重定向到 一个 链接
    那么客户端 看到的地址都是 重定向 到的 链接地址:http://www.baidu.com
  • 重定向到 一个 请求路径 (这一种情况 属于 保护 真正服务地址 的情况)
    那么客户端 看到的地址都是 拼接地址:http://222.22.2.222/aaa/bbb/ccc

2 反向代理还有一些其他的指令,可以了解一下:

  • proxy_connect_timeout 1;
    nginx服务器 与 被代理的服务器 建立连接 的 超时时间,默认60秒
  • proxy_ignore_client_abort on;
    客户端断网时,nginx服务器 是否终断 对 被代理服务器的请求。默认为off。
  • proxy_read_timeout;
    配置 Nginx 向 后端服务器组 发出 read 请求后,等待相应的超时时间;
  • proxy_send_timeout
    配置 Nginx 向后端服务器组发出 write 请求后,等待相应的超时时间;

3 使用反向代理解决跨域

server {
        listen 80;
        server_name aaa.com;
        
        # 前端 vue静态服务
        location / {  
                root /home/meng/;
                index index.html;
                try_files $uri $uri/ /index.html;
        }

        # 代理的 后端服务, 
        # 前端 请求加前缀 /api/* 代理到 后端服务, 实现 跨域处理
        location /api{
                 proxy_set_header Host $proxy_host;
                 proxy_set_header Real-IP $remote_addr;
                 
                 rewrite ^/api_default/(.*)$  /$1 break; # /api/user/info ===url重写===> /user/info
                 proxy_pass http://bbb.com;
        }
}

这样就将对前一个域名 aaa.com; 的请求全都代理到了 bbb.com;,前端的请求都被我们用服务器代理到了后端地址下,绕过了跨域。

5 负载均衡

常用的处理方式

1. 用户手动选择

2. DNS轮询

3. 四/七层负载均衡

  • 七层:
  • 应用层: 为应用程序提供网络服务
  • 表示层: 对数据进行格式化、编码、加密、压缩等操作
  • 会话层: 建立、维护、管理会话链接。
  • 传输层: 建立、维护、管理 端到端 的连接,常见的有TCP、UDP。
  • 网络层: IP寻址和路由选择
  • 数据链路层: 控制网络层 和 物理层 之间的通信
  • 物理层: 比特流传输
  • 四层:
  • 传输层: 建立、维护、管理 端到端 的连接,常见的有TCP、UDP。
  • 网络层: IP寻址和路由选择
  • 数据链路层: 控制网络层 和 物理层 之间的通信
  • 物理层: 比特流传输
  • 实现四层负载均衡的方式:
  • 实现七层负载均衡的方式:

软件: Nginx Hayproxy等

  • 区别:

四层的数据包是在底就进行了分发,而七层则是在最顶端进行分发,所以 四层 比 七层 负载均衡的效率要高
四层不识别 域名,而 七层 要识别域名。

Nginx七层负载均衡

nginx 要实现七层负载均衡 需要用到 proxy_pass代理模块,nginx默认就支持这个模块。

upstream

upstream 负载均衡, 可以理解为 反向代理的 一对多 的一种扩展模式,所以反向代理 又得一些配置, 负载均衡 也可以 使用。

语法 默认值 位置
upstream name {…}; http

server

语法 默认值 位置
server name [paramerters]; upstream

注意: 这个server指令 和 http快中的 是不一样的。

# backend 是后端的意思,可以自定义 upstream backend { 
         server 192.168.1.111:9001; # 链接后面 一定不要带 请求路径 server 192.168.1.111:9002; server 192.168.1.222:9002; } server { 
         listen 8088; server_name localhost; location / { 
         proxy_pass http://backend; } } 

负载均衡状态

状态 概述
down 标记的server不再参与负载均衡
backup 预留的备份服务器
max_fails 允许请求失败的次数
fail_timeout 经过max_fails失败后,服务器暂时停用的时间
max_conns 限制最大的接收连接数
upstream backend { 
         server 192.168.1.111:9001 down; # 标记为永久不可用,一般会需要停机维护的服务器进行设置 server 192.168.1.111:9002; server 192.168.1.222:9002; } upstream backend { 
         server 192.168.1.111:9001 down; server 192.168.1.111:9002 backup;# 为备份服务器,当第三台也不可用时,将启用该第二台服务器。 server 192.168.1.222:9002; } upstream backend { 
         server 192.168.1.111:9001; server 192.168.1.111:9002; server 192.168.1.222:9002 max_fails=3 fail_timeout=15; # 如果 访问 9003 失败的次数 超过3次,将在 15秒内 不再对会该服务器进行访问。 } upstream backend { 
         server 192.168.1.111:9001; server 192.168.1.111:9002; server 192.168.1.222:9002 max_conns=10; # 设置该代理服务器同时活动连接的最大数量,默认为0,便是不限制,这个主要用来 保护 性能不好的服务器,以免被压垮。  } 

负载均衡策略

算法名称 概述
轮训 默认方式
weight 权重方式
ip_hash 根据ip分配方式
least_conn 根据最少连接方式
url_hash 根据URL分配方式
fair 根据响应时间方式
# 每个请求按照时间顺序,依次分配到不同的后端服务器。 upstream backend { 
         server 192.168.1.111:9001; server 192.168.1.111:9002; server 192.168.1.222:9002; } # 权重默认为1, 权重越大 被分到请求的概率就越大。 # 此策略比较适合服务器硬件差别比较大的情况。 upstream backend { 
         server 192.168.1.111:9001 weight=10; server 192.168.1.111:9002 weight=3; server 192.168.1.222:9002; } # 保证 相同IP的请求 下一次 还能能到达 本次访问的服务器 # 该策略无法保证 服务器的 负载均衡,且权限此时也不会起作用。 upstream backend { 
         ip_hash; server 192.168.1.111:9001; server 192.168.1.111:9002; server 192.168.1.222:9002; } # 把请求转发给 连接数 比较少 的后端服务器,解决了 轮训算法的一个痛点, # 轮训算法下,有些请求占用的时间很长,会导致其所在的后端负载堆积较高。 # least_conn就可以达到更好的效果。 upstream backend { 
         least_conn; server 192.168.1.111:9001; server 192.168.1.111:9002; server 192.168.1.222:9002; } # fair采用第三模块实现的负载均衡,需要添加 nginx-upstream-fail # 可以根据页面大小、加载时间长短 智能 的进行负载均衡。 upstream backend { 
         fail; server 192.168.1.111:9001; server 192.168.1.111:9002; server 192.168.1.222:9002; } 

案例:对不同的域名实现负载均衡

upstream aaa { 
         server 192.168.0.111:8080; server 192.168.0.222:8080; } upstream bbb { 
         server 192.168.0.333:8080; server 192.168.0.444:8080; } # 因为多个域名 可以绑定 一个ip,所以 server_name 是不同的。 server { 
         listen 8888; server_name www.aaa.com; location / { 
         proxy_pass http://aaa; } } server { 
         listen 8888; server_name www.bbb.com; location / { 
         proxy_pass http://bbb; } } 

Nginx四层负载均衡

nginx添加stream模块的支持,需要在编译的时候 加上 –with-stream

stream

该指令 提供 在其中指定 流服务器 指令的 配置文件上下文, 和 http指令 同级别。

语法 默认值 位置
stream {…}; main

upstream

该指令和 http 的 upstream 指令是类似的。

events { 
        } stream { 
         upstream backend { 
         server 192.168.1.111:8080; server 192.168.1.222:8080; } server { 
         listen 81; proxy_pass backend; # 注意不是 http://backend; } } http { 
        } 

注意:如果4层负载均衡的 监听 端口 和 http中(当然也包括七层负载均衡)监听的端口 重复了,那么 由于 四层 更偏底层一些,所以 端口被4层占去了。

6.配置HTTPS

下载证书的压缩文件,里面有个 nginx 文件夹,把 xxx.crt 和 xxx.key 文件拷贝到服务器目录,再配置下:

server {
 listen 443 ssl;   # SSL 访问端口号为 443
 server_name sherlocked93.club;         # 填写绑定证书的域名

 ssl_certificate /etc/nginx/https/aaa.crt;   # 证书文件地址
 ssl_certificate_key /etc/nginx/https/aaaa.key;  # 私钥文件地址
 
 ssl_session_timeout 10m;

 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;      #按照以下协议配置
 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
 ssl_prefer_server_ciphers on;

  加上下面几个增强安全性的命令:
 add_header X-Frame-Options DENY;           # 减少点击劫持
 add_header X-Content-Type-Options nosniff; # 禁止服务器自动解析资源类型
 add_header X-Xss-Protection 1;             # 防XSS攻击
 
 location / {
   root         /usr/share/nginx/html;
   index        index.html index.htm;
 }
}

7.日志

Nginx日志主要分为两种:access_log(访问日志)error_log(错误日志)
访问日志主要记录客户端的请求。客户端向Nginx服务器发起的每一次请求都记录在这里。
错误日志记录了访问出错的信息,可以帮助我们定位错误的原因。

访问日志

(1)设置语法

access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]; # 作用域 http,server,location,limit_except # 关闭 访问日志 access_log off; 

说明:

  • path

指定日志的存放文件路径

  • format

指定日志的格式。默认使用预定义的combined
预定义的combined 如下:

log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"'; 
  • buffer
  • flush
  • gzip
  • if

条件判断。如果指定的条件计算为0或空字符串,那么该请求不会写入日志。

栗子

access_log /var/logs/nginx-access.log # 说明: 该例子指定日志的写入路径为/var/logs/nginx-access.log, 日志格式使用默认的combined。 access_log /var/logs/nginx-access.log buffer=32k gzip flush=1m; # 说明: 该例子指定日志的写入路径为/var/logs/nginx-access.log, 日志格式使用默认的combined, 指定日志的缓存大小为32k, 日志写入前启用gzip进行压缩,压缩比使用默认值1, 缓存数据有效时间为1分钟。 

(2)自定义日志格式

如果不想使用Nginx预定义的格式,可以通过log_format指令来自定义。

log_format name [escape=default|json] string ... ; 
  • name

自定义格式的名称。在access_log指令中引用。

  • escape

设置变量中的字符编码方式是json还是default,默认是default。

  • string

要定义的日志格式内容。该参数可以有多个。参数中可以使用Nginx变量。

下面是log_format指令中常用的一些变量:

变量

含义

$bytes_sent

发送给客户端的总字节数

$body_bytes_sent

发送给客户端的字节数,不包括响应头的大小

$connection

连接序列号

$connection_requests

当前通过连接发出的请求数量

$msec

日志写入时间,单位为秒,精度是毫秒

$pipe

如果请求是通过http流水线发送,则其值为”p”,否则为“.”

$request_length

请求长度(包括请求行,请求头和请求体)

$request_time

请求处理时长,单位为秒,精度为毫秒,从读入客户端的第一个字节开始,直到把最后一个字符发送张客户端进行日志写入为止

$status

响应状态码

$time_iso8601

标准格式的本地时间,形如“2017-05-24T18:31:27+08:00”

$time_local

通用日志格式下的本地时间,如”24/May/2017:18:31:27 +0800″

$http_referer

请求的referer地址。

$http_user_agent

客户端浏览器信息。

$remote_addr

客户端IP

$http_x_forwarded_for

当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置。

$request

完整的原始请求行,如 “GET / HTTP/1.1”

$remote_user

客户端用户名称,针对启用了用户认证的请求

$request_uri

完整的请求地址,如 “https://daojia.com/”

栗子

access_log /var/logs/nginx-access.log wtt log_format wtt '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; 

注意: 如果某个变量的值为空,则在日志中输出为 –

错误日志

错误日志的格式是固定的, 不支持 用户自定义。

error_log path(错误日志的目录路径) level(日志等级默认为error); # 作用域 main, http, mail, stream, server, location # 关闭错误日志 error_log /dev/null; # 说明 错误日志 本质上说是 不能关闭的, 但是错误日志的输出 我们不去记录, 就如同 关闭了一样,其实输出还是在一直进行着。 

文件描述符缓存

open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time]; 
  • max

设置缓存中最多容纳的文件描述符数量,如果被占满,采用LRU算法将描述符关闭。

  • inactive

设置缓存存活时间,默认是10s。

  • min_uses

在inactive时间段内,日志文件最少使用几次,才会将该日志文件描述符记入缓存,默认是1次。

  • valid

设置多久对日志文件名进行检查,看是否发生变化,默认是60s。

  • off

不使用缓存。默认为off。

栗子

open_log_file_cache max=1000 inactive=20s min_uses=2 valid=1m; # 说明: 设置缓存最多缓存1000个日志文件描述符, 20s内如果缓存中的日志文件描述符至少被被访问2次,才不会被缓存关闭。 每隔1分钟检查缓存中的文件描述符的文件名是否还存在。 

8.访问控制

allow 和 deny

server { 
         listen 8088; location /ping { 
         allow 60.213.44.66; deny all; proxy_pass http://localhost:8080; } } 

9.限流

限流方式

  • 1、基于 连接数 的限流:

通过 limit_conn_module 模块可以设置每个 IP 或地址的最大并发连接数。
例如,使用 limit_conn_zone 指令定义一个存储区域,然后在 http、server 或 location 块中使用 limit_conn 指令来限制连接数。

  • 2、基于 请求数 的限流:

通过 limit_req_module 模块可以控制每个 IP 或地址的请求速率。
这个模块使用令牌桶算法进行请求的限流。您可以使用 limit_req_zone 指令定义存储区域,然后在 http、server 或 location 块中使用 limit_req 指令来限制请求速率。

说明:连接数 和 请求数 的区别:
连接数: 每个客户端(通常是一个 IP 地址)与服务器建立连接时,都会占用一个连接, 可近似理解为 客户端的数量。
请求数: 客户端 对 服务端 发出的 请求数, 可以理解为 所有客户端发出请求的总和。

连接数限流主要关注于控制并发连接的数量,以保护服务器的网络资源
请求数限流主要关注于控制请求的速率,以保护服务器的计算资源和处理能力。

  • 3、基于 带宽 的限流:

通过 ngx_http_core_module 模块中的 limit_rate 指令,您可以限制整个服务器或指定位置的带宽。这可以确保服务器不会被某个客户端的高速请求耗尽带宽资源。

案例演示

基于 连接数 的限流:

http { # 定义连接数存储区域 # $binary_remote_addr : 这是一个 Nginx 的变量,代表客户端的IP地址 # zone=wtt:10m : 它指定了连接数 限制区域 的 名称为wtt 和 大小10m limit_conn_zone $binary_remote_addr zone=wtt:10m; #单位还可以是: k、m、g server { listen 80; # 针对某个 location 进行连接数限流 location /api/ { # 使用名为 wtt的限制区域, 并限制了每个源 IP 地址最多允许有 10 个并发连接, 如果一个公司的员工 共用一个 IP 明显是不够用的 limit_conn wtt 10; # 最大连接数为 10 # 处理请求的逻辑 ... } } } 
  • limit_conn_zone 和 limit_conn 的关系

limit_conn_zone 指令中设置的大小和 limit_conn 指令中设置的数量是有关系的。它们共同作用于连接数限流。
如果将 limit_conn wtt 设置为 10000,即每个 IP 地址最大连接数为 10000,并且假设每个连接占用的存储空间为 2KB,那么您可以根据以下公式来计算合适的 limit_conn_zone 大小:

limit_conn_zone_size = 10000 * 2KB 
  • 每个 连接 的大小

连接占用的存储空间大小是不固定的,通常情况下,每个连接占用的存储空间可以粗略地估计为以下几个部分的总和:

  1. 连接相关的元数据:包括连接的IP地址、端口号、协议等信息。
  2. 连接状态相关的数据:例如连接的建立时间、最近活动时间、当前状态等。
  3. 请求 和 响应相关的数据:这取决于您是否需要记录请求和响应的详细信息。如果记录了请求和响应的内容,那么存储空间将更大。

基于 请求数 的限流(推荐):

http { # limit_req_zone 指令来 定义 一个名为 "wtt" 的 限流区域 # 限流区域 大小为 10m # 限制了每秒钟最多处理 10 个请求 limit_req_zone $binary_remote_addr zone=wtt:10m rate=10r/s; server { listen 80; server_name example.com; location / { # zone 指的是 使用 名为 wtt 的 限流区域 # burst=5 ==》 当请求超过正常的限流速率时,如果请求数量未超过该阈值,系统将继续处理这些请求;但一旦请求数量达到或超过该阈值,系统将立即拒绝额外的请求,并返回错误响应。 # nodelay 表示超过限流速度的请求将立即返回 503 错误。 limit_req zone=wtt burst=5 nodelay; proxy_pass http://your_backend_server; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } 

扩展: 同时使用 基于 请求数 and 连接数 的限流时

http { limit_req_zone $binary_remote_addr zone=req:10m rate=5r/s; limit_conn_zone $binary_remote_addr zone=conn:10m; server { listen 80; server_name example.com; location / { limit_req zone=req burst=10 nodelay; limit_conn conn 10; proxy_pass http://your_backend_server; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } 

基于 带宽 的限流

区别于 基于 请求数 的是 这里的 rate后面跟的是 带宽 的大小 而不是 速率。

http { limit_req_zone $binary_remote_addr zone=req:10m rate=1m; server { listen 80; server_name example.com; location / { limit_req zone=req; proxy_pass http://your_backend_server; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } 

建议规范

  • 为了使 Nginx 配置更易于维护,建议为每个服务创建一个单独的配置文件,存储在 /etc/nginx/conf.d 目录,根据需求可以创建任意多个独立的配置文件。
  • 独立的配置文件,建议遵循以下命名约定 <服务>.conf,比如域名是 sherlocked93.club,那么你的配置文件的应该是这样的 /etc/nginx/conf.d/sherlocked93.club.conf,如果部署多个服务,也可以在文件名中加上 Nginx 转发的端口号,比如 sherlocked93.club.8080.conf,如果是二级域名,建议也都加上 fe.sherlocked93.club.conf。
  • 常用的、复用频率比较高的配置可以放到 /etc/nginx/snippets 文件夹,在 Nginx 的配置文件中需要用到的位置 include 进去,以功能来命名,并在每个 snippet 配置文件的开头注释标明主要功能和引入位置,方便管理。比如之前的 gzip、cors 等常用配置,我都设置了 snippet。
  • Nginx 日志相关目录,内以 域名.type.log 命名(比如 be.sherlocked93.club.access.log 和 be.sherlocked93.club.error.log )位于 /var/log/nginx/目录中,为每个独立的服务配置不同的访问权限和错误日志文件,这样查找错误时,会更加方便快捷。

常见问题

启动异常

在启动 nginx 服务时 systemctl start nginx, 报错如下:
Job for nginx.service failed because the control process exited with error code. See “systemctl stat

  • 原因1:

nginx配置文件有错误, 通过 nginx -t 进行检查。

  • 原因2:






免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121605.html

(0)
上一篇 2025-10-22 17:00
下一篇 2025-10-22 17:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信