基於 Tornado 實現的 Web 站點反向代理


因為一個奇怪的需求,使用 Python 和 Tornado 框架實現了一個 Web 站點的反向代理。實現的功能是這樣:

  1. 假設這個反向代理網站的地址是 http://www.example.com
  2. 訪問 http://www.example.com/.site.backend_site0/,訪問的是 backend_site0,這個網站可以是部署在內網的某個站點(外網當然也是可以)。
  3. 訪問 http://www.example.com/.site.backend_site1/,訪問另外一個站點 backend_site1

怎么通過一個公共的站點反向代理訪問后端的多個站點,當時的討論帖在這里,我采用的是:

  1. 在url中添加前綴 .site.,第一次訪問的時候使用 http://www.example.com/.site.backend_site/
  2. 服務端識別出請求的后端站點 backend_site 后,會設置 Cookie,.site = backend_site,后續的訪問會根據Cookie來識別出來。
  3. 當訪問另外一個網站 http://www.example.com/.site.backend_site1/,這時候,服務端會清除舊的 Cookie,並設置新的 Cookie,.site = backend_site1,這樣就切換到新的站點 backend_site1
  4. 啟用頁面內容替換,保證頁面內的內網IP地址轉換成反向代理的地址。例如后端站點 backend_site0 的地址是 http://10.1.2.3/,頁面內有鏈接 http://10.1.2.3/img/a.png,將其替換成 /.site.backend_site0/img/a.png

項目的代碼開源在 Github 上,有需要的可以自取。
https://github.com/restran/web_proxy

環境需求

Python 2.7
Tornado 4.0

所代理的后端網站注意事項

  1. url 的前綴不應出現 /.site.
    由於反向代理采用url前綴來區分后端網站,如 /.site.example/,表示后端站點example。
    例如以下為禁用的url:
    /.site./
    /.site.example/
    /.site.example/user/login/

  2. cookies 中不應出現以 .site 命名的 cookie 值,這個 cookie 是用來標識當前訪問的后端站點

CentOS 7.0 部署

Tornado 的部署可以參照這里的教程。通過啟動多個 Tornado 實例,來避免調用到同步函數塊,導致阻塞住,無法響應其他用戶的請求。使用 supervisor 來啟動 Tornado Server,並使用 Nginx 作為 Web 服務器,反向代理后端的這些 Tornado 實例。

修改配置文件 settings.py

# 轉發到后端需要代理的網站的地址列表
forward_list = {
    "baidu": BackendSite('baidu', 'http://www.baidu.com', 'www.baidu.com', []),
    "douban": BackendSite('douban', 'http://www.douban.com', 'www.douban.com', [
        # 使用正則表達式替換頁面內容,參數分別是
        # 需要替換的URI的正則表達式,源字符串的正則表達式,替換后的字符串 
        SubsFilterRules('.', r'http://www\.douban\.com', '/.site.douban'),
        SubsFilterRules('.', r'http://img3\.douban\.com', '/.site.img3.douban'),
        SubsFilterRules('.', r'http://img5\.douban\.com', '/.site.img5.douban'),
    ]),
    "img3.douban": BackendSite('douban', 'http://img3.douban.com', 'img3.douban.com', []),
    "img5.douban": BackendSite('douban', 'http://img5.douban.com', 'img5.douban.com', []),
}

使用 supervisor 啟動 Tornado Server

設置配置文件

vim /etc/supervisord.conf

輸入如下信息

[program:tornado_server_9001]
command=python /home/python/web_proxy/proxy.py --port=9001
directory=/home/python/web_proxy
autorestart=true
redirect_stderr=true
stdout_logfile = /var/log/supervisord/web_proxy.log

[program:tornado_server_9002]
command=python /home/python/web_proxy/proxy.py --port=9002
directory=/home/python/web_proxy
autorestart=true
redirect_stderr=true
stdout_logfile = /var/log/supervisord/web_proxy.log

[program:tornado_server_9003]
command=python /home/python/web_proxy/proxy.py --port=9003
directory=/home/python/web_proxy
autorestart=true
redirect_stderr=true
stdout_logfile = /var/log/supervisord/web_proxy.log

重新加載配置文件

supervisorctl reload

重新啟動所有程序

sudo supervisorctl restart all

配置 nginx

添加 nginx 配置文件

vim /etc/nginx/conf.d/web_proxy.conf

輸入如下配置信息

upstream tornadoes {
    server 127.0.0.1:9001;
    server 127.0.0.1:9002;
    server 127.0.0.1:9003;
}

server {
    listen 9000;
    server_name your_server_name; # 例如輸入服務器IP
    gzip on;
    # 設置允許壓縮的頁面最小字節數,頁面字節數從header頭得content-length中進行獲取。默認值是0,不管頁面多大都壓縮。建議設置成大於1k的字節數,小於1k可能會越壓越大。
    gzip_min_length 1000;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;
    # 1~9,默認為1,數值越大,壓縮率越高,CPU占用越多,時間越久
    gzip_comp_level 3;
    gzip_vary on;
    # 禁用對 IE 6 使用 gzip 壓縮
    gzip_disable "MSIE [1-6]\.";
    gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;

    ## Individual nginx logs
    access_log  /var/log/nginx/web_proxy_access.log;
    error_log   /var/log/nginx/web_proxy_error.log;

    location / {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass http://tornadoes;
    }
}

重啟 nginx

service nginx restart

todo

URL 訪問控制,訪問列表


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM