# 2. 反向代理
#### 1. 什么叫反向代理服務(wù)器?
要說反向代理服務(wù)器,先來說一般的代理服務(wù)器。代理就是受委托去做一些事。假如用戶A委托B去做一些事,做完之后B告訴A結(jié)果。在代理服務(wù)器中也是一樣的道理,用戶A通過代理服務(wù)器B訪問網(wǎng)站C(`www.example.com`),請求先到代理服務(wù)器B,B再轉(zhuǎn)發(fā)請求到網(wǎng)站C,代理服務(wù)器B是真正訪問網(wǎng)站C的,訪問之后再把網(wǎng)站C的應(yīng)答結(jié)果發(fā)給用戶A。這樣給用戶A的感覺是C直接提供服務(wù)的一樣,因為看不到B的整個處理過程。代理服務(wù)器是一個中間者,是充當(dāng)轉(zhuǎn)發(fā)請求的角色。這種代理也叫`正向代理`。
使用正向代理是要在客戶端進(jìn)行設(shè)置,比如瀏覽器設(shè)置代理服務(wù)器的域名或IP,還有端口等。
正向代理的作用有很多,例如,能訪問本無法訪問的,加速,cache,隱藏訪問者的行蹤等,具體的不再詳述了。
`反向代理`(reverse proxy)正好與正向代理相反,對于客戶端而言代理服務(wù)器就像是原始服務(wù)器,并且客戶端不需要進(jìn)行任何特別的設(shè)置。假如用戶A訪問網(wǎng)站B,這個時候網(wǎng)站B充當(dāng)了web服務(wù)器,也充當(dāng)了反向代理服務(wù)器,它充當(dāng)?shù)拇矸?wù)器的角色是這樣,假如用戶A要得到網(wǎng)站C的內(nèi)容,而用戶A又不能直接訪問到(例如網(wǎng)絡(luò)原因),而服務(wù)器B可以訪問到網(wǎng)站C,那服務(wù)器可以得到網(wǎng)站C的內(nèi)容再存起來發(fā)給用戶A,這整個過程用戶A是直接和代理服務(wù)器B交互的,用戶A不知道網(wǎng)站C的存在,這個web服務(wù)器B就是一臺反向代理服務(wù)器,這個網(wǎng)站C就是上游服務(wù)器(upstream servers)。
反向代理的作用是,隱藏和保護(hù)原始服務(wù)器,就像剛才的例子,用戶A根本不知道服務(wù)器C的存在,但服務(wù)器C確實提供了服務(wù)。還有,就是負(fù)載均衡。當(dāng)反向代理服務(wù)器不止一個的時候,就可以做成一個集群,當(dāng)用戶A訪問網(wǎng)站B時,用戶A又需要網(wǎng)站C的內(nèi)容,而網(wǎng)站C有好多服務(wù)器,這些服務(wù)器就形成了集群,而網(wǎng)站B在請求網(wǎng)站C,就可以有多種方式(輪循,hash等),把請求均勻地分配給集群中的服務(wù)器,這個就是負(fù)載均衡。
。
#### 2. 示例
我們先來看最一個最簡單的例子。
##### 2.1 最簡單的反向代理
nginx的反向代理是依賴于[ngx\_http\_proxy\_module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html)這個module來實現(xiàn)的。
反向代理服務(wù)器能代理的請求的協(xié)議包括http(s),F(xiàn)astCGI,SCGI,uwsgi,memcached等。我們這里主要集中在http(s)協(xié)議。
我有一個網(wǎng)站,用的是https協(xié)議來訪問的。用這個協(xié)議訪問的網(wǎng)站在chrome等瀏覽器的地址欄是可以看到一個綠色的代表安全的標(biāo)志的。你請求的所有資源都要是https的,它才會出現(xiàn)。假如你請求了一張外部的圖片,而這張圖片是以http協(xié)議請求的,那這個時候那個安全的標(biāo)志就不存在的。
所以我要把這個https協(xié)議的圖片請求反向代理到http協(xié)議的真實圖片上。https協(xié)議的這張圖片是不存在,而它有一個地址實際指向的內(nèi)容是http協(xié)議中的圖片。
```
# 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;
}
```
假如我的網(wǎng)站是`www.example.com`這樣就能使用`https://www.example.com/newchart/hollow/small/nsh000001.gif`,它指向是`http://image.sinajs.cn/newchart/hollow/small/nsh000001.gif`。
##### 2.2 動態(tài)轉(zhuǎn)發(fā)
我們的網(wǎng)站不止是展示用的,我們還要處理動態(tài)請求,例如表單等。所以nginx也要和php,java,ruby等語言配合。
下面的例子是nginx和unicorn(ruby的應(yīng)用服務(wù)器)的一個例子。
```
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,如果都找不到,才會執(zhí)行`@rails365`的部分,也就是`location @rails365`。
前面兩行是設(shè)置請求的頭部,第三行是設(shè)置不轉(zhuǎn)地址,這些先不管。來看第三行`proxy_pass http://rails365;`。這行會反向代理到`upstream rails365`指定的內(nèi)容。`upstream`里面指定了一個服務(wù)器,這個服務(wù)器和nginx是同一臺機(jī)器的,用的是unix socket來連接,連接的是一個unicorn進(jìn)程。
總結(jié)起來是這樣的。假如用戶要訪問`https://www.rails365.net/articles/`,這個請求不能只靠nginx,因為又不是以.html結(jié)尾,所以轉(zhuǎn)發(fā)給了upstream所指向的服務(wù)器,轉(zhuǎn)發(fā)請求的方式是unix socket,到了unicorn進(jìn)程,unicorn處理后交給nginx,nginx才最終發(fā)給客戶。在這里,nginx還起到一個cache和保護(hù)的作用,unicorn就是上游服務(wù)器。
##### 2.3 websocket
關(guān)于webcoket的概念,這里不再詳細(xì),可以參照這篇文章。
```
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協(xié)議升級為ws協(xié)議,然后通過unix socket連接到puma進(jìn)程,一個支持ws協(xié)議的進(jìn)程。原理跟上面的unicorn差不多。
注意:nginx要支持websocket協(xié)議,必須是 1.3.13或以上版本。
要測試是否成功,有兩種比較簡單的方法。
第一種是在chrome瀏覽器上console那里直接訪問。
比如`new WebSocket('ws://www.example.com/wx');`
第二種就是在chrome的開發(fā)者工具,network那里看有沒有101協(xié)議的請求。
比如。

完結(jié)。
- 介紹
- 安裝
- 1. 基本介紹和配置文件語法
- 2. 反向代理
- 3. gzip 壓縮提升網(wǎng)站性能
- 4. 在線升級
- 5. 監(jiān)控工具 ngxtop
- 6. 編譯第三方模塊
- 7. auth_basic 模塊使用
- 8. 日志分析工具
- 9. 用 nginx 搭建谷歌鏡像網(wǎng)站
- 10. 自制啟動腳本
- 11. 日志切割
- 12. 作為負(fù)載均衡器
- 13. 開啟 debug 模式
- 14. gzip static 模塊探索
- 15. 安裝最新 nginx 的另類方法
- 16. 使用 acme.sh 安裝 Let’ s Encrypt 提供的免費 SSL 證書
- 17. 給 GitLab 應(yīng)用加上 https
