ในสถาปัตยกรรม Microservice เราแบ่งโครงการออกเป็นโมดูลอิสระจำนวนมากซึ่งทำงานร่วมกันผ่านการโทรจากระยะไกล อย่างไรก็ตามในกรณีของการเกิดขึ้นพร้อมกันสูงการเพิ่มจำนวนการสื่อสารจะนำไปสู่การเพิ่มขึ้นของเวลาการสื่อสารทั้งหมด ในเวลาเดียวกันทรัพยากรของพูลเธรดก็มี จำกัด เช่นกัน สภาพแวดล้อมที่เกิดขึ้นพร้อมกันสูงจะทำให้เธรดจำนวนมากอยู่ในสถานะรอซึ่งจะนำไปสู่ความล่าช้าในการตอบสนอง เพื่อที่จะแก้ปัญหาเหล่านี้เราต้องเข้าใจคำขอของ Hystrix
การร้องขอการรวมกันใน Hystrix คือการใช้โปรเซสเซอร์ผสานเพื่อรวมคำขอต่อเนื่องที่ริเริ่มโดยบริการเดียวกันในคำขอเดียวสำหรับการประมวลผล (หน้าต่างเวลาสำหรับคำขอต่อเนื่องเหล่านี้คือ 10ms โดยค่าเริ่มต้น) หนึ่งในคลาสหลักที่เกี่ยวข้องในกระบวนการนี้คือ HystrixCollapser, OK ถัดไปมาดูวิธีการใช้ Hystrix Request Merging
อินเทอร์เฟซผู้ให้บริการ
ฉันจำเป็นต้องจัดหาอินเทอร์เฟซสองแบบในผู้ให้บริการเพื่อให้ผู้บริโภคบริการโทรดังนี้:
@RequestMapping ("/getBook6") รายการสาธารณะ <book> book6 (รหัสสตริง) { System.out.println ("IDS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - - - - - - 33, "Hu Shi", "None")); สำนักพิมพ์ 2 "); Return Book;}อินเทอร์เฟซแรกคืออินเทอร์เฟซแบทช์และอินเทอร์เฟซที่สองเป็นอินเทอร์เฟซที่จัดการคำขอเดียว ในอินเทอร์เฟซแบทช์รูปแบบพารามิเตอร์ IDS ที่ส่งโดยผู้บริโภคบริการคือ 1, 2, 3, 4 ... รูปแบบนี้ ภายใต้สถานการณ์ปกติเราจำเป็นต้องสืบค้นข้อมูลที่เกี่ยวข้องตาม IDs จากนั้นรวบรวมไว้ในชุดที่จะส่งคืน เพื่อประโยชน์ในการประมวลผลง่ายฉันจะส่งคืนชุดข้อมูลเดียวกันไม่ว่าคำขอประเภทใด อินเทอร์เฟซสำหรับการประมวลผลคำขอเดียวนั้นค่อนข้างง่ายดังนั้นฉันจะไม่ทำซ้ำ
ให้บริการผู้บริโภค
ตกลงหลังจากผู้ให้บริการจัดการมาดูกันว่าผู้บริโภคบริการควรจัดการอย่างไร
บริการหนังสือ
ก่อนอื่นเพิ่มสองวิธีลงใน Bookservice เพื่อเรียกอินเทอร์เฟซที่ให้บริการโดยผู้ให้บริการดังนี้:
Public Book Test8 (Long ID) {return resttemplate.getForObject ("http: // hello-service/getbook6/{1}", book.class, id);} รายการสาธารณะ <book> test9 (รายการ <lonl> ids) {system.out.println ( thread.currentthread (). getName ()); หนังสือ [] หนังสือ = RestTemplate.getForObject ("http: // hello-service/getbook6? ids = {1}", หนังสือ []. คลาส, stringutils.join (ids, ",")); return array.aslist (หนังสือ);}Test8 ใช้เพื่อเรียกอินเทอร์เฟซที่ให้ ID เดียว Test9 ใช้เพื่อเรียกอินเทอร์เฟซที่การประมวลผลแบบแบตช์ ในการทดสอบ 9 ฉันพิมพ์เธรดที่มีการทดสอบ 9 เพื่ออำนวยความสะดวกให้เราสังเกตผลการดำเนินการ นอกจากนี้ใน RestTemplate หากค่าส่งคืนเป็นคอลเลกชันเราต้องได้รับมันก่อนด้วยอาร์เรย์ก่อนจากนั้นแปลงเป็นคอลเลกชัน (อาจมีวิธีอื่น ๆ เพื่อนมีคำแนะนำที่ดีกว่าที่จะทำ)
BookbatchCommand
ตกลงหลังจากวิธีการใน Bookservice พร้อมแล้วเราสามารถสร้าง BookbatchCommand ซึ่งเป็นคำสั่งแบทช์ดังนี้:
Public Class BookbatchCommand ขยาย HystrixCommand <list <book>> {รายการส่วนตัว <long> ids; บริการหนังสือส่วนตัว Public BookbatchCommand (รายการ <long> ids, Bookservice Bookservice) {super (setter.withgroupkey (HystrixCommandGroupkey.factory.askey ("CollapsingGroup")) .andCommandKey this.ids = ids; this.bookService = Bookservice; } @Override รายการที่ได้รับการป้องกัน <book> run () พ่นข้อยกเว้น {return bookservice.test9 (ids); -คลาสนี้คล้ายกับคลาสที่เราแนะนำในบล็อกก่อนหน้า พวกเขาทั้งสองสืบทอดมาจาก HystrixCommand และใช้ในการจัดการคำขอที่ผสานและเรียกวิธีการทดสอบ 9 ใน Bookservice ในวิธีการเรียกใช้
BookCollapSecommand
ต่อไปเราจำเป็นต้องสร้าง BookCollapSecommand ที่สืบทอดมาจาก HystrixCollapser เพื่อใช้การร้องขอการรวม ดังนี้:
BookCollapsecommand ขยายชั้นเรียนสาธารณะขยาย HystrixCollapseer <list <book>, หนังสือ, Long> {Bookservice Bookservice ส่วนตัว; ID ยาวส่วนตัว; BookCollapSecommand (Bookservice Bookservice, Long ID) {super (setter.withcollapserkey (Hystrixcollapserkey.factory.askey ("Bookcollapsecommand")) และ Collapserpropertiesdefaults this.bookService = Bookservice; this.id = id; } @Override สาธารณะยาว getRequestArgument () {return id; } @Override Protected HystrixCommand <list <book>> createCommand (คอลเลกชัน <clapsedrequest <Book, Long >> CollapsedRequests) {รายการ <long> ids = new ArrayList <> ids.Addall (ClatrapsedRequests.Stream (). MAP (COLLAPSEDREQUEST :: GETARGUMENT) .Collect (Collector.tolist ())); BookBatchCommand BookBatchCommand = ใหม่ BookBatchCommand (IDS, Bookservice); BookbatchCommand; } @Override Void Void MapResponSetOrequests (รายการ <book> batchResponse, คอลเลกชัน <clatrapsedRequest <Book, Long >> CollapsedRequests) {System.out.println ("MapResponSetorequests"); จำนวน int = 0; สำหรับ (CollapsedRequest <Book, Long> CollapsedRequest: CollapsedRequests) {Book Book = BatchResponse.get (นับ ++); COLTAPSEDREQUEST.SESTRESPONSE (หนังสือ); -เกี่ยวกับชั้นเรียนนี้ฉันจะพูดประเด็นต่อไปนี้:
1. ก่อนอื่นทั้งหมดในวิธีการก่อสร้างเราตั้งค่าหน้าต่างเวลาการร้องขอเป็น 100ms นั่นคือคำขอที่มีช่วงเวลาการร้องขอภายใน 100ms จะถูกรวมเข้ากับคำขอเดียว
2. วิธี CreateCommand ส่วนใหญ่จะใช้ในการรวมคำขอรับ ID ของคำขอแต่ละครั้งที่นี่ใส่ ID เดียวเหล่านี้ลงในคอลเลกชันจากนั้นสร้างวัตถุ BookBatchCommand และใช้วัตถุนี้เพื่อเริ่มคำขอแบตช์
3. วิธี MapResponSetOrequests ส่วนใหญ่ใช้เพื่อตั้งค่าผลลัพธ์คำขอสำหรับแต่ละคำขอ พารามิเตอร์แรกของวิธีนี้แสดงถึงผลลัพธ์ของการร้องขอแบทช์และพารามิเตอร์ที่สองยุบตัวรีเควสต์แสดงถึงคำขอที่รวมกันแต่ละครั้ง จากนั้นเราตั้งค่าผลการร้องขอสำหรับการยุบตัวโดยการข้าม BatchResponse
ตกลงหลังจากการดำเนินการทั้งหมดเหล่านี้เสร็จสมบูรณ์เราสามารถมาทดสอบได้
ทดสอบ
เราสร้างอินเทอร์เฟซการเข้าถึงที่ด้านผู้บริโภคบริการเพื่อทดสอบคำขอผสาน อินเทอร์เฟซทดสอบมีดังนี้:
@RequestMapping ("/test7")@responsebodypublic void test7 () พ่น ExecutionException, interruptedException {HystrixRequestContext บริบท = HystrixRequestContext.initializeContext (); BookCollapSecommand BC1 = ใหม่ BookCollapSecommand (Bookservice, 1L); BookCollapSecommand BC2 = ใหม่ BookCollapSecommand (Bookservice, 2L); BookCollapSecommand BC3 = ใหม่ BookCollapSecommand (Bookservice, 3L); BookCollapSecommand BC4 = ใหม่ BookCollapSecommand (Bookservice, 4L); อนาคต <book> q1 = bc1.queue (); อนาคต <book> q2 = bc2.queue (); อนาคต <book> q3 = bc3.queue (); Book Book1 = q1.get (); Book Book2 = Q2.get (); Book Book3 = q3.get (); Thread.sleep (3000); อนาคต <book> q4 = bc4.queue (); Book Book4 = q4.get (); System.out.println ("book1 >>>"+book1); System.out.println ("Book2 >>>"+Book2); System.out.println ("Book3 >>>"+Book3); System.out.println ("Book4 >>>"+Book4); context.close ();}เกี่ยวกับอินเทอร์เฟซการทดสอบนี้ฉันพูดสองจุดต่อไปนี้:
1. ก่อนอื่นคุณต้องเริ่มต้น HystrixRequestContext
2. สร้างอินสแตนซ์ของคลาส BookCollapSecommand เพื่อเริ่มคำขอส่ง 3 คำขอก่อนจากนั้นนอนเป็นเวลา 3 วินาทีจากนั้นเริ่มคำขอ ด้วยวิธีนี้คำขอ 3 ครั้งแรกจะถูกรวมเข้ากับคำขอเดียว คำขอที่สี่จะไม่ถูกรวมเข้าด้วยกันเนื่องจากช่วงเวลาระหว่างพวกเขาค่อนข้างยาว แต่จะสร้างเธรดเพื่อประมวลผลแยกต่างหาก
ตกลงมาดูผลการดำเนินการดังนี้:
การร้องขอการผสานจะถูกนำไปใช้ผ่านคำอธิบายประกอบ
ตกลงวิธีการรวมคำขอข้างต้นเป็นเรื่องยากเล็กน้อยในการเขียนเราสามารถใช้คำอธิบายประกอบเพื่อใช้ฟังก์ชั่นนี้ได้อย่างสง่างามยิ่งขึ้น ก่อนอื่นเพิ่มสองวิธีใน Bookservice ดังนี้:
@HyStrixCollapser (batchMethod = "test11", collapserProperties = {@HyStrixProperty (name = "timerDelayInmilliseconds", value = "100")}) <book> test10 System.out.println ("test9 ----------"+ids+"thread.currentthread (). getName ():"+thread.currentthread (). getName ()); หนังสือ [] หนังสือ = RestTemplate.getForObject ("http: // hello-service/getbook6? ids = {1}", หนังสือ []. คลาส, stringutils.join (ids, ",")); return array.aslist (หนังสือ);}เพิ่มคำอธิบายประกอบ @HyStrixCollapser เพื่อใช้การร้องขอการผสานในวิธีการทดสอบ 10 ใช้แอตทริบิวต์ batchMethod เพื่อระบุวิธีการประมวลผลหลังจากการร้องขอการรวมและแอตทริบิวต์ CollapserProperties เพื่อระบุแอตทริบิวต์อื่น ๆ
ตกลงหลังจากเขียนใน Bookservice เพียงแค่เรียกมันโดยตรงดังนี้:
@RequestMapping ("/test8")@responsebodypublic void test8 () พ่น executionException, interruptedException {hystrixRequestContext บริบท = hystrixRequestContext.initializeContext (); อนาคต <book> f1 = bookservice.test10 (1l); อนาคต <book> f2 = bookservice.test10 (2l); อนาคต <book> f3 = bookservice.test10 (3L); หนังสือ B1 = f1.get (); หนังสือ B2 = f2.get (); หนังสือ b3 = f3.get (); Thread.sleep (3000); อนาคต <book> f4 = bookservice.test10 (4l); Book B4 = f4.get (); System.out.println ("B1 >>>"+B1); System.out.println ("B2 >>>"+B2); System.out.println ("B3 >>>"+b3); System.out.println ("B4 >>>"+B4); context.close ();}เช่นเดียวกับคำขอก่อนหน้านี้สามคำขอแรกจะถูกรวมเข้าด้วยกันและคำขอที่สี่จะถูกดำเนินการแยกต่างหาก ตกลงและผลการดำเนินการมีดังนี้:
สรุป
ข้อได้เปรียบของการควบรวมกิจการการร้องขอเพื่อน ๆ ได้เห็นว่ามีการรวมคำขอหลายครั้งในการร้องขอการประมวลผลครั้งเดียวซึ่งสามารถบันทึกแบนด์วิดท์เครือข่ายและทรัพยากรพูลเธรดได้อย่างมีประสิทธิภาพ อย่างไรก็ตามมีข้อดีและข้อเสีย หลังจากตั้งค่าการร้องขอการรวมคำขออาจเสร็จสมบูรณ์ใน 5ms แต่ตอนนี้คุณต้องรออีก 10ms เพื่อดูว่ามีคำขออื่น ๆ ด้วยกันหรือไม่ ด้วยวิธีนี้การบริโภคเวลาของคำขอจะเพิ่มขึ้นจาก 5ms เป็น 15ms อย่างไรก็ตามหากคำสั่งที่เรากำลังจะเริ่มต้นคือคำสั่งล่าช้าสูงคุณสามารถใช้คำขอรวมในเวลานี้เนื่องจากการบริโภคเวลาของหน้าต่างเวลาไม่มีนัยสำคัญในเวลานี้ นอกจากนี้การพร้อมกันที่สูงยังเป็นสถานการณ์ที่สำคัญมากสำหรับการควบรวมคำขอ
ตกลงนั่นคือทั้งหมดที่เราขอรวม หากคุณมีคำถามใด ๆ โปรดฝากข้อความและพูดคุย ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น