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

Spring Webflux-服务器/客户端线程的使用

怀经赋
2023-03-14

我正在用Netty玩Spring Webflux(2.0.3.Release),并试图理解服务器和web客户端是如何使用线程的。我用WebClient编写了一些带有http调用链的代码。我怀疑所有调用都是非阻塞的,但我不明白为什么只有一个请求经过整个链路。下面是代码和日志输出:

public class DemoApplication {

private WebClient webclient = WebClient.create("http://localhost:8080/");

public static void main(String[] args) throws Exception {
    new DemoApplication().startServer();
}

public void startServer() throws Exception {
    RouterFunction<ServerResponse> route = routingFunction();
    HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
    ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
    HttpServer server = HttpServer.create("127.0.0.1", 8080);
    server.newHandler(adapter).block();
    Thread.sleep(1000000);
}

public RouterFunction<ServerResponse> routingFunction() throws Exception {
    return route(path("/1"), req -> ok().body(fromPublisher(get1(), String.class)))
            .andRoute(path("/2"), req -> ok().body(fromPublisher(get2(), String.class)))
            .andRoute(path("/3"), req -> ok().body(fromPublisher(get3(), String.class)));
}

public Mono<String> get1() {
    System.out.println("---------REQUEST---------");
    System.out.println("1: " + Thread.currentThread());
    return webclient.get().uri("2").retrieve().bodyToMono(String.class);
}

public Mono<String> get2() {
    System.out.println("2: " + Thread.currentThread());
    return webclient.get().uri("3").retrieve().bodyToMono(String.class);
}

public Mono<String> get3() {
    System.out.println("3: " + Thread.currentThread());
    try {
        Thread.sleep(1250000); // simulate thread somehow got blocked
    } catch (InterruptedException e) {

    }
    return Mono.just("test");
}
}

我对localhost:8080/1进行了4次调用,并得到以下输出。只有一个请求到达了第三个方法。我希望当一个线程被阻塞时,其他三个线程将能够处理其他请求,但它们没有。整个线程池由4个线程组成(与核心数相同)。

---------REQUEST---------
1: Thread[reactor-http-nio-2,5,main]
2: Thread[reactor-http-nio-4,5,main]
3: Thread[reactor-http-nio-2,5,main]
---------REQUEST---------
1: Thread[reactor-http-nio-3,5,main]
2: Thread[reactor-http-nio-1,5,main]
---------REQUEST---------
1: Thread[reactor-http-nio-3,5,main]
2: Thread[reactor-http-nio-1,5,main]
---------REQUEST---------
1: Thread[reactor-http-nio-3,5,main]
2: Thread[reactor-http-nio-1,5,main]

共有1个答案

魏翰
2023-03-14

您已经知道了这一点,但是其他开发人员读到了这一点:您永远不应该在Reactor应用程序中使用阻塞操作--或者如果您使用了阻塞操作,您应该在弹性调度器上调度这些工作,并注意权衡。

如果您想模拟一个需要很长时间响应的远程服务,可以使用delay*运算符,而不必人为地阻塞线程。在本例中,我想您希望模拟这样一个事实,即应用程序的一部分在反应管道中使用阻塞I/O。

我认为您在这里看到的行为与服务器正在调用自己以及WebClient和Netty服务器共享相同的EventLoopGroup有关。我不知道在那种情况下工作偷窃的实现细节。

@Bean
public RouterFunction<ServerResponse> routingFunction() throws Exception {
    return route(all(), this::handler);
}

Mono<ServerResponse> handler(ServerRequest request) {
    System.out.println("---------REQUEST---------");
    System.out.println(Thread.currentThread());
    try {
        Thread.sleep(1250000); // simulate thread somehow got blocked
    } catch (InterruptedException e) {

    }
    return ServerResponse.ok().build();
} 

在本例中,使用curl客户机调用该服务器会显示如下行为(在8核笔记本电脑上)。

---------REQUEST---------
Thread[reactor-http-nio-2,5,main]
---------REQUEST---------
Thread[reactor-http-nio-3,5,main]
---------REQUEST---------
Thread[reactor-http-nio-4,5,main]
---------REQUEST---------
Thread[reactor-http-nio-5,5,main]
---------REQUEST---------
Thread[reactor-http-nio-6,5,main]
---------REQUEST---------
Thread[reactor-http-nio-7,5,main]
---------REQUEST---------
Thread[reactor-http-nio-8,5,main]
---------REQUEST---------
Thread[reactor-http-nio-1,5,main]
 类似资料:
  • 问题内容: 我正在尝试使用我一直在努力的客户端/服务器程序实现多线程。我需要允许多个客户端同时连接到服务器。我目前有4类:客户端,服务器,协议和用于处理线程的工作器。以下代码是我对这些类的拥有的代码: SocketServer类: SocketClient类别: 协议类别: ClientWorker类: 当我运行服务器和客户端时,一切正常。然后,当我尝试运行另一个客户端时,它只是挂在那儿,没有提示

  • 我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我最初的想法如下: 我在服务器上制作了一个中央服务器插座,所有应用程序都可以连接到该插座。此ServerSocket跟踪已连接的套接字(客户端),并将新连接的客户端的IP和端口提供给所有其他客户端。每个客户端都会创建一个新的ServerSocket,所有客户端都可以连接到它。 换句话说:每个客户端都有一个Se

  • 问题内容: 服务器和客户端使用我自己的协议(类似于XMPP)进行通信。我应该实现聊天应用程序。因此,当一个用户写String时,应该立即将其通过服务器发送给其他客户端。我在服务器上有sendToAll方法。但是用户只有在按Enter时才能看到其他用户的消息。 用户如何在不按Enter键的情况下接收消息? 这是我的客户: 和带有ServerThread的服务器。 ServerThread。 问题答案

  • 服务器和客户端使用我自己的协议进行通信,看起来像XMPP。我应该实现聊天应用。因此,当一个用户编写String时,它应该立即通过服务器发送给其他客户端。我在服务器上有sendToAll方法。但用户只有在按下回车键时才能看到其他用户的消息。用户如何在不按回车键的情况下接收消息? 这是我的客户: 以及带有ServerThread的服务器。 服务器线程。

  • 您好,我正在尝试从计算机中的本地客户端连接我的服务器。我有一个远程服务器正在运行。。当我从Netbeans运行代码时,一切都正常。。。当我从CMD尝试时,我得到了这个错误 Java语言com上的lang.NullPointerException。太阳企业命名。实施。SerialContext。com上的getORB(SerialContext.java:347)。太阳企业命名。实施。SerialC