一种多屏时代的通用 web 应用架构
DESCRIPTION
2013-5-19 珠三角技术沙龙分享主题。TRANSCRIPT
一种多屏时代的通用 web 应用架构
赖勇浩 @ 珠三角技术沙龙2013-5-19
自我介绍
● game → webgame → web● 珠三角技术沙龙组委、发起人之一● PyCon China 2011/2012 讲师
– Python 于 webgame 的应用– 页游开发中的 Python 组件与模式
● http://laiyonghao.com/
内容概述
● Web 架构的变迁● 实践经验分享● 未来之路
Web 架构的变迁( 1 )
browser server
text/html
多屏时代有点不同。
Web 架构的变迁( 2 )
browser
serverwap browser
app
Web 架构的变迁( 2 )
● 问题:– 返回什么?
Web 架构的变迁( 2 )
● def request_wants_json():● best = request.accept_mimetypes \● .best_match(['application/json', 'text/html'])● return best == 'application/json' and \● request.accept_mimetypes[best] > \● request.accept_mimetypes['text/html']
Web 架构的变迁( 2 )
● @app.route('/')● def show_items():● items = get_items_from_database()● if request_wants_json():● return jsonify(items=[x.to_json() for x in items])● return render_template('show_items.html',
items=items)
插播: Accept
插播: mimerender
● mimerender = mimerender.FlaskMimeRender()
● render_xml = lambda message: '<message>%s</message>'%message
● render_json = lambda **args: json.dumps(args)● render_html = lambda message:
'<html><body>%s</body></html>'%message● render_txt = lambda message: message
插播: mimerender
● @app.route('/')
● @app.route('/<name>')
● @mimerender(
● default = 'html',
● html = render_html,
● xml = render_xml,
● json = render_json,
● txt = render_txt
● )
● def greet(name='world'):● return {'message':
'Hello, ' + name + '!'}
● if __name__ == "__main__":
● app.run(port=8080)
插播: mimerender
● How to get it
– mimerender is in PyPI, so it's as easy as doing:– $ pip install mimerender
Web 架构的变迁( 2 )
browser
server
text/html
wap browser
app
text/vnd.wap.wml
application/json
Web 架构的变迁( 3 )
● 如果可以通过短信( SMS )使用业务……
Web 架构的变迁( 3 )
browser
adapter
text/html
wap browser
app
text/vnd.wap.wml
application/json
adapter
adapter
server
adapterSMS
application/json
Web 架构的变迁( 3 )
browser
adapter
text/html
wap browser
app
text/vnd.wap.wml
application/json
adapter
adapter
server
adapterSMS
application/json
?
Web 架构的变迁( 3 )
● 业务与展现分享– server 专注业务实现,只需要提供 http api ,无须理会数
据展现形式;– adapter 的业务简单,只需要维护会话,并对请求 / 响应进
行转换;● 易于分工
– 内部可以分小组– 甚至外包(解决了我团队不熟悉短信中心协议的问题)
● 易于扩展– 支持更多设备(如自助终端、语音电话)
Web 架构的变迁( 3 )
● 安全:对数据进行签名– client-id 、 client-key– sha1 – 让 Date header 必填来确保每次请救不同
实践经验分享
● Flask-RESTful
– https://github.com/twilio/flask-restful
Flask-RESTful: Argument Parsing
● parser = reqparse.RequestParser()● parser.add_argument('rate', type=int, help='Rate to
charge for this resource')● args = parser.parse_args()
● 支持必填项、多值项、重命名● 可从 post body 、 query
string 、 headers 、 cookies 、 file uploads 中读取
Flask-RESTful: Output Fields
● resource_fields = {● 'name': fields.String,● 'address': fields.String,● 'date_updated': fields.DateTime,● }● class Todo(Resource):● @marshal_with(resource_fields)● def get(self, **kwargs):● return db_get_todo() # Some function that queries the db
Flask-RESTful: Output Fields
● Renaming Attributes● Default Values● Custom Fields & Multiple Values● Url Field● Complex Structures● List Field● Nested Field
Flask-RESTful: Resource Method Decorators
● def authenticate(func):● @wraps(func)● def wrapper(*args, **kwargs):● ...● class Resource(restful.Resource):● method_decorators = [authenticate] # applies to all
inherited resources
测试
● 一般情况下使用 curl 足矣– $ curl http://localhost:5000/todos/todo3– {"task": "profit!"}
chtest
● $ chtest --help● usage: chtest [-h] [--config-file CONFIG_FILE] --path
PATH [--method METHOD]● [--arg ARG] [--header HEADER] [--ensure-status
ENSURE_STATUS]● [--ensure-header ENSURE_HEADER]● [--ensure-content ENSURE_CONTENT] [--print-
header PRINT_HEADER]● [--print-json-path PRINT_JSON_PATH]
requests
● chtest is requests powered● Requests: HTTP for Humans
– >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))– >>> r.status_code– 200– >>> r.headers['content-type']– 'application/json; charset=utf8'– >>> r.text– u'{"type":"User"...'– >>> r.json()– {u'private_gists': 419, u'total_private_repos': 77, ...}
未来之路
● http-based VS tcp-based● Behavior-Driven Development
Web 架构的变迁( 3 )
browser
adapter
text/html
wap browser
app
text/vnd.wap.wml
application/json
adapter
adapter
server
adapterSMS
RPC ??
RPC 优劣
● 优势– 减少连接数– 更小的数据包– 乱序返回– 握手后的数据不需要签名( SSL/TLS )
● 劣势– 不能利用 HTTP 的基础设施– 需要学习好多新东西
lettuce.it
● Feature: Manipulate strings
● In order to have some fun
● As a programming beginner
● I want to manipulate strings
● Scenario: Uppercased strings
● Given I have the string "lettuce leaves"
● When I put it in upper case
● Then I see the string is "LETTUCE LEAVES"
lettuce.it
● >>> @step('I have the string "(.*)"')● ... def have_the_string(step, string):● ... world.string = string● >>> @step('I put it in upper case')● ... def put_it_in_upper(step):● ... world.string = world.string.upper()● >>> @step('I see the string is "(.*)"')● ... def see_the_string_is(step, expected):● ... assert world.string == expected, \● ... "Got %s" % world.string
lettuce.it
● from lettuce import step● from nose.tools import assert_equals
● @step('some step with "(.*)"'):● def some_step(step, from):● assert_equals(from, 'expectation')
End.
Thanks.
@laiyonghao
额外赠送: flask-pypi-proxy
您值得拥有。