مقدمة
عندما نستخدم تعليق التعليق التوضيحي discoveryClient ، هل سيكون لدينا السؤال التالي: لماذا يؤدي تشغيل خدمة تسجيل الخدمة؟ ألا ينبغي استخدامه كاكتشاف الخدمة؟ دعنا نستكشف رمز المصدر الخاص به بعمق.
1.
لفهم هذه المسألة ، نحتاج إلى فهم هذه الواجهة المهمة:
/ * * حقوق الطبع والنشر 2002-2015 المؤلف أو المؤلفين الأصليين. * * مرخصة بموجب ترخيص Apache ، الإصدار 2.0 ("الترخيص") ؛ * لا يجوز لك استخدام هذا الملف إلا في الامتثال للترخيص. * يمكنك الحصول على نسخة من الترخيص على * * http://www.apache.org/licenses/license-2.0 * * ما لم يكن مطلوبًا بموجب القانون المعمول به أو يتم الاتفاق عليه في الكتابة ، يتم توزيع البرمجيات * الموزعة بموجب الترخيص على أساس "كما هو" ، * دون ضمانات أو شروط من أي نوع ، إما صريحة أو ضمنية. * راجع ترخيص الأذونات اللغوية المحددة والقيود * بموجب الترخيص. */package org.springframework.context ؛/*** واجهة مشتركة تحدد طرقًا للتحكم في دورة حياة البدء/الإيقاف. * حالة الاستخدام النموذجية لهذا هي التحكم في المعالجة غير المتزامنة. * <b> ملاحظة: لا تعني هذه الواجهة الدلالات التلقائية المحددة. * النظر في تطبيق {link smartlifecycle} لهذا الغرض. يمكن تنفيذ </b> * * <p> بواسطة كلا المكونين (عادةً ما يكون حبة زنبركية محددة في سياق الربيع *) وحاويات (عادةً ما يكون {link applicationcontext} * نفسه). ستنشر الحاويات إشارات البدء/الإيقاف إلى جميع المكونات التي * تنطبق داخل كل حاوية ، على سبيل المثال لسيناريو إيقاف/إعادة التشغيل في وقت التشغيل. * * <p> يمكن استخدامها للدعوات المباشرة أو لعمليات الإدارة عبر JMX. * في الحالة الأخيرة ، سيتم تحديد {link org.springframework.jmx.export.mbeanexporter} * مع * {link org.springframework.jmx.export.assembler.interfaceblesbeanfoAnfoSpler} ، واجهة. * * <p> لاحظ أن واجهة دورة الحياة مدعومة فقط على <b> Singleton * Beans </b>. على أي مكون آخر ، ستبقى واجهة دورة الحياة غير مكتشفة * وبالتالي يتم تجاهلها. لاحظ أيضًا أن واجهة {link smartlifecycle} توفر التكامل مع مراحل بدء تشغيل وابحاق سياق التطبيق. * * Author Juergen Hoeller * since 2.0 * seee smartlifecycle * seese configurableApplicationContext * seee org.springframework.jms.listener.abstractmessagelistener * @ دورة الحياة { /*** ابدأ هذا المكون. * <p> يجب ألا يرمي استثناء إذا كان المكون قيد التشغيل بالفعل. * <p> في حالة الحاوية ، سيؤدي ذلك إلى نشر إشارة البدء إلى جميع المكونات * التي تنطبق. * seee smartlifecycle#isautostartup () */ void start () ؛ /** * أوقف هذا المكون ، عادةً بطريقة متزامنة ، بحيث يتم إيقاف المكون تمامًا عند عودة هذه الطريقة. النظر في تطبيق {link smartlifecycle} * و {code stop (runnable)} عندما يكون سلوك التوقف غير المتزامن ضروريًا. * <p> لاحظ أن إشعار الإيقاف هذا غير مضمون قبل التدمير: في * الإغلاق العادي ، ستتلقى الفاصوليا {code} أول إشعار توقف قبل * يتم نشر عمليات استدعاء التدمير العامة ؛ ومع ذلك ، عند التحديث الساخن خلال حياة * سياق أو على محاولات التحديث المجهود ، سيتم استدعاء طرق التدمير فقط. * <p> يجب ألا يرمي استثناء إذا لم يتم بدء المكون بعد. * <p> في حالة الحاوية ، سيؤدي ذلك إلى نشر إشارة التوقف إلى جميع المكونات * التي تنطبق. * seee smartlifecycle#stop (runnable) * see org.springframework.beans.factory.disposablebean#destroy () */ void stop () ؛ /*** تحقق مما إذا كان هذا المكون قيد التشغيل حاليًا. * <p> في حالة الحاوية ، سيعود هذا {code true} فقط إذا كانت جميع مكونات <i> All </i> * تعمل حاليًا. * @إعادة ما إذا كان المكون يعمل حاليًا */ boolean isrunning () ؛}تحدد هذه الواجهة طريقة التحكم في دورة حياة البدء/الإيقاف. عند بدء تشغيل أو توقف حاوية IOC الربيعية ، سيتم إرسال إشارة بدء أو إيقاف إلى كل مكون ، حتى نتمكن من فعل ما نريد في الطريقة المقابلة. يمكننا أن نجد من خلال مخطط الفصل أننا نستخدم ClassPathxMlapplicationContext بشكل شائع
دعنا نوضح القضية بإيجاز وإنشاء فئة mylifecycle:
package org.hzgj.spring.study.context ؛ استيراد org.springframework.context.smartlifecycle ؛ الطبقة العامة mylifecycle تنفذ smartlifecycle {override public start () {system.out.println ("mylifecycle start .... } Override public void stop () {system.out.println ("mylifecycle stop .....") ؛ } Override Public Boolean Isrunning () {return false ؛ } Override Public Boolean IsautostArtup () {return true ؛ } Override public void Stop (Runnable Callback) {} Override public int getPhase () {system.out.println ("phase") ؛ العودة 10 ؛ }}هنا نرث SmartLifecycle. الواجهة ترث دورة الحياة. يتم استخدام طريقة isrunning لاكتشاف ما إذا كان المكون الحالي في حالة التشغيل. لاحظ أنه لا يمكن تشغيله إلا عندما تكون قيمة الإرجاع غير خاطئة.
نقوم بتكوين mylifecycle في ملف تكوين الربيع ، ونمر عبر classpathxmlapplicationContext للحصول على النتائج التالية:
بالإضافة إلى ذلك ، فإن طريقة getPhase هنا هي تحديد قيمة المرحلة (يمكن فهمها على أنها أولوية. كلما كانت القيمة أصغر ، كلما تم تنفيذ دورة الحياة المقابلة أولاً)
2. أبحاث كود المصدر DiscoveryClient
enablediscoveyclient
/ * * حقوق الطبع والنشر 2013-2015 المؤلف أو المؤلفين الأصليين. * * مرخصة بموجب ترخيص Apache ، الإصدار 2.0 ("الترخيص") ؛ * لا يجوز لك استخدام هذا الملف إلا في الامتثال للترخيص. * يمكنك الحصول على نسخة من الترخيص على * * http://www.apache.org/licenses/license-2.0 * * ما لم يكن مطلوبًا بموجب القانون المعمول به أو يتم الاتفاق عليه في الكتابة ، يتم توزيع البرمجيات * الموزعة بموجب الترخيص على أساس "كما هو" ، * دون ضمانات أو شروط من أي نوع ، إما صريحة أو ضمنية. * راجع ترخيص أذونات حوكمة اللغة المحددة والقيود * بموجب الترخيص. */package org.springframework.cloud.client.discovery ؛ import java.lang.annotation.documented ؛ import java.lang.annotation.elementtype ؛ import java.lang.annotation.inherited ؛ import java.lang.annotation.antence java.lang.annotation.target ؛ استيراد org.springframework.context.annotation.import ؛/*** التعليقات التوضيحية لتمكين تنفيذ discoveryclient. * Author spencer gibb * /@target (elementType.type) receent (attreentionpolicy.runtime)@موثقة@الوراثة@استيراد (enableScoveryClientImportselector.class) public interface enableScoveryClient { /** إذا كان ذلك صحيحًا ، فإن serviceregistry سوف يسجل خادمًا محليًا. */ Boolean Autoregister () Default True ؛} يرجى ملاحظة أن @Import(EnableDiscoveryClientImportSelector.class) يمكننا الرجوع إلى هذا الفصل:
/ * * حقوق الطبع والنشر 2013-2015 المؤلف أو المؤلفين الأصليين. * * مرخصة بموجب ترخيص Apache ، الإصدار 2.0 ("الترخيص") ؛ * لا يجوز لك استخدام هذا الملف إلا في الامتثال للترخيص. * يمكنك الحصول على نسخة من الترخيص على * * http://www.apache.org/licenses/license-2.0 * * ما لم يكن مطلوبًا بموجب القانون المعمول به أو يتم الاتفاق عليه في الكتابة ، يتم توزيع البرمجيات * الموزعة بموجب الترخيص على أساس "كما هو" ، * دون ضمانات أو شروط من أي نوع ، إما صريحة أو ضمنية. * راجع ترخيص الأذونات اللغوية المحددة والقيود * بموجب الترخيص. */package org.springframework.cloud.client.discovery ؛ استيراد org.springframework.boot.bind.relaxedPropertyResolver ؛ import org.springframework.cloud.commons.util.springfactoryimportselector ؛ import org.springframework. org.springframework.core.annotation.annotationattributes ؛ استيراد org.springframework.core.antation org.springframework.core.env.mappropertysource ؛ استيراد org.springframework.core.type.annotationmetadata ؛ استيراد java.util.arraylist ؛ java.util.arrays ؛ import java.util.linkedhashmap ؛ */ @order (order.lowest_precedence - 100) الطبقة العامة enableScoveryClientImportSelector يمتد springfactoryimportselector <enableScoveryClient> {Override public [] SelectImports (Metadata) ؛ anotationattributes سمات = التعليقات التوضيحية. boolean autoregister = attributes.getBoolean ("autoregister") ؛ if (autoregister) {list <String> phirthslist = new ArrayList <> (Arrays.Aslist (Imports)) ؛ ervarslist.add ("org.springframework.cloud.client.serviceregistry.autoserviceregistrationConfiguration") ؛ الواردات = phorthslist.toarray (سلسلة جديدة [0]) ؛ } آخر {البيئة env = getEnvironment () ؛ if (configableenvironment.class.isinstance (env)) {configableenVironment configenv = (configableenVironment) env ؛ LinkedHashMap <string ، Object> map = new LinkedHashMap <> () ؛ map.put ("spring.cloud.service-registry.auto-registration.enabled" ، false) ؛ MapPropertySource PropertySource = جديد MapPropertySource ("SpringCloudDiscoveryClient" ، MAP) ؛ configenv.getPropertySources (). addLast (propertySource) ؛ }} إرجاع الواردات ؛ } Override محمية Boolean Isenabled () {return New RelainPropertyResolver (getEnvironment ()). } Override محمية Boolean HasDefaultFactory () {return true ؛ }} طريقة إعادة كتابة هذه الفئة تأتي من مستفيدة الواجهة. يمكننا تتبع الفصل وفقًا للرمز تحت if(autoRegister) : org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration . دعونا نلقي نظرة على الرسم البياني الهيكلي:
يمكننا أن نعلم أن هذا الفصل ينفذ واجهة دورة الحياة ، لذلك دعونا نلقي نظرة على طريقة البدء ، والتي هي في فئة الوالدين AbstractDiscoverylifecycle:
/ * * حقوق الطبع والنشر 2013-2015 المؤلف أو المؤلفين الأصليين. * * مرخصة بموجب ترخيص Apache ، الإصدار 2.0 ("الترخيص") ؛ * لا يجوز لك استخدام هذا الملف إلا في الامتثال للترخيص. * يمكنك الحصول على نسخة من الترخيص على * * http://www.apache.org/licenses/license-2.0 * * ما لم يكن مطلوبًا بموجب القانون المعمول به أو يتم الاتفاق عليه في الكتابة ، يتم توزيع البرمجيات * الموزعة بموجب الترخيص على أساس "كما هو" ، * دون ضمانات أو شروط من أي نوع ، إما صريحة أو ضمنية. * راجع ترخيص الأذونات اللغوية المحددة والقيود * بموجب الترخيص. */package org.springframework.cloud.client.discovery ؛ import java.util.concurrent.atomic.atomicboolean ؛ import java.util.concurrent.atomic.atomicinteger ؛ import javax.annotation.predestroy org.apache.commons.logging.logfactory ؛ استيراد org.springframework.beansexception ؛ استيراد org.springframework.boot.context.embedded.embeddedServletContainerInitialized ؛ org.springframework.cloud.client.discovery.event.instanceregisteredevent org.springframework.context.ApplicationListener ؛ استيراد org.springframework.core.env.environment ؛/*** طرق دورة الحياة التي قد تكون مفيدة وشائعة في تطبيقات DiscoveryClient المختلفة. * * deprecated استخدم {link org.springframework.cloud.client.serviceregistry.abstractautoserviceregistration} بدلاً من ذلك. ستتم إزالة هذا الفصل في قطار الإصدار التالي. * * Author Spencer Gibb */ @ @ @reprecatedpublic class class AbstractDiscoverylifecycle Passiclements Discoverylifecycle ، ApplicationContextAware ، ApplicationListerener <ImbedServletContainerInitializedEvent> {private static final logger. خاص منطقي Autostartup = صحيح ؛ usomicboolean الخاص تشغيل = جديد AtomicBoolean (خطأ) ؛ ترتيب int الخاص = 0 ؛ سياق ApplicationContext الخاص ؛ بيئة البيئة الخاصة ؛ Private AtomicInteger Port = New AtomicInteger (0) ؛ ApplicationContext GetContext () {return context ؛ } Override public void setapplicationContext (ApplicationContext ApplicationContext) يلقي beansexception {this.context = applicationContext ؛ this.environment = this.context.getenvironment () ؛ } deprecated البيئة المحمية getEnvironment () {return Environment ؛ } deprecated AtomicInteger getPort () {return port ؛ } Override Public Boolean IsautostArtup () {return this.autostartup ؛ } Override public void stop (runnable callback) {try {stop () ؛ } catch (استثناء e) {logger.error ("حدثت مشكلة في محاولة لوقف دورة حياة الاكتشاف" ، e) ؛ } callback.run () ؛ } Override public void start () {if (! isEnabled ()) {if (logger.isdebugenabled ()) {logger.debug ("Discovery LifeCycle Dustable. لا تبدأ") ؛ } يعود؛ } // فقط قم بتعيين المنفذ إذا كان nonsecureport هو 0 و this.port! = 0 if (this.port.get ()! = 0 && getConfiguredPort () == 0) {setConfiguredPort (this.port.get ()) ؛ } // تهيئة فقط إذا كان nonsecureport أكبر من 0 ولم يتم تشغيله بالفعل // بسبب حاوية portportinitializer أدناه إذا (! this.running.get () && getConfiguredPort ()> 0) {register () ؛ if (eze leghregisterManagement ()) {registerManagement () ؛ } this.context.publishEvent (جديد stanceregesteredevent <> (هذا ، getConfiguration ())) ؛ this.running.compareanset (خطأ ، صحيح) ؛ }} deprecated محمية ملخص int getConfiguredPort () ؛ deprecated محمية التجريدية void setConfiguredport (int port) ؛ / ** * regurn إذا كان ينبغي تسجيل خدمة الإدارة في {link serviceRegistry} */ يجب أن يكون Boolean المحمي registerManagement () {return getManagement ()! = null && conversionerverportUtIls.isDifferent (this.context) ؛ } / ** * @إعادة الكائن المستخدم لتكوين التسجيل * / deprecated الكائن التجريدي المحمي getConfiguration () ؛ / ** * قم بتسجيل الخدمة المحلية مع سجل الفراغ التجريدي المحمي () ؛ / ** * قم بتسجيل خدمة الإدارة المحلية مع DiscoveryClient */ Recorded Void Recormagement () {}/ ** * DEFISTER SERVICE مع DiscoveryClient */ محمية deregister void () ؛ / ** * إلغاء تسجيل خدمة الإدارة المحلية مع DiscoveryClient */ void deregistermanagement () {}/ ** * return true ، إذا تم تمكين {link discoverylifecycle} *// محمي Boolean isenabled () ؛ / ** * Return the ServiceId من خدمة الإدارة */ deprecated سلسلة محمية getManagementServiceId () {// todo: لاحقة الإدارة القابلة للتكوين إرجاع this.context.getId () + ": management" ؛ } / ** * RETURN اسم خدمة خدمة الإدارة * / @deprecated سلسلة getManagementServicEname () {// toDo: Fuckible Factix return getAppName () + ": management" ؛ } / ** * regurn منفذ خادم الإدارة * / deprecated integer getManagementport () {return congermenterverportutils.getport (this.context) ؛ } / ** * regurn اسم التطبيق ، حاليًا خاصية spring.application.name * / deprecated string محمية getAppName () {return this.environment.getProperty ("spring.application.name" ، "application") ؛ } Override public void stop () {if (this.running.compareanset (true ، false) && isenabled ()) {deregister () ؛ if (leghtregisterManagement ()) {deregisterManagement () ؛ }}} predestroy public void dorder () {stop () ؛ } Override public boolean isrunning () {return this.running.get () ؛ } محمية AtomicBoolean getRunning () {return Running ؛ } Override public int getorder () {return this.order ؛ } Override public int getPhase () {return 0 ؛ } override deprecated public void onapplicationEvent (inserdedServletContainerInitializedEvent حدث) {// todo: أخذ SSL في الاعتبار // لا تسجل منفذ الإدارة كمنفذ if (! ". event.getemBedDedServletContainer (). getPort ()) ؛ this.start () ؛ }}}لاحظ أن هناك جزءًا من هذا الرمز في طريقة البدء:
if (! this.running.get () && getConfiguredPort ()> 0) {register () ؛ if (eze leghregisterManagement ()) {registerManagement () ؛ } this.context.publishEvent (جديد stanceregesteredevent <> (هذا ، getConfiguration ())) ؛ this.running.compareanset (خطأ ، صحيح) ؛ } يرجى ملاحظة register() هي طريقة مجردة في هذه الفئة. لذلك دعونا نلقي نظرة على الكود في فئة التسجيل الملخصي ، وسأقوم بنشر الأجزاء الرئيسية هنا فقط:
// ..... محمية AbstractAutoServiceregistration (ServiceRegistry <R> serviceRegistry ، AutoServicEregistrationProperties Properties) {this.serviceregistry = serviceRegistry ؛ this.properties = الخصائص ؛ } //....../** * قم بتسجيل الخدمة المحلية مع {link serviceRegistry} */Override Void Record () {this.serviceregistry.register (getRegistration ()) ؛ }يمكننا أن نجد أن نوع الخدمة يتم تمريره في المُنشئ ، وهو واجهة يوفر لنا SPRINGCLOUD لتسجيل الخدمة. هنا تنفذ eurekaserviceregistry هذه الواجهة:
/ * * حقوق الطبع والنشر 2013-2016 المؤلف أو المؤلفين الأصليين. * * مرخصة بموجب ترخيص Apache ، الإصدار 2.0 ("الترخيص") ؛ * لا يجوز لك استخدام هذا الملف إلا في الامتثال للترخيص. * يمكنك الحصول على نسخة من الترخيص على * * http://www.apache.org/licenses/license-2.0 * * ما لم يكن مطلوبًا بموجب القانون المعمول به أو يتم الاتفاق عليه في الكتابة ، يتم توزيع البرمجيات * الموزعة بموجب الترخيص على أساس "كما هو" ، * دون ضمانات أو شروط من أي نوع ، إما صريحة أو ضمنية. * راجع ترخيص الأذونات اللغوية المحددة والقيود * بموجب الترخيص. * */package org.springframework.cloud.netflix.eureka.serviceregistry ؛ import java.util.hashmap ؛ import org.apache.commons.logging.log ؛ import org.apache.commons.logging.logfactory ؛ استيراد org.springframework.cloud.client.serviceregistry.serviceregistry ؛ استيراد com.netflix.appinfo.instanceinfo ؛/** logfactory.getLog (eurekaserviceregistry.class) ؛ سجل Void Public Override (eurekaregistration reg) {aysinitializeClient (reg) ؛ if (log.isinfoEnabled ()) {log.info ("تسجيل التطبيق" + reg.getInstanCeConfig (). getAppName () + "مع eureka مع الحالة" + getInstanConfig (). getInitialStatus ()) ؛ } reg.getApplicationInfomanager () .SetInstanCestatus (reg.getInstanceconfig (). getInitialStatus ()) ؛ if (reg.gethealthcheckHandler ()! = null) {reg.geteurekaclient (). registerHealthCheck (reg.gethealthcheckhandler ()) ؛ }} private void andyinitializeClient (eurekaregistration reg) {// قوة تهيئة الوكلاء المحتملين المحتملين reg.getApplicationInfomanager (). getInfo () ؛ reg.geteurekaclient (). getApplications () ؛ } Override public void deregister (eurekaregistration reg) {if (reg.getApplicationInfomanager (). getInfo ()! = null) {if (log.isinfoenabled ()) {log.info ("unsistering application" + reg.getInStanceConfig (). } reg.getApplicationInfomanager (). // يجب أن يحدث إغلاق عميل Eureka مع eurekaregistration.close () // سيقوم التسجيل التلقائي بإنشاء حبة سيتم توزيعها بشكل صحيح // التسجيلات اليدوية سيحتاج إلى الاتصال بـ Close ()}}} efiterride setStatus (eurekaregistration resistration) // TODO: كيف تتعامل مع الحذف بشكل صحيح؟ if ("cancel_override" .equalsignorecase (status)) {registration.geteurekaclient (). cancelOverRidestatus (info) ؛ يعود؛ } // TODO: HOWTO التعامل مع أنواع الحالة عبر أنظمة الاكتشاف؟ extailInfo.instancestatus newStatus = extalInfo.instancestatus.toenum (الحالة) ؛ registration.geteurekaclient (). setStatus (newstatus ، info) ؛ } Override Public Object getStatus (eurekaregistration تسجيل) {hashmap <string ، object> status = new hashmap <> () ؛ informinfo info = registration.getApplicationInfomanager (). getInfo () ؛ status.put ("الحالة" ، info.getStatus (). status.put ("overriddenstatus" ، info.getoverriddenstatus (). toString ()) ؛ حالة العودة ؛ } public void close () {}}لذلك يمكننا تلخيص النقاط التالية:
1. استخدام discoveryClient لتسجيل الخدمة يستخدم آلية دورة الحياة ، وسيتم تنفيذ طريقة register() في التحليل عند بدء تشغيل الحاوية.
2. استخدام discoveryClient أكثر مرونة من enableeurekaclient و enableeurekaserver ، لأنه يمنع تنفيذ تسجيل الخدمة ، ويمكننا حتى تخصيص مركز التسجيل.
3. سيؤدي هذا أيضًا إلى البحث تلقائيًا عن تنفيذ واجهة DiscoveryClient لاكتشاف الخدمة.
3. مركز تسجيل Redis العملي DiscoveryClient
نطبق أدناه متطلبات بناءً على Redis كمركز للتسجيل لفهم DiscoveryClient. بالمناسبة ، دعونا نفهم الواجهات المهمة لـ SpringCloud: ServiceRegistry ، ServiceInstance. قبل ذلك ، سنضيف دعمًا لـ Redis:
مجموعة التجميع: 'org.springframework.boot' ، الاسم: "Spring-Boot-Starter-Data-Redis"
1. تنفيذ واجهة التسجيل
package com.hzgj.lyrk.member ؛ استيراد org.springframework.beans.factory.annotation.value ؛ استيراد org.springframework.cloud.client.serviceregistry java.net.networkInterface ؛ استيراد java.net.uri ؛ استيراد java.util.enumeration ؛ استيراد java.util.map ؛ componentpublic redisregishistration تنفذ التسجيل {value ("$ {server.port}") منفذ Integer الخاص ؛ value ("$ {spring.application.name}") application application application ؛ مضيف سلسلة خاصة public void sethost (سلسلة مضيف) {this.host = host ؛ } public void setport (منفذ integer) {this.port = port ؛ } public void setapplicationName (string applicationName) {this.applicationName = ApplicationName ؛ } Override public string getServiceId () {return applicationName + ":" + gethost () + ":" + getPort () ؛ } Override public string gethost () {try {if (host == null) return getlocalhostlanaddress (). gethostaddress () ؛ عودة مضيف آخر ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } إرجاع فارغ ؛ } Override public int getPort () {return port ؛ } Override public boolean issecure () {return false ؛ } Override public uri geturi () {return null ؛ } Override Public Map <String ، String> getMetAdata () {return null ؛ } السلسلة العامة getServicEname () {return this.applicationName ؛ } inetaddress public getlocalhostlanaddress () يلقي استثناء {try {inetaddress candidateaddress = null ؛ // اجتياز جميع واجهات الشبكة لـ (التعداد ifices = networkInterface.getNetworkInterFaces () ؛ ifaces.hasmoreElements () ؛) {networkInterface iface = (NetworkInterface) ifaces.nextElement () ؛ // اجتياز IP تحت جميع واجهات (التعداد inetaddrs = iface.getInetAddresses () ؛ inetaddrs.hasmoreElements () ؛) {inetaddress inetaddr = (inetaddress) inetaddrs.nextelement () ؛ if (! inetaddr.isloopbackaddress ()) {// استبعاد عنوان نوع loopback if (inetaddr.issitelocaladdress ()) {// إذا كان عنوانًا محليًا للموقع ، فهو إرجاع inetaddr ؛ } آخر إذا (candidateaddress == null) {// لم يتم العثور على عنوان نوع الموقع المحلي ، سجل أولاً عنوان المرشح CandidateadDress = inetaddr ؛ }}}}} if (candidateaddress! = null) {return candidateaddress ؛ } // إذا لم يتم العثور على عنوان غير لطف ، فيمكنك فقط استخدام الحل الأكثر تحديدًا. inetaddress jdksuppliedaddress = inetaddress.getlocalhost () ؛ إرجاع jdksuppliedaddress ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ } إرجاع فارغ ؛ }}ترث هذه الواجهة ServiceIntance ، وبالتالي فإن الوظيفة الرئيسية لهذه الواجهة هي تحديد مواصفات مثيل الخدمة ، مثل ما هو ServiceId ، ما هو رقم المنفذ ، إلخ.
2. تنفيذ واجهة ServiceRegistry
package com.hzgj.lyrk.member ؛ استيراد org.springframework.beans.factory.annotation. serviceRegistry <dredisRegiStration> {autowired private stringRediStemplate Redistemplate ؛ Override Public Void Register (RedisRegistration تسجيل) {String serviceId = registration.getServiceId () ؛ redistemplate.opsforlist (). LeftPush (serviceId ، registration.gethost () + ":" + registration.getport ()) ؛ } Override public void deregister (redisregistration registration) {redistemplate.opsforlist (). remove (registration.getServiceId () ، 1 ، registration.gethost () + ":" + registration.getport ()) ؛ } Override public void close () {//redistemplate.d system.out.println ("مغلق ...") ؛ } Override public void setStatus (تسجيل RedIsRegiStration ، حالة السلسلة) {} Override Public <T> t getStatus (RedIsRegistration تسجيل) {return null ؛ }}تتمثل الوظيفة الرئيسية لهذه الواجهة في تحديد كيفية تسجيل الخدمة وإلغاء الخدمة والتعيين والحصول على حالة الخدمة ، إلخ.
3. ورث الطبقة التجريدية التجريدية
package com.hzgj.lyrk.member ؛ استيراد org.springframework.beans.factory.annotation. org.springframework.cloud.client.serviceregistry.abstractautoserviceregistration ؛ استيراد org.springframework.cloud.client.serviceregistry.serviceregistration> @ @redisautiregired servisiregirecient redisregishration ؛ REDISAUTOSERVICEREGING (SERVICEREGINGING <RedISREGISTRATION> SERVICEREGISTY ، AutoServicEregistrationProperties Properties) {Super (serviceRegistry ، Properties) ؛ // serviceRegistry.register (getRegiStration ()) ؛ } Override محمية int getConfiguredPort () {return redisregistration.getport () ؛ } override void setConfiguredPort (int port) {} override كائن محمي getConfiguration () {return null ؛ } Override محمية Boolean Isenabled () {return true ؛ } OverRide RedisRegistration GetRegiStration () {return redisregishration ؛ } Override RedisRegistration getManagementRegistration () {return null ؛ }}4. تحديد فئة التنفيذ من discoveryclient redisdiscoveryclient
package com.hzgj.lyrk.member ؛ import org.apache.commons.lang.StringUtils ؛ import org.springframework.beans.factory.annotation.autowired ؛ import org.springframework.cloud.client.serviceinstance ؛ import org.springframework.cloud.client.discovery.discoveryClient ؛ استيراد org.springframework.data.core.stringRedIstemplate ؛ استيراد java.util.arraylist ؛ redisDiscoveryClient تنفذ discoveryclient {autowired private stringRediStemplate RedIstemplate ؛ Override Public String Description () {Return "Service Discovery in Redis Centeration Center" ؛ } Override public ServiceInstance getLocalServiceInstance () {return null ؛ } Override Public List <ReviceInstance> getInStances (String ServiceId) {returistemplate.opsforlist (). المدى (ServiceId ، 0 ، -1). PALALLELSTREAM (). MAP ((الوظيفة <string ، serviceInstance>) s -> {redisregistration redisregisterration = new redisregistration () ؛ redisRegistration.setApplicationName (serviceId) ؛ String hostName = stringutils.split (s ، ":") redisregistration.sethost (اسم المضيف) ؛ } Override Public List <String> getServices () {list <string> list = new ArrayList <> () ؛ list.addall (redistemplate.keys ("*")) ؛ قائمة العودة }}يهدف هذا الفصل بشكل أساسي إلى اكتشاف خدمة تسجيل خدمة Redis
5. تحديد فئات التجميع الأوتوماتيكية لإنشاء الفاصوليا المقابلة
package com.hzgj.lyrk.member ؛ استيراد org.springframework.boot.autoconfigure.condition.conditionalonproperty ؛ استيراد org.springframework.boot.context.properties.enableConfigurperties ؛ استيراد استيراد org.springframework.cloud.client.serviceregistry.autoserviceregistrationProperties ؛ استيراد org.springframework.context.annotation.bean ؛ استيراد org.springframework.context.annotation.configuration ؛ استيراد org.springframework.context.annotation.primary ؛@configuration@enableConfigurationProperties (regiSconFig.Class) conditionalonproperty (value = "spring.redis.registry.enabled redisserviceregistry (redisconfig redisconfig) {system.out.println (redisconfig.gethost ()) ؛ إرجاع New Redisserviceregistry () ؛ } bean redisautoserviceregistration redisautoserviceregistration (Redisserviceregistry Redisserviceregistry) {return New RedisaUtoServiceregistration (Redisserviceregistry ، AutoServicerGistrationProperties ()) ؛ } bean @primary redisDiscoveryClient redisDiscoveryClient () {return new redisDiscoveryClient () ؛ }}6. حدد فئة بدء التشغيل
package com.hzgj.lyrk.member ؛ استيراد org.springframework.boot.springapplication ؛ استيراد org.springframework org.springframework.cloud.client.discovery.enablediscoveryClient ؛ استيراد org.springframework.cloud.client.discovery.composite.compositediscoverycoverautoConfigigation ؛ org.springframework.context.configurableApplicationContext ؛ enableScoveryClient@springbootapplication (exclude = {simpleDiscoveryClientAutoConfiguration.class ، compositiveScoveryUtConfiguration.class}) public smessmblication configurableApplicationContext ApplicationContext = springapplication.run (memberapplication.class ، args) ؛ DiscoveryClient DiscoveryClient = ApplicationContext.getBean (discoveryclient.class) ؛ discoveryclient.getServices (). }}هنا ، يتم استبعاد التجميع الافتراضي لـ DiscoveryClient في شرح SpringBootapplication.
عندما نبدأ بنجاح ، يمكننا أن نجد أن وحدة التحكم لديها إخراج اسم الخدمة المقابلة وعنوانها:
نقوم مرة أخرى بإنشاء ملف الجرة من خلال تغليف Gradle وتشغيله:
Java -jar Member-Server-0.0.1-snapshot.jar-server.port = 8800
يمكننا أن نرى أن القيمة المسجلة للخدمة التي تم تخزينها مؤقتًا في Redis:
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.