使用 Vert.x 异步发送HTTP长阻塞请求来提高并发响应

news/2024/11/23 23:10:52/

假设我们开发了一个必须与其他HTTP服务来交互的服务。不幸的是,这些HTTP服务速度慢且是阻塞的。

它可能是一个非常慢的遗留HTTP服务或我们必须使用的一些阻塞 API。无论如何,我们无法控制它。在这里,我们将调用两个HTTP API。其中一个将阻塞2秒钟,另一个将阻塞5秒钟。

一旦两个响应都可用,我们还需要打印响应状态代码。如果我们以老的、非异步反应性方式执行此操作,我们将阻塞调用线程5秒钟。阻塞线程 5 秒效率不高,不是吗?现在就叫你如何使用 Vert.x 异步发送HTTP长阻塞请求来提高并发响应!

服务

我使用“httpstat.us”作为网络服务。这是一个简单的服务,用于生成不同的HTTP代码来测试Web客户端。可以提供额外的参数,在本例中为 sleep ,在规定的时间内阻塞 HTTP 请求。

我将使用“httpie”来测试这两种服务。

服务 1 将阻塞5秒钟,并返回状态代码为 200 的响应:

http://httpstat.us/200?sleep=5000
_____________________________________________HTTP/1.1 200 OK
Content-Length: 6
Content-Type: text/plain
Date: Tue, 08 Mar 2022 17:05:08 GMT
Request-Context: appId=cid-v1:1e93d241-20e4-4513-bbd7-f452a16a5d69
Server: Kestrel
Set-Cookie: ARRAffinity=e2c17206c539113795daf64bd958d003f2b29b9f62da53617beea05468875ba5;Path=/;HttpOnly;Domain=httpstat.us200 OK

服务 2 与前一个相同,只是它阻塞了2秒而不是5秒:

http://httpstat.us/200?sleep=2000
_____________________________________________HTTP/1.1 200 OK
Content-Length: 6
Content-Type: text/plain
Date: Tue, 08 Mar 2022 17:11:53 GMT
Request-Context: appId=cid-v1:1e93d241-20e4-4513-bbd7-f452a16a5d69
Server: Kestrel
Set-Cookie: ARRAffinity=e2c17206c539113795daf64bd958d003f2b29b9f62da53617beea05468875ba5;Path=/;HttpOnly;Domain=httpstat.us200 OK

Web 客户端

我们已经了解了服务。现在,让我们讨论 Web 客户端。现在,我将使用 Vert.x Web 客户端。它是一个异步的,易于使用的 HTTPHTTP/2 客户端.

  private static Future<Integer> service1(WebClient webClient) {return webClient.getAbs("http://httpstat.us/200?sleep=5000").send().onSuccess(response -> System.out.println(MessageFormat.format("[{0}] service 1: response received", Thread.currentThread().getName()))).compose(response -> Future.succeededFuture(response.statusCode()));}private static Future<Integer> service2(WebClient webClient) {return webClient.getAbs("http://httpstat.us/200?sleep=2000").send().onSuccess(response -> System.out.println(MessageFormat.format("[{0}] service 2 response received", Thread.currentThread().getName()))).compose(response -> Future.succeededFuture(response.statusCode()));}

这两种方法非常相似。它们将 WebClient 作为参数并发送返回 Future<Integer> 的 HTTP 请求。其中整数是 HTTP 响应代码。返回的 Future<Integer> 向我们保证结果是异步的。状态代码在稍后可用时将给出回调。

我们需要组合两个Future。使用 Vert.x的 CompositeFuture 可以实现多个future的协调. 它支持并发组合(并行运行多个异步操作)和顺序组合(链式异步操作).

    Future<Integer> service1Code = service1(webClient);Future<Integer> service2Code = service2(webClient);CompositeFuture.all(service1Code, service2Code).onSuccess(ar -> {printResult(ar);countDownLatch.countDown();});

合在一起

最后,我们可以将所有的点点滴滴放在一起,如下所示:

import java.text.MessageFormat;
import java.util.concurrent.CountDownLatch;import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.ext.web.client.WebClient;public class Services {public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(1);// Vertx instance and web clientVertx     vertx     = Vertx.vertx();WebClient webClient = WebClient.create(vertx);Future<Integer> service1Code = service1(webClient);Future<Integer> service2Code = service2(webClient);CompositeFuture.all(service1Code, service2Code).onSuccess(ar -> {printResult(ar);countDownLatch.countDown();});vertx.setPeriodic(1000, l -> System.out.println("[" + Thread.currentThread().getName() + "] is released"));countDownLatch.await();vertx.close();}private static Future<Integer> service1(WebClient webClient) {return webClient.getAbs("http://httpstat.us/200?sleep=5000").send().onSuccess(response -> System.out.println(MessageFormat.format("[{0}] service 1: response received", Thread.currentThread().getName()))).compose(response -> Future.succeededFuture(response.statusCode()));}private static Future<Integer> service2(WebClient webClient) {return webClient.getAbs("http://httpstat.us/200?sleep=2000").send().onSuccess(response -> System.out.println(MessageFormat.format("[{0}] service 2 response received", Thread.currentThread().getName()))).compose(response -> Future.succeededFuture(response.statusCode()));}private static void printResult(CompositeFuture compositeFuture) {System.out.println(Thread.currentThread().getName() + " Result: service1:" + compositeFuture.resultAt(0) + " service2:" + compositeFuture.resultAt(1));}
}

下面是运行代码后打印在控制台上的结果。这两个请求都是从同一个 vertx 事件循环线程调度的。该程序还会每秒打印线程未被阻止的消息。最后,它将打印两个状态代码作为最终结果。如您所见,一切都发生在同一个线程上:

[vert.x-eventloop-thread-1] is released
[vert.x-eventloop-thread-1] is released
[vert.x-eventloop-thread-1] service 2 response received
[vert.x-eventloop-thread-1] is released
[vert.x-eventloop-thread-1] is released
[vert.x-eventloop-thread-1] is released
[vert.x-eventloop-thread-1] service 1: response received
[vert.x-eventloop-thread-1] Result: service1:200 service2:200

总结

这就是我目前所要讨论的全部内容。我希望这篇文章能帮助您现在对如何使用 Vert.x 异步发送长阻塞请求有了更好的理解。


http://www.ppmy.cn/news/63653.html

相关文章

8.最长公共子序列问题

title: 8.最长公共子序列问题 date: 2023-05-02 15:52:40 categories: 大学课程内容大二下算法分析基础 8.最长公共子序列问题 【问题描述】 若给定序列X{x1,x2,…,xm}&#xff0c;则另一序列Z{z1,z2,…,zk}&#xff0c;是X的子序列是指存在一个严格递增下标序列{i1,i2,…,i…

前端学习之使用JavaScript(3)

BOM BOM BOM&#xff08;Browser Object Model&#xff0c;浏览器对象模型&#xff09;是JavaScript中用于与浏览器窗口及其元素进行交互的API。 BOM提供了一系列对象&#xff0c;这些对象代表了浏览器的不同部分&#xff0c;使得开发者能够控制浏览器的各种功能&#xff0c;如…

qt creator添加build步骤删除某个文件

参考&#xff1a;https://blog.csdn.net/weixin_44436546/article/details/113587115 1. windows下配置&#xff1a; 添加build步骤&#xff1b;在commad栏输入cmd,会弹出C:\Windows\system32\cmd.exe&#xff1b;在Arguments栏输入/c release\upgrade.o&#xff1b;Working …

原型模式--深拷贝和浅拷贝

定义 Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype. &#xff08;使用原型实例指定将要创建的对象类型&#xff0c;通过复制这个实例创建新的对象。&#xff09; 从定义中我们我们可以发现&#x…

基数树RadixTree

转自&#xff1a;基数树RadixTree - 知乎 1. 基数树概述 对于长整型数据的映射&#xff0c;如何解决Hash冲突和Hash表大小的设计是一个很头疼的问题。radix树就是针对这种稀疏的长整型数据查找&#xff0c;能快速且节省空间地完成映射。借助于Radix树&#xff0c;我们可以实现…

SpringBoot整合接口管理工具Swagger

Swagger Swagger简介 Springboot整合swagger Swagger 常用注解 一、Swagger简介 ​ Swagger 是一系列 RESTful API 的工具&#xff0c;通过 Swagger 可以获得项目的⼀种交互式文档&#xff0c;客户端 SDK 的自动生成等功能。 ​ Swagger 的目标是为 REST APIs 定义一个标…

嵌入式软考备考_5 安全性基础知识

安全性基础知识 网安问题概述 被动攻击&#xff1a;监听&#xff08;截获&#xff09;。 主动攻击&#xff1a;主动破坏&#xff08;中断篡改&#xff0c;病毒&#xff0c;ddos使得某个服务拒绝服务&#xff0c;重放攻击&#xff1a;黑客截取了正常用户输入用户名密码的加密…

Spring Boot 整合 Swagger 教程详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…