企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 2. 反向代理 #### 1. 什么叫反向代理服务器? 要说反向代理服务器,先来说一般的代理服务器。代理就是受委托去做一些事。假如用户A委托B去做一些事,做完之后B告诉A结果。在代理服务器中也是一样的道理,用户A通过代理服务器B访问网站C(`www.example.com`),请求先到代理服务器B,B再转发请求到网站C,代理服务器B是真正访问网站C的,访问之后再把网站C的应答结果发给用户A。这样给用户A的感觉是C直接提供服务的一样,因为看不到B的整个处理过程。代理服务器是一个中间者,是充当转发请求的角色。这种代理也叫`正向代理`。 使用正向代理是要在客户端进行设置,比如浏览器设置代理服务器的域名或IP,还有端口等。 正向代理的作用有很多,例如,能访问本无法访问的,加速,cache,隐藏访问者的行踪等,具体的不再详述了。 `反向代理`(reverse proxy)正好与正向代理相反,对于客户端而言代理服务器就像是原始服务器,并且客户端不需要进行任何特别的设置。假如用户A访问网站B,这个时候网站B充当了web服务器,也充当了反向代理服务器,它充当的代理服务器的角色是这样,假如用户A要得到网站C的内容,而用户A又不能直接访问到(例如网络原因),而服务器B可以访问到网站C,那服务器可以得到网站C的内容再存起来发给用户A,这整个过程用户A是直接和代理服务器B交互的,用户A不知道网站C的存在,这个web服务器B就是一台反向代理服务器,这个网站C就是上游服务器(upstream servers)。 反向代理的作用是,隐藏和保护原始服务器,就像刚才的例子,用户A根本不知道服务器C的存在,但服务器C确实提供了服务。还有,就是负载均衡。当反向代理服务器不止一个的时候,就可以做成一个集群,当用户A访问网站B时,用户A又需要网站C的内容,而网站C有好多服务器,这些服务器就形成了集群,而网站B在请求网站C,就可以有多种方式(轮循,hash等),把请求均匀地分配给集群中的服务器,这个就是负载均衡。 ![](https://box.kancloud.cn/b9b93fbf080b4b68a9d876f5f0eafb8d_750x498.jpg)。 #### 2. 示例 我们先来看最一个最简单的例子。 ##### 2.1 最简单的反向代理 nginx的反向代理是依赖于[ngx\_http\_proxy\_module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html)这个module来实现的。 反向代理服务器能代理的请求的协议包括http(s),FastCGI,SCGI,uwsgi,memcached等。我们这里主要集中在http(s)协议。 我有一个网站,用的是https协议来访问的。用这个协议访问的网站在chrome等浏览器的地址栏是可以看到一个绿色的代表安全的标志的。你请求的所有资源都要是https的,它才会出现。假如你请求了一张外部的图片,而这张图片是以http协议请求的,那这个时候那个安全的标志就不存在的。 所以我要把这个https协议的图片请求反向代理到http协议的真实图片上。https协议的这张图片是不存在,而它有一个地址实际指向的内容是http协议中的图片。 ``` # https server { server_name www.example.com; listen 443; location /newchart/hollow/small/nsh000001.gif { proxy_pass http://image.sinajs.cn/newchart/hollow/small/nsh000001.gif; } location /newchart/hollow/small/nsz399001.gif { proxy_pass http://image.sinajs.cn/newchart/hollow/small/nsz399001.gif; } ``` 假如我的网站是`www.example.com`这样就能使用`https://www.example.com/newchart/hollow/small/nsh000001.gif`,它指向是`http://image.sinajs.cn/newchart/hollow/small/nsh000001.gif`。 ##### 2.2 动态转发 我们的网站不止是展示用的,我们还要处理动态请求,例如表单等。所以nginx也要和php,java,ruby等语言配合。 下面的例子是nginx和unicorn(ruby的应用服务器)的一个例子。 ``` upstream rails365 { # Path to Unicorn SOCK file, as defined previously server unix:///home/yinsigan/rails365/shared/tmp/sockets/unicorn.sock fail_timeout=0; } server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; server_name www.rails365.net; root /home/yinsigan/rails365/current/public; try_files $uri/index.html $uri @rails365; location @rails365 { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://rails365; } } ``` 先从`try_files $uri/index.html $uri @rails365;`这句说起,它先找根目录`/home/yinsigan/rails365/current/public`下的index.html,假如是`www.rails365.net/about.html`还是会找根目录下的about.html,如果都找不到,才会执行`@rails365`的部分,也就是`location @rails365`。 前面两行是设置请求的头部,第三行是设置不转地址,这些先不管。来看第三行`proxy_pass http://rails365;`。这行会反向代理到`upstream rails365`指定的内容。`upstream`里面指定了一个服务器,这个服务器和nginx是同一台机器的,用的是unix socket来连接,连接的是一个unicorn进程。 总结起来是这样的。假如用户要访问`https://www.rails365.net/articles/`,这个请求不能只靠nginx,因为又不是以.html结尾,所以转发给了upstream所指向的服务器,转发请求的方式是unix socket,到了unicorn进程,unicorn处理后交给nginx,nginx才最终发给客户。在这里,nginx还起到一个cache和保护的作用,unicorn就是上游服务器。 ##### 2.3 websocket 关于webcoket的概念,这里不再详细,可以参照这篇文章。 ``` upstream ws { server unix:///home/eason/tt_deploy/shared/tmp/sockets/puma.sock fail_timeout=0; } server { location /ws/ { proxy_pass http://ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } ``` 先由http协议升级为ws协议,然后通过unix socket连接到puma进程,一个支持ws协议的进程。原理跟上面的unicorn差不多。 注意:nginx要支持websocket协议,必须是 1.3.13或以上版本。 要测试是否成功,有两种比较简单的方法。 第一种是在chrome浏览器上console那里直接访问。 比如`new WebSocket('ws://www.example.com/wx');` 第二种就是在chrome的开发者工具,network那里看有没有101协议的请求。 比如。 ![](https://box.kancloud.cn/563ff4fa33a13d5fce3d4cb2380f2d34_750x132.png) 完结。