เราใช้เวอร์ชัน Java 3.4.6 ในตัวอย่างนี้ ตัวอย่างสะดวกสำหรับทุกคนที่จะพูดคุยหากคุณไม่เข้าใจหลังจากเรียนรู้
การเชื่อมโยง Java Zookeeper สำหรับการพัฒนาแอปพลิเคชันส่วนใหญ่ประกอบด้วยแพ็คเกจ Java สองชุด:
org.apache.zookeeper
org.apache.zookeeper.data
แพ็คเกจ org.apache.zookeeper ประกอบด้วยคำจำกัดความอินเตอร์เฟสที่ตรวจสอบโดย Zookeeper และตัวจัดการการโทรกลับต่างๆสำหรับ Zookeeper มันกำหนดคลาสหลักของไลบรารีคลาสไคลเอนต์ Zookeeper รวมถึงคำจำกัดความคงที่ของประเภทเหตุการณ์และสถานะของ Zookeeper หลายประเภท แพ็คเกจ org.apache.zookeeper.data กำหนดคุณสมบัติที่เกี่ยวข้องกับการลงทะเบียนข้อมูล (หรือที่เรียกว่า Znodes) เช่นรายการควบคุมการเข้าถึง (ACLs), IDs, สถิติ ฯลฯ
org.apache.zookeeper.server, org.apache.zookeeper.server.quorum และ org.apache.zookeeper.server.upgrade แพ็คเกจใน Zookeeper Java API เป็นส่วนหนึ่งของการใช้งานเซิร์ฟเวอร์ แพ็คเกจ org.apache.zookeeper.client ใช้เพื่อสืบค้นสถานะของเซิร์ฟเวอร์ Zookeeper
เตรียมพร้อมสำหรับสภาพแวดล้อมการพัฒนา
Apache Zookeeper เป็นซอฟต์แวร์ที่ซับซ้อนดังนั้นจึงต้องใช้ไลบรารีคลาสอื่น ๆ อีกมากมาย ไลบรารีการพึ่งพารวมอยู่ในไดเรกทอรี LIB เป็นไฟล์ JAR ในการแจกจ่าย Zookeeper ชื่อไฟล์ zookeeper zookeeper คือ zookeeper-3.4.6.jar ตั้งอยู่ในโฮมไดเร็กตอรี่
ในการพัฒนาแอปพลิเคชั่น Java Zookeeper เราต้องตั้งค่า classpath เป็น zookeeper jar และห้องสมุดบุคคลที่สามทั้งหมดที่ Zookeeper ขึ้นอยู่กับ มีไฟล์ zkenv.sh ในไดเรกทอรี bin ซึ่งสามารถใช้ในการตั้งค่า classpath
เราจำเป็นต้องตั้งค่าสคริปต์ดังนี้และเรียกใช้คำสั่งต่อไปนี้ในบรรทัดคำสั่ง:
$ zoobindir = $ {zk_home}/bin $ source $ {zoobindir}/zkenv.shตัวแปรเชลล์ zk_home ถูกตั้งค่าไปยังเส้นทางเพื่อติดตั้ง zookeeper ในการตั้งค่าของฉันคือ/usr/share/zookeeper หลังจากนั้นตัวแปร classpath ถูกตั้งค่าอย่างถูกต้องในระบบของฉันเช่นนี้:
$ echo $ classpath /usr/share/zookeeper-3.4.6/bin/../build/classes: /usr/share/zookeeper-3.4.6/bin /../ build/lib/*. jar: /usr/share/zookeeper-3 : /usr/share/zookeeper-3.4.6/bin /../ lib/slf4j-api-1.6.1.jar: /usr/share/zookeeper-3.4.6/bin /../ lib/netty-3.7.0.final.jar: : /usr/share/zookeeper-3.4.6/bin /../ lib/jline-0.9.94.jar: /usr/share/zookeeper-3.4.6/bin /../ zookeeper-3.4.6.jar: /usr/sharefare : /usr/share/zookeeper-3.4.6/bin /../ conf:
ในระบบปฏิบัติการ Windows คุณต้องเรียกใช้สคริปต์ ZKENV.CMD ตอนนี้คุณสามารถใช้ตัวแปร ClassPath เพื่อรวบรวมและเรียกใช้โปรแกรม Java ที่เขียนโดยใช้ ZooKeeper API สคริปต์ zkenv.sh สามารถพบได้ในไฟล์. bashrc ของไดเรกทอรีโฮมไดเรกทอรีใน Uni/Linux เพื่อหลีกเลี่ยงการใช้ทุกครั้งที่เซสชันเชลล์เริ่มต้นขึ้น
โปรแกรม zookeeper คนแรกที่สอง
ในการแนะนำ Zookeeper Java API ให้เริ่มต้นด้วยโปรแกรมง่าย ๆ ที่สามารถเชื่อมต่อกับอินสแตนซ์ของ Zookeeper ใน LocalHost และหากการเชื่อมต่อสำเร็จมันจะพิมพ์รายการ Znodes ภายใต้เส้นทางรูทของ Zookeeper Namespace
รหัสสำหรับโปรแกรมนี้มีดังนี้:
/*โปรแกรม Zookeeper แรกของเรา*/นำเข้า java.io.ioException; นำเข้า java.util.arraylist; นำเข้า java.util.list; นำเข้า org.apache.zookeeper.evelexception; นำเข้า org.apache.zookeeper.zookeeper; "localhost: 2181"; string zpath = "/"; รายการ <string> zoochildren = new ArrayList <String> (); zookeeper zk = zookeeper ใหม่ (Hostport, 2000, null); ถ้า (zk! = null) {ลอง {zoochildren "); สำหรับ (String Child: Zoochildren) {// พิมพ์ childrensystem.out.println (เด็ก);}} catch (GeterException e) {E.printstacktrace ();} catch (interruptedexception e)ก่อนที่จะสร้างและดำเนินการตัวอย่างโค้ดก่อนหน้าเรามาดูกันว่ามันทำอะไรโดยเฉพาะ รหัสเริ่มต้นด้วยคำสั่งนำเข้า การใช้ข้อความเหล่านี้เรานำเข้าแพ็คเกจที่ต้องการโดยแต่ละองค์ประกอบของโปรแกรม ดังที่ได้กล่าวไว้ก่อนหน้านี้แพ็คเกจ org.apache.zookeeper มีคลาสและอินเทอร์เฟซทั้งหมดที่ลูกค้าต้องการเพื่อโต้ตอบกับเซิร์ฟเวอร์ Zookeeper หลังจากนำเข้าแพ็คเกจแล้วคลาสชื่อ Hellozookeeper จะถูกกำหนดไว้ เนื่องจากเรากำลังเชื่อมต่อกับอินสแตนซ์ของ Zookeeper ที่ทำงานในระบบเดียวกันให้กำหนดสายโฮสต์และสตริงพอร์ตเป็น LocalHost: 2181 ในวิธีหลัก บรรทัดของรหัส ZK = NEW ZOOKEEDER (HostPort, 2000, NULL) เรียกตัวสร้าง Zookeeper ซึ่งพยายามเชื่อมต่อกับเซิร์ฟเวอร์ Zookeeper และส่งคืนข้อมูลอ้างอิง สำหรับโปรแกรมไคลเอนต์ที่เชื่อมต่อกับอินสแตนซ์เซิร์ฟเวอร์ Zookeeper และบำรุงรักษาการเชื่อมต่อนั้นจำเป็นต้องมีเซสชันเรียลไทม์ ในตัวอย่างนี้การอ้างอิงที่ส่งคืนโดยวัตถุ ZK ที่สร้างอินสแตนซ์โดยตัวสร้างแสดงถึงเซสชัน Zookeeper API ถูกสร้างขึ้นรอบ ๆ การอ้างอิงนี้และการโทรแต่ละวิธีต้องมีการอ้างอิงเพื่อดำเนินการ
ตัวสร้างของคลาส Zookeeper ใช้รหัสต่อไปนี้เพื่อสร้างการอ้างอิงไปยังอินสแตนซ์ของ Zookeeper:
ZooKeeper (String ConnectString, Int SessionTimeout, Watcher Watcher)
พารามิเตอร์ที่ใช้มีดังนี้:
ConnectString: โฮสต์ที่คั่นด้วยเครื่องหมายจุลภาค: รายการหมายเลขพอร์ตแต่ละรายการที่สอดคล้องกับเซิร์ฟเวอร์ Zookeeper ตัวอย่างเช่น 10.0.0.1:2001, 10.0.0.2:2002 และ 10.0.0.3:2003 เป็นตัวแทนโฮสต์ที่ถูกต้อง: คู่จับคู่พอร์ตสำหรับวงดนตรี Zookeeper ของสามโหนด SessionTimeout: นี่คือการหมดเวลาเซสชันในมิลลิวินาที นี่เป็นเวลาที่ Zookeeper ไม่ได้รับการเต้นของหัวใจจากลูกค้าก่อนที่จะประกาศสิ้นสุดเซสชัน Watcher: วัตถุ Watcher ที่ได้รับแจ้งหากสร้างขึ้นเมื่อสถานะเปลี่ยนแปลงและเหตุการณ์โหนดเกิดขึ้น วัตถุ Watcher นี้จะต้องสร้างแยกต่างหากผ่านคลาสที่ผู้ใช้กำหนดซึ่งใช้อินเตอร์เฟส Watcher และส่งผ่านวัตถุอินสแตนซ์ไปยังตัวสร้าง Zookeeper แอปพลิเคชันไคลเอนต์สามารถรับการแจ้งเตือนเหตุการณ์ต่าง ๆ เช่นการเชื่อมต่อที่ขาดหายไปการหมดอายุของเซสชัน ฯลฯ
Zookeeper Java API กำหนดตัวสร้างเพิ่มเติมพร้อมพารามิเตอร์สามตัวเพื่อระบุการดำเนินงานขั้นสูงเพิ่มเติม รหัสมีดังนี้:
ZooKeeper (String ConnectString, Int SessionTimeout, Watcher Watcher, Boolean Canbereadonly)
ในคอนสตรัคเตอร์ด้านบนของคลาส Zookeeper หากตั้งค่าเป็น TRUE พารามิเตอร์บูลีน CanberEadonly ช่วยให้ไคลเอนต์ที่สร้างขึ้นสามารถเข้าสู่โหมดอ่านอย่างเดียวในกรณีของพาร์ติชันเครือข่าย โหมดอ่านอย่างเดียวเป็นสถานการณ์ที่ไคลเอนต์ไม่สามารถหาเซิร์ฟเวอร์ส่วนใหญ่ได้ แต่มีเซิร์ฟเวอร์พาร์ติชันที่เข้าถึงได้เพื่อเชื่อมต่อกับมันในโหมดอ่านอย่างเดียวซึ่งอนุญาตให้อ่านคำขออ่านไปยังเซิร์ฟเวอร์ในขณะที่ไม่อนุญาตให้มีการร้องขอการเขียน ลูกค้ายังคงพยายามเชื่อมต่อกับเซิร์ฟเวอร์ส่วนใหญ่ในพื้นหลังในขณะที่ยังคงอ่านอย่างเดียว เซิร์ฟเวอร์พาร์ติชันเป็นเพียงชุดย่อยของกลุ่ม Zookeeper ซึ่งเกิดขึ้นเนื่องจากการจัดสรรเครือข่ายในคลัสเตอร์ เซิร์ฟเวอร์ส่วนใหญ่ประกอบกับโควรัมส่วนใหญ่ในวงดนตรี
ตัวสร้างต่อไปนี้แสดงคำจำกัดความของพารามิเตอร์เพิ่มเติมสองตัว:
ZooKeeper (String ConnectString, Int SessionTimeout, Watcher Watcher, Long SessionID, BYTE [] SessionPasswd)
ตัวสร้างนี้อนุญาตให้วัตถุไคลเอนต์ Zookeeper สร้างพารามิเตอร์เพิ่มเติมสองตัว:
SessionID: ในกรณีที่ไคลเอ็นต์เชื่อมต่อกับเซิร์ฟเวอร์ Zookeeper สามารถใช้รหัสเซสชันเฉพาะเพื่ออ้างถึงเซสชันเซสชันที่เชื่อมต่อก่อนหน้านี้: หากเซสชันที่ระบุต้องใช้รหัสผ่านคุณสามารถระบุได้ที่นี่
ตัวสร้างต่อไปนี้เป็นการรวมกันของการโทรสองครั้งแรก:
ZooKeeper (String ConnectString, Int SessionTimeout, Watcher Watcher, Long SessionID, BYTE [] SessionPasswd, Boolean Canbereadonly)
ตัวสร้างนี้เป็นการรวมกันของการโทรสองครั้งแรกซึ่งช่วยให้การเชื่อมต่อกับเซสชันที่ระบุใหม่พร้อมเปิดใช้งานโหมดอ่านอย่างเดียว
บันทึก
เอกสาร Java API โดยละเอียดสำหรับคลาส Zookeeper สามารถสอบถามได้ที่ http://zookeeper.apache.org/doc/r3.4.6/api/index.html
ตอนนี้กลับไปที่โปรแกรม Zookeeper ของเรา หลังจากเรียกตัวสร้างหากการเชื่อมต่อสำเร็จเราจะได้รับการอ้างอิงไปยังเซิร์ฟเวอร์ Zookeeper เราผ่านการอ้างอิงไปยังวิธี getChildren ผ่านรหัสต่อไปนี้:
zoochildren = zk.getchildren (zpath, false)
วิธีการ getChildren (String Path, Boolean Watch) ของคลาส Zookeeper ส่งคืนรายชื่อลูกของ Znode บนเส้นทางที่กำหนด เราเพิ่งทำซ้ำรายการที่ส่งคืนโดยวิธีนี้และพิมพ์สตริงไปยังคอนโซล
ตั้งชื่อโปรแกรม hellozookeeper.java และรวบรวมโปรแกรมของเราดังนี้:
$ javac -cp $ classpath hellozookeeper.java
ก่อนที่เราจะเรียกใช้โปรแกรมเราต้องเริ่มอินสแตนซ์เซิร์ฟเวอร์ Zookeeper โดยใช้คำสั่งต่อไปนี้:
$ $ {zk_home} /bin/zkserver.sh เริ่มต้นเรียกใช้โปรแกรมดังนี้:
$ java -cp $ classpath hellozookeeper
ผู้ดำเนินการจะพิมพ์ข้อความบันทึกบนคอนโซลแสดงเวอร์ชัน Zookeeper เวอร์ชัน Java, Java ClassPath, สถาปัตยกรรมเซิร์ฟเวอร์ ฯลฯ ที่ใช้ นี่คือข้อความบันทึกเหล่านี้บางส่วน:
ข้อความบันทึกที่สร้างขึ้นโดย Zookeeper Java API นั้นมีประโยชน์มากสำหรับการดีบัก มันให้ข้อมูลเกี่ยวกับไคลเอนต์ที่เชื่อมต่อกับเซิร์ฟเวอร์ Zookeeper สร้างเซสชันและพื้นหลังอื่น ๆ ข้อความบันทึกสามข้อความสุดท้ายที่แสดงด้านบนบอกเราว่าไคลเอนต์เริ่มการเชื่อมต่อโดยใช้พารามิเตอร์ที่ระบุในโปรแกรมอย่างไรและเซิร์ฟเวอร์กำหนดรหัสเซสชันให้กับไคลเอนต์หลังจากการเชื่อมต่อที่ประสบความสำเร็จ
ในที่สุดการดำเนินการของโปรแกรมในที่สุดก็ส่งออกสิ่งต่อไปนี้ในคอนโซล:
เราสามารถใช้เชลล์ Zookeeper เพื่อตรวจสอบความถูกต้องของโปรแกรม:
$ $ zk_home/bin/zkcli.sh -server localhost
ยินดีด้วย! เราเพิ่งเขียนโปรแกรมไคลเอนต์ Zookeeper ครั้งแรกของเราได้สำเร็จ
ประการที่สองใช้อินเทอร์เฟซ Watcher
การตรวจสอบผู้เฝ้าดู Zookeeper ช่วยให้ลูกค้าได้รับการแจ้งเตือนจากเซิร์ฟเวอร์ Zookeeper และจัดการกับเหตุการณ์เหล่านี้เมื่อเกิดขึ้น ZooKeeper Java API ให้อินเทอร์เฟซสาธารณะที่เรียกว่า Watcher ว่าคลาส Handler Event Client ต้องดำเนินการเพื่อรับการแจ้งเตือนเหตุการณ์เกี่ยวกับเหตุการณ์จากเซิร์ฟเวอร์ Zookeeper แอปพลิเคชั่นที่ใช้ไคลเอนต์ดังกล่าวจัดการกับเหตุการณ์เหล่านี้โดยการลงทะเบียนวัตถุโทรกลับกับไคลเอนต์
เราจะใช้อินเทอร์เฟซ Watcher เพื่อจัดการเหตุการณ์ที่สร้างโดย Zookeeper เมื่อข้อมูลที่เกี่ยวข้องกับ Znode มีการเปลี่ยนแปลง
อินเทอร์เฟซ Watcher ได้รับการประกาศดังนี้ในแพ็คเกจ org.apache.zookeeper:
Public Interface Watcher {Void Process (Event WatchEdEvent);}เพื่อแสดงให้เห็นถึงการตรวจสอบข้อมูล Znode (Watcher) มีสองคลาส Java: DataWatcher และ DataUpdater DataWatcher จะทำงานตลอดเวลาและฟังเหตุการณ์ NodeDatachange จาก Zookeeper Server ในเส้นทาง Znode ที่ระบุ /myConfig คลาส DataUpdater จะอัปเดตฟิลด์ข้อมูลเป็นระยะในเส้นทาง Znode นี้ซึ่งจะสร้างเหตุการณ์และเมื่อได้รับเหตุการณ์เหล่านี้คลาส DataWatcher จะพิมพ์ข้อมูลที่เปลี่ยนแปลงไปยังคอนโซล
ต่อไปนี้เป็นรหัสของคลาส dataWatcher.java:
นำเข้า java.io.ioException; นำเข้า org.apache.zookeeper.createMode; นำเข้า org.apache.zookeeper.keeperexception; นำเข้า org.apache.zookeeper.watchedEvent; นำเข้า org.apache.zookeeper.watcher; DataWatcher ใช้ Watcher, Runnable {String Private String hostport = "localhost: 2181"; สตริงคงที่ส่วนตัว zoodatapath = "/myConfig"; byte zoo_data [] = null; zookeeper zk; dataWatcher สาธารณะ znode ถ้าไม่มีอยู่ด้วยรหัสต่อไปนี้: ถ้า (zk.exists (zoodatapath, this) == null) {zk.create (zoodatapath, "" .getBytes (), zoodefs.ids.open_acl_unsafe, createMode.persistent); {e.printstacktrace ();}}} catch (ioexception e) {e.printstacktrace ();}} โมฆะสาธารณะ printdata () พ่น InterruptedException, GeterException {zoo_data = zk.getData ของ Znode ไปยังคอนโซล: System.out.printf ("/ncurrent data @ zk path %s: %s", zoodatapath, zstring);} @ กระบวนการโมฆะ overridepublic (event.getType () == event.eventType.nodedataChanged) {ลอง {printdata ();} catch (interruptedException e) {E.printstacktrace ();} catch (GeterException e) {e.printstacktrace () {dataWatcher dataWatcher = ใหม่ dataWatcher (); dataWatcher.printdata (); dataWatcher.run ();} โมฆะสาธารณะเรียกใช้ () {ลอง {ซิงโครไนซ์ (นี่) {ในขณะที่ (จริง) {รอ ();}}} catch {E.PrintStackTrace (); thread.currentthread (). interrupt ();}}}ลองมาดูรหัสของคลาส DataWatcher.java เพื่อทำความเข้าใจการใช้งานของ Zookeeper Monitor คลาสสาธารณะ DataWatcher ใช้อินเทอร์เฟซ Watcher และอินเตอร์เฟส Runnable และตั้งใจที่จะเรียกใช้มอนิเตอร์เป็นเธรด วิธีหลักสร้างอินสแตนซ์ของคลาส DataWatcher ในรหัสก่อนหน้าตัวสร้าง DataWatcher พยายามเชื่อมต่อกับอินสแตนซ์ของ Zookeeper ที่ทำงานบน LocalHost หากการเชื่อมต่อสำเร็จเราจะใช้รหัสต่อไปนี้เพื่อตรวจสอบว่า Znode Path/MyConfig มีอยู่หรือไม่:
if (zk.exists (zoodatapath, this) == null) {หาก znode ไม่มีอยู่ในเนมสเปซ Zookeeper การเรียกใช้วิธีการมีอยู่จะส่งคืนค่า null และพยายามสร้างเป็น znode ถาวรโดยใช้รหัสดังนี้:
zk.create (zoodatapath, "" .getBytes (), zoodefs.ids.open_acl_unsafe, createMode.persistent);
ถัดไปคือวิธีการกระบวนการซึ่งประกาศในอินเตอร์เฟส Watcher ของ org.apache.zookeeper และนำไปใช้โดยคลาส DataWatcher โดยใช้รหัสต่อไปนี้:
กระบวนการโมฆะสาธารณะ (เหตุการณ์ดูดีบุก) {เพื่อความเรียบง่ายในวิธีการกระบวนการเหตุการณ์ที่ได้รับจากอินสแตนซ์ของ Zookeeper จะถูกพิมพ์และมีเพียงเหตุการณ์ของประเภท nodedataChanged จะถูกประมวลผลเพิ่มเติมดังนี้:
if (event.getType () == event.eventType.nodedataChanged)
เมื่อการอัปเดตหรือการเปลี่ยนแปลงใด ๆ เกิดขึ้นในฟิลด์ข้อมูลของ Znode Path/MyConfig และได้รับเหตุการณ์ประเภท NodedatAChanged วิธีการพิมพ์จะถูกเรียกให้พิมพ์เนื้อหาปัจจุบันของ ZNODE เมื่อเรียกใช้การโทร getData บน Znode เราตั้งค่าจอภาพอีกครั้งซึ่งเป็นพารามิเตอร์ที่สองของวิธีดังที่แสดงในรหัสต่อไปนี้:
zoo_data = zk.getData (zoodatapath, นี่, null);
การตรวจสอบเหตุการณ์เป็นตัวกระตุ้นครั้งเดียวที่ส่งไปยังลูกค้าที่ตั้งค่าการตรวจสอบ เพื่อที่จะได้รับการแจ้งเตือนเหตุการณ์เพิ่มเติมอย่างต่อเนื่องลูกค้าควรรีเซ็ตจอภาพ
DataUpdater.java เป็นคลาสง่าย ๆ ที่เชื่อมต่อกับอินสแตนซ์ Zookeeper ที่ใช้งาน LocalHost และอัปเดตฟิลด์ข้อมูลของ Znode Path/MyConfig ด้วยสตริงแบบสุ่ม ที่นี่เราเลือกที่จะอัปเดต znode ด้วยสตริง Universal Unique identifier (UUID) เนื่องจากการโทร UUID ที่ตามมาจะรับประกันการสร้างสตริงที่ไม่ซ้ำกัน
รหัสคลาส dataupdater.java มีดังนี้:
นำเข้า java.io.ioexception; นำเข้า java.util.uuid; นำเข้า org.apache.zookeeper.evelexception; นำเข้า org.apache.zookeeper.watchedEvent; นำเข้า org.apache.zookeeper.watcher; นำเข้า org.apache.zookeeper.zookeeper "localhost: 2181"; สตริงคงที่ส่วนตัว zoodatapath = "/myconfig"; zookeeper zk; dataupdater สาธารณะ () พ่น ioexception {ลอง {zk = new zookeeper (hostport, 2000, this);} catch (ioexception e) uuid string.public void run () พ่น InterruptedException, GeterException {ในขณะที่ (จริง) {string uuid = uuid.randomuuid (). toString (); byte zoo_data [] = uuid.getBytes (); zk.setData // sleep เป็นเวลา 5 วินาที} catch (interruptedException e) {thread.currentthread (). interrupt ();}}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) throwsioException, interruptedException, getERException {system.out.printf ("/nevent ได้รับ: %s", event.toString ());}}รหัสข้างต้นทำให้เซิร์ฟเวอร์ Zookeeper เรียกเหตุการณ์ NodedataChanged เนื่องจาก DataWatcher ตั้งค่าการตรวจสอบสำหรับเส้นทาง Znode นี้จึงได้รับการแจ้งเตือนเหตุการณ์การเปลี่ยนแปลงข้อมูล จากนั้นจะดึงข้อมูลที่อัปเดตรีเซ็ตการตรวจสอบและพิมพ์ข้อมูลบนคอนโซล
ใช้คำสั่งต่อไปนี้เพื่อรวบรวมคลาส DataWatcher และ DataUpdater:
$ javac cp $ classpath dataWatcher.java $ javac cp $ classpath dataupdater.java
ในการดำเนินการโปรแกรมตรวจสอบและอัปเดตต้องเปิดหน้าต่างเทอร์มินัลสองบาน ฉันต้องการเรียกใช้มอนิเตอร์ก่อนเพราะมันสร้าง znode ของ /myConfig (ถ้ามันไม่ได้ถูกสร้างขึ้นในเนมสเปซของ Zookeeper) ก่อนที่จะเรียกใช้จอภาพตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ Zookeeper กำลังทำงานบนโฮสต์ท้องถิ่น
ในหนึ่งในหน้าต่างเทอร์มินัลให้ดำเนินการคลาส Watcher โดยเรียกใช้คำสั่งต่อไปนี้:
$ java cp $ classpath dataWatcher
เอาต์พุตข้อความที่คล้ายกับข้อความที่แสดงในภาพหน้าจอต่อไปนี้:
ดังที่แสดงในภาพหน้าจอก่อนหน้า Path Znode/MyConfig ถูกสร้างขึ้นโดยคลาส DataWatcher นอกจากนี้ยังพิมพ์เนื้อหาของ Znode แต่ไม่ใช่ในคอนโซลเพราะเราไม่ได้ตั้งค่าข้อมูลใด ๆ เมื่อสร้าง Znode เมื่อ znode ถูกสร้างขึ้นจอภาพในชั้นเรียนจะได้รับการแจ้งเตือนเหตุการณ์ของประเภท nodecreated ซึ่งพิมพ์ในคอนโซล คลาส DataWatcher ยังคงรันและรับฟังเหตุการณ์บนโหนด /myConfig จากเซิร์ฟเวอร์ Zookeeper
มาเรียกใช้คลาส dataupdater ในหน้าต่างเทอร์มินัลอื่น:
$ java -cp $ classpath dataupdater
หลังจากเข้าสู่ระบบข้อความบันทึกเฉพาะของ Zookeeper เริ่มต้นไปยังคอนโซลคลาส DataUpDater จะทำงานโดยไม่ต้องแจ้งเตือน มันตั้งค่าสตริง UUID ใหม่เป็นฟิลด์ข้อมูลของเส้นทาง Zookeeper/myConfig ดังนั้นโปรดดูว่าทุก ๆ 5 วินาทีเอาต์พุตที่แสดงในภาพหน้าจอด้านล่างจะถูกพิมพ์ในหน้าต่างเทอร์มินัลที่ทำงาน DataWatch:
DataWatcher ยังสามารถทดสอบได้โดยใช้เชลล์ Zookeeper ดำเนินการต่อเพื่อเรียกใช้คลาส DataWatcher ในเทอร์มินัลเหมือนก่อนหน้าและเรียกเชลล์ Zookeeper ในเทอร์มินัลอื่นและเรียกใช้คำสั่งที่แสดงในภาพหน้าจอต่อไปนี้:
ในเทอร์มินัลที่ DataWatcher กำลังทำงานข้อความต่อไปนี้จะถูกพิมพ์:
สามตัวอย่าง - การตรวจสอบคลัสเตอร์
บริการยอดนิยมที่ให้บริการผ่านอินเทอร์เน็ตเช่นอีเมลแพลตฟอร์มบริการไฟล์เกมออนไลน์ ฯลฯ ให้บริการโดยเซิร์ฟเวอร์หลายร้อยหรือหลายพันเซิร์ฟเวอร์ที่มีอยู่ในหลาย ๆ ศูนย์ข้อมูลซึ่งมักจะแยกทางภูมิศาสตร์ ในคลัสเตอร์ดังกล่าวโหนดเซิร์ฟเวอร์เฉพาะบางตัวจะถูกตั้งค่าเพื่อตรวจสอบกิจกรรมของเซิร์ฟเวอร์ที่บริการโฮสต์หรือแอปพลิเคชันในเครือข่ายการผลิต ในสภาพแวดล้อมการประมวลผลแบบคลาวด์โหนดการตรวจสอบที่ใช้ในการจัดการสภาพแวดล้อมคลาวด์เรียกว่าตัวควบคุมคลาวด์ งานที่สำคัญของโหนดคอนโทรลเลอร์เหล่านี้คือการตรวจจับความล้มเหลวในเซิร์ฟเวอร์การผลิตแบบเรียลไทม์และแจ้งผู้ดูแลระบบตามลำดับและใช้มาตรการที่จำเป็นเช่นความล้มเหลวในการใช้งานแอปพลิเคชันบนเซิร์ฟเวอร์ที่ล้มเหลวไปยังเซิร์ฟเวอร์อื่น
ในส่วนนี้เราจะใช้ Zookeeper Java Client API เพื่อพัฒนารูปแบบการตรวจสอบคลัสเตอร์แบบมินิมัลลิสต์ การใช้แนวคิด Znode ชั่วคราวของ Zookeeper เพื่อสร้างรูปแบบการตรวจสอบนี้ค่อนข้างง่ายและสง่างามตามที่อธิบายไว้ในขั้นตอนต่อไปนี้:
เซิร์ฟเวอร์การผลิตแต่ละตัวเรียกใช้ไคลเอนต์ Zookeeper เป็น daemon กระบวนการนี้เชื่อมต่อกับเซิร์ฟเวอร์ zookeeper และสร้าง znode ชั่วคราวด้วยชื่อ (โดยเฉพาะชื่อเครือข่ายหรือชื่อโฮสต์) ภายใต้เส้นทางที่กำหนดไว้ล่วงหน้าของ /zookeeper namespace (เช่น /สมาชิก) โหนด Cloud Controller เรียกใช้กระบวนการตรวจสอบ Zookeeper ซึ่งตรวจสอบเส้นทาง/สมาชิกและรับฟังเหตุการณ์ประเภท Nodechildrenchanged กระบวนการตรวจสอบนี้ทำงานเป็นบริการหรือ daemon และตั้งค่าหรือรีเซ็ตการตรวจสอบบนเส้นทางและใช้ตรรกะเพื่อเรียกโมดูลที่เหมาะสมเพื่อดำเนินการที่จำเป็นสำหรับการตรวจสอบเหตุการณ์ ตอนนี้หากเซิร์ฟเวอร์การผลิตถูกปิดเนื่องจากความล้มเหลวของฮาร์ดแวร์หรือซอฟต์แวร์ล่มกระบวนการไคลเอนต์ Zookeeper จะถูกยกเลิกทำให้เซสชันระหว่างเซิร์ฟเวอร์และบริการ Zookeeper ถูกยกเลิก เนื่องจากคุณสมบัติของ Zpremeral Znode นั้นไม่ซ้ำกันบริการ Zookeeper จะลบ Znode ในเส้นทาง/สมาชิกโดยอัตโนมัติเมื่อใดก็ตามที่การเชื่อมต่อไคลเอนต์ถูกปิด การลบ Znode ในเส้นทางจะเพิ่มเหตุการณ์ Nodechildrenchanged ดังนั้นกระบวนการของผู้สังเกตการณ์ในตัวควบคุมคลาวด์จะได้รับแจ้ง โดยการเรียกใช้วิธี getChildren ในเส้นทาง/สมาชิกคุณสามารถกำหนดได้ว่าโหนดเซิร์ฟเวอร์ใดถูกปิด โหนดคอนโทรลเลอร์สามารถใช้มาตรการที่เหมาะสมเช่นดำเนินการกู้คืนตรรกะการกู้คืนเพื่อรีสตาร์ทบริการที่ล้มเหลวในเซิร์ฟเวอร์อื่น ตรรกะนี้สามารถสร้างขึ้นเพื่อทำงานแบบเรียลไทม์เพื่อให้มั่นใจว่าใกล้เคียงกับการหยุดทำงานเป็นศูนย์และบริการที่มีให้บริการสูง
ในการใช้รูปแบบการตรวจสอบคลัสเตอร์นี้เราจะพัฒนาคลาส Java สองคลาส คลาส Clustermonitor จะเรียกใช้การตรวจสอบอย่างต่อเนื่องเพื่อตรวจสอบเส้นทาง/สมาชิกในต้นไม้ Zookeeper หลังจากประมวลผลเหตุการณ์ที่เพิ่มขึ้นเราจะพิมพ์รายการ Znode ในคอนโซลและรีเซ็ตการตรวจสอบ ClusterClient คลาสอื่นจะเริ่มการเชื่อมต่อกับเซิร์ฟเวอร์ Zookeeper และสร้าง Znode ชั่วคราวภายใต้ /สมาชิก
ในการจำลองคลัสเตอร์ที่มีหลายโหนดเราเริ่มไคลเอนต์หลายตัวบนคอมพิวเตอร์เครื่องเดียวกันและสร้าง Znode ชั่วคราวโดยใช้รหัสกระบวนการของกระบวนการไคลเอนต์ โดยการดูข้อมูลประจำตัวของกระบวนการคลาส Clustermonitor สามารถกำหนดกระบวนการไคลเอนต์ที่ถูกปิดและกระบวนการใดที่ยังคงอยู่ที่นั่น ในกรณีที่ใช้งานได้จริงกระบวนการไคลเอนต์มักจะสร้าง Znode ชั่วคราวโดยใช้ชื่อโฮสต์ของเซิร์ฟเวอร์ที่กำลังทำงานอยู่ในปัจจุบัน ซอร์สโค้ดสำหรับสองคลาสนี้แสดงอยู่ด้านล่าง
คลาส Clustermonitor.java ถูกกำหนดดังนี้:
นำเข้า java.io.ioexception; นำเข้า java.util.list; นำเข้า org.apache.zookeeper.createmode; นำเข้า org.apache.zookeeper.keeperexception; นำเข้า org.apache.zookeeper.watchedevent; นำเข้า org.apache. org.apache.zookeeper.zookeeper; Clustermonitor คลาสสาธารณะใช้งาน Runnable {String String ส่วนตัว Private String ROOT = "/สมาชิก"; ผู้เฝ้าดูครั้งสุดท้ายส่วนตัว ConnectionWatcher ส่วนตัว {@overridepublic void process (event watchedEvent) {if (event.getType () == watcher.event.eventType.none && event.getState () == watcher.event.eanty.yncconnected) {system.out.printf ( New Watcher () {@OverridePublic Void Process (Event WatchEdEvent) {System.out.printf ("/Nevent ได้รับ: %S", Event.toString ()); ถ้า (Event.getType () == Event.eventType.nodechildrenchanged) zk.getchildren (สมาชิกรูท, นี่); ผนัง ("!! การเปลี่ยนแปลงสมาชิกคลัสเตอร์ !!!"); ผนัง ("สมาชิก:" + เด็ก);} จับ (GeterException e) {โยน runtimeException ใหม่ (e);} catch (interruptedexception e) = New Zookeeper (Hostport, 2000, ConnectionWatcher); // ตรวจสอบให้แน่ใจว่า znode parent existiF (zk.exists (สมาชิกรูท, เท็จ) == null) {zk.create (สมาชิกรูท, "Clustermonitorroot". getBytes (), ids.open_acl_unsafe znodelist <String> เด็ก = zk.getchildren (สมาชิกรูท, เด็ก Watcher); System.err.println ("สมาชิก:" + เด็ก ๆ );} โมฆะสาธารณะที่ซิงโครไนซ์ปิด () {ลอง {zk.close ();} catch {system.out.printf ("/nmessage: %s", ข้อความ);} โมฆะสาธารณะเรียกใช้ () {ลอง {ซิงโครไนซ์ (นี่) {ในขณะที่ (มีชีวิตอยู่) {รอ ();}}} catch (interruptedexception e) {e.printstacktrace () เป็นโมฆะหลัก (สตริง [] args) พ่น IOException, interruptedException, GeterException {ถ้า (args.length! = 1) {system.err.println ("การใช้งาน: clustermonitor <โฮสต์: พอร์ต>"); system.exit (0);} string hostport = args [0];คลาส ClusterClient.java ถูกกำหนดดังนี้:
นำเข้า java.io.ioException; นำเข้า java.lang.Management.ManagementFactory; นำเข้า org.apache.zookeeper.createMode; นำเข้า org.apache.zookeeper.keeperexception; นำเข้า org.apache.zookeeper.watchedEvent org.apache.zookeeper.zookeeper; Clusterclient คลาสสาธารณะใช้ Watcher, runnable {private string string membershiproot = "/members"; zookeeper zk; คลัสเตอร์สาธารณะ (สตริงโฮสต์พอร์ตยาว) {String processid = pid.toString {E.printStackTrace ();} ถ้า (zk! = null) {ลอง {zk.create (สมาชิกรูท + '/' + processId, processId.getBytes (), ids.open_acl_unsafe, createMode.ephemeral); Void Close () {ลอง {zk.close ();} catch (interruptedException e) {e.printstacktrace ();}}@กระบวนการโมฆะ overridepublic (เหตุการณ์ที่เกิดขึ้น) {system.out.printf ( (จริง) {wait ();}}} catch (interruptedException e) {e.printStackTrace (); thread.currentthread (). interrupt ();} ในที่สุด {this.close ();}} public Static Void Main (args) {ถ้า (args.length! <โฮสต์: พอร์ต> "); system.exit (0);} สตริง hostport = args [0]; // รับชื่อกระบวนการ idstring name = managementFactory.getRuntimemxBean (). getName (); int index = name.indexof ('@'); long processid = long.parselongใช้คำสั่งต่อไปนี้เพื่อรวบรวมสองคลาสนี้:
$ javac -cp $ classpath clustermonitor.java $ javac -cp $ classpath clusterclient.java
ในการดำเนินการโมเดลการตรวจสอบคลัสเตอร์ให้เปิดสองขั้ว ในหนึ่งในเทอร์มินัลให้เรียกใช้คลาส Clustermonitor ในเทอร์มินัลอื่นมีการดำเนินการหลายอินสแตนซ์โดยเรียกใช้คลาส ClusterClient ในพื้นหลัง
ในเทอร์มินัลแรกดำเนินการคลาส Clustermonitor:
$ java -cp $ classpath ClusterMonitorLocalHost: 2181
ดังที่แสดงในตัวอย่างก่อนหน้าคุณจะเห็นข้อความบันทึกการดีบักจาก API ไคลเอ็นต์ ในที่สุดคลาส ClusterMonitor จะเริ่มตรวจสอบเหตุการณ์และป้อนเนื้อหาต่อไปนี้:
ตอนนี้ดำเนินการห้าอินสแตนซ์ของคลาส ClusterClient เพื่อจำลองห้าโหนดของคลัสเตอร์ ClusterClient สร้าง znode ชั่วคราวโดยใช้รหัสกระบวนการของตัวเองในเส้นทาง /สมาชิกของต้นไม้ zookeeper:
$ java -cp $ classpath clusterclient localhost: 2181 2> & 1>/dev/null & [1] 4028 $ java -cp $ classpath clusterclient localhost: 2181 2> & 1>/dev/null & [2] 4045 $ java -cp $ classpath clusterclient -cp $ classpath ClusterClient localhost: 2181 2> & 1>/dev/null & [4] 4072 $ java -cp $ classpath ClusterClient localhost: 2181 2> & 1>/dev/null & [5] 4084
สอดคล้องกับสิ่งนี้จะสังเกตได้ว่าคลาส Clustermonitor ตรวจพบอินสแตนซ์คลาสคลัสเตอร์ใหม่เหล่านี้เนื่องจากเป็นการตรวจสอบเหตุการณ์บนเส้นทาง /สมาชิกของต้นไม้ Zookeeper สิ่งนี้จำลองเหตุการณ์การเข้าร่วมโหนดในคลัสเตอร์จริง เอาต์พุตสามารถเห็นได้ในเทอร์มินัลของคลาส Clustermonitor ซึ่งคล้ายกับที่แสดงในภาพหน้าจอด้านล่าง:
ตอนนี้หากกระบวนการ clusterclient.java ถูกฆ่าตายเซสชันที่จะรักษาด้วยเซิร์ฟเวอร์ Zookeeper จะถูกยกเลิก ดังนั้น Znode ชั่วคราวที่สร้างโดยไคลเอนต์จะถูกลบ การลบจะเรียกเหตุการณ์ nodechildrenchanged ซึ่งจะถูกจับโดยคลาส Clustermonitor สิ่งนี้จำลองสถานการณ์ที่โหนดออกจากคลัสเตอร์
มายุติกระบวนการ clusterclient ด้วย ID 4084:
$ kill -9 4084
ภาพหน้าจอต่อไปนี้แสดงผลลัพธ์ในเทอร์มินัลของคลาส Clustermonitor แสดงรายการกระบวนการที่มีอยู่ในปัจจุบันและรหัสกระบวนการที่เลียนแบบเซิร์ฟเวอร์เรียลไทม์:
การใช้งานตัวอย่างของรูปแบบการตรวจสอบคลัสเตอร์ที่เรียบง่ายและสง่างามด้านบนแสดงให้เห็นถึงพลังที่แท้จริงของ Zookeeper หากไม่มี Zookeeper การพัฒนารูปแบบดังกล่าวที่สามารถตรวจสอบกิจกรรมโหนดในเวลาจริงจะเป็นงานที่น่ากลัวจริง