Style Specifics (รายละเอียดเฉพาะของ Style)
เนื่องจาก domain service ใน service-based architecture โดยทั่วไปมี granularity หยาบ แต่ละ domain service จึงมักถูกออกแบบด้วย layered architectural style ประกอบด้วย API Facade layer, Business layer และ Persistence layer แนวทางออกแบบยอดนิยมอีกอย่างคือการแบ่ง domain service แต่ละตัวออกเป็น subdomain คล้ายกับ modular monolith architectural style (ดู Chapter 11 ) ทั้งสองแนวทางแสดงอยู่ใน Figure 14-2 .
Figure 14-2. รูปแบบการออกแบบ domain service
ไม่ว่าจะออกแบบอย่างไร domain service ต้องมี API access facade บางอย่างที่ UI ใช้ในการโต้ตอบเพื่อรัน business functionality บางอย่าง API access facade มักรับผิดชอบในการ orchestrate คำขอทางธุรกิจจาก UI
ลองพิจารณาตัวอย่างจากเว็บไซต์อีคอมเมิร์ซที่ใช้ service-based architecture มี business request มาจาก UI: ลูกค้ากำลังสั่งซื้อสินค้าบางอย่าง คำขอเดียวนี้ถูกรับโดย API access facade ภายใน domain service ชื่อ OrderService API access facade จะ orchestrate ทุกอย่างที่ต้องเกิดขึ้นเพื่อทำตามคำขอนี้ให้สำเร็จภายในตัวเอง: การวางคำสั่งซื้อ การสร้าง order ID การเรียกเก็บเงิน และการอัปเดตสินค้าคงคลังสำหรับสินค้าแต่ละชิ้นที่สั่งซื้อ ใน microservices architecture การทำตามคำขอนี้ให้สำเร็จน่าจะต้อง orchestrate service แยกกันหลายตัวที่ deploy แยกกันและมีจุดประสงค์เดียว ความแตกต่างของ granularity นี้—ระหว่างการ orchestrate ภายในระดับ class ใน service-based architecture กับการ orchestrate service ภายนอกใน microservices—ชี้ให้เห็นหนึ่งในความแตกต่างสำคัญหลายอย่างระหว่างสอง style นี้
เนื่องจาก domain service มี granularity หยาบ database transaction แบบ ACID (atomicity, consistency, isolation, durability) ทั่วไปพร้อม commit และ rollback มาตรฐานจึงสามารถรับประกัน database integrity ภายใน domain service เดียวได้ เทียบกับ fine-grained single-purpose service ของ distributed architecture ที่กระจายตัวมาก เช่น microservices ซึ่งใช้เทคนิค distributed transaction ที่เรียกว่า BASE transaction (basic availability, soft state, eventual consistency) service แบบ fine-grained เช่นนี้ไม่รองรับ database integrity ในระดับเดียวกับที่ ACID transaction ใน service-based architecture ทำได้
เพื่อแสดงประเด็นนี้ ลองพิจารณากระบวนการ checkout คำสั่งซื้อในตัวอย่างเว็บไซต์อีคอมเมิร์ซแบบ service-based ของเรา สมมติว่าลูกค้าวางคำสั่งซื้อ แต่บัตรเครดิตที่ใช้ชำระเงินหมดอายุแล้ว เนื่องจากการชำระเงินนี้เป็น atomic transaction ภายใน service เดียวกัน service จึงสามารถลบทุกอย่างที่เพิ่มลงฐานข้อมูลไปแล้วออกได้โดยใช้ transaction rollback มาตรฐาน service จะแจ้งลูกค้าว่าไม่สามารถเรียกเก็บเงินได้
ตอนนี้ลองพิจารณากระบวนการเดียวกันนี้ใน microservices architecture ที่มี service ขนาดเล็กและ fine-grained กว่า ก่อนอื่น OrderPlacement service จะรับคำขอ สร้างคำสั่งซื้อ สร้าง order ID และแทรกคำสั่งซื้อลงในตาราง order เมื่อทำเสร็จแล้ว OrderPlacement service จะเรียกระยะไกลไปยัง PaymentService ซึ่งพยายามเรียกเก็บเงิน ถ้าไม่สามารถเรียกเก็บเงินได้เพราะบัตรเครดิตหมดอายุ คำสั่งซื้อก็จะไม่สามารถวางได้ ตอนนี้ข้อมูลอยู่ในสถานะไม่สอดคล้องกัน (inconsistent state): ข้อมูลคำสั่งซื้อถูกแทรกไปแล้ว แต่ยังไม่ได้รับการอนุมัติ จำเป็นต้องมี action แยกที่เรียกว่า compensating update (กล่าวถึงใน Chapter 9 ) นำไปใช้กับ OrderPlacement service เพื่อทำให้ข้อมูลกลับสู่สถานะที่สอดคล้องกัน
Service Design and Granularity (การออกแบบ Service และ Granularity)
เนื่องจาก domain service มี granularity หยาบ พวกมันจึงรองรับ data integrity และ consistency ที่ดีกว่า แต่ก็มี trade-off ใหญ่ตามมา ใน service-based architecture การเปลี่ยนฟังก์ชัน order-placement ใน OrderService จะต้องให้ทีมทดสอบและ redeploy ฟังก์ชันทั้งหมดของ service นั้น รวมถึง payment processing ด้วย แต่ใน microservices architecture การเปลี่ยนแปลงแบบเดียวกันจะกระทบแค่ service OrderPlacement ขนาดเล็กและ fine-grained เท่านั้น โดยไม่ต้องทดสอบหรือ deploy PaymentService เลย นอกจากนี้ เนื่องจาก domain service หนึ่งตัว deploy ฟังก์ชันจำนวนมากกว่า จึงมีความเสี่ยงมากกว่าที่สิ่งอื่นจะพัง (รวมถึง payment processing) ด้วย microservices แต่ละ service มีความรับผิดชอบเดียว จึงมีโอกาสน้อยกว่าที่จะทำให้ฟังก์ชันอื่นพังเมื่อทำการเปลี่ยนแปลง
User Interface Options (ตัวเลือกด้าน User Interface)
service-based architecture style มี UI variant ให้เลือกมากมาย ทำให้มันยืดหยุ่นมาก ตัวอย่างเช่น สถาปนิกสามารถแยก UI monolithic เดียวที่แสดงใน Figure 14-1 ออกเป็น UI แยกหลายตัว ถึงขั้นให้ตรงกับแต่ละ domain service ก็ได้ วิธีนี้จะเพิ่ม scalability, fault tolerance และความคล่องตัว (agility) โดยรวมของระบบ UI variant เหล่านี้แสดงอยู่ใน Figure 14-3 .
Figure 14-3. UI variant สามแบบใน service-based architecture
ตัวอย่างเช่น ระบบสั่งซื้อทั่วไปอาจมี UI สำหรับลูกค้าในการสั่งซื้อ และมี UI ภายในแยกต่างหากสำหรับพนักงานแพ็คสินค้าเพื่อดูรายการที่ต้องแพ็ค และสำหรับ customer support
API Gateway Options (ตัวเลือกด้าน API Gateway)
ด้วยความยืดหยุ่นของ architectural style นี้ จึงสามารถเพิ่ม API layer ที่ประกอบด้วย reverse proxy หรือ API Gateway ระหว่าง UI กับ service ได้ ดังแสดงใน Figure 14-4 วิธีนี้มีประโยชน์สำหรับการเปิดเผยฟังก์ชัน domain service ให้ระบบภายนอกใช้งาน สำหรับการรวม cross-cutting concern ที่ใช้ร่วมกัน (เช่น metric, security, ข้อกำหนดด้าน auditing และ service discovery) เข้าไว้ใน API Gateway และสำหรับการทำ load balancing domain service ที่มีหลาย instance