## Gevent All The Things Wes Mason [@1stvamp](http://twitter.com/1stvamp)
## Who? - @1stvamp (twitter/github) - Engineer at [ServerDensity](http://www.serverdensity.com/) - I release lots of [open source code](http://git.io/1v)
## Gevent "*[gevent](http://gevent.org/) is a coroutine-based Python networking library that uses greenlet to provide a high-level synchronous API on top of the libevent event loop.*"
## Asynchronous - [Asynchronous != parallel](http://blog.golang.org/concurrency-is-not-parallelism) - Non-blocking I/O - CPU bound vs I/O bound - Don't mention the War`^W`GIL
## Green threads - aka Tasklets, micro threads etc. - Lightweight cooperative "threads" - Turns coroutines into full switchable "stacks" - Stackless Python and the `greenlet` module
## What makes Gevent different? - Implicit event loop - Synchronous API - **Monkey patching**
## Out of the box - Non-blocking sockets, and DNS queries - SSL support - TCP server, WSGI server (<1.0.x) - libevent (now libev)
## WSGI? - Plug in a Flask app, patch and go - Multiple instances bound to a single socket/port
### exempli gratia from gevent.wsgi import WSGIServer from gevent.socket import tcp_listener from multiprocessing import Process, cpu_count from serverdensity.proxy.app import app def run(app, listener): http_server = WSGIServer(listener, app) http_server.serve_forever()
### exempli gratia cont. listener = tcp_listener(('127.0.0.1', 8000)) for i in xrange((cpu_count() - 1)): Process( target=run, args=(app, listener) ).start() run(app, listener)
## One Point Oh - **libev** - `gevent.subprocess` - [PyPy](https://github.com/gevent-on-pypy/pypycore)
## Spawning - `Greenlet` class - `Greenlet.spawn(c, [...])` - `greenlet.spawn(c, [...])`
## Flow control - `gevent.sleep(n)` (yield from) - `gevent.join(g)` - `gevent.joinall([...])` - `greenlet.link(g)` - `gevent.shutdown` - Greenlet states - Timeouts
### exempli gratia from gevent import spawn, joinall, sleep def g(): print('foo') sleep(0) print('bar') joinall([spawn(g), spawn(g)])
### exempli gratia cont. foo foo bar bar
## Data structures - Events and Queues (like the standard library) - Groups/Pools/Locks/Semaphores - Thread locals
## Monkey patching - `patch_socket()` - `patch_ssl()` - `patch_time()` - `patch_select()` - `patch_thread()` - `patch_all()`
## Celery - Gevent task runner - Use within processes manually - **Caution**: defaults ahead
## *NOOP*-ish exempli gratia # -> HTTP request mongo.payloads.insert(payloads) tasks.process_payload.apply_async(payload_id) # -> celery task (inside a greenlet) @task def process_payload(payload_id): payload = mongo.payloads.findOne({...}) process = PayloadProcessor(payload) ... return process_alerts.apply_async(payload_id)
### cont. # inside PayloadProcessor # (still within a greenlet, controlled by Celery def send_metrics(self): payload = copy(self.payload) # remove some fields we don't want to send, # turn some to strings gevent.spawn(self._handle_metrics_request, [payload])
### cont. def _handle_metrics_request(self, payload): resp = requests.post(METRICS_URL, data=json.dumps(payload)) if resp.status_code == 200: logging.info(...) return True else: logging.error(...) return False
### deus e.g. def update_check(self, response): # update collections in Mongo from response ... def update_metrics(self): # send a request to the metrics service ... def update_inventory(self): # send a request to the inventory service ...
### deus e.g. cont. # run from a celery task def health_check(self): # get HTTP response from actors ... update_greenlet = spawn(self.update_check, [response]) update_greenlet.link(spawn(self.update_metrics)) update_greenlet.link(spawn(self.update_inventory))
## Notable mentions - [grequests](https://github.com/kennethreitz/grequests) - [geventreactor](https://github.com/jyio/geventreactor) - [ZeroMQ](https://github.com/traviscline/gevent-zeromq)
## sys.exit(0) - Code: [git.io/sd](https://github.com/serverdensity), [git.io/1v](https://github.com/1stvamp) - Slides: [1stvamp.github.com/gevent-talk](http://1stvamp.github.io/gevent-talk)
## ^D - Jonathan "Joff" Oliver: [about.me/joffie](http://about.me/joffie) - Grab me and say hi `:-)`