สถาปัตยกรรมของ OSGi

May 21st, 2009 by roofimon Leave a reply »

พยายามหาเอกสารพิ้นฐานเรื่อง OSGi แต่หายากมากมีอยู่ที่เดียวคือที่เวบ http://www.osgi.org/About/WhatIsOSGi อ่านไปงงไปแต่ดีที่สุดเท่าที่หาได้แล้วครับ การถอดความเป็นไปอย่างยากลำบากเพราะสำนวนเทพมากประกอบกับความรู้ยังไม่มากนัก แต่ก็อ่านกันไปก่อนนะครับ คาดว่าเข้าส่วนของ tutorail แล้วคงจะเห็นภาพมากขึ้น
ส่วนประกอบหลักของ OSGi นั้นประกอบไปด้วย 7 ส่วนด้วยกัน

  1. Bundles – คือคอมโพเนนท์ของแอพพลืเคชั่นที่สร้างขึ้นเพื่อนำไปติดตั้งบน OSGi
  2. Services – ส่วนเชื่อมต่อกับ Bundle ที่ต่อกันแบบพลวัตเพื่อทำให้เกิดสภาพแวดล้อมแบบ publish-find-bind สำหรับการ plain old Java objects.
  3. Life-Cycle – เป็น API ที่ถูกติดตั้งเพื่อใช้ในการทำ install, start, stop, update และ uninstall bundles.
  4. Modules – ที่ชั้นนี้เป็นชั้นที่ถูกสร้างเพื่อกำหนดกระบวนการว่าโค้ดของ Bundle จะถูก import และ export อย่างไร
  5. Security – ชั้นนี้ชัดเจนเรื่องของระบบรักษาความปลอดภัย
  6. Execution Environment – สภาพแวดล้อมในการทำงานชั้นนี้จะทำหน้าที่เตรียมและกำหนดว่ามีคลาสและเมธอดใดบ้างที่สามารถใช้งานได้
  7. ส่วนต่อไปคือรายละเอียดแบบเจาะลึกของส่วนต่างๆ

Modules
แนวคิดพื้นฐานที่ทำให้ระบบของเราสามารถมีความเป็น Modularity ซึ่งเรื่องของ Modularity นั้นก็เป็นเรื่องง่ายๆคือ “assuming less” เป็นเรื่องของการเก็บทุกอย่างให้อยู่ในขอบเขตของตัวเอง ไม่ปล่อยหรือแบ่งใช้อะไร กับคนอื่นมากนัก ซึ่งเรื่อง modularity เป็นหัวใจหลักของ OSGi ในเรื่องของเทคนิคการมัดหรือยึดคอมโพเนนท์เข้าด้วยกัน ซึงในมุมมองของ Java แล้ว bundle มันคือการสร้าง Jar ไฟล์แต่อย่างไรก็ตามข้อเสียคือทุกๆอย่างใน Jar จะสามารถถูกใช้ร่วมกันได้อย่างสมบูรณ์แบบระหว่าง Jar ด้วยกันเอง แต่ในกรณีของ OSGi นั้นจะทำการซ่อนทุกอย่างใน Jar ไว้ยกเว้นแต่จะมีการประกาศให้ใช้อย่างเป็นทางการเท่านั้น ดังนั้ bundle ใดๆที่ต้องการใช้ jar ตัวอื่นจะต้องทำการประกาศการใช้อย่างถูกต้องเท่านั้น
การซ่อนข้อมูลและการเตรียมการ share นั้นทำให้เกิดข้อดีหลายข้อด้วยกันยกตัวอย่างเช่น สามารถทำให้ module ต่างๆที่ถูกติดตั้งใน single JVM นั้นสามารถมีได้หลาย version ได้
Services
เหตุผลที่เราต้องใช้เซอร์วิสโมเดลเนื่องมาจาก Java ได้แสดงให้เราเห็นมานานแล้วว่าการใช้เพียงแค่การแชร์คลาส เพื่อนำมาสร้างงานในเชิง collaborative model เป็นเรื่องที่ยากมาก ซึ่งสิ่งที่จาวาทำได้นั้นคือการใช้ Factories ที่ใช้กระบวนการการทำ dynamic class loading และคุณสมบัติการทำ static ใน java เองยกตัวอย่างเช่นในกรณีที่เราใช้งาน DocumentBuilderFactory เพื่อสร้างอะไรบางอย่างให้เราสิ่งที่เราต้องทำคือการเรียก DocumentBuilderFactory.newInstance() ซึ่งกระบวนการที่เกิดขึ้นข้างหลังคือมันจะสร้าง instance ของคลาสลูก DocumentBuilderFactory ด้วยทุกกรรมวิธีในการใช้ class loader ที่มีในตำรา  Trying to influence what implementation is used is non-trivial (services model, properties, conventions in class name), และแน่นอนสามารถเข้าถึงได้จากทุกๆที่บน VMและ instance นี้ยังทำงานแบบ passive คือมันไม่สารถบอกหรือส่งสัญญาณอะไรออกไปได้ว่าตอนนี้มันพร้อมถูกใช้งานแล้วและอีกเช่นกันที่ผู้ใช้ไใสามารถที่จะเลือกได้ว่า implementation ตัวไหนคือตัวที่เราต้องการกันแน่ และเมื่อ implementation ทำงานเสร็จแล้วมันก็ไม่สามารถที่จะเป็นอิสระได้และที่แย่ที่สุดคือ factory นั้นจะถูกใช้อย่างแพร่หลายใน VM และแต่ละ factory เองก็จะมีกระบวนการทำงานที่ต่างกัน ใช้ไลบรารี่ที่แตกต่างกันอีกเช่นกัน เราไม่สามารถหาศูนย์รวมที่เก็บ implementation ที่เราสามารถเลือกได้ว่าเราจะใช้งานตัวไหนกันแน่
ทางออกสำหรับปัญหานี้คือการใช้ OSGi Service Registry ซึ่งเราสามารถสร้าง bundle ขึ้นมาและลงทะเบียนไว้กับ service registry ว่าเราอยู่ภายใต้อินเทอร์เฟสตัวใด(มากกว่าหนึ่ง) ดังนั้น bundle ตัวอื่นๆจึงสามารถเข้ามาที่ registry และทำการเลือกดูว่ามีออบเจคใดที่มีคุณสมบัติตรงตามที่เราต้องการบ้าง ยกตัวอย่างเช่น เราสามารถเตรียม implementatio คลาสของ DocumentBuilder ไว้เพื่อใช้งานได้โดยจังหวะที่สร้าง instance ของ DocumentBuilderFactoryImpl จะถูกสร้างและลงทะเบียนไว้ภายใต้อินเทอร์เฟส DocumentBuilderFactory ดังนั้น bundle ใดๆก็ตามที่ต้องการใช้ DocumentBuilderFactory สามารถเข้ามาที่ registry และถามหาเซอร์วิสทั้งหมดที่อยู่ภายใต้ DocumentBuilderFactory  แต่ในกรณีที่ไม่พบเซอร์วิสที่ต้องการ bundle สามารถลงทะเบียนเพื่อรอได้และเมื่อใดก็ตามที่เซอร์วิสพร้อมให้บริการจะมีการส่ง callback message  กลับไปที่ bundle นั้นๆ
ดังนั้นภาพที่ออกมาจึงเป็นเชิงที่ bundle สามารถลงทะเบียนเซอร์วิส สามารถเรียกใช้เซอร์วิสและสามารถรอรับฟังความเคลื่อนไหวของเซอร์วิสความสัมพันธ์ระหว่าง bundles กับเซอร์วิสจออกมาในแนวของ many-to-many สามารถดูภาพประกอบได้


เกิดอะไรขึ้นในกรณีที่มี bundle หลายตัวต้องการลงทะเบียนภายใต้ชื่ออินเทอร์เฟสหรือคลาสเดียวกัน เราจะทำไงดี คำตอบคือพรอพเพอร์ตี้นั่นเอง ทุกๆเซอร์วิสที่ต้องการลงทะเบียนจะมีชุดพรอพเพอร์ตี้มาตรฐานและพิเศษเพื่อใช้สำหรับระบุความแตกต่าง และในมุมของการค้นหาก็สามารถทำได้ด้วยการใช้ filter language เข้ามาช่วยเพื่อให้เราสามารถพบเซอร์วิสที่เราต้องการจริงๆ นอกจากนี้เซอร์วิสทั้งหมดนั้นเป็นแบบพลวัตคือเราใช้งานเรียบร้อยเมื่อไหร่ก็สามารถเลิกใช้งานและถอดออกได้ทันที ในขณะเดียวกัน bundle ก็สามารถที่จะถอดเซอร์วิสของตัวเองออกจาก registry ได้ทุกเวลาเช่นกันแม้กระทั้งขณะนั้นยังมีคนใช้งานมันอยู่ด้วยก็ตาม อย่างไรก็ตามกระบวนการแบบนี้ดูเหมือนจะเป็นเรื่องที่ยุ่งยากและซับซ้อนมากๆแต่ปัญหาเรื่องความยุ่งยากก็สามารถลดลงไปได้มากเพราะมีเครื่องมืออย่าง Service Tracker และเฟรมเวิร์คอย่าง iPojo, Spring, Declarative Service ที่ทำให้เรามองเห็นข้อดีที่มีมากกว่าข้อเสียของการทำงานแบบนี้ได้ เรื่องพลวัตนี้เป็นเรื่องซับซ้อนพอสมควรอย่างไรก็ตามถ้าเราเปรียบเทียบกับสิ่งที่เราสามารถสัมผัสได้เราจะมองเห็นภาพมากขึ้น ยกตัวอย่างเช่นเมื่อเราเพิ่มอุปกรณ์ใหม่เข้าไปในเน็ทเวิร์คเซอร์วิสต่างๆของมันจะต้องสามารถถูกเรียกใช้งานได้ เช่นกันเมื่อเราดึงเอาอุปกรณ์นั้นออกจากเน็ทเวิร์คเซอร์วิสต่างๆก็จะหายไปเช่นกัน ในมุมมองของ OSGi นั้นเซอร์วิสอาจถูกหยุดให้บริการในกรณีที่การเชื่อมต่อจากเครื่องรีโมทขาดหายไป  ซึ่งนี่หมายความว่าความมีพลวัตเข้ามาช่วยแก้ปัญหาเรื่องของการ initial ระบบเพราะ OSGi แอพพลิเคชั่นไม่ต้องการเรื่องของลำดับในการ start
เมื่อ service registry ยอมให้ออบเจคทุกๆตัวกลายเป็นเซอร์วิสได้ แล้วนั้นหนทางที่ดีที่สุดในการทำให้เซอร์วิสเหล่านั้นสามารถถูก reuse มากที่สุดคือต้องลงทะเบียนออบเจคเหล่านั้นภายใต้อินเทอร์เฟสมาตรฐานเพื่อลดการผูกพันระหว่าง implementer และโค้ดของ client นี่คือเหตุผลสำคัญที่ทำให้พันธมิตร OSGi มีการร่างมาตรฐานออกมาเพื่อใช้งาน มาตรฐานนี้ได้กำหนดเซอร์วิสพื้นฐานปริมาณมหาศาลไว้ตั้งแต่ Log, Measurement และ State ได้เรียบร้อยแล้ว ซึ่งปัจจุบันมาตรฐานที่ประกาศออกมาเป็นรุ่นที่ 4 แล้ว

Advertisement

Leave a Reply

You must be logged in to post a comment.