ยูเรก้าเป็นแอปพลิเคชั่นการกำกับดูแลบริการที่กระจายอำนาจและคุณสมบัติที่โดดเด่นของมันคือสามารถลงทะเบียนกับที่อยู่ที่คุณกำหนดค่าเป็นทั้งเซิร์ฟเวอร์และบริการ จากนั้นในบทความนี้มาหารือเกี่ยวกับกระบวนการลงทะเบียนของยูเรก้า
1. เซิร์ฟเวอร์ของยูเรก้า
คลาสหลักของฝั่งเซิร์ฟเวอร์ของยูเรก้าคือ Eurekabootstrap ซึ่งใช้ผู้ฟังของ ServletContextListener ดังนั้นเราสามารถสรุปได้ว่า Eureka ถูกนำไปใช้ตามคอนเทนเนอร์ Servlet รหัสคีย์มีดังนี้:
คลาสสาธารณะ Eurekabootstrap ใช้ ServletContextListener {//....omit รหัสที่เกี่ยวข้อง/*** เริ่มต้นยูเรก้ารวมถึงการซิงค์กับเพื่อนคนอื่น ๆ Eureka และเผยแพร่รีจิสทรี * * @See * Javax.servlet.servletContextListener#contextInitialized (javax.servlet.servletContextEvent) */ @Override โมฆะสาธารณะบริบท initeurekaservercontext (); servletContext sc = event.getServletContext (); Sc.SetAttribute (EurekaserverContext.class.getName (), ServerContext); } catch (throwable e) {logger.error ("ไม่สามารถ bootstrap server eureka:", e); โยน runtimeException ใหม่ ("ไม่สามารถ bootstrap Eureka Server:", e); }} // ละเว้นรหัสที่เกี่ยวข้อง ...... }เราจะเห็นได้ว่าเมื่อการเริ่มต้น ServletContext เสร็จสมบูรณ์สภาพแวดล้อมของยูเรก้าจะเริ่มต้นและจากนั้น EurekaserverContext จะเริ่มต้น จากนั้นเรากำลังดูวิธี initeurekaservercontext:
/*** init hook สำหรับบริบทเซิร์ฟเวอร์ แทนที่ตรรกะที่กำหนดเอง */ การป้องกันโมฆะ initeureKaserverContext () พ่นข้อยกเว้น {// ...... ApplicationInfomanager ApplicationInfomanager = null; if (eurekaclient == null) {eurekainstanceconfig instanceconfig = iScloud (configurationManager.getDeploymentContext ())? ใหม่ CloudInstanceconfig (): ใหม่ myDatacenterInstancEconfig (); ApplicationInfomanager = ApplicationInfomanager ใหม่ (Instanceconfig, ใหม่ Eurekaconfigbasedinstanceinfoprovider (Instanceconfig) .get ()); EUREKACLIENTCONFIG EUREKACLIENTCONFIG = ใหม่ defaultEureKaclientConfig (); Eurekaclient = ใหม่ DiscoveryClient (ApplicationInfomanager, EurekaclientConfig); } else {ApplicationInfomanager = Eurekaclient.getApplicationInfomanager (); } Peerawareinstanceregistry Registry; if (isaws (applicationinfomanager.getInfo ())) {registry = new awsinstanceregistry (EurekaserverConfig, Eurekaclient.geteurekaclientconfig (), ServerCodecs, Eurekaclient); awsbinder = ใหม่ awsbinderdelegate (EurekaserverConfig, Eurekaclient.geteurekaclientConfig (), รีจิสทรี, applicationinfomanager); awsbinder.start (); } else {registry = ใหม่ peerawareinstanceregistryImpl (eeurekaserverconfig, eurekaclient.geteurekaclientconfig (), servercodecs, eurekaclient); } //...mit ส่วนหนึ่งของรหัส}ในวิธีนี้วัตถุจำนวนมากที่เกี่ยวข้องกับบริการยูเรก้าจะถูกสร้างขึ้น ที่นี่ฉันแสดงรายการวัตถุหลักสองรายการคือ Eurekaclient และ PeerawareInstanceregistry เราจะพูดถึงส่วนลูกค้าในภายหลัง มาดูกันว่า PeerawareInstanceregistry ใช้อะไรบ้าง ที่นี่ฉันเขียนแผนภาพคลาสเกี่ยวกับคลาสนี้:
ตามแผนภาพของคลาสเราสามารถพบได้อย่างชัดเจนว่าอินเทอร์เฟซระดับบนสุดของ peerawareinstanceregistry คือ leasemanager และ lookupservice ที่การค้นหาการใช้งานกำหนดพฤติกรรมของตัวอย่างการค้นพบขั้นพื้นฐานที่สุดในขณะที่ Leasemanager กำหนดการประมวลผลการลงทะเบียนลูกค้า ดังนั้นในบทความนี้ให้มุ่งเน้นไปที่การใช้งานอินเทอร์เฟซที่เกี่ยวข้องของ LeaseManager มองย้อนกลับไปเรากำลังดู Peerawareinstanceregistry ในความเป็นจริงคลาสนี้ใช้เพื่อคัดลอกข้อมูลที่เกี่ยวข้องภายใต้หลายโหนด ตัวอย่างเช่นหากโหนดลงทะเบียนสำหรับการต่ออายุและออฟไลน์การคัดลอกที่เกี่ยวข้อง (การแจ้งเตือน) จะถูกคัดลอกไปยังแต่ละโหนดผ่านคลาสนี้ มาดูกันว่ามันจัดการกับการลงทะเบียนลูกค้าได้อย่างไร:
/** * ลงทะเบียนข้อมูลเกี่ยวกับ {@link InstanceInfo} และแบบจำลอง * ข้อมูลนี้ไปยังโหนด Eureka Peer Eureka ทั้งหมด หากนี่คือเหตุการณ์การจำลองแบบ * จากโหนดแบบจำลองอื่น ๆ จะไม่ทำซ้ำ * * @param info * The {@link InstanceInfo} ที่จะลงทะเบียนและทำซ้ำ * @param isreplication * จริงถ้านี่เป็นเหตุการณ์การจำลองแบบจากโหนดจำลองอื่น ๆ * เท็จมิฉะนั้น */ @Override void public void register (ข้อมูลอินสแตนซ์ขั้นสุดท้ายข้อมูล, บูลีนขั้นสุดท้าย isreplication) {int rease -leased = lease.default_duration_in_secs; if (info.getLeaseInfo ()! = null && info.getLeaseInfo (). getDurationInsecs ()> 0) {leaseduration = info.getLeaseInfo (). getDurationInsecs (); } super.register (ข้อมูล, การให้เช่า, isreplication); ReplicatoTopeers (action.register, info.getAppName (), info.getId (), ข้อมูล, null, isreplication); -เราจะเห็นได้ว่ามันเรียกวิธีการลงทะเบียนของคลาสพาเรนต์จากนั้นจำลองพฤติกรรมที่สอดคล้องกันไปยังโหนดอื่น ๆ ผ่านตัวทำซ้ำ การจำลองแบบเฉพาะจะไม่ถูกกล่าวถึงที่นี่ มามุ่งเน้นไปที่วิธีการลงทะเบียน เราพบวิธีการลงทะเบียน () ในคลาสหลัก:
/*** ลงทะเบียนอินสแตนซ์ใหม่ที่มีระยะเวลาที่กำหนด * * @see com.netflix.eureka.lease.leaseManager#register (java.lang.Object, int, บูลีน) */ การลงทะเบียนโมฆะสาธารณะ (การลงทะเบียนอินสแตนซ์ แผนที่ <string, สัญญาเช่า <อินสแตนซ์ info >> gmap = registry.get (registrant.getAppName ()); register.increment (isreplication); if (gmap == null) {สุดท้ายพร้อมกันพร้อมกัน <string, lease <innessInfo >> gNewMap = ใหม่พร้อมกันพร้อมกัน <String, สัญญาเช่า <innessInfo >> (); gmap = registry.putifabsent (registrant.getAppName (), gNewMap); if (gmap == null) {gmap = gNewMap; }} สัญญาเช่า <innessInfo> ที่มีอยู่จริง = gmap.get (registrant.getId ()); // รักษา timestamp ที่สกปรกครั้งสุดท้ายโดยไม่ต้องเขียนทับถ้ามีสัญญาเช่าอยู่แล้วถ้า (มีอยู่จริง! = null && (มีอยู่จริง. getholder ()! = null)) {Long ที่มีอยู่ การลงทะเบียนยาว lastdirtytimestamp = registered.getLastDirtyTimestamp (); logger.debug ("พบสัญญาเช่าที่มีอยู่ (มีอยู่ = {}, ให้ = {}", มีอยู่แล้ว การลงทะเบียน lastdirtytimestamp) {logger.warn ("มีสัญญาเช่าที่มีอยู่และการส่งมอบที่สกปรกของสัญญาเช่าที่มีอยู่ {} นั้นยิ่งใหญ่กว่า" + "มากกว่าที่ลงทะเบียน {}" มีอยู่ การลงทะเบียน "); การลงทะเบียน = arilelease.getholder ();}} else {// สัญญาเช่าไม่มีอยู่จริงและด้วยเหตุนี้จึงเป็นการลงทะเบียนใหม่ซิงโครไนซ์ (ล็อค) {ถ้า (this.epectednumberofrenewspermin> 0) {// เนื่องจากลูกค้าต้องการยกเลิก this.epectedNumberOfReneWspermin = this.expectedNumberOfReneWspermin + 2; สัญญาเช่า <contenfo> สัญญาเช่าใหม่ <อินสแตนซ์อินสแตนซ์> (ผู้จดทะเบียน, การให้เช่า);ผ่านซอร์สโค้ดมาเรียงลำดับกระบวนการสั้น ๆ :
1) ก่อนอื่นให้รับคอลัมน์ของวัตถุอินสแตนซ์บริการตามชื่อ AppName หากเป็นโมฆะให้สร้างแผนที่ใหม่และเพิ่มข้อมูลแอปพลิเคชันที่ลงทะเบียนปัจจุบันลงในแผนที่นี้ มีวัตถุเช่าที่นี่ ชั้นเรียนนี้อธิบายถึงแอตทริบิวต์เวลาของ T ทั่วไปเช่นเวลาลงทะเบียนเวลาเริ่มต้นบริการเวลาอัปเดตขั้นสุดท้าย ฯลฯ คุณสามารถให้ความสนใจกับการใช้งาน:
/ * * Copyright 2012 Netflix, Inc. * * ได้รับอนุญาตภายใต้ใบอนุญาต Apache, เวอร์ชัน 2.0 ("ใบอนุญาต"); * คุณไม่สามารถใช้ไฟล์นี้ยกเว้นตามใบอนุญาต * คุณอาจได้รับสำเนาใบอนุญาตที่ * * http://www.apache.org/licenses/license-2.0 * * เว้นแต่ว่ากฎหมายที่บังคับใช้หรือตกลงที่จะเป็นลายลักษณ์อักษรซอฟต์แวร์ * แจกจ่ายภายใต้ใบอนุญาตจะถูกแจกจ่ายใน "ตาม" โดยไม่มีการรับประกันหรือเงื่อนไขใด ๆ * ดูใบอนุญาตสำหรับการอนุญาตการกำกับดูแลภาษาเฉพาะและ * ข้อ จำกัด ภายใต้ใบอนุญาต */แพ็คเกจ com.netflix.eureka.lease; นำเข้า com.netflix.eureka.registry.abstractinstanceregistry;/*** อธิบายความพร้อมใช้งานตามเวลาของ {@link t} วัตถุประสงค์คือการหลีกเลี่ยง * การสะสมของอินสแตนซ์ใน {@link AbstractInstanceregistry} เป็นผลมาจากการปิดตัวที่ไม่ได้รับความสนใจซึ่งไม่ใช่เรื่องแปลกในสภาพแวดล้อม AWS * * หากสัญญาเช่าผ่านไปโดยไม่มีการต่ออายุในที่สุดมันจะหมดอายุอย่างต่อเนื่อง * ทำเครื่องหมาย {@link t} ที่เกี่ยวข้องสำหรับการขับไล่ทันที - นี่คล้ายกับ * การยกเลิกที่ชัดเจนยกเว้นว่าไม่มีการสื่อสารระหว่าง * {@link t} และ {@link leaseManager} * * @author Karthik Ranganathan, Greg Kim */การเช่าคลาสสาธารณะ <t> {enum action {ลงทะเบียน, ยกเลิก, Renew}; สาธารณะคงที่สุดท้าย int default_duration_in_secs = 90; ผู้ถือส่วนตัว; Evictiontimestamp ส่วนตัว การลงทะเบียนส่วนตัวที่ยาวนาน บริการยาวส่วนตัว // ทำให้มันผันผวนเพื่อให้งานหมดอายุจะเห็น LastUpDateTimestamp ที่มีความผันผวนส่วนตัวเร็วขึ้นนี้ ระยะยาวส่วนตัว สัญญาเช่าสาธารณะ (t r, ระยะเวลา int) {holder = r; registrationTimestamp = System.currentTimeMillis (); LastUpDateTimestamp = การลงทะเบียน Timestamp; ระยะเวลา = (DurationInsecs * 1000); } /** * ต่ออายุสัญญาเช่าใช้ระยะเวลาการต่ออายุหากระบุโดย * ที่เกี่ยวข้อง {@link t} ระหว่างการลงทะเบียนมิฉะนั้นระยะเวลาเริ่มต้นคือ * {@link #default_duration_in_secs} */ โมฆะสาธารณะต่ออายุ () {lastUpDateTimestamp = System.currentTimeMillis () + ระยะเวลา; } /*** ยกเลิกสัญญาเช่าโดยการอัปเดตเวลาขับไล่ */ โมฆะสาธารณะยกเลิก () {ถ้า (EvictionTimestamp <= 0) {EvictionTimestamp = System.currentTimeMillis (); }} /*** ทำเครื่องหมายบริการขึ้น สิ่งนี้จะใช้เวลาเพียงครั้งแรกที่เรียกว่า * การโทรที่ตามมาจะถูกละเว้น */ Public Void ServiceUp () {ถ้า (ServiceUptimestamp == 0) {ServiceUptimestamp = System.currentTimeMillis (); }} /*** ตั้งค่าการประทับเวลาของใบไม้ */ โมฆะสาธารณะ setServiceUptimestamp (Long ServiceUptimestamp) {this.serviceUptimestamp = ServiceUptimestamp; } /*** ตรวจสอบว่าสัญญาเช่าของ {@link com.netflix.appinfo.instanceInfo} ได้หมดอายุแล้วหรือไม่ */ บูลีนสาธารณะ isexpired () {return isexpired (0L); } /*** ตรวจสอบว่าสัญญาเช่าของ {@link com.netflix.appinfo.instanceInfo} ได้หมดอายุแล้วหรือไม่ * * โปรดทราบว่าเนื่องจากการต่ออายุ () ทำสิ่ง 'ผิด "และการตั้งค่า LastUpDateTimEStamp เป็น +ระยะเวลามากกว่า * สิ่งที่ควรจะเป็นจริงการหมดอายุจะเป็นระยะเวลา 2 * นี่เป็นข้อผิดพลาดเล็กน้อยและควรส่งผลกระทบต่อการเพิ่มขึ้น บูลีน isexpired (Long AddentalleAsems) {return (EvictionTimestamp> 0 || system.currenttimemillis ()> (lastupDateTimestamp + ระยะเวลา + เพิ่มเติม leaseLeasems);} / ** * ได้รับการลงทะเบียนเมื่อมีการลงทะเบียน GetRegistrationTimestamp () {return registrationTimestamp; LastupDatimestamp; หลายล้านคนตั้งแต่ Epoch เมื่อบริการเช่าถูกทำเครื่องหมายเป็น UP2) ตามรหัสที่ลงทะเบียนในปัจจุบันหากคุณสามารถรับได้ในแผนที่ให้ทำสิ่งต่อไปนี้:
2.1) ตามเวลาสัมผัสของโหนดที่มีอยู่ในปัจจุบันและเวลาสัมผัสของโหนดที่ลงทะเบียนหากเวลาเดิมช้ากว่าเวลาหลังอินสแตนซ์ที่ลงทะเบียนในปัจจุบันจะอยู่ภายใต้อินสแตนซ์ที่มีอยู่
2.2) มิฉะนั้นอัปเดตหมายเลขการต่ออายุที่คาดหวังต่อนาทีและเกณฑ์
3) บันทึกโหนดการลงทะเบียนปัจจุบันลงในแผนที่และกระบวนการลงทะเบียนของเราได้สิ้นสุดลงโดยทั่วไป
2. ไคลเอนต์ยูเรก้า
เมื่อเซิร์ฟเวอร์ servletContext เริ่มต้นจะมีการสร้าง DiscoveryClient เพื่อนที่คุ้นเคยกับยูเรก้าจะต้องคุ้นเคยกับคุณลักษณะทั้งสองนี้: fetchregistry และ registerwitheureka เมื่อทำงานในโหมดอิสระยูเรก้าในสปริงคลูดหากค่าทั้งสองนี้ไม่ใช่เท็จการเริ่มต้นจะรายงานข้อผิดพลาด เหตุใดจึงรายงานข้อผิดพลาด ในความเป็นจริงคำตอบอยู่ในตัวสร้างของ DiscoveryClient:
@Inject DiscoveryClient (ApplicationInfomanager ApplicationInfomanager, EurekaclientConfig, AbstractDiscoveryClientOptionalargs, ผู้ให้บริการ <backupregistry> backupregistryProvider) {//e.oMOMIT ส่วนหนึ่งของรหัส (! ไม่ได้ลงทะเบียนหรือสอบถามข้อมูล "); scheduler = null; HeartBeatexecutor = null; CachereFreshexecutor = null; Eurekatransport = null; InstanceregionChecker = ใหม่ InstanceregionChecker (ใหม่ PropertyBasedAstoreGionMapper (config), clientConfig.getRegion ()); // นี่เป็นเพียงเล็กน้อยของการแฮ็คที่อนุญาตให้ใช้รหัสที่มีอยู่โดยใช้ discoveryManager.getInstance () // เพื่อทำงานกับ di'd discoveryClient discoveryManager.getInstance (). setDiscoveryClient (นี่); DiscoveryManager.getInstance (). seteurekaclientconfig (config); Inittimestampms = System.currentTimeMillis (); logger.info ("การค้นพบไคลเอนต์เริ่มต้นที่ timestamp {} ด้วยจำนวนอินสแตนซ์เริ่มต้น: {}", inittimestampms, this.petapplications (). size ()); กลับ; // ไม่จำเป็นต้องตั้งค่างานเครือข่ายและเราเสร็จแล้ว} ลอง {// ขนาดเริ่มต้นของ 2 - 1 แต่ละรายการสำหรับการเต้นของหัวใจและ cacherefresh scheduler = executors.newscheduledThreadpool (2, threadfactoryBuilder (). HeartBeatexecutor = ใหม่ threadpoolexecutor (1, clientconfig.getheartBeatexecutorthreadPoolsize (), 0, timeUnit.seconds, synchronousqueue ใหม่ <Runnable> (), threadFactoryBuilder (). // ใช้ Handoff Direct CachereFreshexecutor = ใหม่ ThreadPoolexecutor (1, clientConfig.getCachereFreshexecutorthreadPoolsize (), 0, TimeUnit.seconds, Synchronousqueue ใหม่ <Runnable> (), ใหม่ .SetDaemon (จริง) .build ()); // ใช้ Direct Handoff Eurekatransport = New Eurekatransport (); ScheduleserverendPointTask (Eurekatransport, Args); //eibomit บางรหัส InitscheduledTasks (); -ขึ้นอยู่กับซอร์สโค้ดเราสามารถวาดข้อสรุปต่อไปนี้:
1) หากทั้งคู่ควรลงทะเบียน WithEureka และควรจะเป็นเท็จเป็นเท็จจากนั้นกลับมาโดยตรง
2) สร้างพูลเธรดที่ส่ง HeartBeats และรีเฟรชแคช
3) เริ่มต้นงานที่กำหนดเวลาที่สร้างขึ้น
แล้วลองดูที่รหัสต่อไปนี้ในวิธีการ InitscheduledTasks ():
// heartbeat Timer Scheduler.schedule (Timedsupervisortask ใหม่ ("Heartbeat", Scheduler, HeartBeatexecutor, RenewalIntervalinsecs, Timeunit.seconds, Expbackoffbound, New Heartbeatthread ())นี่คือเธรดที่ก่อให้เกิดการดำเนินการตามกำหนดเวลาในไม่กี่วินาทีและดำเนินการ Heartbeat ที่ส่งตามค่า ReneLintervalinsecs เธรด HeartBeatThread ดำเนินการดังนี้:
/*** งานการเต้นของหัวใจที่ต่ออายุสัญญาเช่าในช่วงเวลาที่กำหนด */ คลาสส่วนตัว HeartBeatThread ใช้งานได้ {public void run () {ถ้า (repreh ()) {reminuccessfulheartbeattimestamp = system.currentTimeMillis (); -เราจะเห็นได้ว่าวิธีการเรียกใช้นั้นง่ายมากในการดำเนินการวิธีการต่ออายุและหากมีการบันทึกเวลาสำเร็จ วิธีการต่ออายุ:
/ ** * ต่ออายุด้วยบริการ Eureka โดยการโทรพักที่เหมาะสม */ Boolean Renew () {EUREKAHTTPRESSESPONSE <SNIPYINFO> HTTPRESSPONSE; ลอง {httpresponse = eeurekatransport.registrationClient.sendheartBeat (InstanceInfo.getAppName (), InstanceInfo.getId (), instanceInfo, null); logger.debug ("{} - สถานะการเต้นของหัวใจ: {}", คำนำหน้า + apppathidentifier, httpresponse.getStatusCode ()); if (httpresponse.getStatusCode () == 404) {reregister_counter.increment (); logger.info ("{} - การลงทะเบียนแอป/{}", คำนำหน้า + apppathidentifier, instanceInfo.getAppName ()); Long Timestamp = InstanceInfo.setisdirtywithtime (); ความสำเร็จของบูลีน = ลงทะเบียน (); if (ความสำเร็จ) {InstanceInfo.unsetIsdirty (การประทับเวลา); } คืนความสำเร็จ; } ส่งคืน httpresponse.getStatusCode () == 200; } catch (throwable e) {logger.error ("{} - ไม่สามารถส่ง Heartbeat!", คำนำหน้า + AppPathidentifier, e); กลับเท็จ; -หากการเต้นของหัวใจถูกส่งมาที่นี่หากผลตอบแทนคือ 404 การดำเนินการลงทะเบียนจะดำเนินการ โปรดทราบว่าขึ้นอยู่กับค่าส่งคืน httpresponse เราสามารถสรุปได้ว่าการดำเนินการทั้งหมดเหล่านี้ขึ้นอยู่กับคำขอ HTTP จริงหรือ? มาดูวิธีการลงทะเบียนต่อไป:
/*** ลงทะเบียนกับบริการ Eureka โดยโทรออกที่เหมาะสม */ บูลีนลงทะเบียน () โยนได้ {logger.info (คำนำหน้า + apppathidentifier + ": บริการลงทะเบียน ... "); Eurekahttpresponse <Void> httpresponse; ลอง {httpresponse = eeurekatransport.registrationClient.register (InstanceInfo); } catch (exception e) {logger.warn ("{} - การลงทะเบียนล้มเหลว {}", คำนำหน้า + apppathidentifier, e.getMessage (), e); โยน e; } if (logger.isinfoenabled ()) {logger.info ("{} - สถานะการลงทะเบียน: {}", คำนำหน้า + apppathidentifier, httpresponse.getStatusCode ()); } ส่งคืน httpresponse.getStatusCode () == 204; -ที่นี่วิธีการลงทะเบียนใน Eurekatransport เรียกว่า:
ชั้นสุดท้ายคงที่ระดับสุดท้าย Eurekatransport {Private Closableresolver Bootstrapresolver; TransportClientFactory Private TransportClientFactory; EurekahttpClient ส่วนตัว; EurekahttpClientFactory ส่วนตัว EUREKAHTTPClient ส่วนตัว; Private EurekahttpClientFactory QueryClientFactory; Void Shutdown () {ถ้า (ลงทะเบียน clientfactory! = null) {registrationClientFactory.shutdown (); } if (queryClientFactory! = null) {queryClientFactory.shutdown (); } ถ้า (ลงทะเบียน client! = null) {registrationClient.shutdown (); } if (queryClient! = null) {queryClient.shutdown (); } if (transportClientFactory! = null) {transportClientFactory.shutdown (); -ที่นี่เราจะเห็นว่าไคลเอนต์ของยูเรก้าใช้คำขอ HTTP เพื่อลงทะเบียนบริการซึ่งหมายความว่าเมื่อเราสร้าง DiscoveryClient เราจะลงทะเบียนอินสแตนซ์ด้วยเซิร์ฟเวอร์
3. บริการ REST ที่ให้บริการโดยเซิร์ฟเวอร์
เราได้เห็นรหัสที่ให้โดยเซิร์ฟเวอร์เพื่อจัดการคำขอลงทะเบียนไคลเอ็นต์แล้ว เนื่องจากไคลเอนต์ลงทะเบียนผ่านโปรโตคอล HTTP เซิร์ฟเวอร์จะต้องมีที่อยู่เพื่อจัดการคำขอ HTTP นี้ อันที่จริงเซิร์ฟเวอร์ยูเรก้าใช้มาตรฐาน JAX-RS เพื่อให้วิธีการพักผ่อนเพื่อให้บริการ เราสามารถดูวิธีการ addinstance ของแอปพลิเคชันนี้ได้:
/** * ลงทะเบียนข้อมูลเกี่ยวกับอินสแตนซ์เฉพาะสำหรับ * {@link com.netflix.discovery.shared.application} * * ข้อมูล @param * {@link InstanceInfo} ข้อมูลของอินสแตนซ์ * @param isreplication * พารามิเตอร์ส่วนหัวที่มีข้อมูลว่านี่เป็น * จำลองจากโหนดอื่น ๆ หรือไม่ */@post @consumes ({"แอปพลิเคชัน/json", "แอปพลิเคชัน/xml"}) การตอบสนองสาธารณะ addinstance (อินสแตนซ์ข้อมูลข้อมูล, @headerparam (peereurekanode.header_replication) สตริง isreplication) {logger.debug ("การลงทะเบียนอินสแตนซ์ {} // ตรวจสอบว่า InstanceInfo มีฟิลด์ที่จำเป็นทั้งหมดหาก (ISBLANK (info.getId ())) {return response.status (400) .ENTITY ("หายไปอินสแตนซ์"). สร้าง (); } อื่นถ้า (isblank (info.getHostName ())) {return response.status (400) .Entity ("Missing HostName"). build (); } อื่นถ้า (isblank (info.getipaddr ())) {return response.status (400) .Entity ("ที่อยู่ IP ที่หายไป"). build (); } else if (isblank (info.getAppName ()))) {return response.status (400) .Entity ("Missing AppName"). build (); } else if (! appname.equals (info.getAppName ()))) {return response.status (400) .Entity ("AppName ที่ไม่ตรงกันคาดหวัง" + AppName + "แต่เป็น" info.getAppName ()) } อื่นถ้า (info.getDatacenterInfo () == null) {return response.status (400) .Entity ("หายไป datacenterInfo"). build (); } อื่นถ้า (info.getDatacenterInfo (). getName () == null) {return response.status (400) .ENTITY ("หายไป dataCenterInfo"). build (); } else if (info.getDatacenterInfo (). getName () == null) {return response.status (400) .Entity ("ชื่อ DatacenterInfo" หายไป "). build (); } // จัดการกรณีที่ลูกค้าอาจลงทะเบียนกับ DataCenterInfo ที่ไม่ดีพร้อมข้อมูล DataCenterInfo DatacenterInfo = info.getDatacenterInfo (); if (dataCenterInfo อินสแตนซ์ที่ไม่ซ้ำใคร) {String dataCenterInfoid = ((เฉพาะที่ไม่ซ้ำกัน) DataCenterInfo) .getId (); if (isblank (datacenterInfoid)) {boolean experimental = "true" .equalsignorecase (serverconfig.getExperimental ("ลงทะเบียน. validation.datacenterInfoid")); ถ้า (ทดลอง) {string entity = "dataCenterInfo ประเภท" + datacenterInfo.getClass () + "ต้องมี ID ที่ถูกต้อง"; return response.status (400) .Entity (เอนทิตี). build (); } อื่นถ้า (dataCenterInfo อินสแตนซ์ของ amazoninfo) {amazoninfo amazoninfo = (amazoninfo) dataCenterInfo; String refileId = amazoninfo.get (amazoninfo.metadatakey.instanceId); if (flegeIb == null) {amazoninfo.getMetadata (). ใส่ (amazoninfo.metadatakey.instanceid.getName (), info.getId ()); }} else {logger.warn ("การลงทะเบียน dataCenterInfo ประเภท {} โดยไม่มี ID ที่เหมาะสม", dataCenterInfo.getClass ()); }}}} registry.register (ข้อมูล, "true" .equals (isreplication)); return response.status (204) .build (); // 204 เพื่อย้อนกลับเข้ากันได้}ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น