服务中的异步处理模型

长期以来,异步处理是我感兴趣的主题之一。 我看到了很多有关该主题的文章,但是我较新的文章看到了(至少简短地)涵盖了大多数文章。 我决定尝试填补这一空白。 下面的描述非常简短,但是尝试至少显示每个模型的基本属性。

Callbacks

This one is, probably one of the oldest and probably most widely used. The idea is obvious - configure callback functions (often called handler) and it will be called when request arrives or some other event happens. There are a lot of uses of this model. Probably most famous one are earlier versions of Node.js. In Java world, older versions of Vert.x is a great example of this model.

在代码中,此模型通常类似于以下内容:

    ... // Prepare request
    request.send(asyncResult -> {
        
      if (asyncResult.succeeded()) {
        
        System.out.println(asyncResult.result().body().getString("joke"));       
      }
    });

Lambda传递给请求发送是一个回调函数,当收到请求响应时调用。

尽管此模型看起来很简单,但是它有一个巨大的缺点-回调是不可组合的。 例如,没有简单的方法来创建将在触发其他两个回调时调用的回调。 结果,任何或多或少的复杂处理都会迅速变成回调地狱。

Reactive Streams

This model is quite popular: implementations like RxJava, Project Reactor, Reactive Streams are widely used.

该模型背后的思想是:传入事件/请求/数据/等的每个来源。 表示为流,然后将处理组装为处理该流中元素的管道。 管道可能非常复杂,并且可以由不同的流组成。

该代码通常如下所示:

Observable.fromIterable(words)
 .zipWith(Observable.range(1, Integer.MAX_VALUE), 
     (string, count)->String.format("%2d. %s", count, string))
 .subscribe(System.out::println);

此模型非常强大且方便。 但是,复杂的处理流可能需要一些时间来掌握,而且并不总是很容易掌握。 另一个缺点是每个数据源(包括单个值)都应表示为流。 这通常看起来是虚假的。

Future

的未来表示可能尚不可用,但最终可用的结果:

Future<Result> futureResult = executor.submit(() -> new Result("success"));

Future is composable (although requires quite a lot of ceremony ) but it's far from convenient. If you need to know when result is ready, you have no choice but just convert asynchronous processing into synchronous one by calling Future.get().

Promises

在高层承诺可以认为是期货和回叫。 什么时候诺言 is get resolved (assigned value) 回叫 are invoked automatically:

...
Promise<User> getUserById(UUID userId);
...

getUserById(userId)
    .then(user -> System.out.println("User: " + user));
...

回调函数传递给。然后()方法将在以下时间被调用诺言将得到解决。 可以添加到的回调数量没有限制诺言,因此当实例通过各种方法传递时,它们可以根据需要添加自己的回调。 如果诺言在添加新的回调时已经解决,该回调将立即被调用。 每个回调仅被调用一次,并且仅在一个线程的上下文中被调用,因此无需担心同步问题。

承诺都是可组合的,代码的编写和读取非常简单。 也没有人为表示数据。

These properties of Promises triggered (slow) switching to them in recent versions of Vert.x, although they look somewhat foreign there because callback-based API remains mostly unchanged, so Promises are just wrappers for callbacks.

还有一个实现承诺自Java 8起就存在于JDK中,并称为未来发展。 必须承认,这种实现方式不能直接替代传统的承诺-它非常重量级,并且具有不方便的API。

Instead of afterword

At present I'm working on the library which implements Promises model in more lightweight and convenient to use form.
To get a taste how code utilizing this library might look like:

    public Promise<Either extends BaseError, UserDashboard>> userProfileHandler(final UUID userId) {
        
        return zipAll(userService.userProfile(userId), 
                      userService.followers(userId), 
                      articleService.articlesByUser(userId, Order.DESC), 
                      commentService.commentsByUser(userId, Order.DESC))
                .map(result -> result.mapSuccess(tuple -> tuple.map(UserDashboard::new)));
    }

上面的代码只是一个示例,库本身具有版本0.1.0,但已经可以使用当前状态的库以这种方式编写代码。

from: https://dev.to//siy/asynchronous-processing-models-in-services-3eba

你可能感兴趣的:(java,开发工具)