สังเกตได้เทียบกับที่ไหลได้ rxJava2


128

ฉันได้ดู rx java 2 ใหม่และฉันไม่ค่อยแน่ใจว่าฉันเข้าใจความคิดของbackpressureอีกต่อไป ...

ฉันรู้ว่าเรามีObservableสิ่งนั้นที่ไม่มีbackpressureการสนับสนุนและFlowableนั่นก็มี

จากตัวอย่างสมมติว่าฉันมีflowableกับinterval:

        Flowable.interval(1, TimeUnit.MILLISECONDS, Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    // do smth
                }
            });

สิ่งนี้จะผิดพลาดหลังจากประมาณ 128 ค่าและเห็นได้ชัดว่าฉันใช้เวลาช้ากว่าการรับไอเท็ม

แต่เราก็มีเหมือนกัน Observable

     Observable.interval(1, TimeUnit.MILLISECONDS, Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    // do smth
                }
            });

สิ่งนี้จะไม่ผิดพลาดเลยแม้ว่าฉันจะชะลอการใช้งานไปบ้างก็ยังใช้งานได้ เพื่อให้Flowableทำงานได้สมมติว่าฉันใส่onBackpressureDropตัวดำเนินการความผิดพลาดจะหายไป แต่ไม่ได้แสดงค่าทั้งหมด

ดังนั้นคำถามพื้นฐานที่ฉันไม่สามารถหาคำตอบได้ในหัวของฉันคือเหตุใดฉันจึงต้องสนใจว่าbackpressureเมื่อฉันสามารถใช้แบบธรรมดาObservableยังคงได้รับค่าทั้งหมดโดยไม่ต้องจัดการbuffer? หรืออาจจะจากอีกด้านหนึ่งข้อดีอะไรที่ช่วยbackpressureให้ฉันสามารถจัดการและจัดการกับการบริโภคได้


คำตอบ:


123

สิ่งที่แสดงให้เห็นในทางปฏิบัติคือ backpressure บัฟเฟอร์Flowable.observeOnมีบัฟเฟอร์ 128 องค์ประกอบที่ระบายออกได้เร็วที่สุดเท่าที่ dowstream สามารถรับได้ คุณสามารถเพิ่มขนาดบัฟเฟอร์นี้ทีละขนาดเพื่อจัดการแหล่งที่มาแบบไม่ต่อเนื่องและแนวทางปฏิบัติในการจัดการแรงดันย้อนกลับทั้งหมดยังคงใช้ตั้งแต่ 1.x Observable.observeOnมีบัฟเฟอร์ที่ไม่ถูกผูกไว้ซึ่งจะรวบรวมองค์ประกอบต่างๆและแอปของคุณอาจมีหน่วยความจำไม่เพียงพอ

คุณอาจใช้Observableตัวอย่าง:

  • การจัดการเหตุการณ์ GUI
  • ทำงานกับลำดับสั้น ๆ (รวมน้อยกว่า 1,000 องค์ประกอบ)

คุณอาจใช้Flowableตัวอย่าง:

  • แหล่งที่มาที่เย็นและไม่กำหนดเวลา
  • เครื่องกำเนิดไฟฟ้าเช่นแหล่งที่มา
  • ตัวเข้าถึงเครือข่ายและฐานข้อมูล

ตั้งแต่นี้มีขึ้นมาในคำถามอื่น - มันถูกต้องที่ประเภทที่ จำกัด มากขึ้นเช่นMaybe, SingleและCompletableสามารถเสมอนำมาใช้แทนFlowableเมื่อพวกเขามีความหมายเหมาะสมหรือไม่
david.mihola

1
ใช่Maybe, SingleและCompletableอยู่ไกลขนาดเล็กเกินไปที่จะมีความต้องการของแนวคิด backpressure ใด ๆ ไม่มีโอกาสที่ผู้ผลิตจะปล่อยสินค้าได้เร็วเกินกว่าที่จะบริโภคได้เนื่องจากจะมีการผลิตหรือบริโภค 0–1 รายการ
AndrewF

บางทีฉันอาจจะไม่ถูกต้อง แต่สำหรับฉันควรเปลี่ยนตัวอย่างของ Flowable และ Observable
Yura Galavay

ฉันคิดว่าในคำถามที่เขาขาดกลยุทธ์ backpressure ที่เราจำเป็นต้องให้กับ Flowable ซึ่งอธิบายว่าเหตุใดจึงมีการโยนข้อยกเว้นของแรงดันย้อนกลับที่ขาดหายไปและยังอธิบายว่าเหตุใดข้อยกเว้นนี้จึงหายไปหลังจากที่เขาใช้. onBackpressureDrop () และสำหรับ Observable เนื่องจากไม่มีกลยุทธ์นี้และไม่สามารถจัดหาได้จึงจะล้มเหลวในภายหลังเนื่องจาก OOM
Haomin

111

Backpressure คือการที่คุณสังเกตได้ (ผู้เผยแพร่) กำลังสร้างกิจกรรมมากกว่าที่ผู้ติดตามของคุณจะสามารถจัดการได้ ดังนั้นคุณสามารถทำให้สมาชิกพลาดกิจกรรมหรือคุณอาจได้รับคิวอีเวนต์จำนวนมากซึ่งจะนำไปสู่ความทรงจำที่ไม่เพียงพอในที่สุด Flowableคำนึงถึงแรงดันย้อนกลับ Observableไม่. แค่นั้นแหละ.

มันทำให้ฉันนึกถึงช่องทางหนึ่งซึ่งเมื่อมันมีของเหลวมากเกินไป Flowable สามารถช่วยไม่ให้สิ่งนั้นเกิดขึ้น:

ด้วยแรงดันย้อนกลับอย่างมาก:

ใส่คำอธิบายภาพที่นี่

แต่ด้วยการใช้ flowable จะมีแรงดันย้อนกลับน้อยกว่ามาก:

ใส่คำอธิบายภาพที่นี่

Rxjava2 มีกลยุทธ์แรงดันย้อนกลับบางประการที่คุณสามารถใช้ได้ขึ้นอยู่กับลักษณะการใช้งานของคุณ ตามกลยุทธ์ฉันหมายถึง Rxjava2 จัดหาวิธีจัดการกับอ็อบเจ็กต์ที่ไม่สามารถประมวลผลได้เนื่องจากโอเวอร์โฟลว์ (แรงดันย้อนกลับ)

นี่คือกลยุทธ์ ฉันจะไม่ผ่านมันทั้งหมด แต่ตัวอย่างเช่นหากคุณไม่ต้องการกังวลเกี่ยวกับรายการที่ล้นคุณสามารถใช้กลยุทธ์การดรอปได้ดังนี้:

observable.toFlowable (BackpressureStrategy.DROP)

เท่าที่ฉันรู้ว่าควรมีรายการ จำกัด 128 รายการในคิวหลังจากนั้นอาจมีการล้น (แรงดันย้อนกลับ) แม้ว่าจะไม่ใช่ 128 แต่ก็ใกล้เคียงกับตัวเลขนั้น หวังว่านี่จะช่วยใครบางคนได้

หากคุณต้องการเปลี่ยนขนาดบัฟเฟอร์จาก 128 ดูเหมือนว่าจะทำได้เช่นนี้ (แต่ดูข้อ จำกัด ของหน่วยความจำ:

myObservable.toFlowable(BackpressureStrategy.MISSING).buffer(256); //but using MISSING might be slower.  

ในการพัฒนาซอฟต์แวร์มักจะใช้กลยุทธ์การกดดันกลับหมายความว่าคุณบอกให้ตัวปล่อยช้าลงเล็กน้อยเนื่องจากผู้บริโภคไม่สามารถจัดการกับความเร็วของเหตุการณ์ที่คุณปล่อยออกมาได้


ฉันคิดเสมอว่าแรงดันย้อนกลับเป็นชื่อของกลุ่มกลไกที่จะทำให้ผู้บริโภคแจ้งให้ผู้ผลิตชะลอตัวลง ...
kboom

อาจเป็นกรณี ใช่
j2emanue

มีข้อเสียในการใช้ Flowable หรือไม่?
IgorGanapolsky

ภาพเหล่านี้กำลังโกหกฉัน การทิ้งกิจกรรมจะไม่ลงเอยด้วย "เงินมากกว่า" ที่ด้านล่าง
EpicPandaForce

1
@ j2emanue คุณกำลังสับสนขนาดบัฟเฟอร์สำหรับตัวดำเนินการและตัวดำเนินการ Flowable.buffer (int) โปรดอ่าน javadocs cafefully และแก้ไขคำตอบของคุณตามนี้: reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html
tomek

15

ความจริงที่ว่าการFlowableชนของคุณหลังจากปล่อยค่า 128 โดยไม่มีการจัดการแรงดันย้อนกลับไม่ได้หมายความว่ามันจะพังหลังจากค่า 128 เสมอไป: บางครั้งมันจะพังหลังจาก 10 และบางครั้งก็ไม่ผิดพลาดเลย ฉันเชื่อว่านี่เป็นสิ่งที่เกิดขึ้นเมื่อคุณลองใช้ตัวอย่างObservable- ไม่มีแรงดันย้อนกลับดังนั้นรหัสของคุณจึงทำงานได้ตามปกติในครั้งต่อไปอาจไม่เกิดขึ้น ความแตกต่างใน RxJava 2 คือไม่มีแนวคิดเรื่องแรงดันย้อนกลับในObservables อีกต่อไปและไม่มีวิธีจัดการกับมัน หากคุณกำลังออกแบบลำดับปฏิกิริยาที่อาจต้องมีการจัดการแรงดันย้อนกลับอย่างชัดเจนFlowableนั่นคือทางเลือกที่ดีที่สุดของคุณ


ใช่ฉันสังเกตว่าบางครั้งมันหักหลังจากค่าน้อยลงบางครั้งก็ไม่ได้ แต่อีกครั้งถ้าตัวอย่างเช่นฉันจัดการintervalโดยที่backpressureฉันไม่คาดหวังพฤติกรรมแปลก ๆ หรือปัญหาบางอย่าง?
user2141889

หากคุณแน่ใจว่าไม่มีทางที่จะเกิดปัญหาแรงดันย้อนกลับในลำดับที่สังเกตได้โดยเฉพาะ - ฉันคิดว่ามันเป็นการดีที่จะเพิกเฉยต่อแรงดันย้อนกลับ
Egor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.