Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2017 - Nick DiRienzo, Vinay Tota - How Optimize...

PyBay
August 12, 2017

2017 - Nick DiRienzo, Vinay Tota - How Optimizely Scaled its REST API with Asyncio

Description
With developers, an awesome product isn’t everything, or at least we found that out. More than a product you need a platform. But what is a platform? Learn tips and tricks about building a public API using the latest and greatest tools: OpenAPI, Python 3 and asyncio.

Abstract
With developers, an awesome product isn’t everything, or at least we found that out. More than a product, you need a platform. But what is a platform? And how do you build one alongside all the other weird old code you might have inherited?

In a perfect world, Jeff Dean would ride in on a Unicorn with stone tablets inscribed with UML diagrams of an application architecture so perfect you’d weep with joy. In the real world however that tends not to happen, so the process is a bit more iterative. Sometimes you try things that don’t work or seem silly in retrospect.

Part of our platform journey has been building a public API with our favorite hand picked technologies: OpenAPI and Python 3, especially asyncio. Building a rock solid, fast, and scalable Python application was not all rainbows and unicorns along the way. Through this process, we learned quite a bit about describing REST APIs and how modern Python concurrency mechanisms behave in the real world.

We’ll share how we used OpenAPI to power our public API and improve the developer experience for both internal engineers and external consumers.

We started off with a mix of multiprocessing and asyncio, and have since migrated completely to asyncio. Also, we’ll share a few of the things we've learned in the process, which we hope will help you if you choose to use asyncio.

Bios
Nick DiRienzo is a software engineer at Optimizely. He enjoys writing code in Python, making developers’ lives better, and eating Mission burritos.

Vinay Tota is currently a member of the Application Platform team at Optimizely. A long time ago wanted to be a theoretical physicist but now has way more fun hacking code. More recently he's worked on building high throughput low latency systems for ad serving using Python.
Speaker home page

PyBay

August 12, 2017
Tweet

More Decks by PyBay

Other Decks in Programming

Transcript

  1. We’ll talk about: • Optimizely’s API story • What makes

    an API “good” • Optimizely’s API gateway • Improving it with asyncio • Lessons learned
  2. Optimizely X Full Stack Code Based Experimentation Optimizely X Web

    Visual Editor Based Experimentation Experimentation Platform
  3. Getting Optimizely Results 1. Get Experiment data 2. Get Layer

    data (whatever that is) 3. Get Project Settings
  4. Getting Optimizely Results 1. Get Experiment data 2. Get Layer

    data (whatever that is) 3. Get Project Settings 4. Get results data
  5. 1. Get Experiment data 2. Get Layer data (whatever that

    is) 3. Get Project Settings 4. Get results data GET /v2/experiments/:id/results Getting Optimizely Results
  6. Getting Optimizely Results 1. Get Experiment data 2. Get Layer

    data (whatever that is) 3. Get Project Settings 4. Get results data
  7. 1. Get Experiment data 2. Get Layer data (whatever that

    is) 3. Get Project Settings 4. Get results data /v2/experiments/:id/results Getting Optimizely Results
  8. Benefits of an API gateway Operations through the API look

    a lot like their web UI counterparts
  9. Benefits of an API gateway Operations through the API look

    a lot like their web UI counterparts Allows us to orchestrate APIs instead of data models
  10. Benefits of an API gateway Operations through the API look

    a lot like their web UI counterparts Allows us to orchestrate APIs instead of data models Pulls problems away from business logic into a higher-level
  11. Benefits of an API gateway Operations through the API look

    a lot like their web UI counterparts Allows us to orchestrate APIs instead of data models Pulls problems away from business logic into a higher-level Internal and external consumers go through the same application
  12. Pyramid and Multiprocessing with multiprocessing.Pool() as pool, multiprocessing.Manager() as manager:

    response_queue = manager.Queue() try: # send our requests get back responses from the response_queue finally: pool.join() pool.terminate()
  13. Nonblocking IO Application Kernel Start read() Initiate read, returns immediately

    read() Receive response poll()until data has arrived
  14. async def i_take_a_while(): print('slow func start') await asyncio.sleep(3) print('slow func

    done') async def i_run_fast(): print('fast func start') await asyncio.sleep(1) print('fast func done') async def run_me(): await asyncio.gather( i_run_fast(), i_take_a_while() ) loop = asyncio.get_event_loop() loop.run_until_complete(run_me()) loop.close() Event loop i_take_a_while i_run_fast slow func start fast func start 1 sec after start fast func done 3 sec after start slow func done
  15. Blocking -> Asyncio Gunicorn Pyramid Pyramid View Switch to asyncio

    worker class http://docs.gunicorn.org/en/stable/design.html#async io-workers
  16. async def i_block(): print('slow func start') time.sleep(3) print('slow func done')

    async def i_run_fast(): print('fast func start') await asyncio.sleep(1) print('fast func done') async def run_me(): await asyncio.gather( i_run_fast(), i_block() ) loop = asyncio.get_event_loop() loop.run_until_complete(run_me()) loop.close() Event loop i_block i_run_fast block func start fast func start 3 sec later block func done fast func done
  17. Code is Social • Better make sure it actually works!

    • Pull Request Open 3+ weeks • Everyone on team added as a reviewer • 63 comments on Pull Request • Meetings for questions/concerns
  18. asyncio • asyncio from the start is ideal • But

    can add it later if you have to • Still early, but support will only improve
  19. Good APIs are Hard • Lots of details to get

    right • Using the right technologies helps • Always keep iterating and improving
  20. Q&A