1、使用reactor-netty提供的server和client,同时存在

直接来到DefaultLoopResources.java中,可以看到两个方法

    @Override
    public EventLoopGroup onClient(boolean useNative) {
        if (useNative && LoopResources.hasNativeSupport()) {
            return cacheNativeClientLoops();
        }
        return cacheNioClientLoops();
    }
    @Override
    public EventLoopGroup onServer(boolean useNative) {
        if (useNative && LoopResources.hasNativeSupport()) {
            return cacheNativeServerLoops();
        }
        return cacheNioServerLoops();
    }

然后进入cacheNativeClientLoops()中

    EventLoopGroup cacheNativeClientLoops() {
        EventLoopGroup eventLoopGroup = cacheNativeClientLoops.get();
        if (null == eventLoopGroup) {
            EventLoopGroup newEventLoopGroup = LoopResources.colocate(cacheNativeServerLoops());
            if (!cacheNativeClientLoops.compareAndSet(null, newEventLoopGroup)) {
                // Do not shutdown newEventLoopGroup as this will shutdown the server loops
            }
            eventLoopGroup = cacheNativeClientLoops();
        }
        return eventLoopGroup;
    }

可以看到调了cacheNativeServerLoops()方法,实现了与server共用EventLoopGroup.
那么在编程中, 如何指定EventLoopGroup线程数呢?那么请转到reactor.netty.resources.LoopResources中

int DEFAULT_IO_WORKER_COUNT = Integer.parseInt(System.getProperty(
            ReactorNetty.IO_WORKER_COUNT,
            "" + Math.max(Runtime.getRuntime().availableProcessors(), 4)));

其中ReactorNetty.IO_WORKER_COUNT值为"reactor.netty.ioWorkerCount", 那可以简单通过设置这个值来实现:

System.setProperty("reactor.netty.ioWorkerCount", "2");

或者在jvm参数中设置

java -Dreactor.netty.ioWorkerCount=2

2、使用原生的netty启动server,内部使用reactor-netty-client

查看Transport.java

    /**
     * Run IO loops on the given {@link EventLoopGroup}.
     *
     * @param eventLoopGroup an eventLoopGroup to share
     * @return a new {@link Transport} reference
     */
    public T runOn(EventLoopGroup eventLoopGroup) {
        Objects.requireNonNull(eventLoopGroup, "eventLoopGroup");
        return runOn(preferNative -> eventLoopGroup);
    }

可以明确指定EventloopGroup,比如HttpClient场景

        ConnectionProvider provider = ConnectionProvider.builder("name")
                .pendingAcquireTimeout(Duration.ofSeconds(15))
                .maxConnections(500).build();
        EventLoopGroup group = new NioEventLoopGroup(3);
        HttpClient client = HttpClient.create(provider).runOn(group);
        int s = client.responseTimeout(Duration.ofSeconds(2))
                .get()
                .uri("http://127.0.0.1/remote")
                .responseSingle((res, content) -> {
                    System.out.println(Thread.currentThread());
                    return Mono.just(res.status().code());
                }).doOnError(t -> {
                    System.out.println("========error:" + t);
                }).onErrorReturn(3)
                .block();
        System.out.println(s);

可以与其它地方定义好的eventLoopGroup共用, responseTimeout()针对单个请求还是全局呢?先来看一下方法说明:

    /**
     * Specifies the maximum duration allowed between each network-level read operation while reading a given response
     * (resolution: ms). In other words, {@link io.netty.handler.timeout.ReadTimeoutHandler} is added to the channel
     * pipeline after sending the request and is removed when the response is fully received.
     * If the {@code maxReadOperationInterval} is {@code null}, any previous setting will be removed and no
     * {@code maxReadOperationInterval} will be applied.
     * If the {@code maxReadOperationInterval} is less than {@code 1ms}, then {@code 1ms} will be the
     * {@code maxReadOperationInterval}.
     * The {@code maxReadOperationInterval} setting on {@link HttpClientRequest} level overrides any
     * {@code maxReadOperationInterval} setting on {@link HttpClient} level.
     *
     * @param maxReadOperationInterval the maximum duration allowed between each network-level read operations
     *                                 (resolution: ms).
     * @return a new {@link HttpClient}
     * @since 0.9.11
     * @see io.netty.handler.timeout.ReadTimeoutHandler
     */
    public final HttpClient responseTimeout(@Nullable Duration maxReadOperationInterval) {
        if (Objects.equals(maxReadOperationInterval, configuration().responseTimeout)) {
            return this;
        }
        HttpClient dup = duplicate();
        dup.configuration().responseTimeout = maxReadOperationInterval;
        return dup;
    }

然后来实际验证一下:

    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.create().responseTimeout(Duration.ofSeconds(5));
        int s = client.responseTimeout(Duration.ofSeconds(2))
                .get()
                .uri("http://127.0.0.1:1701/abc")
                .responseSingle((res, content) -> {
                    System.out.println(Thread.currentThread());
                    return Mono.just(res.status().code());
                }).doOnError(t -> {
                    System.out.println("========error:" + t);
                }).onErrorReturn(3)
                .block();
        System.out.println(s);

        int s2 = client
                .get()
                .uri("http://127.0.0.1:1701/abc")
                .responseSingle((res, content) -> {
                    System.out.println(Thread.currentThread());
                    return Mono.just(res.status().code());
                }).doOnError(t -> {
                    System.out.println("========error:" + t);
                }).onErrorReturn(3)
                .block();
        System.out.println(s2);


        TimeUnit.SECONDS.sleep(10);
    }

从实践中来看, 是全局的, 但也可以单次设置, 要注意源码中的一行
HttpClient dup = duplicate();


supermassive
1 声望1 粉丝