一. Nginx介绍 {#content_views}
1. Nginx到底是什么,干什么用?
Nginx是一个 轻量级/高性能的反向代理Web服务器,它是由C语言写的,所以速度非常快、性能非常优秀。它的主要功能就是反向代理、负载均衡、配置SSL证书、防盗链、解决跨域问题、缓存、限流、动静资源分离等等。
上面介绍了Nginx是一台Web服务器,实际上,他并不是一台真正意义上的物理机服务器,并不是主观上真实存在的实体,它是运行在某一台服务器(电脑)上的软件。
那为什么还说它是一台Web服务器呢?我们先来理解一下什么是网关,大家都知道,从一个房间进入另一个房间内,必须经过一个门,就像经过一个"关口",那从一个网络发送一个信息到另一个网络,也必须经过一个"关口",这个关口就可以说是网关。这个关口并不是摆在那里那么简单,关口可以自行决定允不允许让你的消息通过,或者决定是否替你转发和接收消息、把消息分发给其他人,或者帮你的消息添加和预处理一些信息,或者替你回答消息等等功能。
而Nginx就相当于这个网关,转发和接收消息就相当于反向代理,把消息分发给其他人就相当于负载均衡。当我们的服务器(电脑)上安装了Nginx这个软件,通过一些简单的配置并运行这个软件,我们在服务器上运行的项目(例如Java程序)在接收Http请求的时候,这个请求就会被Nginx这个网关先拦截,经过一些上述的处理之后再交给Java程序,此时Nginx就充当了一个网关。因为外网用户的所有请求都会先经过Nginx,所以对于外网的用户来说,他们的请求都是发送给Nginx的,再由Nginx发送给Java程序处理后再发还给用户,那么从用户的角度来看,Nginx就相当于一台服务器在接收和回复用户发送的消息,所以也可以理解为Nginx是一台Web服务器。
2. 为什么要用Nginx?
Nginx跨平台,配置简单。我们可以在Linux系统和windows系统上都开启Nginx服务,配置也非常简单,在linux上,我们通常只需要修改三四行代码,既可以完成对项目的配置。当后端程序重构或者重新部署,例如由Java项目换成go项目,也不需要修改Nginx。
Nginx是由C语言写的,速度非常快,性能优越。目前公认的性能最高的后端语言就是C和C++,而Nginx就是由C写和编译的,其单机并发量非常高,可以达到5w+,而一般的后端Java程序并没有这么高的并发量,所以一般都会选择Nginx当网关放在Java程序之前,提高系统的整体性能。
动静资源分离。一般的前后端分离项目,用户想获取前端静态资源文件,都得先经过后端Java程序的接口再获取服务器上的静态资源文件,这样的效率并不是特别高,而且会占用正常程序接口的连接数量,这时候Nginx的动静资源分离功能就提供了很好的解决方法,一般静态资源文件都放在Nginx服务器中,当Nginx接收到了获取静态资源文件的请求,就直接在Nginx服务器中把放进去的静态资源返回了,而不用真正到达后端接口,这个效率是非常高的,比正常的访问速度会快一倍左右。
在并发量较大的项目中,后端往往会开启多个相同的Java服务,来缓解单服务的压力,我们知道,每一个Java服务程序都会占用一个端口,那前端在后端接口的时候,怎么知道该选用哪个接口呢?这时就可以在所有的Java程序前放置一个Nginx程序,所有的请求都经过Nginx,由Nginx决定分发到哪个端口程序上,这样,虽然后端有很多个Java程序,但对于前端来说,是无感知的,就好像后台只有一个项目在跑一样。
那这么多后端程序在跑,万一有一个程序挂了前端不知道怎么办?放心,Nginx还有一个Keepalive保活机制,Nginx会不断监听后端程序的接口,看该服务是不是在正常运行,万一有一个程序挂了,那么Nginx就不会把前端发来的请求转发给这个接口,确保后端服务的高可用性和稳定性。
二. 具体常见应用
1. 反向代理
(1). 正向代理
说到反向代理,我们常常会想到正向代理,那么两者有何区别呢?
正常情况下,我们访问一个网页、服务器,只需要在浏览器中输入相应的域名或ip地址和端口号,经过DNS解析后,就可以访问到服务器上的资源,这是最普通也是最直接的连接方式,也就是用户端和服务端的直接连接,我们可以直接访问服务器,但是这样有一个问题,我们用户端的ip地址就泄露给了对方,如果我们不想让服务端知道我们的ip地址呢?
这时候就需要正向代理了,不同于反向代理,正向代理的网关是用户端自己配置和搭建的,用户端和网关是一伙的,这样用户端每次要访问服务端的时候,就把请求发到自己配置的网关上,然后由网关转发用户的请求给服务端,服务端返回响应后就再发还给用户。对于服务器来说,具体用户是谁是无感知的,因为请求都来源于网关代理的转发,这样服务端就不知道真正发请求的用户到底是谁。
(2). 反向代理
拿nginx实现的反向代理来说,不同于正向代理,反向代理的网关和服务器是一伙的,用户端无法通过公网直接访问到后台服务器上的Java应用程序,但是可以直接访问nginx网关,再由nginx分发到不同的服务器(或者说应用程序)上,真正提供服务的服务器对于用户来说是无感知的,所有的请求都必须先发送到nginx网关上,再进行请求转发,用户端并不知道真正提供服务的服务器是谁,也不知道它的具体ip地址和端口,所以称之为反向代理。
拿nginx的常见配置来讲,server_name实际上就是本机的ip,listen就是监听这个ip下的某个端口。而location则可以理解要拦截哪个url进行处理,"/"表示拦截所有。proxy_pass则表示把这个拦截的url要转发到哪个服务器上,所以填的是ip+端口。这样就可以做到反向代理,把某个ip+端口+路径的请求给拦截下来,转发到另一个ip+端口+路径的资源上。
2. 负载均衡
通常后端项目并只会开启一个Java应用程序,一般都会开启多个,这时候就需要nginx来选择将所有的请求分发给不同的程序应用,这个过程就是负载均衡。
那我们怎么知道要按哪些规则去分发这些请求呢?nginx中已经提供了几种常见的负载均衡算法,例如默认的轮询算法,按顺序、平均地把每一条请求分发出去。
upstream backserver {
server 192.168.1.1;
server 192.168.1.2;
}
或者按权重分配,权重值高的分配请求也越多。
upstream backserver {
server 192.168.1.13 weight=2;
server 192.168.1.14 weight=8;
}
或者按用户端的ip进行hash运算分配。
upstream backserver {
ip_hash;
server 192.168.0.11:88;
server 192.168.0.13:80;
}
3. 解决跨域问题
location / {
#允许跨域请求的域,* 代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET,POST,PUT,DELETE
add_header 'Access-Control-Allow-Methods' *;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://192.168.1.12:8080;
}
只要在nginx配置中添加相关配置,nginx就会在分发每个请求前,再请求中加上跨域相关配置的请求头,再分发给后端应用,对于前端来说,可以实现无感知的跨域。
4. 限流
漏桶算法
用户端的大量请求(突发流量)会进入nginx内维护的漏桶中,漏桶会按照我们定义的固定的速率给服务器分发请求,正常的请求在服务器处理完后会正常返回给用户端。如果水流过大(突发流量过大)时,漏桶内的水会溢出,这时nginx就把这些溢出的水(流量)直接丢弃,也就是给用户端返回错误信息。
令牌桶算法
用户端发请求给nginx时,每个请求都要去nginx的令牌桶中取一个令牌,令牌桶的容量是我们自己设定的,如果某个请求成功取到了令牌,那么nginx就会把这个请求转发到服务器上进行处理。如果令牌桶已空,请求在nginx令牌桶中取不到令牌,那么nginx会直接返回该请求,也就是给用户端返回错误信息。
三. 常见问题
1. 为什么访问后端服务时,有时候要用ip+端口或者域名+端口,而有时候则可以直接用ip或者域名就可以访问?
HTTP协议默认使用的端口是80,HTTPS协议默认使用的端口是443,这是因为在早期互联网的设计中,为了方便,HTTP和HTTPS协议的默认端口就是这两个端口。一般来说,在浏览器访问网站时,如果没有指定端口号,浏览器会默认使用HTTP协议的80端口或HTTPS协议的443端口进行连接。因此,在设置域名默认端口时,应该考虑使用这两个默认端口之一,以便用户可以直接通过域名访问网站,而不需要手动输入端口号。
但是我们一个服务器上,可能有很多个域名都绑定了这个服务器的ip,每个域名都是一个独立的网站,而且服务器上可能有很多个后端应用服务,而端口(80)只有一个,那这么多网站和服务怎么公用一个端口呢?没错,还是靠nginx,我们只需要配置多个server即可,多个server都监听80端口,再根据域名的不同将请求转发到不同的端口即可 监听www.aa.com域名的80端口,并转发到8080端口
监听www.bb.com域名的80端口,并转发到8081端口
2. 服务器代理和vpn代理有什么不同?
(1). vpn是怎么实现在家也能连到公司内网的?
nginx的代理往往只是代理转发请求,只需要服务端架设nginx开启反向代理或者客户端开启正向代理。而vpn代理则是通过隧道技术在公共网络上模拟出一条点到点的逻辑专线,从而达到安全数据传输的目的,最常见的用处就是人不在公司,通过vpn设备访问公司内网。
当我们不使用vpn时,我们直接访问公司内网,带上的是公网ip,公司内的设备都是内网ip,公司内网没有接入公网,肯定访问不到公司内网,而且人家也不认识你的公网ip,这时候要访问公司内网,有两种方法,一种是从你家专门接一条网线到公司的服务器,听着确实可以,但是实际上确很不现实。第二种方法就是vpn技术,在公网上建立一条专门的隧道,直接连接你的设备和公司内网设备。架设vpn装线,往往需要用户端和服务端都部署和配置装门的vpn设备,也就是上图的vpn网关,例如路由器式vpn、交换机式vpn。
(2). vpn设计与实现
vpn最主要的技术就是隧道技术,隧道技术用通俗的话来讲就是用另一种协议去封装我们使用的协议,隧道协议分为第二、第三层隧道协议,第二层隧道协议(如L2TP、PPTP、L2F等)工作在OSI体系结构的第二层(即数据链路层);第三层隧道协议(如IPSec、GRE等)工作在OSl体系结构的第三层(即网络层),这两个协议会在我们网络层封装完IP头后,再封装IPSec或者GRE头,并进行信息加密,这也是代理服务器不会做的。然后再交由网络接口层添加mac头再丢到公网中,这样公网就认得你的ip并且能找到你公司内网前架设的vpn网关。
vpn设备还会使用常用加解密技术,例如对称密钥加密和非对称密钥加密组合使用,例如用https的TLS加密技术。
密钥管理技术和身份认证及访问控制技术的支持。
(3). 代理服务器和vpn有什么不一样?
-
匿名性不同。虽然它们都位于请求的中间,都隐藏了 IP 地址,并且都将信息转发。
主要区别在于 VPN 需要隧道过程,该过程建立了到 VPN 服务器的直接且不可穿透的连接。代理只是一个开放的端口,是任何人都可以连接到的单个 IP 地址。 -
安全性不同。vpn会加密我们的数据信息,代理服务器不会,因此vpn更加私有,连接不会被穿透,是一个开在公网上的封闭系统。
-
运行级别不同。vpn是运行在操作系统上,由操作系统内核封装,重定向请求流量。代理服务器是软件级别,处于用户态。
-
速度不同。vpn涉及加密解密,数据封装,速度较慢,但因其安全性,价格成本会更高。
四. 结语
✨感谢您的耐心阅读!!!!
✨看完了不妨点赞收藏吧~
✨您的支持是博主创作的最大动力!!!!
✨感谢耐心阅读!!❤️