Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Web应用程序中使用RxJava可观测项无法解释的性能改进不足_Java_Reactive Programming_Rx Java_Netflix - Fatal编程技术网

在Web应用程序中使用RxJava可观测项无法解释的性能改进不足

在Web应用程序中使用RxJava可观测项无法解释的性能改进不足,java,reactive-programming,rx-java,netflix,Java,Reactive Programming,Rx Java,Netflix,我正在执行一些测试,以评估使用基于可观察的反应式API,而不是阻塞传统API是否有真正的优势 整个例子是 令人惊讶的是,结果显示,thoughput结果如下: 最佳:返回包装阻塞操作的可调用/延迟结果的REST服务 还不错:阻止REST服务 最差的:返回延迟结果的REST服务,其结果由RxJava Observable设置 这是我的Spring WebApp: 应用程序: @SpringBootApplication public class SpringNioRestApplication

我正在执行一些测试,以评估使用基于可观察的反应式API,而不是阻塞传统API是否有真正的优势

整个例子是

令人惊讶的是,结果显示,thoughput结果如下:

  • 最佳:返回包装阻塞操作的
    可调用
    /
    延迟结果
    的REST服务

  • 还不错:阻止REST服务

  • 最差的:返回延迟结果的REST服务,其结果由RxJava Observable设置

这是我的Spring WebApp:

应用程序

@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);
    }
}
@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();
    }
}
同步控制器

@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);
    }
}
@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();
    }
}
阻塞:大约404 RPM,但会产生错误

>>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
与可观察的异步不超过20 rpm,并更快地获取错误

>>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 
Observable以10的corePoolSize执行,但将其增加到50也没有任何改善

原因是什么


更新:根据阿卡诺克的建议,我做了以下更改。在服务中从Object.create移动到Object.fromCallable,并在控制器中重新使用了调度程序,但仍然得到了相同的结果。

该问题是由某个点的编程错误引起的。实际上,问题中的例子非常有效

防止其他人出现问题的一个警告是:当心使用
Observable.just(func)
,func实际上是在创建Observable时调用的。因此,放置在那里的任何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;
}
@覆盖
公共可观察负载DataObservable(){
返回Observable.just(generateData()).delay(500,TimeUnit.ms);
}
私有列表生成数据(){
List dataList=new ArrayList();
对于(int i=0;i<20;i++){
数据数据=新数据(“键”+i,“值”+i);
dataList.add(数据);
}
返回数据列表;
}

我在他们帮助我解决问题的地方开始了讨论。

你能用
可观察的。fromCallable
代替
可观察的。创建
?您对
create
的使用似乎有些奇怪。此外,Thread.sleep不能保证精确的睡眠量,但取决于操作系统。在
getVideoInfoAsync
中,您正在不必要地反复创建调度程序包装。您好,阿卡诺克,谢谢您的评论。有几件事,使用Observable.create有什么不对?我也不明白你所说的“一遍又一遍地创建调度器包装器”是什么意思。为了实现它,我遵循了我所看到的,一开始不调用s.onCompleted(),但是缺少处理取消订阅也可能有问题。此外,您应该了解故障是什么,这也可能表明性能损失的来源。您有一个TaskExecutor作为成员字段,但随后使用Scheduler.wrap对
getVideoInfoAsync
的每次调用进行包装,我猜每秒会发生数百次。嗯,我还在原始示例中添加了
s.onCompleted()
,但也没有改进。我在控制台中看到的唯一错误是
o.a.c.c.c.[Tomcat].[localhost]:异常处理错误页[errorCode=0,location=/error]java.lang.IllegalStateException:提交响应后无法转发
我会将observable更改为observable.just并返回一些模拟对象,以排除RxJava的任何缺陷。由于RxJava不做网络,我想您应该有一个框架来做它。根据错误消息,这个框架可能配置错误、过时或只是有缺陷。那么,最终结果是什么呢?结果是Observable的性能比使用Callable略好。
@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;
}