因为一个奇怪的需求,使用 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 访问控制,访问列表

基于 Tornado 实现的 Web 站点反向代理的更多相关文章

  1. Nginx做web服务器反向代理

    实验目的 通过nginx实现反向代理的功能,类似apache反向代理和haproxy反向代理 工作中用nginx做反向代理和负载均衡的也越来越多了 有些公司从web服务器到反向代理,都使用nginx. ...

  2. 基于Windows 配置 nginx 集群 & 反向代理

    1.下载 nginx 下载页面 : http://nginx.org/en/download.html 具体文件: http://nginx.org/download/nginx-1.7.0.zip ...

  3. 浅析web网站反向代理的配置

    一.背景 最近在部署项目到web服务器上时,该项目有一个打开视频监控的功能,视频的服务器是一台内网的服务器,不允许设置外网端口访问,网站服务器和视频服务器在同一个局域网内,可以相互联通.网络拓扑图如下 ...

  4. 通过Apache配置web服务器反向代理

    - 第一步: 到安装好的apache文件目录conf文件下,找到httpd.conf文件 找到如下配置,去掉#可以启动HTTP反向代理功能 : LoadModule proxy_module modu ...

  5. 基于.NET的大型Web站点StackOverflow架构分析(转)

    Stack Overflow网址:http://stackoverflow.com/ 当前访问量:每月9500PV(每天300多万PV) 当前Alexa排名:149 所用.NET技术:C#.Visua ...

  6. 基于tornado实现的web聊天室

    目录结构: # -*- coding:utf-8 -*- import uuid import json import tornado.ioloop import tornado.web import ...

  7. 基于nginx和tengine的tcp反向代理,负载均衡 安装和配置

    先下载nginx_tcp_proxy_module模块. wget https://github.com/yaoweibin/nginx_tcp_proxy_module/archive/master ...

  8. 关于NGINX在wnidows下面和linux下面的多站点的反向代理的配置

    原创文章,转载注明出处 nginx作为一款优秀的反向代理软件,以其好用,易于搭建负载均衡的网站集群而著称,这里分别记录一下工作中用到nginx作为负载以及多站点发布的时候一些配置和注意事项 一  ng ...

  9. Nginx 反向代理、负载均衡、页面缓存、URL重写以及读写分离

    1.环境准备 前端Nginx:10.160.65.44 后端WEB服务器两台:10.160.65.49/10.160.65.50 2.安装Nginx: 下载nginx-1.9.15.tar.gz,放置 ...

随机推荐

  1. POJ 3279 Fliptile 状态压缩,思路 难度:2

    http://poj.org/problem?id=3279 明显,每一位上只需要是0或者1, 遍历第一行的所有取值可能,(1<<15,时间足够)对每种取值可能: 对于第0-n-2行,因为 ...

  2. CSS中em、rem和px的区别

    任意浏览器的默认字体高都是16px.所有未经调整的浏览器都符合: 1em=16px,1rem=16px. EM特点  1. em的值并不是固定的: 2. em会继承父级元素的字体大小. rem特点 r ...

  3. 重写vector类,完成基本功能,不含迭代器

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  4. synchronized一个(二)

    今天遇到了一个关于synchronized的一个问题,关于其持有锁的问题.这个问题以前是有看过相关文章的,但是一直没有记录,今天大概记录一下当前的认知. 对于静态方法,synchronized的使用的 ...

  5. C# 序列化详解,xml序列化,json序列化对比

    本文讲讲一些纯技术的东西.并且讲讲一些原理性的东西,和一般的百度的文章不一致,如果你对序列化不清楚,绝对可以很有收获. 技术支持QQ群(主要面向工业软件及HSL组件的):592132877  (组件的 ...

  6. cool 软件 —— Carnac(实时桌面显示按键)

    1. Carnac 下载地址:Carnac, the Magnificent Keyboard Utility 使用说明:carnac – 在屏幕实时显示按键操作

  7. 响应: 500 OOPS: priv_sock_get_int 错误: 读取目录列表失败

    /************************************************************************* * 响应: 500 OOPS: priv_sock ...

  8. BZOJ5312: 冒险【线段树】【位运算】

    Description Kaiser终于成为冒险协会的一员,这次冒险协会派他去冒险,他来到一处古墓,却被大门上的守护神挡住了去路,守护神给出了一个问题, 只有答对了问题才能进入,守护神给出了一个自然数 ...

  9. AlertDialog中使用ListView绑定数据

    在实际工作过程中,单单使用AlertDialog的单选功能不一定能满足我们的需求,需要绑定数据到 listview 1. 自定义Layout LayoutInflater factory = Layo ...

  10. Python threadpool传递参数

    threadpool模块是一个很老的实现python线程池的模块,pypi已经建议用multiprocessing代替它了,但是,它使用的便捷性还是征服了一批忠实用户. threadpool模块实现多 ...