Nginx教程(小白必看,看了必会,不看血亏),

Notice 测试请打开浏览器禁止缓存

Notice:再使用前,请打开浏览器 F12 然后网络 然后点禁用缓存,避免nginx配置后磁盘缓存的情况。而且,请确认host没问题。
备注:你本地设置的host对服务器反向代理后的就没用了

一、介绍

概述

Nginx是lgor Sysoev为俄罗斯访问量第二的rambler.ru站点设计开发的。从2004年发布至今,凭借开源的力量,已经接近成熟与完善。

Nginx功能丰富,可作为HTTP服务器,也可作为反向代理服务器,邮件服务器。支持FastCGI、SSL、Virtual Host、URL Rewrite、Gzip等功能。并且支持很多第三方的模块扩展。

Nginx的稳定性、功能集、示例配置文件和低系统资源的消耗让他后来居上,在全球活跃的网站中有12.18%的使用比率,大约为2220万个网站。

牛逼吹的差不多啦,如果你还不过瘾,你可以百度百科或者一些书上找到这样的夸耀,比比皆是。

工作模式

分master-worker和单进程模式,单进程模式方便调试,但是不支持平滑升级等,一般只开发环境用。

安装

可参考:
https://blog.csdn.net/wzj_110/article/details/108393207
https://blog.csdn.net/wzj_110/article/details/94202452

二、Nginx功能亮点——为什么要用nginx

最明显的当然是访问ip地址得到对应资源文件,但是比如golang,也能自定义路由去访问,那么为什么要用nginx呢

2.1 性能高

跨平台、配置简单、方向代理、高并发连接:处理2-3万并发连接数,官方监测能支持5万并发,内存消耗小:开启10个nginx才占150M内存 ,nginx处理静态文件好,耗费内存少

异步非阻塞事件处理机制:运用了epoll模型,提供了一个队列,排队解决

所谓静态资源访问,就是存放在nginx的html页面,我们可以自己编写

2.2 反向代理

2.2.1先介绍正向代理

正向代理是一个位于客户端和目标服务器之间的代理服务器(中间服务器)。为了从原始服务器取得内容,客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转交并且将获得的内容返回给客户端。正向代理的情况下客户端必须要进行一些特别的设置才能使用。
在这里插入图片描述

  • 比如,用户A无法访问fa#ce#bo#ok,但是能访问服务器B,而服务器B可以访问fa@ce¥book。于是用户A访问服务器B,通过服务器B去访问fa#c#eb#ook,,服务器B收到请求后,去访问f#b,f#b把响应信息返回给服务器B,服务器B再把响应信息返回给A。这样,通过代理服务器B,就实现了翻【河蟹】墙。

  • 某用户小A,不想要某网站发现他的ip登录过,使用代理ip以后,他在互联网中的所作所为,就好像都是那个代理IP在做的,
    代理ip代替着小A,互联网中的各个server们只知道代理ip来过,不知道小A来过

  • 又比如一些网站禁止一个ip访问太频繁,但client方的小B又需要频繁获取这个网站的信息,那么"正向代理"的代理ip就起作用了,小B只需要频繁更换代理ip来伪装是很多client访问网站就行了。

  • 比如 V_P_N 游戏加速方面的原理,我们要玩网通区的 LOL,但是本机接入的是电信的宽带,玩网通区的会比较卡,这时候就利用 V_P_N 将电信网络变为网通网络,然后在玩网通区的LOL就不会卡了(注意:V_P_N 是不能增加带宽的,不要以为不卡了是因为网速提升了)。
    在这里插入图片描述

2.2.2反向代理是什么

反向代理正好相反。对于客户端来说,反向代理就好像目标服务器。并且客户端不需要进行任何设置。客户端向反向代理发送请求,接着反向代理判断请求走向何处,并将请求转交给客户端,使得这些内容就好似他自己一样,一次客户端并不会感知到反向代理后面的服务,也因此不需要客户端做任何设置,只需要把反向代理服务器当成真正的服务器就好了。
在这里插入图片描述

假设用户A访问 http://www.somesite.com/something.html,但www.somesite.com上并不存在something.html页面,于是接收用户请求的该服务器就偷偷从另外一台服务器上取回来,然后返回给用户,而用户并不知道something.html页面究竟位于哪台机器上。

很多互联网公司的网站,都是做了类似的处理的,用户在网站上的操作和数据,需要在某个重点服务器上进行计算和处理,
这个重要的服务器就等同于"真正的生产车间",
所以就需要一个招待厅,一般的互联网公司都是用的Nginx服务器,
用户感觉自己的请求都是这个"招待厅-nginx服务器"处理的,但其实真正的server被隐藏起来了,
nginx是隐藏的server
这样就可以在nginx前台服务器上做些安全处理,比如"防止客户藏屎",对于一些疑似不安全的请求记录,就不转发到后台主服务器,
再比如如果有人炸掉了招待厅———"DDos"攻击导致服务器崩溃,主要生成环境没被破坏,可以快速搭建一个新的nginx服务器,nginx服务器搭建肯定比系统主环境服务器简单,
————————————————
版权声明:本文为CSDN博主「重启电脑工程师」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44404384/article/details/114675894

2.2.3反向代理的作用

反向代理的作用就比较多了,这里简单列举一下:

  • 保护和隐藏原始资源服务器
    在这里插入图片描述
    用户A始终认为它访问的是原始服务器B而不是代理服务器Z,但实用际上反向代理服务器接受用户A的应答,从原始资源服务器B中取得用户A的需求资源,然后发送给用户A。由于防火墙的作用,只允许代理服务器Z访问原始资源服务器B。尽管在这个虚拟的环境下,防火墙和反向代理的共同作用保护了原始资源服务器B,但用户A并不知情。
  • 加密和SSL加速
  • 负载均衡
    在这里插入图片描述
    后面会详细介绍
  • 缓存静态内容
  • 压缩
  • 减速上传
  • 安全
  • 透明代理
    比较类似正向代理的功能,差别在于客户端根本不知道代理的存在,它改编你的request,并会传送真实IP(使用场景就是公司限制网络的访问)。
    比如为了工作效率或者安全,A公司屏蔽了QQ软件的使用。A公司的员工接上了网络,但发现无法使用qq。这就是透明代理捣的鬼。公司在内网和外网的中间插入一个透明代理,这个代理会根据规则抓取请求内容,遇到qq的请求我就把这个请求给屏蔽掉,这样就完成了透明屏蔽。当然了,如果你明白原理,就可以自己搞个正向代理来绕过公司的屏蔽。
  • 解决前端跨域问题,使用Nginx转发请求。把跨域的接口写成调本域的接口,然后将这些接口转发到真正的请求地址。

2.2.4区别

用户设置上
  • 正向代理需要你主动设置代理服务器ip或者域名进行访问,由设置的服务器ip或者域名去获取访问内容并返回;
  • 反向代理不需要你做任何设置,直接访问服务器真实ip或者域名,但是服务器内部会自动根据访问内容进行跳转及内容返回,你不知道它最终访问的是哪些机器
主体上
  • 正向代理其实是客户端的代理,帮助客户端访问其无法访问的服务器资源。
  • 反向代理则是服务器的代理,帮助服务器做负载均衡,安全防护等。
可见性上
  • 正向代理是代理客户端,为客户端收发请求,使真实客户端对服务器不可见
  • 而反向代理是代理服务器端,为服务器收发请求,使真实服务器对客户端不可见

正向代理伪造client,反向代理伪造server

用途上
  • 正向代理:正向代理用途是为了在防火墙内的局域网提供访问internet的途径。另外还可以使用缓冲特性减少网络使用率
  • 反向代理:反向代理的用途是将防火墙后面的服务器提供给internet用户访问。同时还可以完成诸如负载均衡等功能
安全性:
  • 正向代理:正向代理允许客户端通过它访问任意网站并且隐蔽客户端自身,因此你必须采取安全措施来确保仅为经过授权的客户端提供服务
  • 反向代理:对外是透明的,访问者并不知道自己访问的是代理。对访问者而言,他以为访问的就是原始服务器

正向代理和反向代理的区别
https://blog.51cto.com/u_14097531/4952784
从上面的描述也能看得出来正向代理和反向代理最关键的两点区别:

  • 是否指定目标服务器
  • 客户端是否要做设置

在这里插入图片描述

在这里插入图片描述

2.2.4 php fastcgi就应用了nginx的反向代理

比如你访问我的网站 https://xiaogd.net, 然后你看下主页的请求里的服务器信息, 它告诉你响应这个主页请求的是一台 Nginx server, 如下图所示:
在这里插入图片描述
问题是 Nginx 是最终生成这个网页的 server 吗? 其实不是的! 如果你了解 Nginx, 就会知道它通常只是一个静态资源服务器, 而我的网站主页是一个动态生成的内容, 其实你要是认真看过我网站底部的一个声明, 如下图所示:
在这里插入图片描述
就会明白这个主页其实是 php 的一个叫 wordpress 的建站应用去生成的. 在我的云主机的内部, Nginx 其实是将主页的请求转发给一个所谓的 php-fpm 网关
这个 php-fpm 网关基本可以看作是个 php 的 web 服务器, 不过严格来说它用的协议不是 http, 而是一种内部简化的 fastcgi 协议.
如果你要较真的话, 这可以算是 反向代理 模式, 但整体不全是 http 反向代理, 但对外而言则确实是.
在这里插入图片描述
这是内部配置的一个情况:

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

请求被转发到内部一个在 9000 端口上监听的 php 应用服务器.

从外部浏览器的角度看, 请求直接发给了 Nginx server, 响应也从 Nginx server 里回来了, 中间没有任何的(正向)代理. 至于说你内部请求又被怎么转发了, 显然浏览器是无从知道也不需要去知道的.

站在整个体系设计者的角度去看, 当然但很多请求 Nginx 其实是没有能力去响应的, 它只不过在内部把它代理给了另一个内部的 php 应用服务器, 内部的 php 应用服务器才是最终的响应生成者.

在整个体系里面, Nginx 的角色就是一个"反向代理"服务器, 浏览器被代理了, 但它无从知道自己是否被代理了, 这一切对它而言是透明的, 反正它自己是没有主动走(正向)代理的.

当然了, 你现在知道了我内部的配置, 如果直接访问 http://xiaogd.net:9000, 那就是真正的"直接访问"了, 那就绕过了 Nginx.

#不过需要说明的一点是, 直接访问是访问不通的, 因为 9000 端口并没有对外放开. 
#但是在内部是可以访问到的, 比如这样尝试用 wget 去访问:
wget localhost:9000

这样就是真正的"直接访问"了, 没有任何的代理, 既没有正向代理, 也没有反向代理.
需要说明的一点是, 用 wget 这样去获取响应还是会报错, 因为 wget 使用的是 http 协议, php 的 cgi 网关实际使用的是 fastcgi 协议, 是一个比 http 更为简化的协议, 作为内部通讯更加高效, 不过 wget 不支持这个协议, 但 Nginx 能理解这个协议, 整个过程是这样的:
browser – [http] --> Nginx – [fastcgi] --> php-fpm
严格来说, 不完全是 http 代理, 内部的反向代理实际用的是 fastcgi 网关协议, 不过这个原理还是一样的, 如果内部用一个比如 tomcat 来响应, 那么全程就都可以是 http 协议.
browser – [http] --> Nginx – [http] --> tomcat
而如果在内部发请求 80, 比如 wget localhost 那就还是被反向代理, 请求先到在 80 端口监听的 Nginx, Nginx 再转给 php-fpm.

在这里插入图片描述

2.3 负载均衡

一个很直接的原因就是利用反向代理可以作为内部 负载均衡(load balance) 的手段.

举个例子来说, 假如我现在开发了一个 java web 的应用作为我的网站后台, 我直接部署它到 tomcat 服务器上, 让 tomcat 监听 80 端口, 直接对外服务. 一开始访问量也不大, 所以这样也是没有问题的, 如下图所示:
在这里插入图片描述

注: 因为 http 协议的缺省端口就是 80, 所以用户输入地址时可以省略这个端口号, 也即只需这样:
http://xiaogd.net, 而不是繁琐的像这样: http://xiaogd.net:80, 关于缺省端口的话题,
还是可以参考前面所提的 深入理解端口.

但过一段时间之后, 访问量可能上来了, 一个 tomcat 进程处理不过来, 那怎么办呢? 于是我打算再起一个新的 tomcat 进程, 但这样就面临一个问题, 只有一个 80 端口, 它已经被第一个 tomcat 进程占用, 如果还要再起另外一个, 则只能选用其它的端口, 比如 8080.

当使用另外一个端口时, 确实可以启动两个 tomcat 的进程, 但用户想访问到第二个 tomcat 进程的服务, 却要这样去访问: http://xiaogd.net:8080. 显然, 这样的方案是有问题的, 用户根本不知道 8080 端口上服务的存在, 就算你有办法告诉用户, 用户也可能不太理解, 用户同时也很怕麻烦的, 为啥要我输入一个冒号加 8080 呢?

此外, 就算有些用户愿意如你所说转向访问 8080 端口, 你还是不能很好的控制把访问量平均地分配在两个 tomcat 上, 毕竟这是用户随机决定的, 也许很多用户又突然涌过来了 8080 端口的应用上, 造成了这边的拥挤.

又或者只有很少的用户愿意听从你的劝告转到新的 8080 端口上, 访问还是集中在旧的 80 端口上的, 这样旧的应用上响应还是很缓慢, 而新的应用却因为没几个用户访问而显得空闲, 没有得到充分的使用.

那么, 在这种情况下, 反向代理的好处就体现出来了, 具体的操作是这样的, 让 Nginx 作为一个前置的反向代理, 监听在 80 端口上; 而第一个 tomcat 则躲到幕后, 同时它也不再监听 80 端口(需要让给 Nginx), 而改为监听一个其它没有被使用的端口, 比如 8081, 然后让 Nginx 转发请求给它处理.

当然了, 如果只有一个 tomcat, 配置大概是这样的:(先大概猜一猜什么以上即可 后面会详细说明)

location / {
    
    
    proxy_pass   http://127.0.0.1:8080;
}

请求处理的流程是这样的:

请求: browser – [http] --> Nginx – [http] --> tomcat 响应: browser <–
[http] – Nginx <-- [http] – tomcat

自然, 这种情形下反向代理似乎不太必要, 还加多了一个环节, 响应速度反而慢了.

但如果有两个 tomcat, 情况就不一样了, 此时就可以在 Nginx 这个反向代理的层面, 启用负载均衡的策略, 大概的配置如下:

http {
    
    
    upstream myapp1 {
    
    
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
    }

    server {
    
    
        listen 80;

        location / {
    
    
            proxy_pass http://myapp1;
        }
    }
}

此时, 如果同时涌入了很多请求, Nginx 会把一半的请求交给 8080 端口上的 tomcat, 另一半的请求交给 8081 端口上的 tomcat, 如下图所示:
在这里插入图片描述
对外来看, 所有请求还是 Nginx 来处理, 用户不需要去做选择, 也不需要知道什么 8080, 8081 端口上应用的存在, 他们还是继续访问原来的网址 http://xiaogd.net 即可, 无需做任何改变.

如果你在云上有好几台主机, 甚至还可以将其组成一个内网, 然后将 tomcat 部署在不同的主机上. 比如有三台主机的话, 一台运行 Nginx 监听 80 端口, 其余两台运行 tomcat, 分别监听 8080 和 8081 端口, 同时接受并处理 Nginx 反向代理过来的请求, 如下图所示:
在这里插入图片描述
如果两台 tomcat 主机的配置不同, 比如一台的性能更强劲些, 还可以调整负载的比例(即权重, weight), 让性能更强的一台承担更多的请求:

http {
    
    
    upstream myapp1 {
    
    
        server 192.168.0.20:8080 weight=3;
        server 192.168.0.21:8080 weight=2;
    }

    server {
    
    
        listen 80;

        location / {
    
    
            proxy_pass http://myapp1;
        }
    }
}

如上配置 3:2 的权重比, 让其中一台承担 60% 的请求, 而另一台性能较差的则承担 40%, 也即每 5 个请求, 3 个会被转到 ip 为 20 的主机上, 2 个会转到 ip 为 21 的主机上.

自然, 有人可能还会有疑问, 所有请求都还是要经过 Nginx, 它能处理得过来吗? 答案是可以的, 因为它的功能仅仅是转发, 这就有点像美团外卖, 虽然它每天接受成千上万的人的点餐, 但它自己不需要去买菜, 洗菜, 切菜, 炒菜等, 它仅仅需要把订单交给饭店餐馆, 然后把它们做好的饭菜配送出去, 也即那些耗时的做饭过程都交给了饭店餐馆处理.

在这种反向代理的模式中, 同样的, 生成网页这个重任交到了隐藏在背后的 tomcat, 生成一个复杂的动态网页可能需要经过一些复杂的计算, 要查询数据库, 要拼凑各个页面组件, 可能会比较耗时, 但这些请求被两个 tomcat 应用并发地处理了, 因此响应的速度还是得到了保证, 而这些就是反向代理能给我们带来的好处.

转自 https://zhuanlan.zhihu.com/p/464965616 这个博主主要讲cpp的 其他文章也不错

2.4 健康检查

而且Nginx内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送的请求就不会发送到宕机的服务器了。重新将请求提交到其他的节点上。

2.5服务器限流

Nginx限流就是限制用户请求速度,防止服务器受不了
限流有3种
正常限制访问频率(正常流量)
突发限制访问频率(突发流量)
限制并发连接数
Nginx的限流都是基于漏桶流算法,底下会说道什么是桶铜流

2.6动静分离

Nginx是当下最热的Web容器,网站优化的重要点在于静态化网站,网站静态化的关键点则是是动静分离,动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们则根据静态资源的特点将其做缓存操作。
让静态的资源只走静态资源服务器,动态的走动态的服务器
Nginx的静态处理能力很强,但是动态处理能力不足,因此,在企业中常用动静分离技术。
对于静态资源比如图片,js,css等文件,我们则在反向代理服务器nginx中进行缓存。这样浏览器在请求一个静态资源时,代理服务器nginx就可以直接处理,无需将请求转发给后端服务器tomcat。
若用户请求的动态文件,比如servlet,jsp则转发给Tomcat服务器处理,从而实现动静分离。这也是反向代理服务器的一个重要的作用。

其他

使用Nginx的话还能:
节省宽带:支持GZIP压缩,可以添加浏览器本地缓存
稳定性高:宕机的概率非常小
接收用户请求是异步的

缺点

    动态处理差:nginx处理静态文件好,耗费内存少,但是处理动态页面则很鸡肋,现在一般前端用nginx作为反向代理抗住压力,

三、基础使用

1、命令行相关命令

nginx 的使用比较简单,就是几条命令。

常用到的命令如下:

  • nginx -s stop :快速关闭Nginx,可能不保存相关信息,并迅速终止web服务。
  • nginx -s quit :平稳关闭Nginx,保存相关信息,有安排的结束web服务。
  • nginx -s reload :因改变了Nginx相关配置,需要重新加载配置而重载。
  • nginx -s reopen :重新打开日志文件。
  • nginx -c filename :为 Nginx 指定一个配置文件,来代替缺省的。
  • nginx -t :不运行,而仅仅测试配置文件。nginx 将检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件。
  • nginx -v:显示 nginx 的版本。
  • nginx -V:显示 nginx 的版本,编译器版本和配置参数。

如果不想每次都敲命令,可以在nginx安装目录下新添一个启动批处理文件startup.bat,双击即可运行。内容如下:

@echo off
rem 如果启动前已经启动nginx并记录下pid文件,会kill指定进程
nginx.exe -s stop
 
rem 测试配置文件语法正确性
nginx.exe -t -c conf/nginx.conf
 
rem 显示版本信息
nginx.exe -v
 
rem 按照指定配置去启动nginx
nginx.exe -c conf/nginx.conf

如果是运行在 Linux 下,写一个 shell 脚本,大同小异。

2、nginx 目录结构

[root@localhost ~]# tree /usr/local/nginx
/usr/local/nginx
├── client_body_temp
├── conf                             # Nginx所有配置文件的目录
│   ├── fastcgi.conf                 # fastcgi相关参数的配置文件
│   ├── fastcgi.conf.default         # fastcgi.conf的原始备份文件
│   ├── fastcgi_params               # fastcgi的参数文件
│   ├── fastcgi_params.default       
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types                   # 媒体类型
│   ├── mime.types.default
│   ├── nginx.conf                   # Nginx主配置文件
│   ├── nginx.conf.default
│   ├── scgi_params                  # scgi相关参数文件
│   ├── scgi_params.default           #default结尾的都是备份文件
│   ├── uwsgi_params                 # uwsgi相关参数文件
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp                     # fastcgi临时数据目录
├── html                             # Nginx默认站点目录
│   ├── 50x.html                     # 错误页面优雅替代显示文件,例如当出现502错误时会调用此页面
│   └── index.html                   # 默认的首页文件
├── logs                             # Nginx日志目录
│   ├── access.log                   # 访问日志文件
│   ├── error.log                    # 错误日志文件
│   └── nginx.pid                    # pid文件,Nginx进程启动后,会把所有进程的ID号写到此文件
├── proxy_temp                       # 临时目录
├── sbin                             # Nginx命令目录
│   └── nginx                        # 这是'nginx命令的目录'如Nginx的启动命令
├── scgi_temp                        # 临时目录
└── uwsgi_temp                       # 临时目录
————————————————

版权声明:本文为CSDN博主「小 源」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_51414096/article/details/125293932

3、nginx.conf配置文件结构

...              #全局块

events {         #events块
   ...
}

http      #http块
{
    ...   #http全局块
    server        #server块
    { 
        ...       #server全局块
        location [PATTERN]   #location块
        {
            ...
        }
        location [PATTERN] 
        {
            ...
        }
    }
    server
    {
      ...
    }
    ...     #http全局块
}
  1. 全局块:从配置文件开始到events块之间的内容,主要会设置一些影响Nginx服务器整体运行的配置指令,配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
  2. events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
  3. http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
  4. server块:配置虚拟主机的相关参数,一个http中可以有多个server。server其实就是host,比如www.csdn.com
  5. location块:配置请求的路由,以及各种页面的处理情况。https://editor.csdn.net/md//md/就是location。再如www.csdn.com/index.html,/index.html就是location。需要注意的是,如果没有输入location,如www.csdn.com,那么浏览器会自动帮我们加上/ , /www.csdn.com/
    PS:但是,如果我们访问的是www.csdn.com/a 则不会自动帮我们加上/ 因为这里不只是host了

4、配置文件示例

1)注意配置文件中的结尾有’;‘作为结束~!(切记!)
2)每次实验修改完配置文件后需要’重启 nginx 才会生效’

示例1


worker_processes  1# worker进程的数量
events {
    
                                  					# 事件区块开始
    worker_connections  1024# 每个worker进程支持的最大连接数
}                                    					# 事件区块结束
http {
    
                                   					# HTTP区块开始
    include       mime.types;            				# Nginx支持的媒体类型库文件
    default_type  application/octet-stream;     		# 默认的媒体类型
    sendfile        on;       							# 开启高效传输模式
    keepalive_timeout  65# 连接超时
    
    #可以在nginx.conf同级目录下新建文件夹include
 	#然后里面根据不同的域名命名新建文件夹  再在里面新建vhost.conf文件,/usr/local/nginx/conf/include/csdn.com/csdn.vhost
 	#在里面写server块,避免一个nginx文件配置项太多且不好找 或者误删
 	include include/*/vhost.conf;  
 	include include/*.conf; #类似上面 不过是不建文件夹了 直接以名字命令,可灵活配置 域名视图、个人开发视图~~
 	                     
 	

    server {
    
                								# 第一个Server区块开始,表示一个独立的虚拟主机站点
        listen       80# 提供服务的端口,默认80
        server_name  localhost;       					# 提供服务的域名主机名
        location / {
    
                						# 第一个location区块开始
            root   html;       						# 站点的根目录,相当于Nginx的安装目录
            index  index.html index.htm;      			# 默认的首页文件,多个用空格分开
        }          										# 第一个location区块结果
        error_page   500502503504  /50x.html;     		# 出现对应的http状态码时,使用50x.html回应客户
        location = /50x.html {
    
              				# location区块开始,访问50x.html
            root   html;      							# 指定对应的站点目录为html
        }
    }  

示例2

########### 每个指令必须有分号结束。#################
#user administrator administrators;  #配置用户或者组,默认为nobody nobody。
#worker_processes 2;  #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid;   #指定nginx进程运行文件存放地址
error_log log/error.log debug;  #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg

events {
    
    
    accept_mutex on;   #设置网路连接序列化,防止惊群现象发生,默认为on
    multi_accept on;  #设置一个进程是否同时接受多个网络连接,默认为off
    #use epoll;      #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
    worker_connections  1024;    #最大连接数,默认为512
}

http {
    
    
    include       mime.types;   #文件扩展名与文件类型映射表
    default_type  application/octet-stream; #默认文件类型,默认为text/plain
    #access_log off; #取消服务日志    
    log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式
    access_log log/access.log myFormat;  #combined为日志格式的默认值
    sendfile on;   #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
    sendfile_max_chunk 100k;  #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
    keepalive_timeout 65;  #连接超时时间,默认为75s,可以在http,server,location块。

    upstream mysvr {
    
       
      server 127.0.0.1:7878;
      server 192.168.10.121:3333 backup;  #热备
    }
    
    error_page 404 https://www.baidu.com; #错误页
    
    server {
    
    
        keepalive_requests 120; #单连接请求上限次数。
        listen       4545;   #监听端口
        server_name  127.0.0.1;   #监听地址       
        location  ~*^.+$ {
    
           #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
           #root path;  #根目录
           #index vv.txt;  #设置默认页
           proxy_pass  http://mysvr;  #请求转向上面mysvr 定义的服务器列表
           deny 127.0.0.1;  #拒绝的ip
           allow 172.18.5.54; #允许的ip           
        } 
        
    }
    
}

示例3 默认的nginx.conf长这样

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


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;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #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$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #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;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    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;
    #    }
    #}

}

如何避免conf文件太长

仔细看示例1的include那里

5、server虚拟主机配置详解

示例如下

 server {
    
    
        listen       80;
        server_name  www.lijie.com;
        location / {
    
    
            root   data/www;
            index  index.html index.htm;
        }
    }

listen指令详解

该指令用于配置网络监听。主要有如下三种配置语法结构:

一、配置监听的IP地址

listen address[:port] [default_server] [setfib=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [deferred]
    [accept_filter=filter] [bind] [ssl];

二、配置监听端口

listen port[default_server] [setfib=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] 
    [deferred] [bind] [ipv6only=on|off] [ssl];

三、配置 UNIX Domain Socket

listen unix:path [default_server]  [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] 
    [deferred] [bind] [ssl];

上面的配置看似比较复杂,其实使用起来是比较简单的:

1 listen *:80 | *:8080 #监听所有80端口和8080端口
2 listen  IP_address:port   #监听指定的地址和端口号
3 listen  IP_address     #监听指定ip地址所有端口
4 listen port     #监听该端口的所有IP连接

下面分别解释每个选项的具体含义:

1、address:IP地址,如果是 IPV6地址,需要使用中括号[] 括起来,比如[fe80::1]等。

2、port:端口号,如果只定义了IP地址,没有定义端口号,那么就使用80端口。

3、path:socket文件路径,如 var/run/nginx.sock等。

4、default_server:标识符,将此虚拟主机设置为 address:port 的默认主机。(在 nginx-0.8.21 之前使用的是 default 指令)# 如果没有显式声明 default server 则第一个 server 会被隐式的设为 default server

5、 setfib=number:Nginx-0.8.44 中使用这个变量监听 socket 关联路由表,目前只对 FreeBSD 起作用,不常用。

6、backlog=number:设置监听函数listen()最多允许多少网络连接同时处于挂起状态,在 FreeBSD 中默认为 -1,其他平台默认为511.

7、rcvbuf=size:设置监听socket接收缓存区大小。

8、sndbuf=size:设置监听socket发送缓存区大小。

9、deferred:标识符,将accept()设置为Deferred模式。

10、accept_filter=filter:设置监听端口对所有请求进行过滤,被过滤的内容不能被接收和处理,本指令只在 FreeBSD 和 NetBSD 5.0+ 平台下有效。filter 可以设置为 dataready 或 httpready 。

11、bind:标识符,使用独立的bind() 处理此address:port,一般情况下,对于端口相同而IP地址不同的多个连接,Nginx 服务器将只使用一个监听指令,并使用 bind() 处理端口相同的所有连接。

12、ssl:标识符,设置会话连接使用 SSL模式进行,此标识符和Nginx服务器提供的 HTTPS 服务有关。

server_name指令详解

该指令用于虚拟主机的配置。通常分为以下三种:

1、基于域名的虚拟主机,通过域名来区分虚拟主机——应用:外部网站

需要建立/data/www /data/bbs目录,windows本地hosts添加虚拟机ip地址对应的域名解析;对应域名网站目录下新增index.html文件;


#当客户端访问www.lijie.com,监听端口号为80,直接跳转到data/www目录下文件
    server {
    
    
        listen       80;
        server_name  www.lijie.com;
        location / {
    
    
            root   data/www;
            index  index.html index.htm;
        }
    }
 
	#当客户端访问www.lijie.com,监听端口号为80,直接跳转到data/bbs目录下文件
	 server {
    
    
        listen       80;
        server_name  bbs.lijie.com;
        location / {
    
    
            root   data/bbs;
            index  index.html index.htm;
        }
    }
  • 语法格式如下:
server_name   name ...;
  • 对于name 来说,可以只有一个名称,也可以有多个名称,中间用空格隔开。而每个名字由两段或者三段组成,每段之间用“.”隔开。
server_name 123.com www.123.com
  • 可以使用通配符“*”,但通配符只能用在由三段字符组成的首段或者尾端,或者由两端字符组成的尾端。
server_name *.123.com www.123.*
  • 还可以使用正则表达式,用“~”作为正则表达式字符串的开始标记。
server_name ~^www\d+\.123\.com$;
该表达式“~”表示匹配正则表达式,以www开头(“^”表示开头),
紧跟着一个0~9之间的数字,在紧跟“.123.co”,最后跟着“m”($表示结尾)

  • 以上匹配的顺序优先级如下:
1 ①、准确匹配 server_name
2 ②、通配符在开始时匹配 server_name 成功
3 ③、通配符在结尾时匹配 server_name 成功
4 ④、正则表达式匹配 server_name 成功

2、基于端口的虚拟主机,通过端口来区分虚拟主机——应用:公司内部网站,外部网站的管理后台

使用端口来区分,浏览器使用域名或ip地址:端口号 访问

 #当客户端访问www.lijie.com,监听端口号为8080,直接跳转到data/www目录下文件
	 server {
    
    
        listen       8080;
        server_name  www.lijie.com;
        location / {
    
    
            root   data/www;
            index  index.html index.htm;
        }
    }

	
	#当客户端访问www.lijie.com,监听端口号为80直接跳转到真实ip服务器地址 127.0.0.1:8080
	server {
    
    
        listen       80;
        server_name  www.lijie.com;
        location / {
    
    
		 	proxy_pass http://127.0.0.1:8080;
            index  index.html index.htm;
        }
	}
3、基于 IP 地址的虚拟主机配置

语法结构和基于域名匹配一样,而且不需要考虑通配符和正则表达式的问题。

server_name 192.168.1.1

6、location路由块配置详解

语法格式

location指令的作用是根据用户请求的URI来执行不同的应用,也就是根据用户请求的网站URL进行匹配,匹配成功即进行相关的操作。

 location [ = | ~ | ~* | ^~] uri {
    
    
 
 }

1、= :用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。

2、~:用于表示 uri 包含正则表达式,并且区分大小写。

3、~*:用于表示 uri 包含正则表达式,并且不区分大小写。

4、^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。

注意:如果 uri 包含正则表达式,则必须要有 ~ 或者 ~* 标识。

模糊匹配

1)没有 / 时,location /abc/def可以匹配/abc/defghi请求,也可以匹配/abc/def/ghi

2)而有 / 时,location /abc/def/不能匹配/abc/defghi请求,只能匹配/abc/def/anything这样的请求

正则语法与优先级

在这里插入图片描述
1优先级最高 7最低
更详细的生效顺序可以看:http://wjhsh.net/pangbing-p-6956644.html

示例


#优先级1,精确匹配,根路径
    location =/ {
    
    
        return 400;
    }
 
    #优先级2,以某个字符串开头,以av开头的,优先匹配这里,区分大小写
    location ^~ /av {
    
    
       root /data/av/;
    }
 
    #优先级3,区分大小写的正则匹配,匹配/media*****路径
    location ~ /media {
    
    
          alias /data/static/;
    }
 
    #优先级4 ,不区分大小写的正则匹配,所有的****.jpg|gif|png 都走这里
    location ~* .*\.(jpg|gif|png|js|css)$ {
    
    
       root  /data/av/;
    }
 
    #优先7,通用匹配
    location / {
    
    
        return 403;
     }

location块内部指令

index

该指令用于设置网站的默认首页。

语法为:

index  filename ...; #后面的文件名称可以有多个,中间用空格隔开。
index  index.html index.jsp;

通常该指令有两个作用:第一个是用户在请求访问网站时,请求地址可以不写首页名称;第二个是可以对一个请求,根据请求内容而设置不同的首页。

try_files
location / {
    
    
            try_files $uri $uri/ /index.php?$query_string;

}

当用户请求 http://localhost/example 时,这里的 $uri 就是 /example

try_files 会到硬盘里尝试找这个文件。如果存在名为 /$root/example(其中 $root 是server快定义的)的文件,就直接把这个文件的内容发送给用户。

显然,目录中没有叫 example 的文件。然后就看 $uri/,增加了一个 /,也就是看有没有名为 /$root/example/ 的目录。

又找不到,就会 fall back 到 try_files 的最后一个选项 /index.php,发起一个内部 “子请求”,也就是相当于 nginx 发起一个 HTTP 请求到 http://localhost/index.php

更多示例:

示例一:

location /whsir/ {
    
    
    try_files $uri /whsir/default.gif;
}
说明:

1、访问www.example.com/whsir/123/321(文件不存在)时,此时看到的是default.gif图片,URL地址不变

2、访问www.example.com/whsir/123.png(文件存在)时,此时看到的是123.png图片,URL地址不变

总结:当images目录下文件不存在时,默认返回default.gif

示例二:

location /whsir/ {
    
    
    try_files $uri =403;
}
说明:

1、访问www.example.com/whsir/123.html(文件存在)时,此时看到的是123.html内容,URL地址不变

2、访问www.example.com/whsir/21.html(文件不存在)时,此时看到的是403状态,URL地址不变

总结:和示例一一样,只是将默认图片换成了403状态

示例三:

location /whsir/ {
    
    
    try_files $uri @ab;
}
location @ab {
    
    
    rewrite ^/(.*)$ https://blog.whsir.com;
}
说明:

1、访问www.example.com/whsir/123.html(文件存在)时,此时看到的是123.html内容,URL地址不变

2、访问www.example.com/whsir/21.html(文件不存在)时,此时跳转到吴昊博客,URL地址改变

总结:当文件不存在时,会去查找@ab值,此时在location中定义@ab值跳转到吴昊博客

示例四:

try_files $uri @pro;
location @pro {
    
    
    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_pass https://blog.whsir.com;
}
说明:

1、访问www.example.com/123.html(文件存在)时,此时看到的是123.html内容,URL地址不变

2、访问www.example.com/post-3647.html(文件不存在)时,此时看到的是吴昊博客的内容,URL地址不变

总结:当前服务器上文件不存在时,会进行反向代理
proxy_pass(讲代理的时候再更深入)

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

语法结构如下:

proxy_pass URL;#URL 为被代理服务器的地址,可以包含传输协议、主机名称或IP地址加端口号,URI等。

proxy_pass  http://www.123.com/uri;

7、变量

变量语法

nginx 的’配置文件’使用的就是一门’微型的编程语言’
在 ‘nginx 配置中’,‘变量’只能存放’一种类型的值’,因为也只存在一种类型的值,那就是’字符串’

举例:'nginx.conf 文件’中有下面这一行配置:

set $var "hello world";

特点:我们看到,‘Nginx 变量名’前面’有一个 $ 符号’,这是’语法上’的要求
强调:所有的 ‘Nginx 变量’在 Nginx 配置文件中’引用时都须带上 $ 前缀’,这种表示方法和’Perl、PHP’ 这些语言是’相似’的
变量作用域:整个nginx配置文档

set $a hello;
 
set $b "$a, $a";
 
解释:通过'已有的 Nginx 变量 $a' 的值来'构造'变量 $b 的值,于是'这两条指令顺序'执行完之后,$a 的值是hello,而 $b 的值则是 hello, hello.
 
备注:这种技术在 Perl 世界里被称为"变量插值"(variable interpolation),它让专门的'字符串拼接'运算符
内置变量

在这里插入图片描述


$remote_addr;
  存放了'客户端的地址',注意是客户端的公网IP,也就是一家人访问一个网站,则会显示为'路由器的公网IP'$host。更准确的说是前一节点的IP,不一定是真实的客户端ip。host是访问URL中的域名和端口  www.taobao.com:80
 
$args;
  变量中存放了'请求行中(GET请求)的参数',例如http://node101.yinzhengjie.org.cn/main/index.do?'id=20190221&partner=search'中的id=20190221&partner=search
 
$document_root;
  保存了针对'当前资源的请求''系统根目录',/apps/nginx/html -->对应'root'指令
 
$document_uri;
  保存了当前请求中'不包含指令的URI',注意是'不包含请求'的指令,比如http://node101.yinzhengjie.org.cn/main/index.do?id=20190221&partner=search会'被定义为/main/index.do'
 
$host;
  存放了'请求的host名称' 比如你请求的是百度的域名 那么host就是百度
  和$remote_addr区分,remote_addr是访问者的ip(在反向代理中 是REMOTE_HOST)


 
$http_user_agent;
  '客户端浏览器'的详细信息
 
$http_cookie;
  '客户端的cookie'信息
 
limit_rate 10240;
echo $limit_rate;
  如果nginx服务器使用limit_rate配置了'显示网络速率',则会显示,如果'没有设置','显示0'
 
$remote_port;
  客户端请求Nginx服务器时'随机打开的端口',这是每个'客户端自己的端口'
 
$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;
  请求的'服务器的端口号'
 
+++++++++++++++'补充知识点'+++++++++++++++
 
$arg_name           请求中的'name参数'-->请求的参数的名字,根据'具体情况'而定
$binary_remote_addr 远程地址的'二进制'表示
$body_bytes_sent    已发送的'消息体'字节数
$content_length     HTTP请求信息里的"Content-Length"
$content_type       请求信息里的"Content-Type"
$host               请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名
$http_referer       '引用地址'
$http_via           '最后'一个访问服务器的'ip地址'
$is_args            如果请求行'带有参数',返回"?",否则'返回空字符串'
$nginx_version      当前运行的nginx版本号
$pid                'worker进程'的PID
$query_string$args'相同'
$realpath_root      按root指令或alias指令算出的'当前请求的绝对路径',其中的'符号链接'都会解析成真是文件路径
$request            '用户请求'
$request_body       这个变量(0.7.58+)包含'请求的主要信息',在使用proxy_pass或fastcgi_pass指令的location中'比较有意义'
$request_body_file  客户端'请求主体'信息的'临时文件名'
$request_completion 如果'请求成功',设为"OK";如果'请求未完成'或者'不是'一系列请求中最后一部分则设为空
$request_filename   当前请求的文件路径名,比如/opt/nginx/www/test.php
$request_uri        请求的URI,'带参数'; 比如http://localhost:88/test1/
$uri                请求的URI,可能'和最初的值有不同',比如经过'重定向'之类的
$http_name          用来获取'任意请求头'的值
————————————————
版权声明:本文为CSDN博主「wzj_110」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wzj_110/article/details/112548532

在这里插入图片描述

8、return指令

1、返回状态码

return 404;
location /test {
    
        
            set $name 'user123';

            return 404  $name;
        }

curl -i http://192.168.56.10/test
2、返回字符串(不过输出结果并未见到 状态码后的字符串输出)

location /test {
    
    
            return 200 'hello';
        }

3、地址跳转

location /test {
    
        
            return http://www.baidu.com;
        }

4、返回自定义变量

set $name 'user123';
return 200 $name;

5、返回内置变量

return $uri;

6、返回日志信息实例

return  200 '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';

————————————————
版权声明:本文为CSDN博主「刘远山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39218464/article/details/121184473

9、rewrite

10如何配置ssl

四、反向代理详解

nginx 中常见的反向代理指令有两个:proxy_pass 和 fastcgi_pass,前者使用标准的 HTTP 协议转发,后者使用 FastCGI 协议转发,用于 PHP 等架构的环境。在我要说的这个域名问题上,它们行为是一样的,所以下面仅以 proxy_pass 为例。

proxy_pass后有两种写法

  • 直接接要代理的地址,可以是一台具体的主机(ip),也可以是一个具体的网址
  • 可以配成一组服务器(看负载均衡那里)

简单示例

#使用 Nginx 反向代理,根据访问的路径跳转到不同端口的服务中,Nginx 监听端口为 9001
#访问http://192.168.17.129/edu/直接跳转到 127.0.0.1:8080(内网ip,本机的8080端口)
#访问http://192.168.17.129/vod/直接跳转到 127.0.0.1:8081(内网ip,本机的8081端口)

server {
    
    
	listen       9001;
	server_name  192.168.17.129;

	location ~ /edu/ {
    
    
		proxy_pass  http://127.0.0.1:8080
	}

	location ~ /vod/ {
    
    
		proxy_pass  http://127.0.0.1:8081
	}
}
server {
    
    

 location / {
    
    

 proxy_pass https://github.com;

 }

}

指令

简单的

1、设置 404 页面导向地址

error_page 404 https://www.runnob.com; #错误页
proxy_intercept_errors on; #如果被代理服务器返回的状态码为400或者大于400,设置的error_page配置起作用。默认为off。
2、如果我们的代理只允许接受get,post请求方法的一种

proxy_method get; #支持客户端的请求方法。post/get;
3、设置支持的http协议版本

proxy_http_version 1.0 ; #Nginx服务器提供代理服务的http协议版本1.0,1.1,默认设置为1.0版本

proxy_set_header

重定义转发的请求头

#配置示例
location / {
    
    
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   Host             $http_host;
        proxy_set_header   X-NginX-Proxy    true;
        proxy_set_header   Connection "";
        proxy_http_version 1.1;
        add_header Access-Control-Allow-Origin *;
        proxy_pass  http://127.0.0.1:8889;
    }  

我们假设:

客户端地址(请求服务的地址):192.168.1.1
nignx服务器地址:192.168.1.2
后端服务器地址:192.168.1.3

然后,客户端输入nginx服务器的地址去访问。

X-Real-IP

是指客户端的真实IP,如果设置了$remote_addr这个值,后端服务器就能获取到客户端的真实IP,也就是此例中的192.168.1.1。否则如果不设置,转发了,似乎默认是nginx服务器的地址2

Host
  • host的值设置为$proxyhost,是指proxy_pass中设置的host值,也就是192.168.1.3,也就是服务器的IP地址。

  • 若客户端发过来的请求header中有HOST这个字段,$http_host$host表示的就是原始请求host,比如请求的时候HOST的值是http://test.com,那么反代后还是http://test.com。

  • 若客户端发过来的请求header中没有HOST这个字段,$host表示nginx代理服务器的地址,也就是此例中的192.168.1.2。

  • $httphost不是一个固定的变量,他其实是$http_HEADER通配后的结果,这里的HEADER是一个通配符,通配的是请求头里的header属性,例如$http_content_type表示请求头里content-type属性的值,同理,$http_host指的就是请求头里的host属性。

  • 此外,服务器名可以和后端服务器的端口一起传送:

    proxy_set_header Host   $host:$proxy_port;

三、X-Forwarded-For

这个变量的值有$proxy_add_x_forwarded_for$remote_addr,在只有一个代理服务器的转发的情况下,两者的效果貌似差不多,都可以真实的显示出客户端原始ip。

举例说明,用户A的IP是192.168.1.1,请求一个经过两次nginx转发的应用,在第一台nginx中(192.168.1.2),配置如下:

proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

现在$proxy_add_x_forwarded_for变量的"X-Forwarded-For"部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,那么X-Forwarded-For变量的值就是用户的ip:192.168.1.1。

到第二台nginx,配置如下:

proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,那么X-Forwarded-For的值就变成了"用户的真实ip,第一台nginx的ip",也就是“192.168.1.1, 192.168.1.2”

所以还是建议X-Forwarded-For的值设置成$proxy_add_x_forwarded_for

request_uri

是请求的

其他
默认情况会重定义的请求头

默认情况下,nginx在代理请求中重定义两个请求头,Host和Connection,并且清除值为空的请求头。Host被设置为$proxy_host变量,Connection被设置为close。(似乎还有realip??)

为了防止请求头被转发到被代理服务器

可以将值设置为空字符串,比如:

location /some/path/ {
proxy_set_header Accept-Encoding “”;
proxy_pass http://localhost:8000;}

配置缓冲broxy_buffering

默认请求下,nginx会缓存被代理服务器的响应。响应会被储存在内部缓存中,直到整个响应接收完毕才发送到客户端。缓存有助于慢的客户端的性能优化,因为响应从nginx同步返回给客户端会浪费被代理服务器的时间。然而,当缓存启动后,nginx允许被代理服务器快速地返回响应,nginx存储响应使客户端有更多的时间下载响应。

broxy_buffering用于表示缓存是否开启,默认是开启的。

Proxy_buffers控制分配的缓存区的大小和数量。响应的第一部分会被存储在一个单独的缓存中,缓存的大小由proxy_buffer_size指令设置。这部分通常包含相对较小的响应头。

如果设置缓冲不可用,当接收被代理服务器的响应时,响应会同步地发送到客户端。此设置或许是希望快速互动的客户所需要的。

想要设置缓冲不可用,将location下的proxy_buffering设为off即可,如下所示:

location /some/path/ {
proxy_buffering off;
proxy_pass http://localhost:8000;}
这种情况下,nginx只使用proxy_buffer_size配置的缓冲区去存储当前部分的响应。

其他问题

如何重解析域名

nginx 是怎么解析域名的呢?
答案是启动的时候,只做一次,解析结果会被缓存下来,也就是完全无视 TTL,后续所有的请求转发,都是直接使用缓存下来的 IP,不会再做任何域名解析。对于 github.com 这种返回多个 IP 的情况,nginx 在转发时会自动对 IP 列表进行轮转。

配置动态域名解析

resolver 8.8.8.8;
server {
    
    

 location / {
    
    

 set $servers github.com;

 proxy_pass http://$servers;

 }

}

如上,通过使用变量($servers)的方式可以强制 nginx 遵守域名解析结果的 TTL,过期后自动重新解析。不过这种写法有个副作用,如此配置后 nginx 不会自动使用系统 /etc/resolve.conf 的配置,此时必须使用 resolver 指令手动给它指定一个 DNS 服务器。

其中 8.8.8.8是谷歌的开源免费DNS,国内的有114.114.114.114.如果是内网域名,需要制定内网的DNS服务器

proxy_pass 后面的url 加与不加/的区别 (和try file那个区分开)

使用http://192.168.1.1/proxy/test.html 进行访问。

1、proxy_pass 后没有 / ,走location的相对路径

location /proxy/ {
    
    

 proxy_pass http://127.0.0.1:81;

}

结论:会被代理到http://127.0.0.1:81/proxy/test.html 这个url

2、proxy_pass后有 / 走绝对路径 :
不会把已匹配部分也就是 location 中匹配的路径部分加入代理 uri

location /proxy/ {
    
    

 proxy_pass http://127.0.0.1:81/;

}

结论:会被代理到http://127.0.0.1:81/test.html 这个url

在nginx中配置proxy_pass时,如果是按照^~匹配路径时,要注意

  • proxy_pass后的url最后的/,当加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;
  • 如果没有/,则会把匹配的路径部分也给代理走。

当一台机器部署了多个web服务,想要根据server名字负载均衡访问的时候

设置setheader host那个选项

获取真实ip

proxy_set_header Host $host; #只要用户在浏览器中访问的域名绑定了 VIP VIP 下面有RS;则就用$host ;host是访问URL中的域名和端口  www.taobao.com:80
proxy_set_header X-Real-IP $remote_addr;  #把源IP 【$remote_addr,建立HTTP连接header里面的信息】赋值给X-Real-IP;这样在代码中 $X-Real-IP来获取 源IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;#在nginx 作为代理服务器时,设置的IP列表,会把经过的机器ip,代理机器ip都记录下来,用 【,】隔开;代码中用 echo $x-forwarded-for |awk -F, '{print $1}' 来作为源IP

五、负载均衡详解

三种负载均衡的算法

在这里插入图片描述

如何配置-upstream

upstream mysvr {
    
     
    server 192.168.10.121:3333;
    server 192.168.10.122:3333;
}
server {
    
    
    ....
    location  ~*^.+$ {
    
             
        proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表         
    }
}

注意到上面似乎只能ip,无法域名 域名的后面详解

负载均衡的几种算法的写法

1 轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某个服务器宕机,能自动剔除故障系统。

upstream backserver {
    
     
 server 192.168.0.12; 
 server 192.168.0.13; 
} 

2 权重(加权轮询) weight

weight的值越大分配
到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。其次是为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源。

upstream backserver {
    
     
 server 192.168.0.12 weight=2; 
 server 192.168.0.13 weight=8; 
} 

权重越高,在被访问的概率越大,如上例,分别是20%,80%。

3 ip_hash( IP绑定)

每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题

upstream backserver {
    
     
 ip_hash; 
 server 192.168.0.12:88; 
 server 192.168.0.13:80; 
 #ip_hash;#也可写在最后一行
} 

4 热备

如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA突然A挂啦,BBBBBBBBBBBBBB…

upstream mysvr {
    
     
    server 127.0.0.1:7878; 
    server 192.168.10.121:3333 backup;  #热备     
}

5 fair(第三方插件)

必须安装upstream_fair模块。
对比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,响应时间短的优先分配。

upstream backserver {
    
     
 server server1; 
 server server2; 
 fair; 
} 

哪个服务器的响应速度快,就将请求分配到那个服务器上。

6 url_hash(第三方插件)

必须安装Nginx的hash软件包
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。

upstream backserver {
    
     
 server squid1:3128; 
 server squid2:3128; 
 hash $request_uri; 
 hash_method crc32; 
}

7 更多配置参数

到这里你是不是感觉nginx的负载均衡配置特别简单与强大,那么还没完,咱们继续哈,这里扯下蛋。

关于nginx负载均衡配置的几个状态参数讲解。

  • down,表示当前的server暂时不参与负载均衡。
  • backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
  • max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
  • fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。
upstream mysvr {
    
     
    server 127.0.0.1:7878 weight=2 max_fails=2 fail_timeout=2;
    server 192.168.10.121:3333 weight=1 max_fails=2 fail_timeout=1;    
}

提高可用性

如果你的nginx服务器给2台web服务器做代理,负载均衡算法采用轮询,那么当你的一台机器web程序iis关闭,也就是说web不能访问,那么nginx服务器分发请求还是会给这台不能访问的web服务器,如果这里的响应连接时间过长,就会导致客户端的页面一直在等待响应,对用户来说体验就打打折扣,这里我们怎么避免这样的情况发生呢。这里我配张图来说明下问题。

在这里插入图片描述

如果负载均衡中其中web2发生这样的情况,nginx首先会去web1请求,但是nginx在配置不当的情况下会继续分发请求道web2,然后等待web2响应,直到我们的响应时间超时,才会把请求重新分发给web1,这里的响应时间如果过长,用户等待的时间就会越长。

下面的配置是解决方案之一。

proxy_connect_timeout 1; #nginx服务器与被代理的服务器建立连接的超时时间,默认60秒
proxy_read_timeout 1; #nginx服务器想被代理服务器组发出read请求后,等待响应的超时间,默认为60秒。
proxy_send_timeout 1; #nginx服务器想被代理服务器组发出write请求后,等待响应的超时间,默认为60秒。
proxy_ignore_client_abort on; #客户端断网时,nginx服务器是否终端对被代理服务器的请求。默认为off。
5、如果使用upstream指令配置啦一组服务器作为被代理服务器,服务器中的访问算法遵循配置的负载均衡规则,同时可以使用该指令配置在发生哪些异常情况时,将请求顺次交由下一组服务器处理。

proxy_next_upstream timeout; #反向代理upstream中设置的服务器组,出现故障时,被代理服务器返回的状态值。
状态值可以是:error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off

error:建立连接或向被代理的服务器发送请求或读取响应信息时服务器发生错误。
timeout:建立连接,想被代理服务器发送请求或读取响应信息时服务器发生超时。
invalid_header:被代理服务器返回的响应头异常。
off:无法将请求分发给被代理的服务器。
http_400,…:被代理服务器返回的状态码为400,500,502,等。

拓展-------LVS、四层代理和七层转发

更多可参考https://baijiahao.baidu.com/s?id=1672520162384771451&wfr=spider&for=pc

lvs是什么

LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一。在linux内存2.6中,它已经成为内核的一部分,在此之前的内核版本则需要重新编译内核。
LVS主要用于多服务器的负载均衡。它工作在传输层,可以实现高性能,高可用的服务器集群技术。
它廉价,可把许多低性能的服务器组合在一起形成一个超级服务器。
它易用,配置非常简单,且有多种负载均衡的方法。它稳定可靠,即使在集群的服务器中某台服务器无法正常工作,也不影响整体效果。
另外可扩展性也非常好。

因为lvs工作在传输层,所以相对于其他的负载均衡的解决办法(DNS域名轮流解析、应用层负载的调度、客户端的调度等,它的效率是非常高的)

LVS的通过控制IP来实现负载均衡。IPVS是其具体的实现模块。
在这里插入图片描述

lvs和nginx负载均衡的区别

那为什么还需要用 LVS 呢?

随着 Internet 的爆炸性增长以及日常生活中的日益重要的作用,Internet 上的流量速度增长,以每年 100% 以上的速度增长。服务器上的工作负载压力也迅速增加,因此服务器在短时间内将会过载,尤其是对于受欢迎的网站而言。

LVS 与 Nginx 功能对比

LVS 比 Nginx 具有更强的抗负载能力,性能高,对内存和 CPU 资源消耗较低;
LVS 工作在网络层,具体流量由操作系统内核进行处理,Nginx 工作在应用层,可针对 HTTP 应用实施一些分流策略;
LVS 安装配置较复杂,网络依赖性大,稳定性高。Nginx 安装配置较简单,网络依赖性小;
LVS 不支持正则匹配处理,无法实现动静分离效果。
LVS 适用的协议范围广。Nginx 仅支持 HTTP、HTTPS、Email 协议,适用范围小;

相关术语

LVS 涉及相关的术语及说明

上述内容中涉及到很多术语或缩写,这里简单解释下具体的含义,便于理解。

DS:Director Server,前端负载均衡节点服务器。
RS:Real Server,后端真实服务器。
CIP:Client IP,客户端 IP 地址。
VIP:Virtual IP,负载均衡对外提供访问的 IP 地址,一般负载均衡 IP 都会通过 Virtual IP 实现高可用。
RIP:RealServer IP,负载均衡后端的真实服务器 IP 地址。
DIP:Director IP,负载均衡与后端服务器通信的 IP 地址。
CMAC: 客户端 MAC 地址,LVS 连接的路由器的 MAC 地址。
VMAC: 负载均衡 LVS 的 VIP 对应的 MAC 地址。
DMAC: 负载均衡 LVS 的 DIP 对应的 MAC 地址。
RMAC: 后端真实服务器的 RIP 地址对应的 MAC 地址。

4层代理和7层代理(nginx也有)

这里的层是OSI 7层网络模型,OSI 模型是从上往下的,越底层越接近硬件,越往上越接近软件,这七层模型分别是物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

4层是指传输层的 tcp / udp 。

7层是指应用层,通常是http 。

代理原理:

4层用的是NAT技术。NAT英文全称是“Network Address Translation”,中文意思是“网络地址转换”,请求进来的时候,nginx修改数据包里面的目标和源IP和端口,然后把数据包发向目标服务器,服务器处理完成后,nginx再做一次修改,返回给请求的客户端。

7层代理:需要读取并解析http请求内容,然后根据具体内容(url,参数,cookie,请求头)然后转发到相应的服务器,转发的过程是:建立和目标机器的连接,然后转发请求,收到响应数据在转发给请求客户端。

优缺点对比:

性能:

理论上4层要比7层快,因为7层代理需要解析数据包的具体内容,需要消耗额外的cpu。但nginx具体强大的网络并发处理能力, 对于一些慢连接,nginx可以先将网络请求数据缓冲完了一次性转发给上游server,这样对于上游网络并发处理能力弱的服务器(比如tomcat),这样对tomcat来说就是慢连接变成快连接(nginx到tomcat基本上都是可靠内网),从而节省网络数据缓冲时间,提供并发性能。

灵活性:

由于4层代理用的是NAT,所以nginx不知道请求的具体内容,所以nginx啥也干不了。 用7层代理,可以根据请求内容(url,参数,cookie,请求头)做很多事情,比如:

a:动态代理:不同的url转发到不同服务器。

b.风控:屏蔽外网IP请求某些敏感url;根据参数屏蔽某些刷单用户。

c.审计:在nginx层记录请求日志。

结论:

由于现在机器cpu性能都很好,4层代理并没有明显的性能优势,而7层代理在业务层面优势明显,所以一般直接选择7层代理就OK了

现在nginx也支持四层负载了……

六 rewrite

注意的是 用的是正则捕获组的写法 必须要用括号的形式
$1 2 3代表第n个捕获组

还有permeant等多种

以后补充 rewrite和代理的区别

七、限流处理

Nginx限流就是限制用户请求速度,防止服务器受不了
限流有3种方式

  • 正常限制访问频率(正常流量)
  • 突发限制访问频率(突发流量)
  • 限制并发连接数
    Nginx的限流都是基于漏桶流算法,底下会说道什么是桶铜流

正常限制访问频率(正常流量)

限制一个用户发送的请求,我Nginx多久接收一个请求。
Nginx中使用ngx_http_limit_req_module模块来限制的访问频率,限制的原理实质是基于漏桶算法原理来实现的。在nginx.conf配置文件中可以使用limit_req_zone命令及limit_req命令限制单个IP的请求处理频率。

#定义限流维度,一个用户一分钟一个请求进来,多余的全部漏掉
	limit_req_zone $binary_remote_addr zone=one:10m rate=1r/m;
 
	#绑定限流维度
	server{
    
    
		location/seckill.html{
    
    
			limit_req zone=zone;	
			proxy_pass http://lj_seckill;
		}
  }

1r/s代表1秒一个请求,1r/m一分钟接收一个请求, 如果Nginx这时还有别人的请求没有处理完,Nginx就会拒绝处理该用户请求。

突发限制访问频率(突发流量):

限制一个用户发送的请求,我Nginx多久接收一个。
上面的配置一定程度可以限制访问频率,但是也存在着一个问题:如果突发流量超出请求被拒绝处理,无法处理活动时候的突发流量,这时候应该如何进一步处理呢?Nginx提供burst参数结合nodelay参数可以解决流量突发的问题,可以设置能处理的超过设置的请求数外能额外处理的请求数。我们可以将之前的例子添加burst参数以及nodelay参数:

#定义限流维度,一个用户一分钟一个请求进来,多余的全部漏掉
	limit_req_zone $binary_remote_addr zone=one:10m rate=1r/m;
 
	#绑定限流维度
	server{
    
    
		location/seckill.html{
    
    
			limit_req zone=zone burst=5 nodelay;
			proxy_pass http://lj_seckill;
		}
	}

为什么就多了一个 burst=5 nodelay; 呢,多了这个可以代表Nginx对于一个用户的请求会立即处理前五个,多余的就慢慢来落,没有其他用户的请求我就处理你的,有其他的请求的话我Nginx就漏掉不接受你的请求

限制并发连接数

Nginx中的ngx_http_limit_conn_module模块提供了限制并发连接数的功能,可以使用limit_conn_zone指令以及limit_conn执行进行配置。接下来我们可以通过一个简单的例子来看下:

http {
    
    
		limit_conn_zone $binary_remote_addr zone=myip:10m;
		limit_conn_zone $server_name zone=myServerName:10m;
	}
    server {
    
    
        location / {
    
    
            limit_conn myip 10;
            limit_conn myServerName 100;
            rewrite / http://www.lijie.net permanent;
        }
    }

上面配置了单个IP同时并发连接数最多只能10个连接,并且设置了整个虚拟服务器同时最大并发数最多只能100个链接。当然,只有当请求的header被服务器处理后,虚拟服务器的连接数才会计数。刚才有提到过Nginx是基于漏桶算法原理实现的,实际上限流一般都是基于漏桶算法和令牌桶算法实现的。接下来我们来看看两个算法的介绍:

如何实现,漏桶算法和令牌桶算法

漏桶算法

漏桶算法是网络世界中流量整形或速率限制时经常使用的一种算法,它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,通过它,突发流量可以被整形以便为网络提供一个稳定的流量。也就是我们刚才所讲的情况。漏桶算法提供的机制实际上就是刚才的案例:突发流量会进入到一个漏桶,漏桶会按照我们定义的速率依次处理请求,如果水流过大也就是突发流量过大就会直接溢出,则多余的请求会被拒绝。所以漏桶算法能控制数据的传输速率。
在这里插入图片描述

令牌桶算法

令牌桶算法是网络流量整形和速率限制中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。Google开源项目Guava中的RateLimiter使用的就是令牌桶控制算法。令牌桶算法的机制如下:存在一个大小固定的令牌桶,会以恒定的速率源源不断产生令牌。如果令牌消耗速率小于生产令牌的速度,令牌就会一直产生直至装满整个令牌桶。
在这里插入图片描述

动静分离处理

Nginx怎么做的动静分离?
只需要指定路径对应的目录。location/可以使用正则表达式匹配。并指定对应的硬盘中的目录。如下:(操作都是在Linux上)

location /image/ {
    
    
            root   /usr/local/static/;
            autoindex on;
        }
1,创建目录
mkdir /usr/local/static/image

2.进入目录
cd /usr/local/static/image

3.放一张照片上去#
1.jpg

4.重启 nginx
sudo nginx -s reload

5.打开浏览器 输入 server_name/image/1.jpg 就可以访问该静态图片了

————————————————
版权声明:本文为CSDN博主「小 源」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_51414096/article/details/125293932

其他

惊群现象:一个网路连接到来,多个睡眠的进程被同时叫醒,但只有一个进程能获得链接,这样会影响系统性能。
17.Nginx配置高可用性怎么配置?
当上游服务器(真实访问服务器),一旦出现故障或者是没有及时相应的话,应该直接轮训到下一台服务器,保证服务器的高可用
Nginx配置代码:

server {
    
    
        listen       80;
        server_name  www.lijie.com;
        location / {
    
    
		    ### 指定上游服务器负载均衡服务器
		    proxy_pass http://backServer;
			###nginx与上游服务器(真实访问的服务器)超时时间 后端服务器连接的超时时间_发起握手等候响应超时时间
			proxy_connect_timeout 1s;
			###nginx发送给上游服务器(真实访问的服务器)超时时间
            proxy_send_timeout 1s;
			### nginx接受上游服务器(真实访问的服务器)超时时间
            proxy_read_timeout 1s;
            index  index.html index.htm;
        }
 }

18.Nginx怎么判断别IP不可访问?

 # 如果访问的ip地址为192.168.9.115,则返回403
     if  ($remote_addr = 192.168.9.115) {
    
      
         return 403;  
     }  

19.怎么限制浏览器访问?

## 不允许谷歌浏览器访问 如果是谷歌浏览器返回500
 	if ($http_user_agent ~ Chrome) {
    
       
        return 500;  

————————————————
版权声明:本文为CSDN博主「小 源」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_51414096/article/details/125293932

rewrite全局变量

参考

【nginx】教程,超级详细,简单易懂 https://blog.csdn.net/weixin_51414096/article/details/125293932

2 https://www.weixueyuan.net/nginx/compile/ 这个也不错

猜你喜欢

转载自blog.csdn.net/S_ZaiJiangHu/article/details/126838279
今日推荐