الشريط هو مشروع مفتوح المصدر أصدره Netflix. تتمثل وظيفتها الرئيسية في توفير خوارزميات موازنة تحميل البرامج من جانب العميل لتوصيل خدمات Netflix المتوسطة معًا. يوفر مكون عميل الشريط سلسلة من عناصر التكوين الكاملة مثل مهلة الاتصال ، وإعادة المحاولة ، وما إلى ذلك. ببساطة ، هو سرد جميع الآلات وراء Load Balancer (LB لفترة قصيرة) في ملف التكوين. سيساعدك Ribbon تلقائيًا على توصيل هذه الآلات بناءً على قواعد معينة (مثل الاقتراع البسيط ، والاتصال الفوري ، وما إلى ذلك). لدينا أيضًا طريقة سهلة للغاية لتنفيذ خوارزميات موازنة التحميل المخصصة باستخدام الشريط.
عندما يتعلق الأمر بتحميل الموازنة ، عادة ما تفكر في موازنة التحميل على الخادم. تشمل المنتجات الشائعة الاستخدام أجهزة LBS أو خدمات السحابة ، Nginx ، وما إلى ذلك ، والتي هي كل منتجات مألوفة.
يوفر Spring Cloud Ribbon ، والذي يسمح لمصل الخدمة بالحصول على قدرات موازنة التحميل. من خلال التكامل الوثيق مع Eureka ، ليست هناك حاجة لإعداد خدمات موازنة التحميل في مجموعة الخدمة ، والتي تبسط بشكل كبير الهيكل داخل مجموعة الخدمة.
لا أريد أن أكتب المزيد من المقدمات الافتراضية بالتفصيل ، على أي حال ، يمكنني رؤية المقدمات ذات الصلة في كل مكان.
فقط افتح الرمز ومعرفة كيفية تنفيذ الشريط من خلال الكود.
إعدادات
شرح مفصل:
1. تكوين تكوين Ribbonautoconfiguration مثيل ribbonloadbalancerclient.
موقع الكود:
Spring-Cloud-Netflix-Core-1.3.5.release.jar
org.springframework.cloud.netflix.ribbon
ribbonautoconfiguration.class
@configuration@intendalonclass ({iclient.class ، resttemplate.class ، asyncresttemplate.class ، ribbon.class})@ribbonclients@autoconfigureafter (name = "org.springframework.cloud.netflix.eureka.eurekaclientautoconfiguration")@autoconfigurebefore ( ribbonautoconfiguration {// shemitbeanconditionalonmissingbean (loadBalancerClient.class) ploodbalancerclient loadbalancerclient () {return new RibbonLoadBalancerClient (SpringClientFactory ()) ؛ } // shf}دعونا أولاً نلقي نظرة على العناصر الشرطية للتكوين. يجب تنفيذ تكوين تكوين Ribbonautoconfiguration قبل تكوين تكوين LoadBalanceraUtoconfiguration ، لأنه سيتم استخدام مثيل RibbonloadBalancerClient في تكوين تكوين LoadBalanCerautoconfiguration.
يرث RibbonLoadBalancerClient من واجهة loadbalancerclient ، هو عميل موازنة التحميل ومتصل سياسة موازنة التحميل.
2.LoadBalanCerInterceptorConfig توليد التكوين:
1). تحميل مثيل BalancerIntercope
يشمل:
ribbonloadbalancerclient مثيل من فئة تنفيذ loadbalancerclient
loadBalancerRequestFactory: مثيل
2) .RestTemplate Custom RestTemplateCustomizer مثيل
موقع الكود:
الربيع-السحابة--1.2.4.Release.Jar
org.springframework.cloud.client.loadbalancer
loadBalancerautoconfiguration.class
@configuration@intenalonclass (resttemplate.class) conditionalonbean (loadbalancerclient.class) enableConfigurationProperties (loadbalancerretryProperties.Class) ploodbalancerefigonfiguration loadBalancerRequestFactory (loadBalancerClient loadBalancerClient) {إرجاع جديد loadBalanCerRequestFactory (loadBalancerClient ، Transformers) ؛ } configurationconditionalonMissingClass ("org.springframework.retry.support.retrytemplate") static class loadbalannistroceptorconfig LoadBalancerInterceptor (LoadBalancerClient ، requestFactory) ؛ } beanconditionalonmissingbean public resttemplateCustomizer restTemplateCustomizer (Final LoadBalanCerInterceptor loadBalanCerInterceptor) {return new resttemplateCustomizer () {Override public void تخصيص (resttemprate) restTemplate.getInterceptors ()) ؛ list.add (loadBalanCerInterceptor) ؛ RestTemplate.setInterceptors (قائمة) ؛ }} ؛ }} // حذفت}دعونا نلقي نظرة على ظروف التكوين أولاً:
مطلوب أنه يجب أن يكون هناك فئة RestTemplate في بيئة المشروع.
مطلوب أنه يجب أن يكون هناك مثيل لفئة التنفيذ لواجهة LoadBalancerClient ، أي أن ribbonloadbalancerclient تم إنشاؤها في الخطوة السابقة.
3. تكوين جميع مثيلات RestTemplate من خلال RestTemplateCustomizer التي تم إنشاؤها في الخطوة أعلاه ، والتي تتمثل في ضبط اعتراض موازنة التحميل على مثيل RestTemplate.
@configuration@intenalonclass (resttemplate.class) conditionalonbean (loadbalancerclient.class) enableConfigurationProperties (loadbalancerretryProperties.class) الطبقة العامة loadBalanceraUtoconFiguration قائمة <RestTemplateCustomizer> المخصصين) {return new SmartInitializingSingleton () {Override public void aftersingletonSinStantAnted () {for (restTemplate: chuctionizizer: customizer) }}}}}}} ؛ } // dishconfigurationconditionalonMissingClass ("org.springframework.retry.support.retrytemplate LoadBalancerInterceptor (LoadBalancerClient ، requestFactory) ؛ } beanconditionalonmissingbean public resttemplateCustomizer restTemplateCustomizer (Final LoadBalanCerInterceptor loadBalanCerInterceptor) {return new resttemplateCustomizer () {Override public void تخصيص (resttemprate) restTemplate.getInterceptors ()) ؛ list.add (loadBalanCerInterceptor) ؛ RestTemplate.setInterceptors (قائمة) ؛ }} ؛ }} // حذفت}RestTemplate.SetInterceptors (قائمة) هذا المكان هو المكان الذي يتم فيه حقن اعتراض موازنة التحميل.
يمكن تخمينه في الواقع من هذا المكان ، حيث يمكن لـ RestTemplate بناء الطلبات المقابلة لتحقيق موازنة التحميل من خلال اعتراضات الحقن.
يمكن أن نرى أيضًا أنه يمكنك تخصيص التقاطع لتحقيق أغراض أخرى.
4. تكوين التكوين ribbonclientconfort
موقع الكود:
Spring-Cloud-Netflix-Core-1.3.5.release.jar
org.springframework.cloud.netflix.ribbon
ribbonclientConfiguration.class
suppressWarnings ("deprecation")@configuration@enableConfigurationProperties // أمر مهم هنا ، يجب أن يكون الأخير هو الافتراضي ، يجب أن يكون أولاً اختياريًا // انظر https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issueComment-316281653@import( {OKHTTPRIBBOBBONCONFIGURINT.CLASCINGURINT.CLASTCONFIGURIN حذف bean @conditionalonmissingbean public iLoAdbalancer RibbonLoadBalancer (ICLientConfig config ، serverlist <Server> serverlist ، serverlistfilter <Server> serverlistfilter ، IRUL this.propertiesfactory.get (iloadbalancer.class ، config ، name) ؛ } إرجاع ZoneAwareloadBalancer الجديد <> (التكوين ، القاعدة ، ping ، قائمة الخادم ، ServerListFilter ، ServerListUpDater) ؛ } // حذفت}يرث ZoneawareloadBalancer من واجهة iloadbalancer ، التي لها طريقة:
/*** اختر خادمًا من موازن التحميل. * * مفتاح param كائن قد يستخدمه موازن التحميل لتحديد الخادم الذي سيتم إرجاعه. NULL إذا * لا يستخدم موازن التحميل هذه المعلمة. * @خادم RETURN المختار */ Server Public Coinserver (مفتاح الكائن) ؛
ZoneawareloadBalancer هو فئة تنفيذ موازنة تحميل محددة ، وهي أيضًا فئة موازنة التحميل الافتراضية. يتم تحديد مثيل خدمة معين من خلال تطبيق طريقة Choiceserver.
اعتراض وطلب
1. استخدم RestTemplate لأداء طلبات مختلفة مثل GET والنشر ، والتي يتم تنفيذها جميعها من خلال طريقة doExecute.
موقع الكود:
Spring-Web-4.3.12.Release.Jar
org.springframework.web.client
RestTemplate.class
يمتد RestTemplate من الطبقة العامة ، يمتد اعتراضها ، قم بتنفيذ عمليات الاستعادة {// محمية قليلاً <T> t doexecute (URI url ، httpmethod method ، requestCallback requestCallback ، desponsextractor <T> responsextractor) يلقي RestClientException {Advent.notnull (url ، '' 'url') ؛ Assert.notnull (طريقة ، "طريقة" يجب ألا تكون فارغة ") ؛ clientHttpresponse استجابة = null ؛ حاول {clientHttPrequest request = createrequest (url ، method) ؛ if (requestCallback! = null) {requestCallback.dowithRequest (request) ؛ } استجابة = request.execute () ؛ المعالج (url ، الطريقة ، الاستجابة) ؛ if (responseExtractor! = null) {return reviewExtractor.extractData (response) ؛ } آخر {return null ؛ }} catch (ioException ex) {String Resource = url.toString () ؛ Query Query = url.getRawquery () ؛ Resource = (Query! = null؟ Resource.SubString (0 ، Resource.indexof ('؟'))): Resource) ؛ رمي ResourceAccessException ("I/O خطأ على" + method.name () + "طلب/" " + Resource +"/":" + ex.getMessage () ، ex) ؛ } أخيرًا {if (response! = null) {response.close () ؛ }}} // shreed}في نهاية المطاف ، استدعاء طرق طلب HTTP المختلفة المدعومة طريقة DoExecute ، والتي تستدعي طريقة الإنشاء لإنشاء مثيل الطلب ، وتنفيذ الطلب للحصول على كائن الاستجابة.
2. قم بإنشاء مثيل طلب لإنشاء مصنع
في الكود السابق ، يتم استدعاء طريقة createrequest لإنشاء مثيل الطلب ، الذي يتم تعريفه في الفئة الأصل.
قم بتنظيم علاقة الميراث الرئيسية الأولى:
يتم تعريف طريقة createrequest فعليًا في فئة HTTPACCESSER ARCRENT.
الفئة التجريدية العامة httpaccessor {private clientHttPrequestFactory requestFactory = new SimpleClientHttPrequestFactory () ؛ public void setRequestFactory (clientHtpRequestFactory requestFactory) {Assert.notnull (requestFactory ، " this.requestfactory = requestFactory ؛ } clientHttPrequestFactory getRequestFactory () {return this.requestfactory ؛ } clientHttprequest createrequest (URI url ، httpmethod method) يلقي iOexception {clientHttPrequest request = getRequestFactory (). createrequest (url ، method) ؛ if (logger.isdebugenabled ()) {logger.debug ("تم إنشاء" + method.name () + "طلب /" " + url +" /"") ؛ } طلب الإرجاع ؛ }}اتصل بالطريقة getRequestFactory في طريقة createrequest للحصول على مثيل الطلب لإنشاء المصنع. في الواقع ، لم يتم تعريف getRequestFactory في فئة HTTPACCESSR الحالية ، ولكن تم تعريفها في الفئة الفرعية اعتراضها.
يعرض الفئة المجردة العامة اعتراضات attpaccessor httpaccessor {قائمة خاصة <clientHttPrequestInterceptor> interceptors = new ArrayList <ClientHttPrequestInterceptor> () ؛ setInterceptors public void (قائمة <clientHtpRequestInterceptor> اعتراض) {this.Interceptors = Interceptors ؛ } القائمة العامة <clientHttPrequestInterceptor> getInterceptors () {return Interceptors ؛ } Override Public ClientHttPrequestFactory getRequestFactory () {clientHttPrequestFactory pelegate = super.getRequestFactory () ؛ if (! collectionUtils.isempty (getInterceptors ())) {return new enterceptlienthttprequestfactory (depigate ، getInterceptors ()) ؛ } آخر {إرجاع مندوب ؛ }}}لقد قمت بعمل صغير هنا. أولاً ، قمت بإنشاء وحصلت على مصنع SimpleClientHttPrequestFactory من خلال فئة HTTPACCESSSER. ينشئ هذا المصنع بشكل أساسي مثيلات طلب أساسية عندما لا يكون هناك اعتراض.
ثانياً ، عندما يكون هناك حقن اعتراضية ، قم بإنشاء مصنع اعتراض clienthttprequestfactory. هذا المصنع ينشئ مثيل طلب مع اعتراض. نظرًا لتمريض اعتراض موازنة التحميل ، يتم إنشاؤه من مصنع CentercleientHttPrequestFactory.
3. قم بإنشاء مثيل طلب من خلال المصنع
عند إنشاء مثيل ، يعتمد ذلك على طريقة Createrequest للمصنع.
الطبقة العامة اعتراض ClientHttpRequestFactory تمتد AbstractClientHttPrequestFactoryWrapper {القائمة النهائية الخاصة <ClientHttPrequestInterceptor> اعتراض ؛ Public IncepttingClientHttPrequestFactory (ClientHttPrequestFactory requestFactory ، قائمة <ClientHttPrequestInterceptor> اعتراض) {super (requestFactory) ؛ this.Interceptors = (Interceptors! = NULL؟ التقاطعات: المجموعات. <clientHTTPRequestInterceptor> فارغة ()) ؛ } Override ClientHttprequest createrequest (Uri URI ، httpmethod httpmethod ، clientHttpRequestFactory requestFactory) {return new interceptclienthttprequest (requestFactory ، this.Interceptors ، uri ، httpmethod) ؛ }}وهذا يعني مثيل تعترض جديد ClientHttPrequest وحقن مصنع إنشاء مثيل التقاطع والطلب الأساسي.
4. اطلب المثيل لاستدعاء طريقة التقاطع في اعتراض موازنة التحميل التي تم حقنها في مرحلة التكوين
يمكن ملاحظة من الخطوة 1 أنه بعد إنشاء مثيل الطلب ، يتم تنفيذ الطلب عن طريق تنفيذ طريقة تنفيذ مثيل الطلب.
ClientHttpRequest request = createrequest (url ، method) ؛ if (requestCallback! = null) {requestCallback.dowithRequest (request) ؛} reponse = request.execute () ؛مثيل الطلب الفعلي هو اعتراض clienthttprequest ، والتنفيذ هو في الواقع في فئة الأم.
موقع تعريف الفئة:
Spring-Web-4.3.12.Release.Jar
org.springframework.http.client
اعتراض clienthttprequest.class
ألق نظرة على علاقة الميراث.
يتم استدعاء طريقة التنفيذ التي تنفذها الفئة الفرعية بالفعل في طريقة التنفيذ.
Public Abstract Class AbstractClientHttpRequest تنفذ ClientHttPrequest {Private Final Httpheaders Headers = New Httpheaders () ؛ المنطقية الخاصة التي تم تنفيذها = false ؛ Override Public Final Httpheaders getheaders () {return (this.executed؟ httpheaders.readonlyhttpheaders (this.headers): this.headers) ؛ } Override Public Final OutputStream getBody () يلقي ioException {AssertNotExecuted () ؛ إرجاع getBodyinternal (this.headers) ؛ } Override Public Final ClientHttPresponse execute () يلقي ioException {assertNotExecuted () ؛ clientHttPresponse نتيجة = executeinternal (this.headers) ؛ this.executed = true ؛ نتيجة العودة } void void assertNotExecuted () {assert.state (! this.executed ، "clientHttPrequest تم تنفيذه بالفعل") ؛ } محمي Orgrated OutderStream getBodyinternal (HttPheaders Headers) يلقي ioException ؛ ClientHttpresponse المحمي المحمي (Httpheaders رؤوس) يلقي ioException ؛}في الواقع ، إنها طريقة التنفيذ في فئة اعتراض clienthttprequest. التي يتم فيها استدعاء تنفيذ Executor InterceptErequestExecution. مرر المستوى وحدد أنه إذا تم حقن اعتراض ، يتم استدعاء طريقة التقاطع للاعتراض.
المعترض هنا هو في الواقع مثيل توازن التحميل المحمل المحمل المحمل في مثيل RestTemplate أثناء مرحلة التكوين. يمكنك الرجوع إلى الخطوة 2 من مرحلة التكوين أعلاه.
Class ClepttiNsclientHttpRequest يمتد AbstractBufferingClientHttPrequest {// desferride clienthttpresponse executeinternal (HttPheaders Quactions ، byte [] bufferedoutput) ioException {interceptexecation requestexecotion = new InterceptExecotion () ؛ Return requestExecution.execute (هذا ، bufferedoutput) ؛ } فئة خاصة اعتراضات DelecteSexecution تنفذ clientHttPrequestExecution {private Final Iterator <ClientHttPrequestInterceptor> iterator ؛ Public InlevtingRequestExecution () {this.iterator = interceptors.iterator () ؛ } Override public clientHttPresponse execute (httprequest request ، byte [] body) يلقي ioException {if (this.iterator.hasnext ()) {clientHttPrequestInterceptor nextInterceptor = th th th th th th th th th th th th th th th th th th th th th th th th this.iterator.next () ؛ إرجاع NextInterceptor.Intercept (طلب ، الجسم ، هذا) ؛ } else {clientHttpRequest depegate = requestFactory.Createquest (request.geturi () ، request.getMethod ()) ؛ لـ (map.entry <string ، list <string >> الإدخال: request.getheaders (). intplesSet ()) {list <string> values = intervevalue () ؛ لـ (قيمة السلسلة: القيم) {depegate.getheaders (). add (Entpl.getKey () ، value) ؛ }} if (body.length> 0) {StreamUtils.copy (body ، devate.getBody ()) ؛ } إرجاع مندوب. execute () ؛ }}}}5. يستدعي اعتراض موازنة التحميل عميل موازنة التحميل
في طريقة التقاطع في فئة LoadBalancerInterceptor من فئة توازن التحميل ، يتم استدعاء طريقة التنفيذ لفئة تنفيذ العميل الموازنة بين العميل.
الفئة العامة loadBalanCerInterceptor تنفذ clientHttPrequestInterceptor requestfactory pladBalancerRequestFactory الخاص ؛ publicalancerInterceptor (LoadBalancerClient loadBalancer ، loadBalancerRequestFactory requestFactory) {this.loadbalancer = loadBalancer ؛ this.requestfactory = requestFactory ؛ } publicalancerInterceptor (LoadBalancerClient loadBalancer) {// للتوافق مع الوراء هذا (LoadBalancer ، new LoadBalancerRequestFactory (loadBalancer)) ؛ } Override Public ClientHttpResponse Intercept (طلب httprequest النهائي ، byte النهائي [] body ، clienthttprequestexecution تنفيذ) رمي ioException {final uri originaluri = request.geturi () ؛ ServiceName = OriginalUri.gethost () ؛ assert.state (servicename! = null ، "طلب URI لا يحتوي على اسم مضيف صالح:" + OriginalURI) ؛ return this.loadbalancer.execute (servicename ، requestFactory.createquest (طلب ، الجسم ، التنفيذ)) ؛ }}في الخطوة 1 من مرحلة التكوين ، يمكنك أن ترى أن فئة التنفيذ عبارة عن RibbonLoadBalancerClient.
6. يقوم عميل موازنة التحميل باستدعاء سياسة موازنة التحميل لتحديد مثيل الخدمة المستهدفة والبدء في طلب
في أول طريقة تنفيذ وطريقة getServer لـ RibbonloadBalancerClient ، يمكننا أن نرى أنه في الواقع ، يتم تحديد طريقة Choiceserver لفئة تنفيذ IloAdbalancer وتسليمها إلى كائن الطلب التالي لبدء طلب.
فئة تنفيذ موازنة التحميل هنا هي مثال Load Load-Area-Area-Area-Area-Area-Area-Area على ZoneaWareLoadBalancer بشكل افتراضي ، ويختار خدمة داخليًا من خلال سياسة التوازن.
يمكن العثور على إنشاء ZoneawareloadBalancer في الخطوة 4 من مرحلة التكوين.
الطبقة العامة ribbonloadbalancerclient تنفذ loadbalancerclient {Override public <t> t تنفيذ (سلسلة serviceid ، loadBalancerRequest <t> طلب) رمي ioException {iloadbalancer loadBalancer = getLoadBalancer (serviceid) ؛ خادم خادم = getServer (loadBalancer) ؛ if (server == null) {refl new alficalstateException ("لا توجد مثيلات متاحة لـ" + serviceId) ؛ } ribbonserver ribbonserver = new ribbonserver (serviceid ، server ، issecure (server ، serviceid) ، serverIntrospector (serviceId) .getMetAdata (server)) ؛ إرجاع تنفيذ (ServiceId ، Ribbonserver ، طلب) ؛ } Override Public <T> t تنفيذ (سلسلة serviceId ، serviceInstance serviceInstance ، loadBalanCerRequest <T> request) رمي ioException {server server = null ؛ if (serviceinstance extryof ribbonserver) {server = ((ribbonserver) serviceInstance) .getServer () ؛ } if (server == null) {refl new alficalstateException ("لا توجد مثيلات متاحة لـ" + serviceId) ؛ } ribbonloadbalancertext context = this.clientFactory .getLoadBalanCerContext (serviceId) ؛ RibbonStatsRecorder StatsRecorder = New RibbonStatsRecorder (Context ، Server) ؛ حاول {t returnval = request.apply (serviceInstance) ؛ StatsRecorder.RecordStats (ReturnVal) ؛ إرجاع العودة. } // catch ioException و rethrow حتى يتصرف RestTemplate بشكل صحيح (ioException ex) {StatsRecorder.RecordStats (ex) ؛ رمي السابقين } catch (استثناء ex) {statsRecorder.RecordStats (ex) ؛ ReflectionUtils.RethRowRuntimeException (EX) ؛ } إرجاع فارغ ؛ }. } return loadBalancer.ChooseServer ("Default") ؛ // TODO: معالجة أفضل للمفتاح} محمي IloAdbalancer getLoadBalancer (String serviceId) {return this.clientfactory.getLoadBalancer (serviceId) ؛ } ribbonserver الفئة الثابتة العامة تنفذ ServiceInstance {Private Final String ServiceId ؛ خادم الخادم النهائي الخاص ؛ نهائي خاص آمن ؛ خريطة خاصة <String ، String> Metadata ؛ ribbonserver العامة (سلسلة serviceid ، خادم خادم) {this (serviceId ، server ، false ، مجموعات. <string ، string> frankMap ()) ؛ } ribbonserver العامة (String ServiceId ، خادم الخادم ، آمن منطقي ، خريطة <string ، string> metadata) {this.serviceId = serviceId ؛ this.server = server ؛ this.secure = آمن ؛ this.metadata = بيانات التعريف ؛ } // refress}}بعد الانتهاء من الرمز ، دعنا نلخصه.
عند استخدام RestTemplate لطلب خدمات أخرى ، يتم استخدام مثيل طلب HTTP العادي داخليًا لإرسال الطلبات.
بعد إضافة التعليق التوضيحي المتوازن إلى RestTemplate ، في الواقع ، من خلال التكوين ، يتم حقن اعتراض موازنة التحميل في RestTemplate ، مما يسمح لموازن التحميل باختيار الخدمة المناسبة وفقًا لسياسته المقابلة قبل إرسال طلب.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.