服务框架: Thrift & PasteScript

6,935 views
6,744 views

Published on

2 Comments
37 Likes
Statistics
Notes
No Downloads
Views
Total views
6,935
On SlideShare
0
From Embeds
0
Number of Embeds
24
Actions
Shares
0
Downloads
252
Comments
2
Likes
37
Embeds 0
No embeds

No notes for slide

服务框架: Thrift & PasteScript

  1. 1. : Thrift & PasteScript BPUG, Sep, 2010
  2. 2. • IaaS - Infrastructure as a Service • PaaS - Platform as a Service • SaaS - Software as a Service
  3. 3. • • • • • /
  4. 4. Service
  5. 5. HTTP + web.py import web import urllib urls = ('/add', 'add') def add(a, b): f = urllib.urlopen('http:// class add: calculator.services.douban.com/add?a=%s&b= def GET(self): %s' % (a, b)) i = web.input() r = f.read() r = int(i.a) + int(i.b) return int(r) return str(r) app = web.application(urls, globals) if __name__ == '__main__': app.run()
  6. 6. • • JSON • HTTP overhead
  7. 7. Thrift http://incubator.apache.org/thrift/
  8. 8. Thrift • • C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, OCaml • • struct, list, set, map • • oneway calling • RPC
  9. 9. Thrift Example struct UserProfile { 1: i32 uid, class UserStorageHandler : virtual public UserStorageIf { 2: string name, public: 3: string blurb UserStorageHandler() { } // Your initialization goes here service UserStorage { } void store(1: UserProfile user), UserProfile retrieve(1: i32 uid) void store(const UserProfile& user) { } // Your implementation goes here printf("storen"); } void retrieve(UserProfile& _return, const int32_t uid) { # Make an object // Your implementation goes here up = UserProfile(uid=1, printf("retrieven"); name="Mark Slee", } blurb="I'll find something to put here.") }; # Talk to a server via TCP sockets, using a binary protocol int main(int argc, char **argv) { transport = TSocket.TSocket("localhost", 9090) int port = 9090; transport.open() shared_ptr<UserStorageHandler> handler(new UserStorageHandler()); protocol = TBinaryProtocol.TBinaryProtocol(transport) shared_ptr<TProcessor> processor(new UserStorageProcessor(handler)); shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); # Use the service we already defined shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFac service = UserStorage.Client(protocol) shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory( service.store(up) TSimpleServer server(processor, serverTransport, transportFactory, proto server.serve(); # Retrieve something as well return 0; up2 = service.retrieve(2) }
  10. 10. Thrift thrift package generated code Protocol Processor (binary) (dispatcher) Transport Handler (socket) (app code)
  11. 11. Thrift • • •
  12. 12. • • •
  13. 13. PasteScript http://pythonpaste.org/script/
  14. 14. Paste • WSGI • • Paste • PasteScript • PasteDeploy
  15. 15. PasteScript • paster serve • templates
  16. 16. paster serve • paster serve --reload --monitor-restart development.ini [server:main] use = egg:Paste#http host = 0.0.0.0 port = 5000 [app:main] use = egg:MyWSGIApp # Logging configuration [loggers] keys = root, access_log ...
  17. 17. Thrift server app Protocol Processor (binary) (dispatcher) Transport Handler (socket) (app code)
  18. 18. paster serve • paster serve --reload --monitor-restart development.ini [server:main] use = egg:DoubanService#thread_pool port = 9090 pool_size = 10 [app:main] use = egg:CalculatorServer # Logging configuration [loggers] keys = root, access_log ...
  19. 19. setuptools entry points DoubanService/setup.py: entry_points = """ [paste.server_runner] thread_pool = doubanservice.server:thread_pool_server_runner """ CalculatorServer/setup.py: entry_points = """ [paste.app_factory] main = calculator_server.makeapp:make_app """
  20. 20. app from .gen.calculator import Iface, Processor from .app import Handler def make_app(global_config, **local_conf): handler = Handler() processor = Processor(handler) return processor
  21. 21. server runner def thread_pool_server_runner(app, global_conf, **kwargs): for name in ['port', 'pool_size']: if name in kwargs: kwargs[name] = int(kwargs[name]) pool_size = kwargs.pop('pool_size') host = kwargs.pop('host', '0.0.0.0') transport = TSocket.TServerSocket(**kwargs) transport.host = host tfactory = TTransport.TBufferedTransportFactory() pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = ThreadPoolServer(app, transport, tfactory, pfactory) if pool_size: server.threads = pool_size server.serve()
  22. 22. • (paster serve) • ([server:main] use) • • (--reload) • ([loggers])
  23. 23. Paste Template DoubanService/setup.py: entry_points = """ [paste.server_runner] thread_pool = doubanservice.server:thread_pool_server_runner [paste.paster_create_template] doubanservice = doubanservice.templates:DoubanServiceTemplate doubanservice_server_py = doubanservice.templates:ServerPyTemplate doubanservice_client_py = doubanservice.templates:ClientPyTemplate """ paster create -t doubanservice calculator
  24. 24. doubanservice template class DoubanServiceTemplate(paste.script.templates.Template): _template_dir = 'doubanservice' summary = "A DoubanService project" def post(self, command, output_dir, vars): for filename in ['gen', 'create-server', 'create-client']: os.chmod(os.path.join(output_dir, filename), 0755) doubanservice/templates/doubanservice/ ├── +package+.thrift_tmpl ├── create-client_tmpl ├── create-server_tmpl vi calculator.thrift └── gen_tmpl ./create-server py ./create-client py ./gen
  25. 25. server_py template doubanservice/templates/server-py/ ├── +package+ │   ├── __init__.py │   ├── app.py_tmpl │   └── makeapp.py_tmpl ├── development.ini_tmpl ├── gen_tmpl ├── production.ini_tmpl ├── remote_tmpl ├── scripts │   └── censor-server-py ├── serve vi calculator_server/app.py ├── setup.cfg ./serve ├── setup.py_tmpl └── tests ./remote add 1 2
  26. 26. client_py template doubanservice/templates/client-py ├── +package+ │   ├── __init__.py class Client(BaseClient): │   └── client.py_tmpl __metaclass__ = ClientMetaClass ├── gen_tmpl service_name = '${service}' ├── setup.py_tmpl thrift_module = ${service}_genmod └── tests port = 9090 connect_timeout = 1000 read_timeout = 5000 ${service} = Client() from calculator_client import calculator print calculator.add(1, 2)
  27. 27. Demo a calculate service
  28. 28. A New OpenSource Project...
  29. 29. OneRing Build Desktop Applications Using Web Technology http://code.google.com/p/onering-desktop/
  30. 30. • Web • HTML5+CSS3 / • Javascript / • AJAX • • Qt (mac, windows, linux) • Cairo (windows, linux) • WebKit Framework (mac) • • C API DLL • Python - WSGI
  31. 31. #!/usr/bin/env python import json import web import onering urls = ( '/init', 'init', '/', 'index', ) class init: def GET(self): web.header('Content-Type', 'application/json') return json.dumps({'width': 400, 'height': 300, 'url': '/'}) class index: def GET(self): web.header('Content-Type', 'text/html') return """<html> <head><script type="text/javascript" src="onering://onering/onering.js"></script></head> <body> <p>Hello, world!</p> <button onclick="javascript:ONERING.exit()">Exit</button> </body></html>""" app = web.application(urls, globals()) if __name__ == '__main__': onering.register_wsgi_app("demo", app.wsgifunc()) onering.loop("demo")
  32. 32. Join Us If You Know... • C++ / C / Objective-C / Python • Qt / win32 / Cocoa / GTK • WebKit / Gecko • Javascript / HTML5 • Python C API / py2exe / py2app • C • Win/Mac/Linux •
  33. 33. • • HTML5 •
  34. 34. Thanks Q &A

×