配置 Spring WebFlux WebClient 以使用自定义线程池
Configuring Spring WebFlux WebClient to use a custom thread pool
是否可以将 WebClient 配置为使用 reactor-http-nio 线程池以外的自定义线程池(使用 Netty 时)?如果可能的话,我们能否以某种方式将自定义线程池限制为 运行 仅在特定处理器内核上?
是的。可以的。
创建一些你自己的线程池和EventLoopGroup(或者创建NioEventLoopGroup bean)。例如:
{
Intger THREADS = 10;
BasicThreadFactory THREADFACTORY = new BasicThreadFactory.Builder()
.namingPattern("HttpThread-%d")
.daemon(true)
.priority(Thread.MAX_PRIORITY)
.build();
EXECUTOR = new ThreadPoolExecutor(
THREADS,
THREADS,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
THREADFACTORY,
new ThreadPoolExecutor.AbortPolicy());
NioEventLoopGroup RESOURCE= new NioEventLoopGroup(THREADS,EXECUTOR);
}
注册您自己的 ReactorResourceFactory。并提供自己的基于自定义线程Executor的EventLoopGrooup
@Bean
public ReactorResourceFactory reactorResourceFactory(NioEventLoopGroup RESOURCE) {
ReactorResourceFactory f= new ReactorResourceFactory();
f.setLoopResources(new LoopResources() {
@Override
public EventLoopGroup onServer(boolean b) {
return RESOURCE;
}
});
f.setUseGlobalResources(false);
return f;
}
然后注册ReactorClientHttpConnector。在下面的示例中,它使用自定义 SSL Context
@Bean
public ReactorClientHttpConnector reactorClientHttpConnector(ReactorResourceFactory r) throws SSLException {
SslContext sslContext = SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
return new ReactorClientHttpConnector(r, m -> m.secure(t -> t.sslContext(sslContext)));
}
最终构建 WebClient
@Bean
public WebClient webClient(ReactorClientHttpConnector r) {
return WebClient.builder().clientConnector(r).build();
}
如果您想对 WebServer 使用相同的方法。对 ReactiveWebServerFactory 做同样的配置。
@Bean
public ReactiveWebServerFactory reactiveWebServerFactory(NioEventLoopGroup RESOURCE) {
NettyReactiveWebServerFactory factory = new NettyReactiveWebServerFactory();
factory.addServerCustomizers(hs->hs.tcpConfiguration(s->s.runOn(RESOURCE)));
return factory;
}
进口:
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.client.reactive.ReactorResourceFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.resources.LoopResources;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
import java.util.concurrent.*;
是否可以将 WebClient 配置为使用 reactor-http-nio 线程池以外的自定义线程池(使用 Netty 时)?如果可能的话,我们能否以某种方式将自定义线程池限制为 运行 仅在特定处理器内核上?
是的。可以的。
创建一些你自己的线程池和EventLoopGroup(或者创建NioEventLoopGroup bean)。例如:
{ Intger THREADS = 10; BasicThreadFactory THREADFACTORY = new BasicThreadFactory.Builder() .namingPattern("HttpThread-%d") .daemon(true) .priority(Thread.MAX_PRIORITY) .build(); EXECUTOR = new ThreadPoolExecutor( THREADS, THREADS, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), THREADFACTORY, new ThreadPoolExecutor.AbortPolicy()); NioEventLoopGroup RESOURCE= new NioEventLoopGroup(THREADS,EXECUTOR); }
注册您自己的 ReactorResourceFactory。并提供自己的基于自定义线程Executor的EventLoopGrooup
@Bean public ReactorResourceFactory reactorResourceFactory(NioEventLoopGroup RESOURCE) { ReactorResourceFactory f= new ReactorResourceFactory(); f.setLoopResources(new LoopResources() { @Override public EventLoopGroup onServer(boolean b) { return RESOURCE; } }); f.setUseGlobalResources(false); return f; }
然后注册ReactorClientHttpConnector。在下面的示例中,它使用自定义 SSL Context
@Bean public ReactorClientHttpConnector reactorClientHttpConnector(ReactorResourceFactory r) throws SSLException { SslContext sslContext = SslContextBuilder .forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .build(); return new ReactorClientHttpConnector(r, m -> m.secure(t -> t.sslContext(sslContext))); }
最终构建 WebClient
@Bean public WebClient webClient(ReactorClientHttpConnector r) { return WebClient.builder().clientConnector(r).build(); }
如果您想对 WebServer 使用相同的方法。对 ReactiveWebServerFactory 做同样的配置。
@Bean
public ReactiveWebServerFactory reactiveWebServerFactory(NioEventLoopGroup RESOURCE) {
NettyReactiveWebServerFactory factory = new NettyReactiveWebServerFactory();
factory.addServerCustomizers(hs->hs.tcpConfiguration(s->s.runOn(RESOURCE)));
return factory;
}
进口:
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.client.reactive.ReactorResourceFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.resources.LoopResources;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
import java.util.concurrent.*;