ก่อนที่ HystrixCommand คุณสามารถใช้การควบรวมกิจการ ( HystrixCollapser เป็นคลาสแม่ที่เป็นนามธรรม) เพื่อรวมหลายคำขอเข้าด้วยกันแล้วเริ่มการโทรไปยังระบบการพึ่งพาแบ็กเอนด์
รูปด้านล่างแสดงจำนวนเธรดและจำนวนการเชื่อมต่อเครือข่ายในสองกรณี: ครั้งแรกคือไม่ใช้การควบรวมกิจการและที่สองคือการใช้การควบรวมกิจการ (สมมติว่าลิงก์ทั้งหมดขนานกันในหน้าต่างเวลาสั้น ๆ เช่นภายใน 10ms)
ทำไมต้องใช้คำขอรวม?
การร้องขอการผสานใช้เพื่อลดจำนวนเธรดและการเชื่อมต่อเครือข่ายที่จำเป็นในการดำเนินการ HystrixCommand พร้อมกัน การรวมการร้องขอจะดำเนินการโดยอัตโนมัติและไม่บังคับให้นักพัฒนาซอฟต์แวร์ประสานการร้องขอแบทช์ด้วยตนเอง
บริบททั่วโลก - บริบททั่วโลก (ครอบคลุมหัวข้อ Tomcat ทั้งหมด)
ประเภทการผสานนี้จะทำในระดับแอปพลิเคชันทั่วโลกดังนั้นคำขอของผู้ใช้ในเธรด Tomcat ใด ๆ สามารถรวมเข้าด้วยกันได้
ตัวอย่างเช่นหากคุณกำหนดค่า HystrixCommand เพื่อรองรับการพึ่งพาคำขอของผู้ใช้เพื่อดึงข้อมูลการจัดอันดับภาพยนตร์เมื่อเธรดผู้ใช้ใด ๆ ใน JVM เดียวกันทำให้คำขอดังกล่าว Hystrix เพิ่มคำขอพร้อมกับคำขออื่น ๆ ในการโทรเครือข่ายที่ยุบตัวเดียวกัน
บริบทคำขอผู้ใช้ - บริบทคำขอ (เธรด Tomcat เดี่ยว)
หากคุณกำหนดค่า HystrixCommand เพื่อจัดการคำขอแบตช์เฉพาะสำหรับผู้ใช้รายเดียว Hystrix สามารถรวมคำขอในเธรด Tomcat (คำขอ)
ตัวอย่างเช่นหากผู้ใช้ต้องการโหลดบุ๊คมาร์คของวัตถุวิดีโอ 300 รายการแทนที่จะดำเนินการตามคำขอเครือข่าย 300 ครั้ง Hystrix สามารถรวมเข้าด้วยกันได้
Hystrix เป็นขอบเขตการร้องขอตามค่าเริ่มต้น ในการใช้ฟังก์ชั่นการร้องขอ-การร้องขอ (ขอแคช, ขอล่มสลาย, บันทึกการร้องขอ) คุณต้องจัดการวงจรชีวิตของ HystrixRequestContext (หรือใช้ HystrixConcurrencyStrategy )
ซึ่งหมายความว่าคุณต้องเรียกใช้รหัสต่อไปนี้ก่อนที่จะดำเนินการตามคำขอ:
การคัดลอกรหัสมีดังนี้: HystrixRequestContext Context = HystrixRequestContext.initializeContext ();
และดำเนินการในตอนท้ายของคำขอ:
Context.shutdown ();
ในแอปพลิเคชัน Javaweb Standard คุณยังสามารถใช้ตัวกรอง servlet เพื่อเริ่มต้นวงจรชีวิตนี้
คลาสสาธารณะ HystrixRequestContextServletFilter ใช้ตัวกรอง {โมฆะสาธารณะ dofilter (คำขอ servletrequest, การตอบสนอง servletResponse, ห่วงโซ่ตัวกรอง) โยน ioexception, servletexception ลอง {chain.dofilter (คำขอ, การตอบกลับ); } ในที่สุด {context.shutdown (); -จากนั้นกำหนดค่าใน web.xml
<Tilter> <Display-Name> HystrixRequestContextServletFilter </display-Name> <filter-Name> HystrixRequestContextServletFilter </filter-name> <filter-mapping> <filter-name> HystrixRequestContextServletFilter </filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
หากคุณกำลังพัฒนา Springboot รหัสมีดังนี้:
@WebFilter (filtername = "HystrixRequestContextServletFilter", urlpatterns = "/*") คลาสสาธารณะ HystrixRequestContextServletFilter ใช้ตัวกรอง {@Override void init servletResponse servletResponse, filterchain filterchain) พ่น IOException, servletexception {HystrixRequestContext บริบท = HystrixRequestContext.initializeContext (); ลอง {filterchain.dofilter (servletrequest, servletResponse); } ในที่สุด {context.shutdown (); }} @Override โมฆะสาธารณะทำลาย () {}}@springbootapplication@enablediscoveryclient@enablefeignclients@enablehystrix // นี่เป็นสิ่งจำเป็นมิฉะนั้นตัวกรองจะไม่ถูกต้อง @ServletComponentScanpublic คลาสแอปพลิเคชัน -
การร้องขอการผสานมีค่าใช้จ่ายเท่าไหร่?
ค่าใช้จ่ายในการเปิดใช้งานการร้องขอคือความล่าช้าก่อนที่คำสั่งจริงจะถูกดำเนินการ ค่าใช้จ่ายที่ใหญ่ที่สุดคือขนาดของหน้าต่างแบทช์ซึ่งเป็น 10ms โดยค่าเริ่มต้น
หากคุณมีคำสั่งที่ใช้เวลา 5ms ในการดำเนินการและมีหน้าต่างแบทช์ 10ms กรณีที่เลวร้ายที่สุดของเวลาดำเนินการคือ 15ms โดยทั่วไปคำขอจะไม่เกิดขึ้นเมื่อเปิดหน้าต่างแบทช์ดังนั้นค่ากลางของหน้าต่างเวลาคือครึ่งหนึ่งของหน้าต่างเวลาในกรณีนี้มันคือ 5ms
ไม่ว่าค่าใช้จ่ายนี้จะคุ้มค่าหรือไม่นั้นขึ้นอยู่กับคำสั่งที่ดำเนินการและคำสั่งความล่าช้าสูงจะไม่ได้รับผลกระทบจากความล่าช้าเฉลี่ยเล็กน้อย ยิ่งไปกว่านั้นจำนวนการเกิดขึ้นพร้อมกันของคำสั่งที่กำหนดก็เป็นคีย์: หากมีการรวมคำขอน้อยกว่า 1 หรือ 2 ครั้งค่าใช้จ่ายจะไม่คุ้มค่า ในความเป็นจริงการร้องขอการทำซ้ำแบบต่อเนื่องในเธรดเดียวจะเป็นคอขวดที่สำคัญและการทำซ้ำแต่ละครั้งจะรอเวลารอหน้าต่าง 10ms
อย่างไรก็ตามหากมีการใช้คำสั่งเฉพาะในปริมาณมากในเวลาเดียวกันและสามารถโทรออกได้หลายสิบหรือหลายร้อยครั้งในแบทช์ในเวลาเดียวกันค่าใช้จ่ายมักจะมากกว่าการเพิ่มขึ้นของปริมาณงานที่เกิดขึ้นเนื่องจาก Hystrix ลดจำนวนเธรดที่ต้องการ (ข้อความนี้ไม่ใช่เรื่องง่ายที่จะเข้าใจในความเป็นจริงหากการเกิดขึ้นพร้อมกันค่อนข้างสูงค่าใช้จ่ายนั้นคุ้มค่าเพราะ Hystrix สามารถประหยัดเธรดและทรัพยากรการเชื่อมต่อได้จำนวนมาก)
กระบวนการร้องขอการผสาน (ดังที่แสดงด้านล่าง)
ความรู้เชิงทฤษฎีได้รับการอธิบาย มาดูตัวอย่างด้านล่าง ตัวอย่างด้านล่างรวม Eureka+Feign+Hystrix สำหรับตัวอย่างที่สมบูรณ์โปรดตรวจสอบ: https://github.com/jingangwang/micro-service
ชั้นเรียน
ผู้ใช้ระดับสาธารณะ {ID จำนวนเต็มส่วนตัว; ชื่อผู้ใช้สตริงส่วนตัว; อายุจำนวนเต็มส่วนตัว ผู้ใช้สาธารณะ () {} ผู้ใช้สาธารณะ (ID จำนวนเต็ม, ชื่อผู้ใช้สตริง, อายุจำนวนเต็ม) {this.id = id; this.username = ชื่อผู้ใช้; this.age = อายุ; } จำนวนเต็มสาธารณะ getId () {return id; } โมฆะสาธารณะ setId (ID จำนวนเต็ม) {this.id = id; } สตริงสาธารณะ getUserName () {ส่งคืนชื่อผู้ใช้; } โมฆะสาธารณะ setUserName (ชื่อผู้ใช้สตริง) {this.userName = ชื่อผู้ใช้; } Public Integer Getage () {return Age; } การตั้งค่าโมฆะสาธารณะ (อายุจำนวนเต็ม) {this.age = อายุ; } @Override สตริงสาธารณะ toString () {final StringBuffer sb = new StringBuffer ("ผู้ใช้ {"); sb.append ("id ="). ผนวก (id); sb.append (", username = '"). ผนวก (ชื่อผู้ใช้) .append ('/''); sb.append (", age ="). ผนวก (อายุ); sb.append ('}'); ส่งคืน sb.toString (); -รหัสผู้ให้บริการ
@restcontroller @requestmapping ("ผู้ใช้") คลาสสาธารณะ userController {@requestmapping ("getuser") ผู้ใช้สาธารณะ Getuser (ID จำนวนเต็ม) {ส่งคืนผู้ใช้ใหม่ (ID, "ทดสอบ", 29); } @RequestMapping ("getAllUser") รายการสาธารณะ <user> getAllUser (รหัสสตริง) {string [] split = ids.split (","); return arrays.aslist (split) .stream () .map (id -> ผู้ใช้ใหม่ (จำนวนเต็ม. valueof (id), "ทดสอบ"+id, 30)) .collect (collectors.tolist ()); -รหัสผู้บริโภค
userfeignclient
@feignClient (name = "Eureka-Provider", configuration = feignConfiguration.class) ส่วนต่อประสานสาธารณะ userfeignlient {/** * ค้นหาผู้ใช้โดย ID * @param id ผู้ใช้ ID * @return user */@requestmapping (value = "ผู้ใช้/getuser.json" id); /*** เกินรายการผู้ใช้* @param id id id รายการ* @return collection ผู้ใช้*/@requestmapping (value = "user/getalluser.json", method = requestmethod.get) รายการ <ผู้ใช้> findalluser (@requestparam ("ids")Userservice (ตั้งค่าเป็นบริบททั่วโลก)
@ServicePublic คลาส UserserVice {@AutoWired UserFeignClient UserFeignClient; / ** * MaxRequestSinBatch คุณสมบัตินี้ตั้งค่าจำนวนสูงสุดของคำขอสำหรับการประมวลผลแบบแบตช์ค่าเริ่มต้นคือจำนวนเต็ม MAX_VALUE * TIMERDELAYINMILLISECONDS คุณสมบัตินี้จะใช้เวลานานกว่าการประมวลผลแบตช์ com.netflix.hystrix.hystrixcollapser.scope.global, batchMethod = "FindAlluser", clinproperties = {@HyStrixProperty (name = "timerDelayinMilliseconds", value = "5000"), @hystrixproperty }) อนาคตสาธารณะ <user> ค้นหา (ID จำนวนเต็ม) {return null; } @HyStrixCommand (commandkey = "findalluser") รายการสาธารณะ <user> findalluser (รายการ <teger> ids) {ส่งคืน userfeignlient.findalluser (stringutils.join (ids, ",")); -FeigncollapserController
@requestmapping ("ผู้ใช้") @restcontrollerpublic คลาส FeignCollapSerController {@AutoWired Userservice Userservice; @RequestMapping ("FindUser") ผู้ใช้สาธารณะ GetUser (ID จำนวนเต็ม) โยน ExecutionException, InterruptedException {return Userservice.find (id) .get (); - ในรหัสข้างต้นเราอยู่ในบริบททั่วโลก (คำขอทั้งหมดจากเธรด Tomcat สามารถรวมเข้าด้วยกัน) หน้าต่างเวลารวมคือ 5s (ทุกคำขอต้องรอ 5s ก่อนที่จะมีการร้องขอ) และจำนวนการควบใหญ่สูงสุดคือ 5 ในไปรษณีย์
localhost: 8082/ผู้ใช้/finduser.json? id = 123189891
localhost: 8082/ผู้ใช้/finduser.json? id = 222222
ผลลัพธ์จะแสดงในรูปด้านล่างและคำขอทั้งสองจะถูกรวมเข้ากับคำขอชุดเดียว
ลองทดสอบบริบทคำขอ (ขอบเขตคำขอ) เพิ่ม HystrixRequestContextServletFilter ที่กล่าวถึงข้างต้นและแก้ไขผู้ใช้บริการ
HystrixRequestContextServletFilter
/** * @author wjg * @date 2017/12/22 15:15 */ @webfilter (filtername = "HystrixRequestContextServletFilter", urlpatterns = "/ *") servletexception {} @Override โมฆะสาธารณะ dofilter (servletrequest servletrequest, servletResponse servletResponse, filterChain filterChain) พ่น IOException, servletexception {hystrixRequestContext บริบท = hystrixRequestContext ลอง {filterchain.dofilter (servletrequest, servletResponse); } ในที่สุด {context.shutdown (); }} @Override โมฆะสาธารณะทำลาย () {}}Userservice (ตั้งเป็นบริบทคำขอ)
@ServicePublic คลาส UserserVice {@AutoWired UserFeignClient UserFeignClient; / ** * MaxRequestSinBatch คุณสมบัตินี้ตั้งค่าจำนวนสูงสุดของคำขอสำหรับการประมวลผลแบบแบตช์ค่าเริ่มต้นคือจำนวนเต็ม MAX_VALUE * TIMERDELAYINMILLISECONDS คุณสมบัตินี้จะใช้เวลานานกว่าการประมวลผลแบตช์ com.netflix.hystrix.hystrixcollapser.scope.request, batchMethod = "FindAlluser", collapserProperties = {@HyStrixProperty (name = "TimerDelayInMilliseconds", value = "5000") }) อนาคตสาธารณะ <user> ค้นหา (ID จำนวนเต็ม) {return null; } @HyStrixCommand (commandkey = "findalluser") รายการสาธารณะ <user> findalluser (รายการ <teger> ids) {ส่งคืน userfeignlient.findalluser (stringutils.join (ids, ",")); -FeignCollapser2Controller
@requestmapping ("ผู้ใช้") @restcontrollerpublic คลาส FeignCollapser2Controller {@AutoWired Userservice Userservice; @RequestMapping ("findUser2") รายการสาธารณะ <user> getUser () พ่น ExecutionException, interruptedException {Future <user> user1 = userservice.find (1989); อนาคต <user> user2 = userservice.find (1990); รายการ <user> ผู้ใช้ = arrayList ใหม่ <> (); users.add (user1.get ()); users.add (user2.get ()); ผู้ใช้ที่ส่งคืน; - เราพิมพ์ในบุรุษไปรษณีย์: localhost: 8082/ผู้ใช้/finduser2.json
คุณจะเห็นว่าการโทรติดต่อกันสองครั้งภายในคำขอจะถูกรวมเข้าด้วยกัน โปรดทราบว่าสิ่งนี้เป็นไปไม่ได้ที่จะใช้ userserver.find (1989) .get () โดยตรงไม่เช่นนั้นการประมวลผลจะดำเนินการโดยตรงตามการซิงโครไนซ์และจะไม่ถูกรวมเข้าด้วยกัน หากสองหน้าแท็บเรียกที่อยู่ข้างต้นในเวลาเดียวกันพบว่ามีการเริ่มต้นคำขอสองชุดซึ่งหมายความว่าขอบเขตคือขอบเขตการร้องขอ
การอ้างอิงมีดังนี้:
https://github.com/netflix/hystrix/wiki/how-to-use
//www.vevb.com/article/140530.htm
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น