قبل HystrixCommand ، يمكنك استخدام عملية دمج الطلب ( HystrixCollapser هي فئة الوالدين المجردة) لدمج طلبات متعددة في واحدة ثم بدء مكالمات إلى نظام التبعية الخلفية.
يوضح الشكل أدناه عدد مؤشرات الترابط وعدد اتصالات الشبكة في حالتين: الأول هو عدم استخدام عملية دمج ، والثاني هو استخدام عملية دمج الطلب (على افتراض أن جميع الروابط متوازية في نافذة زمنية قصيرة ، مثل 10 مللي ثانية).
لماذا تستخدم طلب طلب؟
يتم استخدام دمج الطلب لتقليل عدد مؤشرات الترابط واتصالات الشبكة المطلوبة لأداء عمليات إعدام HystrixCommand المتزامنة. يتم تنفيذ دمج الطلب تلقائيًا ولا تجبر المطورين على تنسيق طلبات الدُفعات يدويًا.
السياق العالمي - السياق العالمي (امتداد جميع خيوط Tomcat)
يتم تنفيذ هذا النوع من الدمج على مستوى التطبيق العالمي ، لذلك يمكن دمج طلب أي مستخدم على أي موضوع Tomcat معًا.
على سبيل المثال ، إذا قمت بتكوين HystrixCommand لدعم أي تبعيات لطلب المستخدم لاسترداد تصنيفات الأفلام ، عندما يقوم أي مؤشر ترابط مستخدم في نفس JVM بتقديم مثل هذا الطلب ، يضيف Hystrix طلبه مع أي طلب آخر إلى نفس مكالمة الشبكة المنهارة.
سياق طلب المستخدم - سياق الطلب (موضوع Tomcat واحد)
إذا قمت بتكوين HystrixCommand للتعامل مع طلبات الدُفعات فقط لمستخدم واحد ، فيمكن أن تقوم Hystrix بدمج الطلبات في موضوع Tomcat (طلب).
على سبيل المثال ، إذا أراد المستخدم تحميل إشارة مرجعية تضم 300 كائن فيديو ، بدلاً من تنفيذ 300 طلب شبكة ، يمكن لـ Hystrix دمجها في واحدة.
Hystrix هو scope scope بشكل افتراضي. لاستخدام الوظيفة التي يتوصل إليها الطلب (طلب التخزين المؤقت ، انهيار الطلب ، سجل الطلب) ، يجب عليك إدارة دورة حياة HystrixRequestContext (أو تنفيذ HystrixConcurrencyStrategy بديل)
هذا يعني أنك تحتاج إلى تنفيذ الرمز التالي قبل تنفيذ طلب:
نسخة الكود كما يلي: HystrixRequestContext Context = HystrixRequestContext.InitializeContext () ؛
وتنفيذ في نهاية الطلب:
context.shutdown () ؛
في تطبيقات Javawebs القياسية ، يمكنك أيضًا استخدام مرشح Servlet لتهيئة دورة الحياة هذه
الطبقة العامة HystrixRequestContextServletfilter تنفذ مرشح {public void dofilter (servletRequest request ، servletResponse ، سلسلة filterchain) يلقي iOexception ، servleTexception {hystrixRequestContext context = hystrixrequestcontext.initializext () ؛ حاول {chain.dofilter (طلب ، استجابة) ؛ } أخيرًا {context.shutdown () ؛ }}}ثم قم بتكوينه في web.xml
<Ivilter> <Display-Name> HystrixRequestContexTservletFilter </isplay-name> <filter-name> hystrixRequestContexTservletfilter </filter-name> <lilter-class> com.netflix.hystrix.contrib.requestservlet <Filter-mapping> <filter-name> hystrixRequestContexTservletFilter </filter-name> <url-pattern>/*</url-pattern> </filter mapping>
إذا كنت تقوم بتطوير Springboot ، فإن الكود كما يلي:
webfilter (filtername = "hystrixRequestContexTservletFilter" ، urlpatterns = "/*") الفئة العامة hystrixRequestContexTservletfilter تنفذ filter { @override public void init (filterConfig filterConfig) throwsexpice {} ServletRequest ، ServletResponse ServletResponse ، filterchain filterchain) يلقي ioException ، servletexception {hystrixRequestContext context = hystrixRequestContext.InitializeContext () ؛ حاول {filterchain.dofilter (servletRequest ، servletResponse) ؛ } أخيرًا {context.shutdown () ؛ }} Override public void Dride () {}} @springbootapplication@enableScoveryClient@enablefeignclients@enableHyStrix // هذا مطلوب ، وإلا فإن المرشح غير صالح servletcomponentscanpublic application {public static void main (string [] args) }}ما هي تكلفة طلب الدمج؟
تكلفة دمج طلب التمكين هي التأخير قبل تنفيذ الأمر الفعلي. أكبر تكلفة هي حجم نافذة الدُفعات ، والتي هي 10 مللي ثانية افتراضيًا.
إذا كان لديك أمر يستغرق 5 مللي ثانية للتنفيذ ولديه نافذة دفعة 10 مللي ثانية ، فإن أسوأ حالة في وقت التنفيذ هي 15 مللي ثانية. بشكل عام ، لن يحدث الطلب عند فتح نافذة الدُفعة للتو ، وبالتالي فإن القيمة الوسيطة لنافذة الزمن هي نصف النافذة الزمنية ، في هذه الحالة هي 5 مللي ثانية.
ما إذا كانت هذه التكلفة تستحق ذلك تعتمد على تنفيذ الأمر ، ولا تتأثر الأوامر ذات الكلية العالية بكمية صغيرة من متوسط التأخير الإضافي. علاوة على ذلك ، فإن مقدار التزامن أمر معين هو أيضًا مفتاح: إذا تم الجمع بين أقل من 1 أو 2 طلب ، فإن التكلفة لا تستحق ذلك. في الواقع ، سيكون دمج طلب التكرار المتسلسل في موضوع واحد عنق الزجاجة الرئيسي للأداء ، وسينتظر كل تكرار وقت انتظار نافذة 10 مللي ثانية.
ومع ذلك ، إذا تم استخدام أمر معين بكميات كبيرة في نفس الوقت ويمكنه إجراء العشرات أو حتى مئات المكالمات على دفعات في نفس الوقت ، فإن التكلفة عادة ما تكون أكثر بكثير من الزيادة في الإنتاجية التي تحققت ، لأن Hystrix يقلل من عدد الخيوط التي تتطلبها ، التبعيات. (ليس من السهل فهم هذا المقطع. في الواقع ، إذا كان التزامن مرتفعًا نسبيًا ، فإن التكلفة تستحق ذلك ، لأن Hystrix يمكن أن يوفر الكثير من المواضيع وموارد الاتصال).
عملية طلب الدمج (كما هو موضح أدناه)
تم شرح المعرفة النظرية. دعونا نلقي نظرة على الأمثلة أدناه. الأمثلة أدناه تدمج Eureka+Feign+Hystrix. للحصول على مثال كامل ، يرجى التحقق من: https://github.com/jingangwang/micro-service
فئة الكيان
مستخدم الفئة العامة {private integer id ؛ اسم المستخدم الخاص بالسلسلة الخاصة ؛ عصر عدد صحيح خاص ؛ user user () {} المستخدم العام (معرف Integer ، اسم المستخدم ، عصر INTEGER) {this.id = id ؛ this.username = اسم المستخدم ؛ this.age = العمر ؛ } integer getId () {return id ؛ } public void setId (integer id) {this.id = id ؛ } السلسلة العامة getUserName () {return username ؛ } public void setusername (string username) {this.userName = username ؛ } integer getAge () {return Age ؛ } public void setage (integer age) {this.age = age ؛ } Override Public String ToString () {Final StringBuffer SB = جديد StringBuffer ("user {") ؛ sb.append ("id ="). append (id) ؛ sb.append ("، username = '"). إلحاق (اسم المستخدم) .append ('/'') ؛ sb.append ("، Age ="). إلحاق (العمر) ؛ sb.append ('}') ؛ إرجاع sb.tostring () ؛ }}رمز مزود الخدمة
@restController @requestMapping ("user") الفئة العامة USERCONTROLLER {REQUESTMAPPING ("getUser") المستخدم العام getUser (integer id) {إرجاع مستخدم جديد (معرف ، "اختبار" ، 29) ؛ } @requestmapping ("getAlluser") قائمة عامة <Seter> getAlluser (string ids) {string [] split = ids.split ("،") ؛ إرجاع صفائف. }}رمز المستهلك
userFeignClient
dignclient (name = "eureka-provider" ، configuration = feignConfiguration.class) واجهة عامة userFeignClient {/** * ابحث عن المستخدم بواسطة ID * @param معرف المستخدم * user user */ @ @requestmapping (value = "user/getUser.json" ، method = requestMethod.get) /*** تجاوز قائمة المستخدم* قائمة معرف المعرف* param* @REGRUNT COLLECTION*/REQUESTMAPPE (value = "user/getAlluser.json" ، method = requestMethod.get) قائمة <Sether> findAlluser ( @requestparam ("ids") ؛ ids) ؛}}userService (تم تعيينه على السياق العالمي)
servicepublic class userService {autowired userfeignclient userFeignClient ؛ / ** * maxRequestSinBatch تحدد هذه الخاصية الحد الأقصى لعدد الطلبات لمعالجة الدُفعات ، والافتراضي هو integer.max_value * timerDelayInMillisEconds هذه الخاصية تحدد المدة التي تستغرقها معالجة الدُفعات ، الافتراضي هو 10 مللي ثانية * param */ @ @ @ @ @ com.netflix.hystrix.hystrixcollapser.scope.global ، batchmethod = "findalluser" ، closterProperties = {hystrixproperty (name = "maxReQueNMIliSeConds" ، value = "5000") ، @hyStrixProperty ("name =" maxrebatch المستقبل <Sether> Find (INTEGER ID) {return null ؛ } hystrixCommand (commandKey = "FindAlluser") قائمة عامة <Seter> bindalluser (قائمة <integer> ids) {return userfeignclient.findalluser (stringutils.join (ids ، "،" ، ")) ؛ }}FeignCollapserController
requestmapping ("user") @restControllerPublic class feignCollapserController {autowired private orperviceervice ؛ requestmapping ("FindUser") المستخدم العام getUser (INTEGER ID) يلقي ExecutionException ، interruptedException {return userservice.find (id) .get () ؛ } في الكود أعلاه ، نحن في السياق العالمي (يمكن دمج جميع الطلبات من سلاسل ترابط Tomcat) ، ونافذة وقت الدمج هي 5s (يجب أن تنتظر كل طلب 5s قبل بدء الطلب) ، والحد الأقصى لعدد الدمج هو 5. في ساعي البريد ، نبدأ طلبين في 5S ، لكن معرفات المستخدم مختلفة.
LocalHost: 8082/user/finduser.json؟ id = 123189891
LocalHost: 8082/user/finduser.json؟ id = 222222
يتم عرض النتيجة في الشكل أدناه ، ويتم دمج الطلبين في طلب دفعة طلب واحد.
دعنا نختبر سياق الطلب (scope-scope) ، وأضف HystrixRequestContextServletFilter المذكورة أعلاه ، وتعديل مستخدمي المستخدمين
HystrixRequestContextservletfilter
/** * Author wjg * date 2017/12/22 15:15 */ @webfilter (filetername = "HystrixRequestContextServletfilter" ، urlpatterns = "/ *") public class hystrixRextServilter direments filter ServleTexception {} Override public void dofilter (servletrequest servletrequest ، servletResponse ServletResponse ، filterchain filterchain) يلقي ioexception ، servletexception {hystrixrequestcontext context = hystrexrequestcontext.initializext () ؛ حاول {filterchain.dofilter (servletRequest ، servletResponse) ؛ } أخيرًا {context.shutdown () ؛ }} Override public void Dride () {}}userService (تعيين كسياق طلب)
servicepublic class userService {autowired userfeignclient userFeignClient ؛ ؟ com.netflix.hystrix.hystrixcollapser.scope.request ، BatchMethod = "FindAlluser" ، collapserProperties = {HystrixProperty (name = "maxReQuInMillisonds" ، value = "5000") ، @hyStrixProperty ("name =" maxrebatch "، المستقبل <Sether> Find (INTEGER ID) {return null ؛ } hystrixCommand (commandKey = "FindAlluser") قائمة عامة <Seter> bindalluser (قائمة <integer> ids) {return userfeignclient.findalluser (stringutils.join (ids ، "،" ، ")) ؛ }}FeignCollapser2Controller
requestmapping ("user") @restControllerPublic class feignCollapser2Controller {Autowired private uservicevice uservice ؛ requestmapping ("FindUser2") قائمة عامة <Sether> getUser () يلقي ExecutionException ، InterruptedException {future <serve> user1 = userService.find (1989) ؛ مستقبل <Sether> user2 = UserService.find (1990) ؛ قائمة <Sether> المستخدمين = جديد ArrayList <> () ؛ users.add (user1.get ()) ؛ users.add (user2.get ()) ؛ إرجاع المستخدمين ؛ }} نحن نكتب في Postman: LocalHost: 8082/user/findUser2.json
يمكنك أن ترى أنه يتم دمج مكالمتين متتاليتين ضمن طلب ما. لاحظ أن هذا غير ممكن استخدام usererServer.find (1989) .get () مباشرة ، وإلا فإن المعالجة سيتم تنفيذها مباشرة وفقًا للمزامنة ولن يتم دمجها. إذا قامت صفحتان لتبحذين بتركيب العنوان أعلاه في نفس الوقت ، فقد وجد أنه تم بدء طلبين دفعين ، مما يعني أن النطاق هو نطاق الطلب.
المراجع كما يلي:
https://github.com/netflix/hystrix/wiki/how-to-use
//www.vevb.com/article/140530.htm
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.