概念
什么是Nginx?
Nginx
(发音同“engine X”
)是异步框架的网页服务器,也可以用作反向代理、负载平衡器和HTTP
缓存。该软件由伊戈尔·赛索耶夫创建并于2004
年首次公开发布。2011
年成立同名公司以提供支持。2019
年3
月11
日,Nginx
公司被F5 Networks
以6.7亿美元收购。
Nginx
是免费的开源软件,根据类BSD
许可证的条款发布。一大部分Web
服务器使用Nginx
,通常作为负载均衡器。 --维基百科
Nginx
是一个高性能的 HTTP
和反向代理服务器,特点是占用内存少,并发能力强,事实上 Nginx
的并发能力确实在同类型的网页服务器中表现较好。
Nginx
专为性能优化而开发,性能是其最重要的要求,十分注重效率,有报告 Nginx
能支持高达 50000
个并发连接数。
前端为什么要理解 nginx
的一些常用概念?
学习Nginx
能让你更加了解整个互联网产品的运作流程,反向代理负载均衡这些东西看起来距离前端很远,其实前端的每一个页面都和他们息息相关。
最主要的Nginx
是一种很好的解决问题的工具。
有了更多的储备知识,能更好的定位问题。
什么是代理?
代理是在服务器和客户端之间假设的一层服务器,代理将接收客户端的请求并将它转发给服务器,然后将服务端的响应转发给客户端。
正向代理与反向代理
正向代理:
正向代理(Forward Proxy)
,意思是一个位于客户端和原始服务器(origin server)
之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
正向代理是为我们服务的,即为客户端服务的,客户端可以根据正向代理访问到它本身无法访问到的服务器资源。比如:在天朝翻墙访问 “油管”,就是典型的正向代理。
下面这张图能比较清楚的表示其区别:
负载均衡
负载均衡是用来解决大流量问题,也就是承载请求的数量,因为每台服务器可承受的访问量是有限的,随着公司的发展访问量会越来越大,这个时候我们会选择通过增加服务器的方式来平衡每台服务器所受的压力。
每一次web请求进来,nginx
都可以选择一台压力较少的服务器,然后将请求发送给这台服务进行处理。这就是负载均衡。
负载均衡就是用来帮助我们将众多的客户端请求合理的分配到各个服务器,以达到服务端资源的充分利用和更少的请求时间。
在服务领域一旦很多应用服务构成集群,一定会带来两个需求:
第一个需求我们需要动态的扩容,也就是服务器不够用的时候增加服务器,在增加服务器的过程是不可能关闭网站,他一定要是一个用户无感知的过程。
第二个则是有些服务出问题的时候我们需要做容灾,假设我们的服务器集群中一台服务器出现了问题,是不应该影响用户正常访问的,nginx
会把请求发送给其它正常的服务器保证线上用户的正常使用。
而这两个需求 Nginx
可以进行简单的配置就可以实现。
内置策略包括:轮询、加权轮询、Ip hash
(根据访问ip
的hash
结果分配,这样每个访客固定访问一个应用服务器,可以解决session
共享的问题)等。
一些常见的负载均衡模式:
1、轮询策略(默认)
2、加权轮询策略
2、最小连接数策略
3、最快响应时间策略
负载均衡示意图:
例如图中,所有的客户端一共发起了1500
个请求, Nginx
代理服务器分别分发给了三台服务器各 500
个请求。 负载均衡就是用来帮助我们将众多的客户端请求合理的分配到各个服务器,以达到服务端资源的充分利用和更少的请求时间。
动静分离
为了加快网站的解析速度,可以把动态页面和静态页面或者资源(比如图片等)由不同的服务器来解析,加快解析速度,降低原来单个服务器的压力。
gzip压缩
nginx
还提供 gzip
压缩,做完gzip
压缩以后,传输的字节数会大幅度减少。
https
域名证书
证书一般包含两个文件证书名字.key
和证书名字.pem
,将下载好的证书放在/usr/local/nginx/conf/certs
文件夹下,certs
文件夹需要手动创建。
然后编辑conf/nginx.conf
文件,和http
不同https
使用的是443
端口,默认情况下nginx.conf
是关闭了这个端口的。listen
中开启的是443端口。
安装
brew install nginx
Nginx文件位置
/usr/local/etc/nginx
nginx
常用命令
nginx -v
版本号
nginx -s stop
关闭nginx
nginx
启动nginx
nginx -s reload
重新加载配置文件conf
基本配置
配置结构
nginx配置文件的基本结构:
events {
}
http
{
server
{
location path
{
...
}
location path
{
...
}
}
server
{
...
}
}
配置文件组成
1、全局块
全局块是默认配置文件从开始到events
块之间的一部分内容,主要设置一些影响Nginx
服务器整体运行的配置指令,因此,这些指令的作用域是Nginx
服务器全局。
通常包括配置运行Nginx
服务器的用户(组)、允许生成的worker process
数、Nginx
进程PID
存放路径、日志的存放路径和类型以及配置文件引入等。
# 指定可以运行nginx服务的用户和用户组,只能在全局块配置。这个用户和用户组是指 Nginx 用户和用户组,可以动态添加。
# user [user] [group]
# 将user指令注释掉,或者配置成nobody的话所有用户都可以运行
# user nobody nobody;
# user指令在Windows上不生效,如果你制定具体用户和用户组会报小面警告
# nginx: [warn] "user" is not supported, ignored in D:\software\nginx-1.18.0/conf/nginx.conf:2
# 指定工作线程数,可以制定具体的进程数,也可使用自动模式,这个指令只能在全局块配置。
# worker_processes number | auto;
# 例子:指定4个工作线程,这种情况下会生成一个master进程和4个worker进程。这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量越多,但是受到硬件、软件等设备的制约。
# worker_processes 4;
# 指定pid文件存放的路径,这个指令只能在全局块配置
# process id:nginx会启动多个进程,而发信号的时候需要知道要向哪个进程发信号。不同的进程有不同的pid(process id)
# pid logs/nginx.pid;
# 指定错误日志的路径和日志级别,此指令可以在全局块、http块、server块以及location块中配置。
# error_log [path] [debug | info | notice | warn | error | crit | alert | emerg]
# error_log logs/error.log notice;
# error_log logs/error.log info;
2、events
块
events
块涉及的指令主要影响Nginx
服务器与用户的网络连接。常用到的设置包括是否开启对多worker process
下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型处理连接请求,每个worker process
可以同时支持的最大连接数等。
这一部分的指令对Nginx
服务器的性能影响较大,在实际配置中应该根据实际情况灵活调整。
# 当某一时刻只有一个网络连接到来时,多个睡眠进程会被同时叫醒,但只有一个进程可获得连接。如果每次唤醒的进程数目太多,会影响一部分系统性能。在`Nginx`服务器的多进程下,就有可能出现这样的问题。
# 开启的时候,将会对多个`Nginx`进程接收连接进行序列化,防止多个进程对连接的争抢
# 默认是开启状态,只能在`events`块中进行配置
# accept_mutex on | off;
# 如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接。
# 如果nginx使用kqueue连接方法,那么这条指令会被忽略,因为这个方法会报告在等待被接受的新连接的数量。
# 默认是off状态,只能在event块配置
# multi_accept on | off;
# 指定使用哪种网络IO模型,method可选择的内容有:select、poll、kqueue、epoll、rtsig、/dev/poll以及eventport,一般操作系统不是支持上面所有模型的。
# 只能在events块中进行配置
# use method
# use epoll
# 设置允许每一个worker process同时开启的最大连接数,当每个工作进程接受的连接数超过这个值时将不再接收连接
# 当所有的工作进程都接收满时,连接进入logback,logback满后连接被拒绝
# 只能在events块中进行配置
# 注意:这个值不能超过超过系统支持打开的最大文件数,也不能超过单个进程支持打开的最大文件数
# worker_connections 1024;
3、http
块
http
块是Nginx
服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这个模块中。
1)、http
全局块 --- 可以嵌套多个server
,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。
2)、server
块 --- 配置虚拟主机的相关参数,一个http
中可以有多个server
。
a、全局server
块
b、location
块 --- 配置请求的路由,以及各种页面的处理情况。
3)、upstream
:配置后端服务器具体地址,负载均衡配置不可或缺的部分。
nginx location
匹配规则
语法 | 匹配规则 |
---|---|
= | 用于标准uri前,要求请求字符串与uri严格匹配。如果已经匹配成功,就停止继续向下搜索并立即处理此请求 |
^~ | 用于标准uri前,要求Nginx服务器找到标识uri和请求字符串匹配度最高的location后,立即使用此location处理请求,而不再使用location块中的正则uri和请求字符串做匹配 |
~ | ~ 开头表示区分大小写的正则匹配 |
~* | ~* 开头表示不区分大小写的正则匹配 |
!和!* | !和!*分别为区分大小写不匹配及不区分大小写不匹配的正则 |
/ | 通用匹配,任何请求都会被匹配到 |
优先匹配 = 精确匹配,若未匹配到则转下一步;
依照最大前缀匹配规则,先匹配普通规则(空,~),若匹配到~则使用;若匹配到空或者未匹配到,则转下一步;
按照物理存储顺序,匹配到任意一条正则,则马上使用;
示例一:
location /a/b/ {
return 666;
}
# 优先匹配 =
location =/a/b/ {
return 888;
}
示例二:
# 匹配规则示例,最大前缀匹配
location /a/b/ {
return 666;
}
location /a/b/c {
return 777;
}
示例三:
# 正则location匹配顺序,按照文件的物理顺序匹配,匹配到一条之后就直接使用,停止之后的匹配
location ~* /a {
return 999;
}
location ~* /[a-z] {
return 888;
}
额外知识:除了返回状态码,还可以返回别的,比如json:
location /a/b/ {
return 200 '{"name":"liuzhixiang05","id":"100"}';
}
实例
实例一:跨域解决及反向代理
跨域的定义
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。通常不允许不同源间的读操作。
同源的定义
如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
nginx解决跨域的原理
比如:
前端的域名为:fe.server.com
后端服务的域名为:dev.server.com
在fe.server.com
对dev.server.com
发起请求一定会出现跨域。
只需要启动一个nginx
服务器,将 server_name
设置为 fe.server.com
,然后设置相应的location
以拦截前端需要跨域的请求,最后将请求代理回 dev.server.com
。如下面的配置:
server {
listen 80;
server_name fe.server.com;
location / {
proxy_pass dev.server.com;
}
}
新建一个前端项目,使用
Nginx
当做静态资源服务器,见配置
location / {
root /Users/mtdp/Documents/project/nginx-test/fe/;
index index.html;
}
这个时候访问 localhost:3029
就会访问到新建的html
文件。
此时启动server
,一个简单的node
服务,里面有一个接口,端口为3030
:
而此时直接在localhost:3029
请求这个3030
端口的接口,肯定会跨域。
然后就可以在nginx中配置:
location ^~ /api/ {
proxy_pass http://localhost:3030/api/;
}
这样配置好之后,当请求路径是以 /api/ 开头的,都会被 nginx 代理到 localhost:3030/api/ ,这样前端访问的是 localhost:3029/api/user,从而不会跨域。
实例二:类正向代理
开启两个服务,nginx 配置不同的路由匹配规则,nginx代理到不同的服务。
第一个服务:端口为3031;
第二个服务:端口为3032;
页面新增入口:
分别点击之后,会打到不同的服务上面。
这样就实现了不同路由请求了不同服务的配置。这个其实是
Nginx
代替真实客户端请求另一个域名,所以是类似正向代理的作用。
实例三:负载均衡
配置 upstream:
http {
upstream myservice {
server localhost:3031;
server localhost:3032;
}
server {
listen 3029;
server_name localhost;
location / {
proxy_pass http://myservice;
}
}
}
直接访问 http://localhost:3029 会发现会打到不同的服务。
1、轮询策略(默认)
# nginx.config
upstream myservice {
server localhost:3031;
server localhost:3032;
server localhost:3033;
}
客户端的请求会轮询发放到这三个服务器,总体上每个服务器处理的请求数量会保持一致一致。
2、加权轮询策略
# nginx.config
upstream myservice {
server localhost:3031 weight=2;
server localhost:3032;
server localhost:3033;
}
客户端的请求会按照权重轮询发放到这三个服务器,第一个服务器处理的请求是总数 1/2,第二个是 1/4,第三个也是1/4。
3、最小连接数策略
upstream balanceServer {
least_conn; #最小连接数
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
4、最快响应时间策略
upstream balanceServer {
fair; # 最快响应时间,依赖三方插件
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
优先分配给响应时间最短的服务器。
总结
1、本次分享介绍了 nginx
常见基本概念,例如反向代理,负载均衡等。
2、演示了几个实例,旨在更好的理解 nginx
的常见配置和基本概念。
3、nginx
的功能非常强大,还有很多需要探索。有兴趣的同学可以进行更加深入的研究。