2015-12-15 7 views
13

मैं मूल्यांकन करने के लिए कुछ परीक्षण कर रहा हूं कि पारंपरिक लोगों को अवरुद्ध करने के बजाय, अवलोकनशील पर आधारित प्रतिक्रियाशील एपीआई का उपयोग करने में वास्तविक लाभ है या नहीं।वेब अनुप्रयोगों में आरएक्सजेवा ऑब्जर्वेबल्स का उपयोग करके प्रदर्शन सुधार की अनूठी कमी

  • सबसे अच्छा: बाकी सेवा है कि एक Callable/DeferredResult कि अवरुद्ध संचालन लपेटता लौट

    पूरे उदाहरण available on Githug

    हैरानी की बात है परिणाम बताते हैं कि thoughput परिणाम हो रहा है।

  • बुरा नहीं: आरईएसटी सेवाओं को अवरुद्ध करना।

  • सबसे खराब: बाकी सेवा है कि एक DeferredResult जिसका परिणाम एक RxJava नमूदार द्वारा निर्धारित है लौटने।

    आवेदन:

    @SpringBootApplication 
    public class SpringNioRestApplication { 
    
        @Bean 
        public ThreadPoolTaskExecutor executor(){ 
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
         executor.setCorePoolSize(10); 
         executor.setMaxPoolSize(20); 
         return executor; 
        } 
    
        public static void main(String[] args) { 
         SpringApplication.run(SpringNioRestApplication.class, args); 
        } 
    } 
    

    SyncController:

यह मेरा स्प्रिंग WebApp है

@RestController("SyncRestController") 
@Api(value="", description="Synchronous data controller") 
public class SyncRestController { 

    @Autowired 
    private DataService dataService; 

    @RequestMapping(value="/sync/data", method=RequestMethod.GET, produces="application/json") 
    @ApiOperation(value = "Gets data", notes="Gets data synchronously") 
    @ApiResponses(value={@ApiResponse(code=200, message="OK")}) 
    public List<Data> getData(){ 
     return dataService.loadData(); 
    } 
} 

AsyncController: दोनों कच्चे प्रतिदेय और प्रत्यक्ष अंतिमबिंदुओं

@RestController 
@Api(value="", description="Synchronous data controller") 
public class AsyncRestController { 

    @Autowired 
    private DataService dataService; 

    private Scheduler scheduler; 

    @Autowired 
    private TaskExecutor executor; 

    @PostConstruct 
    protected void initializeScheduler(){ 
     scheduler = Schedulers.from(executor); 
    } 

    @RequestMapping(value="/async/data", method=RequestMethod.GET, produces="application/json") 
    @ApiOperation(value = "Gets data", notes="Gets data asynchronously") 
    @ApiResponses(value={@ApiResponse(code=200, message="OK")}) 
    public Callable<List<Data>> getData(){ 
     return (() -> {return dataService.loadData();}); 
    } 

    @RequestMapping(value="/observable/data", method=RequestMethod.GET, produces="application/json") 
    @ApiOperation(value = "Gets data through Observable", notes="Gets data asynchronously through Observable") 
    @ApiResponses(value={@ApiResponse(code=200, message="OK")}) 
    public DeferredResult<List<Data>> getDataObservable(){ 
     DeferredResult<List<Data>> dr = new DeferredResult<List<Data>>(); 
     Observable<List<Data>> dataObservable = dataService.loadDataObservable(); 
     dataObservable.subscribeOn(scheduler).subscribe(dr::setResult, dr::setErrorResult); 
     return dr; 
    } 
} 

DataServiceImpl

@Service 
public class DataServiceImpl implements DataService{ 

    @Override 
    public List<Data> loadData() { 
     return generateData(); 
    } 

    @Override 
    public Observable<List<Data>> loadDataObservable() { 
     return Observable.create(s -> { 
      List<Data> dataList = generateData(); 
      s.onNext(dataList); 
      s.onCompleted(); 
     }); 
    } 

    private List<Data> generateData(){ 
     List<Data> dataList = new ArrayList<Data>(); 
     for (int i = 0; i < 20; i++) { 
      Data data = new Data("key"+i, "value"+i); 
      dataList.add(data); 
     } 
     //Processing time simulation 
     try { 
      Thread.sleep(500); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     return dataList; 
    } 
} 

के साथ मैं सेवा प्रतिक्रिया समय को बढ़ाने के लिए एक Thread.sleep(500) देरी निर्धारित किया है।

लोड परीक्षण से वहाँ परिणाम हैं:

Async प्रतिदेय साथ: 700 आर पी एस, कोई त्रुटि

>>loadtest -c 15 -t 60 --rps 700 http://localhost:8080/async/data  
... 
Requests: 0, requests per second: 0, mean latency: 0 ms 
Requests: 2839, requests per second: 568, mean latency: 500 ms 
Requests: 6337, requests per second: 700, mean latency: 500 ms 
Requests: 9836, requests per second: 700, mean latency: 500 ms 
... 
Completed requests: 41337 
Total errors:  0 
Total time:   60.002348360999996 s 
Requests per second: 689 
Total time:   60.002348360999996 s 

को अवरुद्ध करने: चारों ओर 404 आर पी एस लेकिन त्रुटियों

>>loadtest -c 15 -t 60 --rps 700 http://localhost:8080/sync/data  
... 
Requests: 7683, requests per second: 400, mean latency: 7420 ms 
Requests: 9683, requests per second: 400, mean latency: 9570 ms 
Requests: 11680, requests per second: 399, mean latency: 11720 ms 
Requests: 13699, requests per second: 404, mean latency: 13760 ms 
... 
Percentage of the requests served within a certain time 
    50%  8868 ms 
    90%  22434 ms 
    95%  24103 ms 
    99%  25351 ms 
100%  26055 ms (longest request) 

100%  26055 ms (longest request) 

    -1: 7559 errors 
Requests: 31193, requests per second: 689, mean latency: 14350 ms 
Errors: 1534, accumulated errors: 7559, 24.2% of total requests 
का उत्पादन

अवलोकन के साथ Async: नहीं 20 से अधिक आर पी एस, और हो जाता है त्रुटियों जल्दी

>>loadtest -c 15 -t 60 --rps 700 http://localhost:8080/observable/data 
Requests: 0, requests per second: 0, mean latency: 0 ms 
Requests: 90, requests per second: 18, mean latency: 2250 ms 
Requests: 187, requests per second: 20, mean latency: 6770 ms 
Requests: 265, requests per second: 16, mean latency: 11870 ms 
Requests: 2872, requests per second: 521, mean latency: 1560 ms 
Errors: 2518, accumulated errors: 2518, 87.7% of total requests 
Requests: 6373, requests per second: 700, mean latency: 1590 ms 
Errors: 3401, accumulated errors: 5919, 92.9% of total requests 

10 की एक corePoolSize साथ नमूदार कार्यान्वित, लेकिन 50 को इसे बढ़ाने या तो कुछ भी सुधार नहीं हुआ।

स्पष्टीकरण क्या हो सकता है?

अद्यतन: जैसा कि अर्नकोड द्वारा सुझाए गए अनुसार मैंने निम्नलिखित परिवर्तन किए हैं। Object.create से ऑब्जेक्ट से हटाया गया। सेवा में सक्षम और नियंत्रक में शेड्यूलर का पुन: उपयोग किया, लेकिन फिर भी मुझे एक ही परिणाम मिलते हैं।

+0

आप 'Observable.fromCallable' बजाय' Observable.create' का उपयोग करें सकते हैं? 'निर्माण' का आपका उपयोग अजीब लगता है। इसके अलावा, थ्रेड स्लीप नींद की मात्रा exaclty की गारंटी नहीं देता है लेकिन ओएस पर निर्भर करता है। 'GetVideoInfoAsync' में आप अनावश्यक रूप से शेड्यूलर रैपर बना रहे हैं। – akarnokd

+0

हाय अर्कनोक, आपकी टिप्पणी के लिए धन्यवाद। कुछ चीजें, Observable.create का उपयोग करने में क्या गलत है? इसके अलावा मुझे "शेड्यूलर रैपर बनाने और ओवर" बनाने का मतलब नहीं मिलता है। इसे लागू करने के लिए मैं पीछा किया मैं क्या देखा [यहाँ dzone में] (https://dzone.com/articles/rx-java-subscribeon-and) – codependent

+0

आप एक शुरुआत के लिए s.onCompleted(), लेकिन कमी कॉल नहीं करते सदस्यता रद्द करने का भी समस्याग्रस्त हो सकता है। इसके अतिरिक्त, आपको देखना चाहिए कि विफलता क्या है जो प्रदर्शन हानि के स्रोत को भी इंगित कर सकती है। आप एक सदस्य क्षेत्र के रूप में एक TaskExecutor है, लेकिन उसके बाद आप 'getVideoInfoAsync' के हर मंगलाचरण जो मेरा अनुमान है कि सैकड़ों बार एक दूसरे होता है के लिए Scheduler.wrap साथ लपेट। – akarnokd

उत्तर

4

समस्या कुछ बिंदु पर एक प्रोग्रामिंग त्रुटि की वजह से किया गया था। दरअसल सवाल में उदाहरण पूरी तरह से काम करता है। समस्या हो रही से दूसरों को रोकने

एक चेतावनी: Observable.just(func) का उपयोग कर से सावधान, समारोह वास्तव में प्रत्यक्ष निर्माण पर कहा जाता है। इसलिए किसी भी Thread.Sleep रखा बुला धागा

@Override 
public Observable<List<Data>> loadDataObservable() { 
    return Observable.just(generateData()).delay(500, TimeUnit.MILLISECONDS); 
} 

private List<Data> generateData(){ 
    List<Data> dataList = new ArrayList<Data>(); 
    for (int i = 0; i < 20; i++) { 
     Data data = new Data("key"+i, "value"+i); 
     dataList.add(data); 
    } 
    return dataList; 
} 

वहाँ अवरुद्ध कर देगा मैं RxJava Google group में एक चर्चा शुरू कर दिया है, जहां वे मुझे इस पर काम में मदद की।

+1

तो, अंतिम परिणाम क्या है? – Rekin

+1

नतीजा यह है कि अवलोकन योग्य प्रदर्शन केवल कॉल करने योग्य उपयोग से थोड़ा बेहतर है। – codependent

संबंधित मुद्दे