在上一章最简单理解CGI,FastCGI,WSGI 我们将fastcgi规范类比HTTP。下面我们通过一个案例更加明白fastcgi
我们使用的是 nginx作为前端 代理,我们包装了gevent_fastcgi FastCGIServer 作为我们的FastCGI Server。
nginx配置:
1 #user nobody; 2 worker_processes 1; 3 4 #error_log logs/error.log; 5 #error_log logs/error.log notice; 6 #error_log logs/error.log info; 7 8 #pid logs/nginx.pid; 9 10 11 events { 12 worker_connections 1024; 13 } 14 15 16 http { 17 include mime.types; 18 default_type application/octet-stream; 19 20 #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 21 # '$status $body_bytes_sent "$http_referer" ' 22 # '"$http_user_agent" "$http_x_forwarded_for"'; 23 24 #access_log logs/access.log main; 25 26 sendfile on; 27 #tcp_nopush on; 28 29 #keepalive_timeout 0; 30 keepalive_timeout 65; 31 32 #gzip on; 33 34 server { 35 listen 80; 36 server_name localhost; 37 38 #charset koi8-r; 39 40 #access_log logs/host.access.log main; 41 42 location / { 43 root html; 44 index index.html index.htm; 45 } 46 # 所有以.py结尾的都发送到localhost:9000进行处理 47 location ~.py{ 48 fastcgi_pass localhost:9000; 49 fastcgi_param QUERY_STRING $query_string; 50 fastcgi_param REQUEST_METHOD $request_method; 51 fastcgi_param CONTENT_TYPE $content_type; 52 fastcgi_param CONTENT_LENGTH $content_length; 53 fastcgi_param SCRIPT_NAME $fastcgi_script_name; 54 fastcgi_param REQUEST_URI $request_uri; 55 fastcgi_param DOCUMENT_URI $document_uri; 56 fastcgi_param DOCUMENT_ROOT $document_root; 57 fastcgi_param SERVER_PROTOCOL $server_protocol; 58 fastcgi_param HTTPS $https if_not_empty; 59 fastcgi_param GATEWAY_INTERFACE CGI/1.1; 60 fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; 61 fastcgi_param REMOTE_ADDR $remote_addr; 62 fastcgi_param REMOTE_PORT $remote_port; 63 fastcgi_param SERVER_ADDR $server_addr; 64 fastcgi_param SERVER_PORT $server_port; 65 fastcgi_param SERVER_NAME $server_name; 66 } 67 68 #error_page 404 /404.html; 69 70 # redirect server error pages to the static page /50x.html 71 # 72 error_page 500 502 503 504 /50x.html; 73 location = /50x.html { 74 root html; 75 } 76 77 # proxy the PHP scripts to Apache listening on 127.0.0.1:80 78 # 79 #location ~ .php$ { 80 # proxy_pass http://127.0.0.1; 81 #} 82 83 # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 84 # 85 #location ~ .php$ { 86 # root html; 87 # fastcgi_pass 127.0.0.1:9000; 88 # fastcgi_index index.php; 89 # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 90 # include fastcgi_params; 91 #} 92 93 # deny access to .htaccess files, if Apache's document root 94 # concurs with nginx's one 95 # 96 #location ~ /.ht { 97 # deny all; 98 #} 99 } 100 101 102 # another virtual host using mix of IP-, name-, and port-based configuration 103 # 104 #server { 105 # listen 8000; 106 # listen somename:8080; 107 # server_name somename alias another.alias; 108 109 # location / { 110 # root html; 111 # index index.html index.htm; 112 # } 113 #} 114 115 116 # HTTPS server 117 # 118 #server { 119 # listen 443; 120 # server_name localhost; 121 122 # ssl on; 123 # ssl_certificate cert.pem; 124 # ssl_certificate_key cert.key; 125 126 # ssl_session_timeout 5m; 127 128 # ssl_protocols SSLv2 SSLv3 TLSv1; 129 # ssl_ciphers HIGH:!aNULL:!MD5; 130 # ssl_prefer_server_ciphers on; 131 132 # location / { 133 # root html; 134 # index index.html index.htm; 135 # } 136 #} 137 138 }
下面在贴出 FasctCGI Server端的代码:
1 from gevent_fastcgi.server import FastCGIServer 2 from gevent_fastcgi.wsgi import WSGIRequestHandler 3 4 5 def wsgi_app(environ, start_response): 6 print 'Request from ', environ['HTTP_USER_AGENT'] 7 start_response('200 OK', [('Content-type', 'text/html')]) 8 yield '<html><head><title>test fastcgi</title></head><body>' 9 yield '<table border="2">' 10 for k, v in environ.items(): 11 yield '<tr><td>%s</td><td>%s</td></tr>'%(k, v) 12 yield '</table>' 13 yield '</body></html>' 14 15 request_handler = WSGIRequestHandler(wsgi_app) 16 server = FastCGIServer(('127.0.0.1', 9000), request_handler, num_workers=4) 17 server.serve_forever()
使用了生成器的方式,性能比较高。
上面的代码该一下(改成WSGIServer)马上就能切换成 WSGI Server了,我们按照WSGI的规范进行扩展一下,就是一个支持WSGI Web框架了。现在应该很清楚CGI,FastCGI,WSGI技术了吧,只要把这些技术弄明白了,我们就能随意组合HTTP Server 和 运用服务器(FastCGI Server,WSGI Server等)。
分别运行nginx和运行上面的脚本程序.
输入任何以.py结尾的请求,将会输出一张 FastCGI的环境变量的表。例如: localhost/script/test.py
下面汇总一下CGI,FastCGI,WSGI相关的技术文章
CGI 粗谈CGI
FastCGI http://www.fastcgi.com/drupal/node/6?q=node/15
WSGI http://wsgi.readthedocs.org/en/latest/index.html
以及他们之间的关系 Python Web初学解惑之 WSGI、flup、fastcgi、web.py的关系
其实看源码和这些协议的白皮书是最好的,如果还有不明白的可以留言。关于这CGI,FastCGI,WSGI以及相关知识,我研究了一个星期, 都是直接看这些 协议 的标准说明书,也研究了很多实现了这些协议 的服务器,当然基本都是Python源码。所以大家有什么困惑可以互相交流一下。