Python async? web app แบบไม่โม code

ตั้งแต่มี node.js มาหลายคนก็อยากจะเขียน web app แบบ async บ้างเพราะมันรับ request ต่อวินาทีได้เยอะ ที่มันทำได้เพราะมันมาจัดการ schedule task เอง มี event loop เอง แล้วก็ไม่ต้องไป switch task บ่อย ๆ แบบที่ไม่จำเป็น ใช้ I/O หรืออย่างอื่นที่กำหนดทีค่อย switch ใน task queue

แต่มันก็มีประเด็นว่า (1) ไม่เขียน JS ได้ไหม ทีมใช้ Python งี้ (2) เขียนธรรมดาไม่ callback ไม่ async/await เพิ่มมาได้ไหม สองประเด็นนี้นอกจากจะเป็นเรื่องความยุ่งยากแล้ว บางทีก็มี code เก่าด้วย

ท่าแรกที่ผมนึกออกเลยคือใช้ Tornado มันเป็น async แน่ใช้ Python ด้วย แต่ว่า code นีเปลี่ยนเยอะเลย

อีกท่าคือใช้ Meinheld ดู code ก็เขียนธรรมดานี่เอง แต่ใช้ non-blocking I/O และ event loop จะ async ได้หรือเปล่าผมก็ไม่แน่ใจ

Meinheld มี task queue ของตัวเองโดยใช้ picoev ที่ไปใช้ประโยชน์จาก epoll ของ Linux (kernel) อีกที เวลาสลับ task ใช้ greenlet มาช่วย; event ตอนที่ทำ I/O มาจาก socket ที่เขาเขียนใหม่ ใช้ non-blocking I/O แล้วก็ไปใช้ wait คล้าย ๆ promise ในนั้นเลย แล้วก็เอาไปแทนที่ socket มาตรฐาน โดยใช้ท่า monkey patch ที่มักจะโดนทัดทานไม่ให้ใช้นั่นเอง

วิธีใช้ก็แค่ pip install ให้เรียบร้อย แล้วไปเรียก gunicorn แล้วเพิ่ม option นี้ไป –worker-class=”egg:meinheld#gunicorn_worker”

ประสิทธิภาพจากที่ไปดู Benchmark ตัวที่ใช้ Bottle.py + Meinheld ผลออกมาดีกว่า Express.js และดีกว่า Framework ที่ใช้ Go บางตัวด้วยซ้ำ

มันก็ดูจะมีข้อจำกัดอยู่บ้างที่ว่า event loop นี่มัน switch ตาม socket ของ Python อย่างเดียว สมมุติว่าใช้ PostgreSQL ผ่าน libpq หรือไปอ่านเขียนไฟล์มันก็คงไม่ switch ให้ อีกประเด็นหนึ่งคือ ผมเดา ๆ ว่า context ที่ต้องเก็บไปกับ task queue มันน่าจะใหญ่กว่า node.js เพราะน่าจะต้องไปยุ่งกับ stack ด้วยมั้ง

เรื่องว่า stable ไหมนี่ผมก็ไม่ทราบเหมือนกัน นอกจากนั้นแล้วก็ยังไม่เคยใช้ และไม่มีแผนที่จะใช้ด้วย

ผมยกตัวอย่างนี้ขึ้นมาเพื่อจะบอกว่าการเพิ่มประสิทธิภาพของ web app โดยใช้ async ที่ใช้ประโยชน์ของ event loop และ non-blocking I/O อาจจะไม่ต้องเปลี่ยนไปเขียน JS หรือ Go หรือไม่ต้องแม้แต่จะแก้ code เลยก็ได้ วิธีที่ยกมาอาจจะใช้ในภาษาอื่นนอกจาก Python ได้ด้วยและอาจจะมีคนทำอยู่แล้วด้วย

update1: จะใช้ Tornado ก็ได้ จริงท่าที่เขียนข้างบนมันก็คือการใช้ Async worker ของ Gunicorn นี่เอง ซึ่งเลือกเป็น Tornado  ได้ด้วย

Advertisements
This เรื่อง was posted in ไม่มีหมวดหมู่. Bookmark the permalink.

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s