这个小节我们学习下Nginx
的代理服务。
在没有代理的情况下 客户端是直接和服务端进行直接连接。当存在代理的时候所有的请求和想要都需要经过代理。
按照应用分类可以分为正向代理和反向代理。
正向代理
当我们在一个局域网内想上外网或者想翻墙的时候就需要一个正向代理。代理服务器会通过DNS解析域名请求服务返回给客户端。正向代理代理的是客户端,为客户端提供服务。代理请求DNS服务器。
反向代理
反向代理一般用在针对性访问某个站点。需要客户端自己通过DNS获得域名解析。反向代理代理的对象是服务端,是为服务端提供服务的。(如根据路由分发请求等)
参考文章: 正向代理与反向代理的区别
Nginx作为代理的模块
常见的Nginx
作为反向代理支持协议
反向代理模块 | Nginx配置模块 |
---|---|
http、websocket、https | ngx_http_proxy_module |
fastcgi | ngx_http_fastcgi_module |
uwsgi | ngx_http_uwsgi_module |
grpc | ngx_http_v2_module |
常见的Nginx
作为正向代理支持协议:
注意:不能支持
HTTPS
协议。
Nginx作为反向代理场景
配置语法:
1 | Syntax: proxy_pass URL; |
URL
表示如果我们请求到Nginx
代理服务器进行转发到对应的链接。
URL
的格式有以下三种
1 | http://localhost:8000/uri/ |
最后一个进程间通信的一个socket
方式。
🌰
我们编写一个在8080端口的应用,这个8080是公网无法访问到的
1 | server { |
在上面应用的家目录下有一个 test_proxy.html 文件
使用代理配置 将 80端口的访问代理到8080
1 | server { |
这样我们即使在主机8080端口没有开放的情况下,还可以访问到对应的服务。
Nginx作为正向代理场景
在程序服务器上配置只有指定IP
能够访问
1 | server { |
这样如果不是指定IP
是不允许访问的。
在程序允许访问的服务器(即代理服务器上做请求转发)来解决只能运行在指定服务器上访问的限制。
1 | server { |
完成上面配置之后还需要在客户端配置代理服务器(IP+端口)。因为正向代理代理的是客户端。
我们使用代理插件或者代理工具配置程序允许访问的服务器。
整体流程就是存在一个服务只能运行某些IP进行访问,我们在对应的IP上安装NGINX服务,并开启反向代理功能转发访问受限的请求,除此之外还要再客户端配置一些本地正向代理。即实际是先访问正向代理服务器,然后由正向代理服务器进行反向代理转发,最后获取到受限制的服务。
更多关于代理模块的: 官方文档
其他配置语法–缓冲区:
1 | Syntax: proxy_buffering on | off; |
扩展:proxy_buffer_size
, proxy_busy_buffers_size
, proxy_buffers
开启缓冲区是指将客户端请求的数据缓存一些(尽可能的收集完客户端的请求)再发往服务端,内容存在内存中,当内存不够的时候,存在硬盘的临时文件目录下。
其他配置语法–跳转重定向:
1 | Syntax: proxy_redirect default; |
处理301重定向请求。
其他配置语法–头信息:
1 | Syntax: proxy_set_header field value; |
扩展配置: proxy_set_body
, proxy_hide_header
。
设置经过代理服务器的IP。
其他配置语法–超时:
1 | Syntax: proxy_connect_timeout time; |
扩展:proxy_read_timeout
, proxy_send_timeout
代理服务器到真正服务器之间的超时关系。
一般配置代理如下:
1 | proxy_redirect default; |
Nginx实现websocket代理
WebSocket协议相比较于HTTP协议成功握手后可以多次进行双向通讯,直到连接被关闭。
但是WebSocket中的握手和HTTP中的握手兼容(websocket的实现在http的基础上),它使用HTTP中的Upgrade协议头(客户端向服务端发起)将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的基础设施。
WebSocket工作在HTTP的80和443端口并使用前缀ws://
或者wss://
进行协议标注,在建立连接时使用HTTP/1.1的101状态码进行协议切换,当前标准不支持两个客户端之间不借助HTTP直接建立Websocket连接。
1 | map $http_upgrade $connection_upgrade { |
其中的 map
映射
1 | Syntax: map $var1 $var2 { ... } |
参考文章:nginx map使用方法
fastcgi代理及配置语法
我们将服务端程序分为了web服务器和应用程序服务器。
web服务器是用于处理HTML文件,让客户可以通过浏览器进行访问。主流的有apache,IIS,nginx,lghttpd等。
应用服务器处理业务逻辑,比如使用python的django,flask写成的程序
通常来自客户端浏览器的请求被web服务器截获,如果是静态请求,则如nginx会自己做处理,如果是动态请求,则会抛给后端应用服务器来处理。于是如何在web服务器与应用服务器之间进行通信成了主要问题,这就引出了以下三种处理的接口:CGI,FastCGI,WSGI
1. CGI
通用网关接口(Common Gateway Interface/CGI)描述了客户端和服务器程序之间传输数据的一种标准,可以让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。CGI 独立于任何语言的,CGI 程序可以用任何脚本语言或者是完全独立编程语言实现,只要这个语言可以在这个系统上运行。Unix shell script, Python, Ruby, PHP,perl, Tcl, C/C++, 和 Visual Basic 都可以用来编写 CGI 程序。
最初,CGI 是在 1993 年由美国国家超级电脑应用中心(NCSA)为 NCSA HTTPd Web 服务器开发的。这个 Web 服务器使用了 UNIX shell 环境变量 来保存从 Web 服务器传递出去的参数,然后生成一个运行 CGI 的独立的进程。cgi的处理流程如下图所示:
l step1. web 服务器收到客户端(浏览器)的请求Http Request,启动CGI程序,并通过环境变量、标准输入传递数据
l step2. cgi进程启动解析器、加载配置(如业务相关配置)、连接其它服务器(如数据库服务器)、逻辑处理等
l step3. cgi程将处理结果通过标准输出、标准错误,传递给web 服务器
l step4. web 服务器收到cgi返回的结果,构建Http Response返回给客户端,并杀死cgi进程
web服务器与cgi通过环境变量、标准输入、标准输出、标准错误互相传递数据。
总结:CGI使外部程序与Web服务器之间交互成为可能。CGI程式运行在独立的进程中,并对每个Web请求建立一个进程,这种方法非常容易实现,但效率很差,难以扩展。面对大量请求,进程的大量建立和消亡使操作系统性能大大下降。此外,由于地址空间无法共享,也限制了资源重用。
2. FastCGI
快速通用网关接口(Fast Common Gateway Interface/FastCGI)是通用网关接口(CGI)的改进,描述了客户端和服务器程序之间传输数据的一种标准。FastCGI致力于减少Web服务器与CGI程式之间互动的开销,从而使服务器可以同时处理更多的Web请求。与为每个请求创建一个新的进程不同,FastCGI使用持续的进程来处理一连串的请求。这些进程由FastCGI进程管理器管理,而不是web服务器。
当进来一个请求时,Web 服务器把环境变量和这个页面请求通过一个unix domain socket(都位于同一物理服务器)或者一个IP Socket(FastCGI部署在其它物理服务器)传递给FastCGI进程。
l step1. Web 服务器启动时载入初始化FastCGI执行环境 。 例如IIS ISAPI、apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi
l step2. FastCGI进程管理器自身初始化,启动多个CGI解释器进程并等待来自Web 服务器的连接。启动FastCGI进程时,可以配置以ip和UNIX 域socket两种方式启动。
l step3. 当客户端请求到达Web 服务器时, Web 服务器将请求采用socket方式转发到 FastCGI主进程,FastCGI主进程选择并连接到一个CGI解释器。Web 服务器将CGI环境变量和标准输入发送到FastCGI子进程。
l step4. FastCGI子进程完成处理后将标准输出和错误信息从同一socket连接返回Web 服务器。当FastCGI子进程关闭连接时,请求便处理完成。
l step5. FastCGI子进程接着等待并处理来自Web 服务器的下一个连接。
由于 FastCGI 程序并不需要不断的产生新进程,可以大大降低服务器的压力并且产生较高的应用效率。它的速度效率最少要比CGI 技术提高 5 倍以上。它还支持分布式的部署, 即 FastCGI 程序可以在web 服务器以外的主机上执行。
总结:CGI 就是所谓的短生存期应用程序,FastCGI 就是所谓的长生存期应用程序。FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。
Fastcgi代理配置
1 | Syntax: fastcgi_pass address; |
address为后端的fastcgi server的地址
示例:
1 | fastcgi_pass localhost:9000; |
1 | Syntax: fastcgi_index name; |
设置默认的首页文件 结合 fastcgi_param 一起设置
1 | Syntax: fastcgi_param parameter value [if_not_empty]; |
通过 fastcgi_param 设置变量,并将设置的变量传递到后端的FastCGI serve。
Uwsgi反向代理模式
uWSGI处在Nginx和WEB应用程序之间。
为什么WEB框架要使用uwsgi?
优势:安全(对于Django需要普通用户启动),效率
Nginx结合uwsgi能够实现动静分离 效率更高。通过Nginx
能够做到动静分离。