Nginx 是一款轻量级的 Web 服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。
实际上,他并不是一台真正意义上的物理机服务器,并不是主观上真实存在的实体,它是运行在某一台服务器(电脑)上的软件。
那为什么还说它是一台Web服务器呢?我们先来理解一下什么是网关,大家都知道,从一个房间进入另一个房间内,必须经过一个门,就像经过一个“关口”,那从一个网络发送一个信息到另一个网络,也必须经过一个“关口”,这个关口就可以说是网关。这个关口并不是摆在那里那么简单,关口可以自行决定允不允许让你的消息通过,或者决定是否替你转发和接收消息、把消息分发给其他人,或者帮你的消息添加和预处理一些信息,或者替你回答消息等等功能。
而Nginx就相当于这个网关,转发和接收消息就相当于反向代理,把消息分发给其他人就相当于负载均衡。当我们的服务器(电脑)上安装了Nginx这个软件,通过一些简单的配置并运行这个软件,我们在服务器上运行的项目(例如Java程序)在接收Http请求的时候,这个请求就会被Nginx这个网关先拦截,经过一些上述的处理之后再交给Java程序,此时Nginx就充当了一个网关。因为外网用户的所有请求都会先经过Nginx,所以对于外网的用户来说,他们的请求都是发送给Nginx的,再由Nginx发送给Java程序处理后再发还给用户,那么从用户的角度来看,Nginx就相当于一台服务器在接收和回复用户发送的消息,所以也可以理解为Nginx是一台Web服务器。
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就不会把前端发来的请求转发给这个接口,确保后端服务的高可用性和稳定性。
进入下载地址,选择Stable version(稳定版)下的 window版本,这次选择的是nginx/Windows-1.24.0,下载后进行解压,主要目录如下
Nginx的配置文件是在conf目录下的nginx.conf文件。
http {
# ...
server {
listen 80;
server_name localhost;
# ...
}
# ...
}
可以看到Nginx默认配置的端口号是 80。如果Nginx的80端口号被占用,我们就需要去修改。我们可以直接在 nginx.conf 配置文件里面修改端口号。或者杀死占用80端口的进程,这里不再详细讲解。
http {
# ...
server {
listen 81;
server_name localhost;
# ...
}
# ...
}
双击nginx目录下的nginx.exe应用程序,一般情况下,会有一个黑色的弹窗一闪而过,这就代表启动成功了。
推荐命令行启动。在nginx安装目录执行命令。直接输入 nginx
或者 start nginx
,然后回车,就可以启动nginx了。
然后在浏览器地址栏输入 localhost:81,然后再回车。不过不推荐。
关闭nginx的命令:nginx -s stop
所谓热部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中断请求,就能让配置文件生效!
nginx -s reload
windows下面就是
nginx.exe -s reload
注释行以#
作为开头;
配置指令是一个字符串,可以用单引号或者双引号括起来,也可以不括。但是如果配置指令包含特殊字符,例如:空格符、分号(、花括号({}),就需要使用引号将其括起;
root '/home/example.com/my web pages'
注意:无论使用单引号、双引号,nginx都认为没有区别
找到 Nginx 安装目录下的 conf 目录下 nginx.conf 文件,Nginx 的基本功能配置是由它提供的。
Nginx 的配置文件(conf/nginx.conf)整体上分为如下几个部分:
配置层级图如下所示。
location [ = | ~ | ~* | !~ | !~* | ^~ | @ ] uri {...}
=
表示精确匹配,如果找到,立即停止搜索并立即处理此请求
~
表示执行一个正则匹配,区分大小写匹配
~*
表示执行一个正则匹配,不区分大小写匹配
!~
区分大小写不匹配
!~*
不区分大小写不匹配
^~
即表示只匹配普通字符(空格)。使用前缀匹配,^
表示非,即不查询正则表达式。如果匹配成功,则不再匹配其他 location。
@
指定一个命名的 location,一般只用于内部重定向请求。例如 error_page, try_files
uri
是待匹配的请求字符串,可以不包含正则表达式,也可以包含正则表达式;
不加 < [ ~ | ~* ] < [ ^~ ] < [ = ]
示例如下
location = / {
# 精确匹配/,主机名后面不能带任何字符串 /
# 只匹配http://abc.com
# http://abc.com [匹配成功]
# http://abc.com/index [匹配失败]
}
location ^~ /img/ {
# 以 /img/ 开头的请求,都会匹配上
# http://abc.com/img/a.jpg [成功]
# http://abc.com/img/b.mp4 [成功]
}
location ~* /Example/ {
# 则会忽略 uri 部分的大小写
# http://abc.com/test/Example/ [匹配成功]
# http://abc.com/example/ [匹配成功]
}
location /documents {
# 如果有正则表达式可以匹配,则优先匹配正则表达式。
# http://abc.com/documentsabc [匹配成功]
}
location / {
# http://abc.com/abc [匹配成功]
}
正常情况下,我们访问一个网页、服务器,只需要在浏览器中输入相应的域名或ip地址和端口号,经过DNS解析后,就可以访问到服务器上的资源,这是最普通也是最直接的连接方式,也就是用户端和服务端的直接连接,我们可以直接访问服务器,但是这样有一个问题,我们用户端的ip地址就泄露给了对方,如果我们不想让服务端知道我们的ip地址呢?
这时候就需要正向代理了,不同于反向代理,正向代理的网关是用户端自己配置和搭建的,用户端和网关是一伙的,这样用户端每次要访问服务端的时候,就把请求发到自己配置的网关上,然后由网关转发用户的请求给服务端,服务端返回响应后就再返还给用户。对于服务器来说,具体用户是谁是无感知的,因为请求都来源于网关代理的转发,这样服务端就不知道真正发请求的用户到底是谁。
resolver 114.114.114.114 8.8.8.8;
server {
resolver_timeout 5s;
listen 81;
access_log e:/wwwrootproxy.access.log;
error_log e:/wwwrootproxy.error.log;
location / {
proxy_pass http://$host$request_uri;
}
}
resolver
是配置正向代理的DNS服务器,listen
是正向代理的端口,配置好了就可以在代理插件上面使用服务器ip+端口号进行代理了。
拿nginx实现的反向代理来说,不同于正向代理,反向代理的网关和服务器是一伙的,用户端无法通过公网直接访问到后台服务器上的Java应用程序,但是可以直接访问nginx网关,再由nginx分发到不同的服务器(或者说应用程序)上,真正提供服务的服务器对于用户来说是无感知的,所有的请求都必须先发送到nginx网关上,再进行请求转发,用户端并不知道真正提供服务的服务器是谁,也不知道它的具体ip地址和端口,所以称之为反向代理。
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:8080;
}
}
拿nginx的常见配置来讲,server_name
实际上就是本机的ip或域名,listen
就是监听这个ip或域名下的某个端口。而location
则可以理解要拦截哪个url进行处理,/
表示拦截所有。proxy_pass
则表示把这个拦截的url要转发到哪个服务器上,所以填的是ip+端口。这样就可以做到反向代理,把某个ip+端口+路径的请求给拦截下来,转发到另一个ip+端口+路径的资源上。
但是我们一个服务器上,可能有很多个域名都绑定了这个服务器的ip,每个域名都是一个独立的网站,而且服务器上可能有很多个后端应用服务,而端口(80)只有一个,那这么多网站和服务怎么公用一个端口呢?没错,还是靠nginx,我们只需要配置多个server即可,多个server都监听80端口,再根据域名的不同将请求转发到不同的端口即可。
监听www.aa.com域名的80端口,并转发到8080端口
server {
listen 80;
server_name www.aa.com;
location / {
proxy_pass http://xxx:8080;
}
}
监听www.bb.com域名的80端口,并转发到8081端口
server {
listen 80;
server_name www.bb.com;
location / {
proxy_pass http://xxx:8081;
}
}
当有2台或以上服务器时,根据规则随机的将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。而Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。
每个请求按时间顺序逐一分配到不同的后端服务器,也就是说第一次请求分配到第一台服务器上,第二次请求分配到第二台服务器上,如果只有两台服务器,第三次请求继续分配到第一台上,这样循环轮询下去,也就是服务器接收请求的比例是 1:1, 如果后端服务器 down 掉,能自动剔除。轮询是默认配置,不需要太多的配置。
upstream serverList {
server localhost:8080;
server localhost:8081;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://serverList;
}
}
负载均衡的核心代码为
upstream serverList {
server localhost:8080;
server localhost:8081;
}
这里配置了2台服务器,当然实际上是一台,只是端口不一样而已,而8081的服务器是不存在的,也就是说访问不到,但是我们访问 http://localhost 的时候,也不会有问题,会默认跳转到 http://localhost:8080 具体是因为Nginx会自动判断服务器的状态,如果服务器处于不能访问(服务器挂了),就不会跳转到这台服务器,所以也避免了一台服务器挂了影响使用的情况,由于Nginx默认是RR策略,所以我们不需要其他更多的设置。
指定轮询几率,weight
和访问比率成正比,用于后端服务器性能不均的情况。如果不设置,则默认为 1。 例如
upstream serverList {
server localhost:8080 weight=9;
server localhost:8081 weight=1;
}
那么10次一般只会有1次会访问到8081,而有9次会访问到8080
上面的2种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash
了,iphash
的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
upstream serverList {
ip_hash;
server localhost:8080;
server localhost:8081;
}
按后端服务器的响应时间来分配请求,响应时间短的优先分配。这个配置是为了更快的给用户响应。
upstream serverList {
fair;
server localhost:8080;
server localhost:8081;
}
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。在upstream
中加入hash
语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
upstream serverList {
hash $request_uri;
hash_method crc32;
server localhost:8080;
server localhost:8081;
}
以上5种负载均衡各自适用不同情况下使用,所以可以根据实际情况选择使用哪种策略模式,不过fair
和url_hash
需要安装第三方模块才能使用。
假设有 2 台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA 突然 A 挂了,服务器处理请求的顺序:BBBBBBBBBBBBBB…
upstream web_servers {
server 127.0.0.1:7878;
server 192.168.10.121:3333 backup; #热备
}
Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,同时现在也很流行动静分离,就可以通过Nginx来实现。
server {
listen 80;
server_name localhost;
location / {
root E:/wwwroot;
index index.html;
}
}
这样如果访问 http://localhost 就会默认访问到E盘wwwroot目录下面的index.html,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署。
动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。
upstream serverList{
server localhost:8080;
server localhost:8081;
}
server {
listen 80;
server_name localhost;
location = / {
root e:/wwwroot;
index index.html;
}
# 所有静态请求都由nginx处理,存放目录为wwwroot
location ~ \.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
root e:/wwwroot;
}
# 所有动态请求都转发给tomcat处理
location ~ \.(jsp|do)$ {
proxy_pass http://serverList;
}
}
这样我们就可以把HTML、图片、css、js放到wwwroot目录下,而tomcat只负责处理jsp和请求。
例如当我们后缀为gif的时候,Nginx默认会从wwwroot获取到当前请求的动态图文件返回,当然这里的静态文件跟Nginx是同一台服务器,我们也可以在另外一台服务器,然后通过反向代理和负载均衡配置过去就好了,只要搞清楚了最基本的流程,很多配置就很简单了,另外localtion后面其实是一个正则表达式,所以非常灵活。root说明是静态资源,可以由Nginx进行返回;而proxy_pass说明是动态请求,需要进行转发,比如代理到Tomcat上。
一般情况下我们会设置 html 文件不做任何缓存 no-store
, 其他文件可以设置一个比较长的缓存时间,由于我们的入口文件一般是 html, 每次上线后更新 html 内的引用即可保证我们的资源引用都是正确的。
server {
location ~* \.html$ {
add_header Cache-Control no-cache, no-store, must-revalidate;
add_header Pragma no-cache;
add_header Expires 0;
}
location ~* \.(css|js|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff)$ {
add_header Cache-Control max-age=31536000;
}
}
对 html 设置不缓存, 其他静态资源设置1年的缓存
跨域资源共享(CORS
)是一种安全策略,用于控制哪些网站可以访问资源。当前端应用程序和后端API位于不同的域上时,通常会遇到跨域问题。Nginx可以通过设置响应头来解决这个问题。
location / {
# 允许跨域请求的域,* 代表所有
add_header Access-Control-Allow-Origin *;
# 允许请求的header DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range
add_header Access-Control-Allow-Headers *;
# 允许带上cookie请求
add_header Access-Control-Allow-Credentials true;
# 允许请求的方法,比如 GET,POST,PUT,DELETE,OPTIONS
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
proxy_pass http://192.168.1.12:8080;
}
Access-Control-Allow-Headers 项对于没有凭据的请求(没有 HTTP cookie 或 HTTP 认证信息的请求),值
*
仅作为特殊的通配符值。在具有凭据的请求中,它被视为没有特殊语义的文字标头名称“ *”。请注意,Authorization标头不能使用通配符,并且始终需要明确列出。
用户端的大量请求(突发流量)会进入nginx内维护的漏桶中,漏桶会按照我们定义的固定的速率给服务器分发请求,正常的请求在服务器处理完后会正常返回给用户端。如果水流过大(突发流量过大)时,漏桶内的水会溢出,这时nginx就把这些溢出的水(流量)直接丢弃,也就是给用户端返回错误信息。
用户端发请求给nginx时,每个请求都要去nginx的令牌桶中取一个令牌,令牌桶的容量是我们自己设定的,如果某个请求成功取到了令牌,那么nginx就会把这个请求转发到服务器上进行处理。如果令牌桶已空,请求在nginx令牌桶中取不到令牌,那么nginx会直接返回该请求,也就是给用户端返回错误信息。
http {
gzip on; # 开始 gzip
gzip_comp_level 5; # 压缩级别: 1-9
gzip_min_length 1k; # gzip 压缩文件体积的最小值
# ...
}
gzip相关详细信息可以参考这篇文章 利用gzip优化vue项目
返回 http 状态码和可选的第二个参数也可以直接是重定向的 URL
return code [text];
return code URL;
return URL;
示例如下:
location / {
return 404; # 直接返回状态码
}
location / {
return 404 "pages not found"; # 返回状态码 + 一段文本
}
location / {
return 302 /bbs; # 返回状态码 + 重定向地址
}
location / {
return https://www.baidu.com; # 返回重定向地址
}
通过使用 rewrite
指令重写请求 URI。
第一个(必需)参数是请求 URI 必须匹配的正则表达式。
第二个参数(必需)是用于替换匹配 URI 的 URI。
可选的第三个参数为重写策略
last
重写后的 URL 发起新请求,再次进入 server 段,重试 location 的中的匹配;break
直接使用重写后的 URL ,不再匹配其它 location 中语句;redirect
返回 302 临时重定向;permanent
返回 301 永久重定向;location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
nginx指令error_page
的作用是当发生错误的时候能够显示一个预定义的uri。
语法(此处为简写):
error_page code [ code... ] uri
示例:
error_page 502 503 /error.html;
location = /error.html {
root /usr/share/nginx/error.html;
}
这样实际上产生了一个内部跳转(internal redirect),当访问出现502、503的时候就能返回error.html中的内容,这里需要注意是否可以找到error.html页面,所以加了个location保证找到你自定义的error页面。
访问日志:需要开启压缩 gzip on
; 否则不生成日志文件,打开 log_format
、access_log
注释
gzip on;
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 /usr/local/etc/nginx/logs/host.access.log main;
#禁止访问某个目录
location / {
allow 192.168.0.0;
allow 127.0.0.1;
deny all;
#这段配置值允许192.168.0.0和127.0.0.1网段的请求,其他来源IP全部拒绝。
}
nginx 的配置文件中可以使用的内置变量以美元符 $
开始。其中,大部分预定义的变量的值由客户端发送携带。
$args
:请求行中的参数。例如,请求URL为/index.html?page=2,那么$args
的值就是page=2。$content_length
:请求头中的 Content-length
字段。$content_type
:请求头中的 Content-Type
字段。$host
:请求行的主机名,为空则为请求头字段 Host
中的主机名,再为空则与请求匹配的 server_name
。$http_user_agent
:客户端 agent
信息。$http_cookie
:客户端 cookie
信息。$limit_rate
:这个变量可以限制连接速率。$request_method
:客户端请求的动作,通常为 GET
或 POST
。$remote_addr
:客户端的 IP
地址。$remote_port
:客户端的端口。$remote_user
:已经经过 Auth Basic Module 验证的用户名。$request_filename
:当前请求的文件路径,由 root
或 alias
指令与 URI
请求生成。$scheme
:HTTP
方法(如 http,https)。$server_protocol
:请求使用的协议,通常是 HTTP/1.0 或 HTTP/1.1。$server_addr
:服务器地址,在完成一次系统调用后可以确定这个值。$server_name
:服务器名称。$server_port
:请求到达服务器的端口号。$request_uri
:包含请求参数的原始 URI,不包含主机名,如:”/foo/bar.php?arg=baz”。$uri
:不带请求参数的当前URI,uri 不包含主机名,如”/foo/bar.html”。# 以下是全局段配置
#user administrator administrators; #配置用户或者组,默认为nobody nobody。
#worker_processes 2; #设置进程数,默认为1
#pid /nginx/pid/nginx.pid; #指定nginx进程运行文件存放地址
error_log log/error.log debug; #制定日志路径,级别:debug|info|notice|warn|error|crit|alert|emerg
# events段配置信息
events {
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off
#use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
worker_connections 1024; #最大连接数,默认为512
}
# http、配置请求信息
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区块开始,表示一个独立的虚拟主机站点
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
}
}
}
nginx的代理往往只是代理转发请求,只需要服务端架设nginx开启反向代理或者客户端开启正向代理。而代理则是通过隧道技术在公共网络上模拟出一条点到点的逻辑专线,从而达到安全数据传输的目的,最常见的用处就是人不在公司,通过设备访问公司内网。
当我们不使用时,我们直接访问公司内网,带上的是公网ip,公司内的设备都是内网ip,公司内网没有接入公网,肯定访问不到公司内网,而且人家也不认识你的公网ip,这时候要访问公司内网,有两种方法,一种是从你家专门接一条网线到公司的服务器,听着确实可以,但是实际上却很不现实。第二种方法就是技术,在公网上建立一条专门的隧道,直接连接你的设备和公司内网设备。架设装线,往往需要用户端和服务端都部署和配置专门的设备,也就是上图的网关,例如路由器式、交换机式。
设计与实现
最主要的技术就是隧道技术,隧道技术用通俗的话来讲就是用另一种协议去封装我们使用的协议,隧道协议分为第二、第三层隧道协议,第二层隧道协议(如L2TP、PPTP、L2F等)工作在OSI体系结构的第二层(即数据链路层);第三层隧道协议(如IPSec、GRE等)工作在OSl体系结构的第三层(即网络层),这两个协议会在我们网络层封装完IP头后,再封装IPSec或者GRE头,并进行信息加密,这也是代理服务器不会做的。然后再交由网络接口层添加mac头再丢到公网中,这样公网就认得你的ip并且能找到你公司内网前架设的网关。
设备还会使用常用加解密技术,例如对称密钥加密和非对称密钥加密组合使用,例如用https的TLS加密技术。密钥管理技术和身份认证及访问控制技术的支持。
代理服务器和有什么不一样?
匿名性不同。虽然它们都位于请求的中间,都隐藏了 IP 地址,并且都将信息转发。
主要区别在于 VPN 需要隧道过程,该过程建立了到 VPN 服务器的直接且不可穿透的连接。代理只是一个开放的端口,是任何人都可以连接到的单个 IP 地址。
安全性不同。会加密我们的数据信息,代理服务器不会,因此更加私有,连接不会被穿透,是一个开在公网上的封闭系统。
运行级别不同。是运行在操作系统上,由操作系统内核封装,重定向请求流量。代理服务器是软件级别,处于用户态。