当前位置: 首页 > 知识库问答 >
问题:

如何提高单核cpu反应式编程的性能

锺离刚洁
2023-03-14

我有一个连接到第三方服务并将结果返回给客户端的应用程序。在内部,应用程序向第三方服务发出GET请求并获取结果。我已经使用Reactor和reactive代码在重负载下扩展应用程序。这是一个SpringBoot项目,它运行嵌入式Tomcat并依赖于Web客户端(被动netty向第三方发出请求)。不知何故,CPU利用率和响应时间都比阻塞模式差。硬件设置在Kubernetes中运行单核。

该项目建立在库伯内特斯内部,在一个核心的单吊舱上运行。我尝试以反应性的方式,但应用程序是慢得多,甚至CPU利用率高时,与阻塞架构相比。

 public Mono<ResponseEntity<?>> get(HttpServletRequest request)
   {
      return Mono.create ( callback -> {
         Mono<Response> response = Make HTTP GET Call using webClient.
         response.subscribe(response -> {
         callback.success(response);
         },error -> {
         callback.error(error);
         }
       });
    }

在传统的阻塞模式下,当采用反应式方法时,我可以看到更好的性能和更低的CPU使用率。造成这种差异的原因可能是什么?因为只有一个核心,这是因为上下文切换吗?如果是,我们如何通过单核架构获得更好的性能

共有2个答案

邹英发
2023-03-14

在整个反应链中应该只有一个订阅。尽可能地推迟——最后一次订阅。让我们重新编写您的代码:

public Mono<ResponseEntity<?>> get(HttpServletRequest request) {
      return Mono.just(requestObject)
                 .flatmap(a -> makeAsyncCall(a))
                 .doOnError(err -> doSomethingOnError());
}

你可以订阅你在哪里开始你的反应链。通常,这将是控制器。

这将是:

Mono.just(request)
    .flatMap(request -> get(request))
    .subscribe(response -> setDeferredResult(response));

return deferredResult;
司英飙
2023-03-14

我真的不明白你为什么在中间订阅来提取响应。订阅我认为是一个昂贵的过程,只应该由调用客户端完成一次。

这是一个例子,说明我将如何使用doOnError方法来处理错误和映射响应。

public Mono<Foo> bar() {
    return client.get()
            .uri("/something")
            .accept(MediaType.APPLICATION_JSON)
            .exchange()
            .flatMap(response -> response.bodyToMono(Foo.class))

}

public Mono<Bar> foo() {
    return bar()
        .flatMap(stuff -> {
         return // Map it here to something else that 
                // is getting returned to the calling client
        })
        .doOnError(FooBarException::new);
 类似资料:
  • 我知道当一个分支很容易预测时,最好使用IF语句,因为分支是完全自由的。我了解到,如果分支不容易预测,那么CMOV会更好。但是,我不太明白如何实现这一点? 问题域肯定还是一样的——我们不知道下一条要执行的指令的地址?因此,我不明白在整个管道中,当执行CMOV时,它是如何帮助指令获取器(过去有10个CPU周期)选择正确的路径并防止管道暂停的? 有人能帮我了解一下CMOV是如何改进分支的吗?

  • 1 程序员需要什么技能? 编程技巧和熟练度 软件工程 拓宽眼界 交流沟通 2 如何一步步提高技能? 3 参考

  • (在单CPU的情况下)为了理解volatile——我知道volatile强制线程使用主内存,并且不会将副本保留在其本地内存中。 在一篇StackOverFlow帖子中,我看到java线程使用CPU缓存,而使用volatile则会强制使用主内存 线程缓存和Java内存模型。 如果是这种情况,那么应该没有内存可见性的问题,因为一个线程可以看到其他线程写的值(假设在单个核心CPU上,我们将有单个缓存)。

  • 我对将CPU密集型web应用部署到Azure应用程序服务实例很感兴趣。我找不到有关Azure应用程序服务的CPU使用率和/或限制的任何详细信息。我担心的是,如果不了解我的应用程序的CPU规格/限制,我就无法规划如何准确规划基于云的物理基础设施(使用Azure应用程序服务)。 我的应用程序将使用OpenCV计算机视觉库对数百/数千张高质量图像进行重图像处理、人脸检测和人脸识别。这自然是一个CPU密集

  • 我开始更多地接受反应式编程,并试图将其应用于我的典型业务问题。我经常使用的一种模式是数据库驱动类。我有一些已定义的单元类,如ActionProfile,其实例由ActionProfileManager管理,它从数据库表中创建实例并将其存储在映射中 然而,如果我想让它更具反应性,那么创建地图会打破单子。我可以做的一种方法是将映射本身设置为可观察的,并返回一个monad来为客户端查找特定的键。然而,中

  • 反应式编程是一种编程范式,用于处理数据流和变化的传播。 这意味着当一个组件发出数据流时,更改将通过响应式编程库传播到其他组件。 变化的传播将持续到最终接收器。 事件驱动和反应式编程之间的区别在于事件驱动的编程围绕事件而反应式编程围绕数据。 ReactiveX或RX用于反应式编程 ReactiveX或Raective Extension是最着名的反应式编程实现。 ReactiveX的工作取决于以下两