- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在执行一些测试,以评估使用基于 Observables 的响应式(Reactive) API 而非传统的阻塞式 API 是否具有真正的优势。
整个例子是available on Githug
令人惊讶的结果表明thoughput结果是:
最好的:返回包装阻塞操作的 Callable
/DeferredResult
的 REST 服务。
还不错:阻止 REST 服务。
最差:返回 DeferredResult 的 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);
}
}
同步 Controller :
@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:具有原始的 Callable 和 Observable 端点
@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 with Callable:700 rps,无错误
>>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 rps 但产生错误
>>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 with Observable:不超过 20 rps,更快出错
>>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 也没有任何改善。
有什么解释?
更新:根据 akarnokd 的建议,我进行了以下更改。在服务中从 Object.create 移动到 Object.fromCallable 并在 Controller 中重用了 Scheduler,但我仍然得到相同的结果。
最佳答案
问题是由某个时刻的编程错误引起的。实际上,问题中的示例非常有效。
一个警告,以防止其他人遇到问题:小心使用 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;
}
我在 RxJava Google group 开始讨论他们帮我解决了这个问题。
关于java - 在 Web 应用程序中使用 RxJava Observables 无法解释的缺乏性能改进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34286017/
我不明白为什么我的 Java 代码没有出现错误。我有一个使用泛型类型的类: import java.util.*; // For ArrayList public class Hat { pub
我正在 Pygame 中开发一款射击类游戏供我自己娱乐,在创建玩家的基本 Action 的过程中我遇到了一些疑问,“Dash”和“Switch”均未按预期工作。 ... def switch(self
当我加载一个显示的网页时,为什么我要为每个图像的 HTTP 请求打开一个新的 TCP 连接?为什么在页面加载期间不重复使用单个 TCP 连接? 最佳答案 我认为浏览器通常会打开多个连接,以便它可以并行
我一直在谷歌搜索,只能找到 a trivial example Compute Capability 3.0 中的新动态并行性在其链接的其中一份技术简报中介绍 from here .我知道 HPC 专
我使用 Telerik 和 Microsoft CDN,分别用于它们各自的 AJAX 工具包。两者在 99% 的情况下都工作得很好。然而,我最近在两家不同的咖啡馆工作并访问了我的网站:第一家咖啡馆不允
我在一家从事网络托管的 IT 公司工作,而且我个人对 SQL 非常缺乏经验*。 *看起来很糟糕 我的一个客户正在尝试将 Epos 系统与其 magento 网站集成,在 Epos 集成过程中,他们遇到
我的代码现在有一个循环,它调用蒙特卡洛函数来计算多个样本的简单积分(y=x,从 0 到 1),并将总时间和积分值写入文本文件。然后循环增加线程数并继续前进。现在大约有 8 个线程,时间峰值约为 2.6
所以 HTTP/2 增加了我想要利用的性能。出于各种原因,我不喜欢连接我的 javascript,而 HTTP/2 无论如何都会使它变得不必要。 但是。我正在开发一个将部署在客户本地网络中的网络应用程
我写了一个非常简单的 Haskell 程序: main = print $ sum $ map read ["55", "99", "101"] 鉴于我过去的经验,我预计会得到一个“歧义类型”错误,因
我是一名优秀的程序员,十分优秀!