akka-best-reactive-toolkit
akka-best-reactive-toolkit

เรามาเริ่มเรียนรู้เรื่อง Akka กันก่อนเลยดีกว่า เจ้า Akka ….. คือร้านอาหารญี่ปุ่นปิ้งย่างชื่อดังร้านนึงที่เจ้าของร้านคือ สุภาเจษฐ (แอน) และ ชิตพล (โบ๊ท) วิวัฒนาเกษม เป็นคนรุ่นใหม่รักการทำอาหารญี่ปุ่นเป็นชีวิตจิตใจ …

เห่ย ไม่ใช่ล่ะ นั้นมันร้านปิ้งย่าง ไม่ใช่ Akka Toolkit !!! 🙂 Akka คือ สุดยอดของสุดยอด Toolkit ที่ Backend ของทุกบริษัทที่ต้องการจะจัดการเรื่องของ Transaction จํานวนมหาศาล และ Concurrent จํานวนมากควรจะนําเข้ามาใช้มากๆเลย …. เจ้า Akka ไม่ได้มีไรมากเหนือไปกว่า Toolkit ที่ยึดหลักของ Reactive Manifesto (ท่องไว้ Event Driven, Scalable, Resilient, Responsive เดี๋ยวอธิบายละเอียดๆๆ ข้างล่าง) ซึ่ง Akka มันจะมีหัวใจหลักๆอยู่แค่ 4 components เท่านั้น หรือ จริงๆมีอีกแต่สิ่งที่เราใช้บ่อยๆ คือ

  1. Akka Actor (ตัวนี้ต้องเรียกว่า พ่อทุกสถาบันเพราะมันคือหัวใจหลักของทุกตัวต่อจากนี้เลย)
  2. Akka Http
  3. Akka Stream
  4. Akka Cluster

ตัวมันเองเขียนด้วย Scala บน JVM เพราะฉะนั้น support Java อยู่แล้ว แต่เจ้า Toolkit ตัวนี้ มันยังมีในภาษาอื่นๆด้วย เกือบทุกภาษหลักเลย

  1. Akka
  2. Akka.NET
  3. Python Akka

ทีนี้ก็พอรู้แล้วว่า Akka คืออะไรใช่มั้ย แต่มาลงรายละเอียดกันแต่ละตัวเลยดีกว่า ว่าคืออะไรบ้าง?

ก่อนจะข้ามไป มารู้จัก Reactive Manifesto

สมองคนเราถนัดจําเป็นรูปมากกว่า มารู้จักแค่รูปข้างล่างนี้พอ

Reactive Manifesto
Reactive Manifesto (https://www.reactivemanifesto.org/)

หลักการณ์ของ Reactive ค่อนข้างอ่านแล้วเข้าใจยาก เพราะมันโยงไปโยงมาหลายเรื่อง แต่จริงๆแล้วหลักการณ์ไม่มีไรมาก ปัญหามันเกิดมาจาก การเติบโตของระบบนั้นเอง สมัยก่อนเรามี server กันแบบหลักสิบเครื่องเท่านั้น แต่พอยุคนี้ที่อะไรก็ผ่านอินตราเนตหมด แปลว่า Request มันก็เพิ่มขึ้นมหาศาลๆ ตามจํานวน Devices นั้นแหละ

IoT-connected-device
IoT-connected-device (https://www.statista.com/statistics/471264/iot-number-of-connected-devices-worldwide/)

อย่างภาพนี้บอกจํานวนของ devices บนโลกใบนี้ที่ต่ออินเตอร์เนต สมัยก่อน 2015 มีประมาณ 15.41 billons ก็ว่าเยอะแล้ว แต่นี้แค่ 2 ปีเพิ่มเป็น 20.35 billons เพิ่มมา 30% อะ แปลว่า request ที่ไป server เพิ่มมาอีก 4.94 พันล้านเครื่อง !!! 🙂 แล้ว Server Architecture เก่าๆจะทํายังไง? พังสิครับ? เวลา response time, service maintenance, data generated มากมายก่ายกอง เราเลยมาศึกษา Reactive นั้นเอง

หัวใจหลักของ Reactive คือ 4 อย่างตามรูปข้างบน (ดูจาก Bottom up ไป value น่ะ)

  1. Message Driven
    • ระบบใหญ่ๆที่มี Thread เยอะๆ เวลาจะคุยกันแต่ก่อนจะมี share ข้อมูลที่เดียวกัน ลองนึกภาพ server 3 ตัว รออ่าน data file นึง เพื่อดูว่าตัวไหนทําไรอยู่ เป็น synchronous กัน
    • แต่ลองคิดภาพ server 1000 ตัวสิแย่งกันตายเลยปะ? บล๊อคกันเองตาย เพราะฉะนั้นมันต้องเป็น asynchronous message passing ไปมาระหว่างระบบ ไม่ให้มันบล๊อคกันเอง
  2. Resilient
    • ระบบเมื่อเจอกับ Failure ถ้าใช้หลักของ reactive มันต้องสามารถทํา delegation ไปให้ component อื่นๆได้ โดยไม่มีปัญหา ไม่ใช่ว่า system อื่นๆจะตายไปด้วย
    • ลองนึกภาพ web application architecture ที่ database อยู่ล่างสุด ถ้า Database ตาย ไม่ใช่ว่า เว็ปจะต้องตายด้วยน่ะ เจ้าระบบพวกนี้มันต้องแก้ปัญหาด้วย replication, isolation แล้วก็ delegation (แปลภาษาคนก็คือ มันต้องมีหลาย node ตัวไหนตายไปมันก็ขึ้นแทนกัน และ แยกกันชัดเจน ไม่งั้นมันจะลากกันไปตาย)
  3. Elastic
    • ระบบต้องยืดหยุ่นพอที่จะสามารถ resources allocated เมื่อเกิดโหลดเยอะๆได้ ไม่ทําให้เกิด bottlenecks ขึ้นมาในระบบ
    • ฟังแล้วคงยังไม่เครียล์ แต่หลักๆคือ ถ้าเกิด load จํานวนมหาศาลจาก 100 requests/sec เป็น 1,000 requests/sec ระบบ reactive มันต้องมีความสามรถที่จะจัดการ resource ได้ไม่ใช่ตายไปเลย แล้วต้องรอให้มาเพิ่มเครื่อง
  4. Responsive
    • สั้นๆง่ายๆ เจ้า 3 ตัวบนรวมมาเป็นระบบ reactive ที่ responsive ได้เร็วสุดๆ ไม่มีสะดุดยิ่งกว่าเนตทรูนั้นเอง
    • เช่น ไม่ตายเมื่อมี failure, ไม่บล๊อคกันเอง สื่อสารกันโดยไม่สนใจใคร, จัดการ resource ตัวเองได้เมื่อเจอ big impact request

คําถามพูดทําไมเยอะแยะ … เพราะ Akka ใช้หลักการณ์จากทั้ง 4 ข้อ นั้นแหละมันจะโยงกลับไปหมดเลย!!! 🙂  ฉะนั้นตอนนี้เข้าใจคร่าวๆไว้ก่อนน่ะ แล้วมาอ่าน Akka กันว่ามันคืออะไร แล้วมาเทียบกันอีกที (อ่านฉบับภาษาไทยของพี่ปุ๋ยได้เลย)

ทําไมเราต้องการ Akka Framework?

เจ้า Akka Framework เนี่ยจริงๆแล้วมันถูกคิดค้นขึ้นมา 10 กว่าปีล่ะ จาก Carl Hewitt เพื่อเอามาจัดการกับระบบ Parallel แต่สมัยก่อน Hardware กับ Infrastructure หลายๆอย่างยังไม่เอื้ออํานวยเท่าไร แต่พอมาเป็นยุคนี้แล้วมันเลยพร้อมล่ะ ที่จะแก้ปัญหา Parallel System ที่ Object Oriented Programming Model ทั่วไปแก้ให้ไม่ได้ แต่ Actor Model ทําได้ 🙂

ยกตัวอย่างจากอันนี้เลยน่ะ sequence diagram อันนี้แสดงให้เห็นถึงเรื่องของ behavior ของระบบที่จะเกิด method call เป็นทอดๆไป

OOP-runtime-behavior
OOP-runtime-behavior (https://doc.akka.io/docs/akka/current/guide/actors-motivation.html)

ซึ่งถ้าเราวาดเส้น lifelines ก็จะเป็นแบบข้างล่าง เห็นว่ามันเรียกไปเป็นขั้นๆยังไง

oop-lifelines
oop-lifelines (https://doc.akka.io/docs/akka/current/guide/actors-motivation.html)

ดูเหมือนดี และ ปกติทั่วไปใช่มั้ย????? ถ้าใช่ แสดงว่าเรายังไม่ได้เคยคิดเรื่องของ “Multi Thread” สิน่ะ เพราะไอ้เจ้าเส้นสีแดงเนี่ยมันคือ Single Thread ไงล่ะ ตัวเดียว วิ่งอันเดียวก็สบายสิครับพี่น้อง ลองมาดูภาพข้างล่างกัน

oop-multithread
oop-multithread (https://doc.akka.io/docs/akka/current/guide/actors-motivation.html)

เห็นม่ะ เริ่มยุ่งแล้วล่ะ อันนี้แค่ 2 thread เองน่ะ ลองคิดภาพเป็น 1000 thread สิ เละเทะแน่ 🙂

แล้วเราทําไงล่ะ? ปกติถ้าเขียน Java ก็ 2 ท่าเบสิกเลยล่ะด้วย Synchronize กับ Notify กันไปมาระหว่าง Thread

java-multithreading-technique
java-multithreading-technique (https://beginnersbook.com/2013/03/multithreading-in-java/)

อย่างที่บอกปัญหาไปในตอนต้นเรื่องล่ะว่า เรื่องของการจัดการระบบที่ไม่ได้ Follow Reactive Manifesto จะมีปัญหาเรื่อง Message Driven นั้นเอง เพราะท่าปกติต้อง Lock ด้วย Synchronize หรือถ้าจะคุยกันระหว่าง thread ก็ต้องไปส่ง notify() ใน synchronize โหมด …. ฟังแล้ววุ่นวายจนปวดตับมั้ยล่ะ? 🙂

นั้นเลยเป็นเหตุผลที่เรามาสนใจ Akka Actor Model แทนไงล่ะ

Akka Actor คืออะไร?

มันคือ โมเดลการออกแบบที่เป็นตัวช่วยไม่ให้เราต้องมานั่งปวดหัวกับการ Lock และ ช่วยให้เราสามารถสื่อสารกันระหว่าง Object ได้อย่างง่ายดายมาก โดยการ passing message ไปมา ตามหลักของ Reactive Manifesto นั้นเอง

actor-sending-message-between-actor
actor-sending-message-between-actor (https://doc.akka.io/docs/akka/current/guide/actors-intro.html)

ที่ใช้คําว่า passing message ไม่ใช่ calling methods เพราะว่า การส่ง message เนี้ย เราไม่ได้ต้องการ return value ไง เรา delegates work ไปที่ actor ตัวอื่นๆเลย แล้วถ้ามันจะส่งค่ากลับมันก็ใช้ reply message กลับมานั้นเอง ดังตัวอย่างข้างล่างนี้เลยยย

actor-passing-model
actor-passing-model (https://doc.akka.io/docs/akka/current/guide/actors-intro.html)

จากรูปข้างบนก็คือมันไม่ทําการ Lock แล้ว แต่มันรับ message มาจากทั้งสอง Actor แล้วก็ค่อยทําทีล่ะอันแทน 🙂

Akka actor รูปร่างหน้าตาแบบไหน?

ซึ่งจริงๆแล้วเจ้า Akka Actor ที่เราเรียกๆกันมันมีรูปร่างหน้าตาแบบนี้

akka-actor-overview
akka-actor-overview (https://doc.akka.io/docs/akka/current/guide/tutorial_1.html)

ให้นึกถึง Tree เลย เวลาพูดถึง Actor 🙂 เพราะว่า Actor Akka ถูกสร้างตาม Reactive Manifesto ใช่มั้ยล่ะ? เพราะฉะนั้นหลักการณ์นึงของ Reactive คือ Resilient ที่เมื่อระบบเกิดปัญหาขึ้นมา ระบบส่วนอื่นต้องทํางานต่อได้โดยไม่หยุดชะงัก

actor-handle-error-situations
actor-handle-error-situations (https://doc.akka.io/docs/akka/current/guide/actors-intro.html)

Akka จึงออกแบบระบบขึ้นมาเรียกว่า Supervisor ที่มีความสามารถในการ restart child actor หรือจะ stop child actor แบบ completely เลยก็ได้ ด้วยระบบนี้จะทําให้ parent node มีความสามารถในการวางแผนว่าจะจัดการยังไงกับ child actor fail ขึ้นมา 🙂 แต่ในกรณีกลับกันถ้า Parent Actor ตาย เจ้า child actor ก็จะตายหมดน่ะ เพื่อป้องกัน Resource lock นั้นเองเป็น resource management แบบนึง

กลับมาที่โครงสร้างของ Akka Actor อีกที อย่างที่เห็นภาพน่ะว่ามันเป็น Tree แล้วเวลาเราสร้าง Actor มันจะเข้าไปจับกับ Tree นั้นๆ …. แล้วสงสัยมั้ย Actor ก้อนแรกมันจะไปจับกับใครล่ะ ในเมื่อยังไม่มี Tree มาก่อนเลย?

akka-actor-overview
akka-actor-overview

ระบบ akka จะสร้างให้ก่อน 3 actor โดยมีตัวพ่อคือ root guardian คุมทุกสถาบัน แล้วหลังจากนั้นก็จะมี actor มือซ้าย และ ขวา คือ user และ system ตามลําดับ โดย actor ที่เราสร้างทั้งหมดจะไปเกาะกับ user ทั้งหมดแล้วก็ไล่ลงมาเรื่อยๆๆๆนั้นเอง 🙂

Akka actor in action

ดูตัวอย่างได้จากโค้ด scala นี้เลย

example-code-actor-hierarchy
example-code-actor-hierarchy (https://doc.akka.io/docs/akka/current/guide/tutorial_1.html)

ทุกครั้งที่เราสร้างระบบ Actor ขึ้นมาเราจะใช้ คําสั่งแค่สองอย่างนี้เอง

  1. ActorSystem
  2. system.actorOf

จะเห็นจากตัวอย่างว่ามันสร้าง System “testSystem” ขึ้นมา แล้วก็ joinด้วย actorof ของ system ไหน (ในรูปจะเห็นว่ามัน Reference ไปที่ PrintMyActorRefActor ด้วย เพราะมันจะเป็น childnode ที่เสียบต่อก้นมันขึ้นไปนั้นเอง) หลังจากนั้นก็จะกลายเป็น tree ตามรูปข้างล่างเลย

actor-system-arch
actor-system-arch

นั้นคือภาพรวมของ actor เวลาสร้าง actor ใหม่ๆขึ้นมานั้นเองง … ซึ่งจริงๆมันก็จะมีรายละเอียดอื่นๆเช่น Actor lifecycle เช่น preStart กับ postStop เพื่อใช้ในการจัดการ resources ต่างๆเวลาเกิด หรือ ดับนั้นเอง 🙂

แล้วเราจะติดต่อกับ Akka Actor ยังไง?

เรารู้จัก Actor Model แล้วเนอะ ทีนี้สงสัยมั้ยว่า เราจะติดต่อกับ Actor model ต่างๆยังไง เท่าที่เราเห็นก็คือแค่ Actor คุยกันเอง มี Supervisor อย่างนั้น อย่างนี้ แล้วคนอื่นจะ request เข้ามายังไง?

คําตอบง่ายมากคือ Akka HTTP นั้นเอง … ใน Akka HTTP ฒันถูกสร้างออกมาเพื่อเป็น Integration Layers ให้กับโลกภายนอก เพื่อให้คนมาติดต่อผ่าน REST/HTTP interface นั้นเอง

akka-http-example
akka-http-example (https://doc.akka.io/docs/akka-http/current/java/http/introduction.html)

ถ้าใครเคยเขียน Web Framework มาซักตัวก็จะเข้าใจว่า มันจะมีการสร้างไฟล์ Route ตัวนึงเพื่อใช้จัดการ Rest Interface ซึ่งเจ้า Akka HTTP ก็แบบเดียวกันนั้นแหละ ตามตัวอย่างคือสร้าง ActorSystem Routes ขึ้นมา เพื่อใช้จัดการ Route Path นั้นเอง

ทําไมสร้าง Route ด้วย Actor? นี้เป็นคําถามที่ควรจะถามที่สุดเลย …. คําตอบก็คือ เพราะทุกอย่างคือ Actor Model นั้นเองบนโลกของ Concurrent 🙂 ทุกๆอย่างมีรากฐานจาก Actor เพื่อให้มันเข้าโหมด Reactive Manifesto นั้นเอง (Plugin ที่นิยมใช้กันก็จะเป็น Sprary เพื่อให้ไม่ต้องที่มันสร้าง On top of Akka Scala เลยเพราะฉะนั้น fully asynchronous, non-blocking แน่นอน ไม่ต้องมานั่งเขียนไรเยอะแยะแบบตัวอย่าง)

Akka Stream?

เรารู้แล้วว่า Actor คืออะไร? จะเชื่อมต่อกับ Actor ยังไง? ที่นี้เรามาเข้าใจว่าเรา consume service ยังไงด้วยดีกว่า..

ก่อนอื่นเริ่มจากการนึกภาพ Netflix ที่จะฉายหนังเรื่องนึงขนาด 4GB บน server คําถามคือ เวลาที่เราเปิดไฟล์หนังดูผ่านเนตเนี้ย? มันทํางานยังไง? มันไม่ได้ download ลงมาทั้ง 4GB บนเครื่องหรอกน่ะ มันแบ่งเป็นส่วนแล้วค่อยประมวลผล อาจจะผ่าน cluster ก็ได้ โดยจังหวะที่ส่งข้อมูลประมวลกันไปมาเนี่ยทั้ง Download และ Upload น่ะ มันเรียกว่า streaming นั้นเอง!

ซึ่งเจ้า Actor เองก็ใช้ Stream เหมือนกัน เพราะเวลามันที่ transfer ข้อมูลกันระหว่าง Actor นี่มันมีความเป็นไปได้ที่จะเกิดข้อผิดพลาดขึ้น โดยมันก็จะมีความสามารถหลากหลายอย่างเช่น Back-pressure ที่จะบีบท่อ stream ให้เล็กลงเมื่อ consumer รับไม่ไหว (ตามหลัก Reactive Streams)

ไว้ถึงเวลาต้องใช้ลึกๆค่อยเขียนเพิ่มอีกที 🙂

จบซะที..

ถึงตรงนี้คงพอเข้าใจเพิ่มขึ้นแล้วล่ะ ว่า Actor Model คืออะไร? Akka คืออะไร? แต่พวกรายละเอียดปลีกย่อยต้องไปอ่านกับลงมือลองเล่นดูอีกทีน่ะ

ถ้ายาวไปจําไรไม่ได้ จําแค่สองอย่าง

  1. Reactive Manifesto
    • Responsive
    • Resilient
    • Elastic
    • Message Driven
  2. Actor == Tree
    • Supervisor ( Resilient – Reactive Manifesto)

ได้แค่นี้ก็คุ้มที่จะอ่านแล้วล่ะ 🙂

Leave a Reply

avatar

This site uses Akismet to reduce spam. Learn how your comment data is processed.