前言:我们从事web开发,在项目上线以后我们大部分都需要在服务器上面使用nginx做反向代理或者负载均衡来提高我们项目的并发量,本人我只是针对于反向代理这一块来做之前一些项目使用总结
一.关于正反向代理
我们使用nginx做反向代理的时候,我们首先要要知道什么是代理,通俗点代理其实就是一个中介,A和B本来可以直接连接,这个时候中间插入一个C,C就是中介 刚开始的时候,代理多数是帮助内网客户端访问外网服务端 后来出现了反向代理,'反向'这个词语在这里的意思是指方向相反,即代理将来自外网客户端的请求转发到内网服务器,从内到外,所以现在就有了正反向代理
正向代理
首先要明白正向代理代理的是客户端,我们客户端通过vpn访问,实际上服务端并不知道访问他的客户端的具体地址,只知道的是vpn的地址
用途:
1.访问原来无法访问的资源,如google
2.可以做缓存,加速访问资源
3.对客户端访问授权,上网进行认证
4.代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息
反向代理
反向代理代理的是我们的服务端,正常的客户端请求通过http或者https发送过来,会直接访问到我们的服务端,在python中我们会使用web服务器网关比如uwsgi做请求的处理,再经过我们的中间件,最终抵达我们的路由层,而当我们使用了反向代理以后,客户端并不会直接访问到我们的服务端,而是访问的是nginx服务器,由nginx做请求的转发,转发给我们web服务器
用途:
1.保证内网的安全,阻止web攻击,大型网站,通常会将反向代理作为公网访问地址,web服务器是内网 2.负载均衡,通过反向代理服务器来优化网站的负载
总结:
正向代理是客户端代理,代理客户端,服务端不知道实际发起请求的客户端
反向代理是服务端代理,代理服务端,客户端不知道实际提供服务的服务端
二.nginx基本了解
nginx是一款轻量级的web服务器,他可以做反向代理也可以实现负载均衡,而且nginx的负载均衡是七层的负载均衡他可以识别ip、端口、应用层的协议以及域名,我们想要使用nginx做反向代理,首先大概了解一下nginx的运行,当一个nginx运行以后他会有一个master进程以及多个worker进程,master主要负责读取nginx.conf配置文件以及管理worker进程,真正做请求转发的是worker进程,当nginx运行起来以后就可以看到有master进程和worker进程了,worker进程默认配置是1个,我们可以在配置文件中进行修改,注意,我们之前说的都是进程,那当我们想要开启多个worker进程的时候,就要注意我们的cpu核数是否足够,否则开启多个worker进程会造成我们cpu的使用率过高影响服务器性能
上面就是我们启动的一个nginx服务,我们可以看到其中PID 为30665的是nginx的master进程,而PID为30667的是worker进程,这里为什么只有一个worker进程,我们可以查看nginx的配置文件,就明白了
worker_processes 1;
# 我们可以看到配置文件中有这么一句话,这句话就表示的是worker进程的个数,如果我们将这个数量进行改变,那么worker进程的数量也会发生改变
现在我们可以尝试改变worker进程的数量,来看看是否会发生改变
vim nginx.conf
# 进入配置文件进行修改
worker_processes 2;
# 这个时候我们将worker进程数量改为了2
这个时候我们要进行nginx的重新加载:sudo /usr/local/nginx/sbin/nginx -s reload
我们再去查看nginx的启动以后得进程:
root 1562 1545 0 8月02 ? 00:00:00 runsv nginx
root 1573 1562 0 8月02 ? 00:00:00 svlogd -tt /var/log/gitlab/nginx
nobody 13347 30665 0 15:33 ? 00:00:00 nginx: worker process
nobody 13348 30665 0 15:33 ? 00:00:00 nginx: worker process
root 30665 1 0 14:50 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
这个时候我们可以看到我们的master进程不变,由于重新启动了他的所以PID发生了改变,但是我们可以明显的看到worker进程数量变成了两一个,一个PID为13347另一个PID为13348,所以我们可以通过配置文件来改变worker进程的数量
总结:
master进程的作用:
-
启动和停止工作进程:当你启动 Nginx 时,主进程会负责创建工作进程,并将请求分配给它们。当你停止 Nginx 时,主进程会关闭所有工作进程。
-
监控工作进程的状态:主进程会监控工作进程的健康状况。如果某个工作进程意外终止或停止响应,主进程会重新启动新的工作进程来替代它,以确保服务的可用性和稳定性。
-
处理信号:主进程会接收操作系统发送的信号,并根据信号执行相应的操作。例如,当你向 Nginx 发送 HUP 信号时,主进程会重新加载配置文件,以便动态更新配置而无需停止整个服务。
-
管理日志和子进程:主进程会处理日志记录和子进程的管理。例如,主进程可以设置工作进程将日志信息写入指定的日志文件中。
因此,主进程在 Nginx 中是至关重要的组成部分,它起着协调和管理工作进程的作用,确保服务器的正常运行。工作进程则负责处理客户端请求,并执行实际的请求处理逻辑
worker进程的作用:
它的主要作用是接收和处理客户端请求。
具体来说,工作进程的功能包括:
-
处理客户端请求:工作进程负责接收来自客户端的HTTP请求,并根据配置文件中的规则进行处理。它可以执行各种操作,如代理请求到上游服务器、提供静态文件、执行缓存等。
-
并发处理:由于每个工作进程独立运行,Nginx 可以在并发请求上实现高性能和高吞吐量。每个工作进程可以同时处理多个客户端请求,从而有效地利用系统资源。
-
负载均衡:工作进程还可以配合负载均衡算法,将请求分发给多个上游服务器,实现负载均衡和高可用性。通过使用多个工作进程,Nginx 可以同时处理多个请求,并将它们分配给各个上游服务器,降低单个服务器的压力。
-
缓存功能:工作进程可以使用内存缓存或磁盘缓存,提供高效的静态内容访问。通过将经常请求的静态内容缓存在工作进程中,可以减轻上游服务器的负载,提高响应速度。
总之,工作进程是 Nginx 的核心组件之一,它负责接收和处理客户端请求,实现高性能、高并发、负载均衡和缓存等功能
三.nginx的配置文件
我们想要使用nginx,就绕不开nginx得配置文件,全名是nginx.conf,我们想要实现反向代理,就需要去改配置文件,所以我们需要去看一下nginx的配置文件里面是什么
命令:cat nginx.conf
因为配置文件比较长,所以我们分段进行了解
#user nobody;
worker_processes 2;#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;
}
user: 该指令指定了Nginx运行的用户和用户组。在这里,用户被设置为“nobody”,表示以非特权用户身份运行,并降低了可能面临的安全风险
worker_processes:就是我们的进程数,刚才被我们修改为了2
error_log: 这个指令定义了错误日志的路径和级别。在这里,Nginx 错误日志被设置为 logs/error.log,并且可以通过使用 notice 或 info 级别来记录不同类型的错误信息。如果你需要调试或查看 Nginx 运行时的错误,请查看这个日志文件
events: 这个块定义了 Nginx 如何处理事件,如连接、关闭等。在这里,worker_connections 指令指定了每个工作进程可同时处理的最大连接数
pid: 这个指令定义了包含主进程PID的文件路径。在这里,PID 文件被设置为 logs/nginx.pid。 如果需要管理或关掉 Nginx 进程,可以使用这个文件
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;
# }
#}
这么长一段他都属于nginx对于http请求做转发的配置
-
include: 该指令用于引入其他的配置文件。在这里,Nginx 包含了一个名为 mime.types 的文件,用于定义 MIME 类型和文件扩展名的映射关系。
-
default_type: 这个指令定义了默认的 MIME 类型。在这里,所有未知类型的文件都会按照二进制流(application/octet-stream)的方式进行处理。
-
sendfile: 这个指令指定是否启用零拷贝技术来传输文件。在这里,被设置为 on,表示启用了零拷贝技术来提高文件传输效率。
-
keepalive_timeout: 这个指令定义了客户端和服务器之间保持连接的超时时间。在这里,被设置为 65 秒。如果客户端在 keepalive_timeout 时间内没有发起新的请求,连接就会被关闭。
-
server: 这个指令定义了一个虚拟主机的配置信息。在这里,监听地址为 80 端口,服务名称为 localhost。
-
location: 这个指令用于配置不同路径下的不同行为。在这里,Nginx 在根目录下的 / 路径下提供了一个文件静态服务器。当请求以 / 开头时,Nginx 会在 html 目录下查找对应的文件。
-
error_page: 这个指令用于定义错误页面和错误码。在这里,Nginx 会在返回 500、502、503 或 504 错误时,重定向到 /50x.html 页面,该页面也在 html 目录下。
总之,这个配置文件定义了 Nginx 的基本参数和一个简单的文件静态服务器,为 Web 应用提供了必要的支持。
1.我们可以看到server这个大配置里面,listen后面紧跟着80,也就是意味着我们现在启动的nginx他监听我们这台服务器端的80端口,也就意味着我们现在可以通过访问服务器的80端口访问到我们的nginx,尝试访问可以看到这样一段话
证明我们的nginx服务是正常启动的,也是可以访问到的
2. location
这个是非常重要的,我们要配置http的反向代理,就需要再location这里进行配置,配置我们项目的IP和端口,如下:
server {
listen 80;
servser_name: # 这里修改为网站的域名,没有域名就使用服务器IP地址和端到
charset utf-8;
location / {
include uwsgi_params;
uwsgi_pass ; # 端口要和uwsgi里配置的一样
uwsgi_param ; #wsgi.py所在的目录名+.wsgi
uwsgi_param ; # 项目路径
}
# 新增的配置静态文件
location /static {
}
}
这样就是一个简单的nginx.conf反向代理的配置了,我们可以看一眼我们nginx服务器监听着80端口,
server_name为我们网站的ip地址+端口,当通过80端口发送请求,就会被我们的nginx服务器转发给我们的uwsgi跑的ip地址和端口,将请求转发给我们的后端,但是一般我们的项目肯定不止后端,我们一个项目运行在服务器上面有前段和后端两个,下面就是一个简单的前后端一起被nginx代理
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
# 前段部分
server {
listen 80;
servser_name: # 这里修改为网站的域名,没有域名就使用服务器IP地址:80
charset utf-8;
location / {
root /home/html # 这里表示我们html访问的路径,所以我们要将编译后的Vue静态 资源放在这个目录下面
index index.html # 表示访问跟会访问index.html页面
try_filed $uri $uri/index.html # 这个是Vue必须配置的,解决单页面刷新404问题
}
}
server {
listen 8000;
servser_name: # 这里修改为网站的域名,没有域名就使用服务器IP地址和端到
charset utf-8;
location / {
include uwsgi_params;
uwsgi_pass ; # 端口要和uwsgi里配置的一样
uwsgi_param ; #wsgi.py所在的目录名+.wsgi
uwsgi_param ; # 项目路径
}
# 新增的配置静态文件
location /static {
}
}
}
上面这个配置就是我们比较常见的配置了,他在http请求中配置了前端和后端,当我们想服务器地址80端口发送请求,nginx会从/home/html目录下找到index.html静态资源返回到前端,当我们前端加载完毕以后ajax请求会向我们服务器的8000端口发送请求,这个请求会被nginx转发给我们的uwsgi服务,然后从后端成功拿到数据资源,再返回到前端加载页面,最终让用户看到我们正常的页面,可以画一个简单的结构图让我们理解
上面就算简单的一个架构图,我们可以从图中可以看到实际上我们客户端所有的请求都被我们的nginx服务器所接收转发,ajax发送8000端口请求被nginx转发给我们的uwsgi服务器,处理过后的http请求才由我们的django后端真正的做处理,最终将数据返回给我们的前端,页面加载成功
继续读配置文件,下面是关于hppts请求的代理
# 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;
# }
这段代码是一个注释块,意味着它被用于说明 HTTPS 服务器的配置方式,但在实际配置中被禁用了。
HTTPS 是 HTTP 协议的安全版本,其使用了 SSL/TLS 加密协议来保护数据传输的安全性。在 Nginx 的配置文件中,可以通过 server 块来配置 HTTPS 服务器。这个注释块给出了一个示例 HTTPS 服务器的配置方式,包括监听端口、域名、SSL/TLS 证书的路径和缓存设置等。除此之外,还有一个 location 块,用于配置请求路径的处理方式。
如果需要启用这个 HTTPS 服务器,可以将这个注释块中的内容取消注释,并根据需要进行适当的修改。例如:
- 修改
listen
配置项来设置 HTTPS 服务器监听的端口号和 IP 地址; - 修改
server_name
配置项来设置主机名,匹配客户端请求的域名; - 设置正确的 SSL/TLS 证书路径和私钥路径,以便 Nginx 可以加载它们;
- 根据需要修改缓存设置和加密算法。
最后,记得重新加载或重启 Nginx 服务器,以使 HTTPS 服务器的配置生效。
通过nginx.conf文件我们就可以实现我们的反向代理,只需要配置我们的location选项就可以了
三.nginx的高级
现在有一个场景,我们想要对nginx进行平滑的修改,不停掉nginx的服务,但是可以改变了nginx的配置文件,想要如何实现:
思路:我们知道nginx的master进程负责的内容有读取nginx.conf内容,worker进程负责处理请求,那么我们是不是可以在不停机的情况下让master进程主动去读取nginx.conf得内容,这个时候我们再主动的产生worker进程,由新的进程来进行配置修改后的处理,而旧的进程在处理完请求以后直接干掉,那怎么实现呢?
要实现在不停机的情况下对 Nginx 进行平滑修改,你可以按照以下步骤进行操作:
-
修改 Nginx 配置文件(nginx.conf)中的相应配置项,例如 server 块、location 块等。确保新的配置文件内容已经准备好。
-
/usr/local/nginx/sbin/nginx -s reload这个命令会通知 Nginx 的主进程重新读取配置文件并启动新的 worker 进程。
-
此时,Nginx 主进程会开始读取新的配置文件,并创建新的 worker 进程来处理新的请求。旧的 worker 进程会继续处理完当前正在进行的请求,并在处理完成后被停止。
通过这种方式,Nginx 实现了平滑的配置文件修改。旧的 worker 进程会在处理完请求后停止,而新的 worker 进程会根据新的配置文件重新启动。
需要注意的是,这种平滑修改配置的方式并不是完全零停机,因为会有一小段时间的过渡期。在过渡期间,旧的和新的 worker 进程可能同时存在,但这个过程对于大多数请求来说是无感知的。
我们能实现这样的操作,其实根源于nginx的信号
在 Nginx 中,可以使用不同的信号与主进程进行通信,以控制其行为。以下是常用的 Nginx 信号:
-
reload:重新加载配置文件,并启动新的 worker 进程,平滑地将新配置应用到服务器。可以使用命令
nginx -s reload
发送该信号给主进程。 -
stop:停止 Nginx 服务器的运行,发送该信号给主进程即可,命令为
nginx -s stop
。 -
quit:优雅地关闭 Nginx 服务器,在处理完当前请求后停止进程。发送该信号给主进程,命令为
nginx -s quit
。 -
reopen:重新打开日志文件,发送该信号给主进程,命令为
nginx -s reopen
。通常用于将日志文件切割归档时使用。 -
reload/upgrad:升级 Nginx 执行文件。首先,通过重新编译或替换 Nginx 可执行文件。然后,向主进程发送
nginx -s reload
信号,重新加载配置文件和启动新的 worker 进程。
这些信号是通过向 Nginx 主进程发送操作系统级别的信号来实现的。可以使用操作系统提供的工具(如 kill 命令)或其他脚本来发送这些信号。