Nginx+Fastcgi+Webpy惊险之旅

自从去年11月份跳槽之后,就告别了熟悉的c#,涉险Python开发,顺便开始熟悉管理之道

最近一直忙于一个新产品的beta版上线公测,该产品涉及到好几个子系统,为了节约空间,这些子系统全部部署在一台64位Linux机器上,通过不同端口访问,惊险之旅自此开始…

项目情况大致如下

A子系统: nginx管理静态文件,动态请求基于jsonp方式访问不同域名下的网关应用

B子系统: nginx管理静态文件,动态请求通过nginx反向代理映射到fastcgi+webpy模块上,认证方式使用webpy内置的session机制

测试环境包括平时的开发测试和部署之后的内部测试,不久之前测试人员经常跟我反映:

部署在内网中的B子系统在用浏览器登录几分钟之后就出现频繁的404回应,根本无法使用,但在强制清除cookie之后又可以正常使用,不久之后又恢复不能访问现象…

分析

起初我很是奇怪,按理说只有当静态文件不存在时nginx才会返回404错误,而现在访问的是配置在nginx.conf中的一个动态路径,该动态路径请求通过fastcgi最终会映射到某个python class的GET或POST方法中,那为什么nginx会返回404呢?

查阅相关文档之后发现

fastcgi在遇到webpy或其他后端http模块处理极慢的情况下,也就是说超过nginx允许的应答时间,nginx就会对此动态路径请求做出404的应答

针对此情况,我开始着手准备一系列测试和实验

实验

实验一:剥离fastcgi,单独使用webpy,进行压力测试

这个实验很简单,只需要注释掉一行代码,便可以以纯webpy方式访问,基于webpy的python应用main入口一般都是这样:

1

2

3

4

 

if __name__ == "__main__":

    web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func,addr)

    app.add_processor(web.loadhook(session_hook))

    app.run()

 

只需要注释掉第二行即可,之后在终端下运行python <filename>.py,webpy会默认监听本地的8080端口,之后无论是通过浏览器还是其他方式访问相应地址即可

同时,还需要准备一份发起http请求的代码,python用来干这活最简单不过了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

 

import httplib

  

server = "192.168.2.2:8080"

url = "/user/login?username=xxx@domain.com&password=111&rnd=33"

  

class perftest:

    def __init__(self):

        pass

          

    def run(self):

        conn = httplib.HTTPConnection(server)

        for i in range(100):

            try:

                conn.request("GET", url)

                rsp = conn.getresponse()

  

                if 200 == rsp.status:

                    print "headers", rsp.getheaders()

                    content = rsp.read()

                    print "content", content

            except Exception, ex:

                print "ERR:", ex

        conn.close()

 

跑了几次压力之后,webpy扛不住了…开始大面积抛异常,大致意思是python自带的logging模块出错,因为有频繁的文件打开关闭操作,某个操作导致文件句柄被非法访问…

在查看相关的log封装类之后发现,python的日志模块设计实在是有点不够内聚,也可以说不够彻底吧,不由得想起了之前用过的log4net,真是简洁啊

出错的原因在项目中开发同事封装的log模块多次执行了addHandler和removeHandler操作,据说在之前的开发过程中还出现过一行日志打印多遍的情况,而且随着程序的运行,相同的日志会越来越多…

顺手将该封装修改为单例类之后,故障解除

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pspwx.html