美文网首页
为何现在响应式编程在业务开发微服务开发不普及

为何现在响应式编程在业务开发微服务开发不普及

作者: 干货满满张哈希 | 来源:发表于2021-02-08 03:19 被阅读0次

为何现在响应式编程在业务开发微服务开发不普及

主要因为数据库 IO,不是 NIO。

不论是Java自带的Future框架,还是 Spring WebFlux,还是 Vert.x,他们都是一种非阻塞的基于Ractor模型的框架(后两个框架都是利用netty实现)。

在阻塞编程模式里,任何一个请求,都需要一个线程去处理,如果io阻塞了,那么这个线程也会阻塞在那。但是在非阻塞编程里面,基于响应式的编程,线程不会被阻塞,还可以处理其他请求。举一个简单例子:假设只有一个线程池,请求来的时候,线程池处理,需要读取数据库 IO,这个 IO 是 NIO 非阻塞 IO,那么就将请求数据写入数据库连接,直接返回。之后数据库返回数据,这个链接的 Selector 会有 Read 事件准备就绪,这时候,再通过这个线程池去读取数据处理(相当于回调),这时候用的线程和之前不一定是同一个线程。这样的话,线程就不用等待数据库返回,而是直接处理其他请求。这样情况下,即使某个业务 SQL 的执行时间长,也不会影响其他业务的执行。

但是,这一切的基础,是 IO 必须是非阻塞 IO,也就是 NIO(或者 AIO)。官方JDBC没有 NIO,只有 BIO 实现。这样无法让线程将请求写入链接之后直接返回,必须等待响应。但是也就解决方案,就是通过其他线程池,专门处理数据库请求并等待返回进行回调,也就是业务线程池 A 将数据库 BIO 请求交给线程池B处理,读取完数据之后,再交给 A 执行剩下的业务逻辑。这样A也不用阻塞,可以处理其他请求。但是,这样还是有因为某个业务 SQL 的执行时间长,导致B所有线程被阻塞住队列也满了从而A的请求也被阻塞的情况,这是不完美的实现。真正完美的,需要 JDBC 实现 NIO。

Java 自带的 Future 框架可以这么用JDBC:

@GetMapping
public DeferredResult<Result> get() {
DeferredResult<Result> deferredResult = new DeferredResult<>();
CompletableFuture.supplyAsync(() -> {
            return 阻塞数据库IO;
        //dbThreadPool用来处理阻塞的数据库IO
        }, dbThreadPool).thenComposeAsync(result -> {
    //spring 的 DeferredResult 来实现异步回调写入结果返回
    deferredResult.setResult(result);
});
return deferredResult;
}

WebFlux 也可以使用阻塞JDBC,但是同理:

@GetMapping
public Mono<Result> get() {
return Mono.fromFuture(CompletableFuture.supplyAsync(() -> {
            return 阻塞数据库IO;
        //dbThreadPool用来处理阻塞的数据库IO
        }, dbThreadPool));
}

Vert.x 也可以使用阻塞的JDBC,也是同理:

@GetMapping
public  DeferredResult<Result> get() {
DeferredResult<Result> deferredResult = new DeferredResult<>();
getResultFromDB().setHandler(asyncResult -> {
            if (asyncResult.succeeded()) {
                deferredResult.setResult(asyncResult.result());
            } else {
                deferredResult.setErrorResult(asyncResult.cause());
            }
        });
return deferredResult;
}

private WorkerExecutor dbThreadPool = vertx.createSharedWorkerExecutor("DB", 16);

private Future<Result> getResultFromDB() {
    Future<Result> result = Future.future();
    dbThreadPool.executeBlocking(future -> {
            return 阻塞数据库IO;
        }, false, asyncResult -> {
            if (asyncResult.succeeded()) {
                result.complete(asyncResult.result());
            } else {
                result.fail(asyncResult.cause());
            }
        });
    return result;
}

相当于通过另外的线程池(当然也可以通过原有线程池,反正就是要用和请求不一样的线程,才能实现回调,而不是当次就阻塞等待),封装了阻塞 JDBC IO。

但是,这样几乎对数据库IO主导的应用性能没有提升,还增加了线程切换,得不偿失。所以,需要使用真正实现了 NIO 的数据库客户端。目前有这些 NIO 的 JDBC 客户端,但是都不普及:

  1. Vert.x 客户端:https://vertx.io/docs/vertx-jdbc-client/java/
  2. r2jdbc 客户端:http://r2dbc.io/
  3. Jasync-sql 客户端:https://github.com/jasync-sql/jasync-sql

相关文章

  • 为何现在响应式编程在业务开发微服务开发不普及

    为何现在响应式编程在业务开发微服务开发不普及 主要因为数据库 IO,不是 NIO。 不论是Java自带的Futur...

  • RectiveCocoa的学习(一)

    RectiveCocoa 的代码风格 函数式编程 响应式编程 ReactiveCocoa在iOS开发时的作用有:替...

  • iOS函数响应式编程RAC基本用法收集

    前言 iOS函数响应式编程以及ReactiveCocoa的使用已经是普及的开发中里面常见用到的技能,本文只意在收集...

  • 前端随笔

    响应式编程 响应式编程【Reactive Programming】依赖事件? 回调?在响应式编程里,按时间排列的事...

  • 探究flutter中的Builder和StatefulBuild

        flutter开发的官方推荐是响应式编程,响应式编程简单理解是数据流变化自动驱动view层刷新的一种开发方...

  • RxSwift初探(1)

    一、前提:函数响应式编程思想 简单来说 函数响应式编程 = 函数式编程 + 响应式编程 (1)函数式 函数式编程是...

  • 响应式架构简介

    为什么企业级软件难以开发   在介绍响应式编程技术会使软件开发工作变得简单之前,让我们先了解一下开发企业级软件为何...

  • Angular表单验证

    angular4里一个响应式编程的小例子 Angular2 响应式表单验证 Angular开发(十一)-关于响应式...

  • SpringFlux入门(上篇)

    SpringBoot WebFlux 什么是响应式编程 什么是flux 开始fluxflux为开发人员提供了两种开...

  • Swift5.0 - day13 - 响应式编程

    一、响应式编程 1.1、响应式编程(Reactive Programming,简称RP)响应式编程是一种编程范式,...

网友评论

      本文标题:为何现在响应式编程在业务开发微服务开发不普及

      本文链接:https://www.haomeiwen.com/subject/iqqxxltx.html