一层一层说网站 python wsgi 简介 及 常用中间件 张沈鹏 42qu.com 作者....
TRANSCRIPT
一层一层说网站PYTHON WSGI 简介 及 常用中间件
张沈鹏 42qu.com 作者
著名的洋葱
请求 (Request) 的构成1. 网址 : 用户输入
2. COOKIE: 网站设置
3. 其他 HTTP 头 : 浏览器
GET /@zsp HTTP/1.1Host: kanrss.comUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-cn,zh;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: GB2312,utf-8;q=0.7,*;q=0.7Keep-Alive: 115Connection: keep-aliveCookie: B=kwyP64YM; __utma=5797929.751142743.1280312171.1280312171.1280312171.1; __utmb=5797929.5.10.1280312171; __utmz=5797929.1280312171.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); Hm_lvt_fc05ad55c7dcadfd714baf512f9146b3=1280312172072; Hm_lpvt_fc05ad55c7dcadfd714baf512f9146b3=1280312287556; __utmc=5797929Cache-Control: max-age=0
响应 Response 构成
HTTP/1.1 200 OKServer: nginx/0.7.65Date: Wed, 28 Jul 2010 10:24:29 GMTContent-Type: text/html; charset=UTF-8Connection: keep-aliveContent-Encoding: gzipContent-Length: 6241
<!doctype html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><link href="http://stdyun.net/css/a6hYw~g.css" rel="stylesheet" type="text/css"><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script><script src="/js/~QFhCQ~s.js"></script><title> 张沈鹏 (KanRSS.com/ 码农 行业 :互联网 )</title></head><body><div id="h"><div class="C"><div id="hnav"><a href="/"> 首页 </a> <a href="/auth/apply"> 注册 </a> <a href="/auth/login"> 登录 </a></div></div></div><div class="C"><div class="at"> <div class="atimg"> <a href="/auth/login?path=/%40zsp" class="bwc" onclick="return poplogin('/@zsp')"> 追随 </a><div><a href="/@zsp"><img class="img9
常见洋葱核结构 简化图
Request Parser
Model
Control
URL Route Template
WSGI Server
Request
Nginx DNS
CGI -> WSGIhttp://www.python.org/dev/peps/pep-0333/
def run_with_cgi(application): environ = dict(os.environ.items()) environ['wsgi.input'] = sys.stdin environ['wsgi.errors'] = sys.stderr environ['wsgi.version'] = (1,0) environ['wsgi.multithread'] = False environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] = True if environ.get('HTTPS','off') in ('on','1'): environ['wsgi.url_scheme'] = 'https' else: environ['wsgi.url_scheme'] = 'http'.................
os.environ
http://angeloce.javaeye.com/blog/523242
REQUEST_METHOD -> GET 或 POST
PATH_INFO -> /xxx/xx
QUERY_STRING -> 在 "?" 后面的请求 URL 部分 . 可以为空
HTTP_ Variables -> 与客户端支持的 HTTP 请求头一致的变量 .( 也就是以 "HTTP_" 开头命名的变量 .) 这些变量是否出现都要与 HTTP 请求头中的变量保持一致 .
...............
WSGI Serverimport tornado.wsgiimport tornado.httpserverimport tornado.ioloop
def WSGIServer(port, application):container = tornado.wsgi.WSGIContainer(application)http_server = tornado.httpserver.HTTPServer(container)http_server.listen(port)tornado.ioloop.IOLoop.instance().start()
洋葱核def app(environ, start_response): status = '200 OK'
response_headers = [('Content-type','text/plain'),
]
start_response(status, response_headers) return ['Hello']
1. environ2. start_response3. return ['xxxx']
Request Parser
• yaro - Yet Another Request Object• http://lukearno.com/projects/yaro/1. 简化 environ 的访问environ['QUERY_STRING'] hl=zh-CN&source=hp&q=python&aq=f&aqi=&aql=&oq=&gs_rfai=->req.query = {
"hl":"zh-CN","source":"hp",
....
Request Parser
2. 封装 start_responsestatus = '200 OK'response_headers = [('Content-type','text/plain'),]start_response(status, response_headers)return ['Hello']->from yaro import Yaro@Yarodef hello_world(req): return "Hello World!" 当然 , 也被封装一些状态码
yaro.Request.redirect("/xxx/xxx/xxx")301 status
URL RouteURL -> Python Function
http://kanrss.com/at/cloudwu/t/1270561->mysite/ctrl/at/__init__.py
@route_render_funcdef t(id=None): owner = request.owner ...
URL Route常用方式 正则匹配
application = tornado.web.Application([ (r"/", MainHandler), (r"/story/([0-9]+)", StoryHandler),])
class StoryHandler(tornado.web.RequestHandler): def get(self, story_id): self.write("You requested the story " + story_id)
Url Route -- 文件路径映射http://mayoufour.googlecode.com/svn/trunk/mypylib/mypy/urlroute.py 创意衍生自 Quixote查找映射的函数 = {
路径 1 :{路径 2:{
模块名 : 函数名称 }
}}
"/at/cloudwu/t/1270561".split("") -> 'at','cloudwu', // 被当作 at._access(id) 函数的参数吃掉't', '1270561', // 被当作 at.t(id) 函数的参数吃掉
Model表 的 映射• CREATE TABLE `user` (• `id` int(10) unsigned NOT NULL AUTO_INCREMENT,• `name` varbinary(24) NOT NULL,• `url` varbinary(60) DEFAULT NULL,• `ver` tinyint(3) unsigned NOT NULL DEFAULT '0',• `state` tinyint(3) unsigned NOT NULL DEFAULT '40',• PRIMARY KEY (`id`),• UNIQUE KEY `url` (`url`),• KEY `state` (`state`),• KEY `name` (`name`)• )->user.name , user.state
Model表的行为ban_user -> 设置 user.state + 删除 user_session 使其退出登录
表 与的 表 互动table user <=> table user follow->def follower_by_user_id(user_id):....
Control
1. 提交表单的数据格式效验 2. 从 Model 获取页面需要的数据 3. 权限不对的时候 给出错误提示if not user.can_admin(group): G.error = " 你没有权限管理该小组 "
-- 传递变量 --> 模板
模板 %for i in items: <item> <title>${i['title']}</title> <link>${i['link']}</link> <dc:creator>${i['author']}</dc:creator>
<description><![CDATA[${i['desc']}]]></description> <pubDate>$
{format_rfc822_date(i['pubdate'])}</pubDate> <guid isPermaLink="true">${i['link']}</guid> </item> %endfor
被遗忘缓存Model -> memcache -> Control
1. 缓存 id 列表mc_book_section_id_ordered_can_view = McCacheA("BookSectionIdOrderedCanV
iew:%s")
@mc_book_section_id_ordered_can_view("{id}")def book_section_id_ordered_can_view(id):
book_list = book_section_ordered(id)return [
i.id for i in book_list if i.can_view]
2. 缓存对象user_list = User.mc_get_list(user_id_list)
需要在有改动的时候手工清理
被遗忘缓存Template -> memcache -> WSGI Server页面局部的 memcache 缓存<%def name="mycomp" cached="True" cache_tim
eout="300" cache_type="memcached"> other text</%def>
节省取数据 + 模板的开销
一般自动超时失效
被遗忘缓存WSGI Server -> Nginx Proxy Cache -> ... server_name rss_group.kanrss.com;
location ~ ^/(\d+)$ { proxy_pass http://kanrss/vgroup/$1/rss_feed; proxy_cache KFS; proxy_cache_valid 200 304 301 302 30m; proxy_cache_valid any 1m; proxy_cache_key "$host$request_uri"; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; }
比如 RSS (firefox会检查收藏夹中的 rss更新 -> 压力不小 ) 比如 一些不经常变的 Ajax 响应 (比如搜索的自动完成 ?)
还没有说的 ...
•辅助开发• WEB前端优化•异步运行•长连接• OpenID.... ... ....
更多更多 ...• Profile?
更多更多 ...• Debug?
更多更多 ...• Auto Restart ?
https://mayoufour.googlecode.com/svn/trunk/mypylib/mypy/reloader.py
https://mayoufour.googlecode.com/svn/trunk/mypylib/mypy/reload_server.py
42qu.com
区
找到给你答案的人
import syssys.exit()