Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

服务框架: Thrift & PasteScript

7.753 Aufrufe

Veröffentlicht am

服务框架: 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

×