怎么用python写一个反向代理

Python011

怎么用python写一个反向代理,第1张

import BaseHTTPServer

import hashlib

import os

import urllib2

class CacheHandler(BaseHTTPServer.BaseHTTPRequestHandler):

    def do_GET(self):

      m = hashlib.md5()

      m.update(self.path)

      cache_filename = m.hexdigest()

      if os.path.exists(cache_filename):

          print "Cache hit"

          data = open(cache_filename).readlines()

      else:

          print "Cache miss"

          data = urllib2.urlopen("http://targetserver" + self.path).readlines()

          open(cache_filename, 'wb').writelines(data)

      self.send_response(200)

      self.end_headers()

      self.wfile.writelines(data)

def run():

    server_address = ('', 8000)

    httpd = BaseHTTPServer.HTTPServer(server_address, CacheHandler)

    httpd.serve_forever()

if __name__ == '__main__':

    run()

介绍NGINX和Python如何配合使用

Python以易用,有趣而出名,它让软件开发变得简单,据说运行性能也高于其他脚本语言(PHP最新版本PHP 7的性能好像可以与Python一较高下)

每一个人都希望自己的网站或应用可以运行得更快。但是每一个网站在大流量和流量激增时都容易遇到性能问题,甚至当机,业务繁忙时,这种情况会更加糟糕。其实无论流量是稳定增长,还是陡峭增长,所有网站都面临性能和当机的困扰。

NGINX和NGINX插件的出现就是为了解决这个问题。他们通过三种不同的方式来改善网站性能:

1、web服务 – 最初开发NGINX是为了解决 C10K 问题 – 可以轻松支撑10,000或更多的并发连接。使用NGINX为你的Python应用提供web服务,可以让你的网站运行更快,即便在小流量的情况下也有效果。当你的用户成千上万时,确定无疑,它可以提供更高的性能,更少的崩溃,以及更少的当机时间。你也可以使用NGINX提供静态文件缓存或者微缓存服务,一个独立的NGINX反向代理也是很好的选择(见下一段)。

2、反向代理– 你可以在应用服务的前端用NGINX做反向代理。NGINX接收Web请求并分发到你的应用服务。这个“怪招”可以让你的网站运行得更快,减少当机,消费更少的服务资源,而且可以提高安全性。你也可以在反向代理服务器上缓存静态资源(非常高效),添加静态内容的微缓存,以减少应用自身的负载,等等。

3、为多个应用服务提供动态均衡 – 通过布署反向代理服务。通过多应用服务并行运行和NGINX或者NGINX插件来做流量负载均衡。通过这种布署,根据流量需要,增长稳定性和运行时间需要,你可以很轻松地在线扩展网站性能。如果你需要让给定用户的会话在同一个服务上,你只需要配置负载均衡以支持会话持久化。

不管是为你的Python应用提供网站服务,还是做反向代理服务,还是做负载均衡,或者三者都用,NGINX和NGINX插件都会给你带来优势。

这是本系列(由两部分组成)中的第一篇文章,将会介绍五个提升Python应用性能的技巧,包括如何使用NGINX或NGINX插件提供web服务,如何实现静态文件的缓存,如何为动态内容做微缓存。在第二部分,我们将介绍如果用NGINX或NGINX插件提供反向代理服务,以及如何为多个应用服务提供负载均衡。

技巧 1– 定位Python性能瓶颈

有两种截然不同的情况会让你的Python应用遇到性能问题– 第一,每天有海量用户;第二,高负载。大部分网站长都不需要担心性能问题,因为他们的负载很小,根据我们的拙见,他们应该努力降低响应时间。将响应时间控制在毫秒级是一个非常困难且不被关注的工作。但可以让我们的用户体验更好,业绩更优秀。

但是这篇博文和剩下的第二部分,将关注每个人都确实关注的场景:当网站繁忙时可能会出现的性能问题,如性能大幅下降和当机。还有黑客模拟大量用户攻击造成的流量激增,同时提高网站性能也是处理攻击的重要步骤。

像Apache HTTP Server这样的系统会为每个用户分配一定数量的内存,随着用户的不断增加,物理内存不堪重负。服务器开始使用磁盘的交换分区,性能直线下降,性能问题和当机接踵而至。这篇博文中所介绍的迁移到NGINX,有助于解决这一问题。

Python特别容易出现内存相关的性能问题,因为与其他脚本语言相比,Python通常是使用更多的内存来执行任务(所以执行速度快)。所以在相同条件下,与用其他语言写的应用相比,你的Python应用更容易在少量用户的情况下而“绊倒”。

优化你的应用对解决问题会有所帮助,但要解决流量相关的性能问题,这通常不是最好最快的方式。这篇博文及剩下的第二部分,将介绍一种最好并且最快的方式。在实施这些措施之后,再采取一切方法优化你的应用,或者使用微服务架构重写。

技巧 2 – 选择单服务或者微服务布署

小网站在单个服务器上就可以运行得很好。大的网站需要多个服务器。但如果你处于中间地带–或者你的网站从一个小网站变成一个大网站– 你可以做一些有趣的选择。

如果你使用单机布署,大流量和浏览激增会给你带来很大的风险。你的扩展手段非常有限,无外乎优化你的应用,把web服务切换到NGINX,使用一个更大更快的服务器,或者使用内容分发网络(CDN)。所有这些可选项的实施都耗时耗钱,而且在实施过程中还有引入bug的风险。

另外一个很显然的风险是单机布署存在单点故障问题 – 很多问题可以导致你的站点挂掉,而且没有快速简单的解决方案。

使用NGINX做为应用的代理服务

如果你把服务切换成NGINX并且使用单机布署,你可以自由地选择使用开源的NGINX或者NGINX插件。NGINX包括企业级支持和一些扩展功能。像实时活动监测这样的扩展功能是支持单机布署的。如果做为反向代理,采用分布式布署,你可以使用其他NGINX插件,如负载均衡和会话持久化。

有很多事情都要考虑周详,除非你确定你的网站在未来很长时间内都是一个小网站,不需要关心当机问题,否则,你要明白,单机布署存在很多风险。分布式布署比较易于扩展 – 单点故障可以通过工程解决,性能可以按需调整,可以快速扩充服务器能力。

技巧 3 – 使用NGINX替换你的Web服务

在Web时代的早期,Apache就是web服务的同义词。但NGINX自2000年出现以来,迅速流行开来;现在已经是排名第一的web服务,被1,000, 10,000多个网站和世界上最繁忙的100,000多个网站使用。

NGINX最初是为了解决C10K问题而开发 – 在给定内存预算下支持10,000+并发。其他web服务需要为每个连接分配内存块,所以他们会耗尽物理内存,当数以千记的用户在同一时间访问一个网站,它会变慢甚至崩溃。NGINX处理器可以单独处理一个请求,也可以优雅地扩展,同时处理多个用户。(这可以很好地解决额外问题,后面会详述。)

一个高层NGINX架构图如下所示。

NGINX 架构, 选自开源应用架构第二卷

在上图,一个Python应用服务被布署在后端的应用服务块中,如图所示,它通过FastCGI被访问。NGINX不“知道”怎么运行Python,所以它需要一个网关连结需要的环境。FastCGI是一个被PHP,Pyhton和其他语言广泛使用的接口。

但是,连结Python和NGINX的流行方案是网络服务网关接口(WSGI)。WSGI工作在多线程和多进程环境下,所以他兼容本文所提到的所有布署选项。

如果你将web服务迁移到NGINX,这里有一些有用的软件:

Configuring gunicorn – “Green Unicorn”是一个流行的WSGI服务,配合NGINX使用。

Configuring uWSGI – 另一个流行的WSGI服务,配合NGINX使用. uWSGI包含NGINX指令支持。

Using uWSGI, NGINX, and Django – 一个流行的Python web框架。

下面的代码片断将向你展示如何配置NGINX和uWSGI – 这个案例中的工程使用Python框架Django。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

http

{

...

upstream

django {

server

127.0.0.1:29000

}

server

{

listen

80

server_name

myapp.example.com

root

/var/www/myapp/html

location

/ {

index

index.html

}

location

/static/

{

alias

/var/django/projects/myapp/static/

}

location

/main {

include

/etc/nginx/uwsgi_params

uwsgi_pass

django

uwsgi_param

Host $host

uwsgi_param

X-Real-IP $remote_addr

uwsgi_param

X-Forwarded-For $proxy_add_x_forwarded_for

uwsgi_param

X-Forwarded-Proto $http_x_forwarded_proto

}

}

}

技巧 4 – 实现静态文件缓存

缓存静态内容包括:为不经常变更的文件保存副本 – 不经常是指数小时或者永远 – 副本保存在其他位置而不是应用服务中。典型的静态内容是网页中经常用到的JPEG图片。

缓存静态文件是提升应用性能的常用手段,经常被用到:

1、用户浏览器

2、互联网提供商 – 从公司网络到互联网提供商(ISP)

3、web服务, 也就是本文所讲的

在web服务端实现静态文件缓存有两个好处:

1、为用户提供快速服务 – NGINX 专门为静态文件缓存做过优化,对静态内容请求的处理比应用服务要快。

2、减少应用服务负载– 应用服务不需要处理已经缓存的静态文件,已经由web服务接管。

缓存静态文件在单服务器上也可以很好的实现,但底层硬件资源仍然是由web服务和应用服务所共享。如果web服务要处理频率的静态文件访问 – 甚至是海量 – 应用服务可以使用的硬件资源就会变少,一些功能可能就会变慢。

如果要支持浏览器缓存,需要正确设置静态文件的头部信息。如HTTPCache Control(特别是它的max age设置),Expires,和Entity标记。如果想深入了解,参见NGINX Plus的管理员指南:使用NGINX为uWSGI和Django提供应用网关

下面的NGINX配置代码用来缓存静态文件,包括JPEG文件,GIF文件,PNG文件,MP4文件,Powerpoint文件,和一些其他文件,请把www.example.com替换成你自己的网址。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

server

{

#

substitute your web server's URL for

"www.example.com"

server_name

www.example.com

root

/var/www/example.com/htdocs

index

index.php

access_log

/var/log/nginx/example.com.access.log

error_log

/var/log/nginx/example.com.error.log

location

/ {

try_files

$uri $uri/ /index.php?$args

}

location

~ \.php$ {

try_files

$uri =404

include

fastcgi_params

#

substitute the socket, or address and port, of your Python server

fastcgi_pass

unix:/var/run/php5-fpm.sock

#fastcgi_pass

127.0.0.1:9000

}

location

~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg

|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid

|midi|wav|bmp|rtf)$

{

expires

max

log_not_found

off

access_log

off

}

}

技巧 5 – 实现微服务

微缓存可以很明显的大幅提升Python, PHP和一些其他语言开发的应用服务性能,根据是否适合缓存,可以把网页分成三类:

静态文件 – 这类文件适合缓存,见技巧4所述。

动态,非个性化页面 – 因为它们需要刷新,这些文件通常不适合做缓存。例如未登录前的电商用户所看到的页面(见下一点) – 可用商品和推荐相似商品经常要发生改变,所以必须生成新页面。但是,如果有另外一个用户,在10毫秒之后发送同样请求,将前一用户看到的网页缓存并发送给后一用户就变得合情合理。

动态,个性化页面 –这些不适合缓存,因为它们是针对具体用户的,同一个用户不希望两次看到同一个个性化页面。例如一个电商用户登录后的页面不应该展示给另外一个用户。

静态文件和非个化性动态内容可以缓存

微缓存适用于上面提到的第二类页面–动态,非个性化页面。“微”是指很短的时间。如果你的网站在一秒内要多次生成同一个页面,如果你把这个页面只缓存一秒,并不影响该页面的刷新。但这个短暂的缓存可以极大的降低应用服务的负载,特别是流量较大时。将原来在一个缓存区间内,同一内容生成10,或者20,甚至100次,调整为只生成一次并缓存,为其他用户提供缓存内容。

这个效果是很神奇的。一个服务如果一秒钟要处理大量请求会变得很慢,但如果只处理一个请求,就会变得很快。(包括任何个性化页面)。我们自己的Owen Garrett有一篇博客对微服务的优势做了详情介绍,里面还有配置代码。主要要修改的地方是把代理缓存过期时间设为一秒,只需要几行配置代码就可以搞定。

1

2

3

4

5

6

proxy_cache_path

/tmp/cache keys_zone=cache:10m levels=1:2

inactive=600s max_size=100m

server

{

proxy_cache

cache

proxy_cache_valid

200

1s

...

}

更多配置样例,参见Tyler Hicks Wright关于Python和uWSGI如何使用NGINX的博客。

总结

在第一部分,我们回顾了一下在单机环境下提高Python应用性能的解决方案,还有缓存的使用,在单机情况下缓存可以应用于反向代理服务器或者独立缓存服务(缓存比独立服务性能更好)。在下一部分,我们将会介绍分布式环境下的性能提升方案。

如果你想在应用中使用更多的NGINX Plus特性,如实时事件监测,在线修改配置,你可以马上开通30天免费试用,或者联系我们,可以获得一个真实例子。

刚接触的一个涉及实时通信的h5项目,前期开发没遇到什么大问题,在pc端chrome调试都一切正常,

用手机访问页面时,却出现了一个问题,node启动服务的命令行界面并没有打印出用户访问页面的信息,

也就是说手机端的页面没有连接到websocket服务,且本地计算机和手机是连的是同一个wifi,也就是说网络环境相同,

那为何会造成本地调试可行,而手机访问又不能连接websocket服务呢?

在网上查找的各种资料,其实基本都与此问题无关,

最后突然想起前段时间做过的一个python项目,在linux搭建的环境为gunicorn+python+nginx , 而gunicorn充当的就是一个启动python环境的角色,而gunicorn访问的是localhost+端口,再利用nginx做反向代理,这个项目非常类似,于是我想到了做nginx反向代理。

nginx反向代理简单解释,用户访问页面,由nginx转接,转到服务器端的内部开放端口(不对外)。

问题原因:

手机端进入页面时访问的是内网ip,这时nginx能识别内网ip,并转到对应的项目上,但是页面js调用的socket= io('ws://内网ip:3000'),并不能直接访问websocket,会先转到nginx,再由nginx来访问websocket服务,websocket所开放的端口,相当于内部端口,并不能对外访问

解决办法:

1. 修改html的js,var socket = io('ws://内网ip:81') 这里的81并不是websocket的访问端口,而是nginx的访问端口

2. 做反向代理(配置如下)

配上wsServer.js

index.html