This paper mainly studies the NettyConfiguration of spring cloud gateway
NettyConfiguration
@Configuration @ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true) @EnableConfigurationProperties @AutoConfigureBefore(HttpHandlerAutoConfiguration.class) @AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class}) @ConditionalOnClass(DispatcherHandler.class) public class GatewayAutoConfiguration { @Configuration @ConditionalOnClass(HttpClient.class) protected static class NettyConfiguration { @Bean @ConditionalOnMissingBean public HttpClient httpClient(@Qualifier("nettyClientOptions") Consumer<? super HttpClientOptions.Builder> options) { return HttpClient.create(options); } @Bean public Consumer<? super HttpClientOptions.Builder> nettyClientOptions(HttpClientProperties properties) { return opts -> { // configure ssl HttpClientProperties.Ssl ssl = properties.getSsl(); if (ssl.isUseInsecureTrustManager()) { opts.sslSupport(sslContextBuilder -> { sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); }); } // configure pool resources HttpClientProperties.Pool pool = properties.getPool(); if (pool.getType() == DISABLED) { opts.disablePool(); } else if (pool.getType() == FIXED) { PoolResources poolResources = PoolResources.fixed(pool.getName(), pool.getMaxConnections(), pool.getAcquireTimeout()); opts.poolResources(poolResources); } else { PoolResources poolResources = PoolResources.elastic(pool.getName()); opts.poolResources(poolResources); } // configure proxy if proxy host is set. HttpClientProperties.Proxy proxy = properties.getProxy(); if (StringUtils.hasText(proxy.getHost())) { opts.proxy(typeSpec -> { ClientProxyOptions.Builder builder = typeSpec .type(ClientProxyOptions.Proxy.HTTP) .host(proxy.getHost()); PropertyMapper map = PropertyMapper.get(); map.from(proxy::getPort) .whenNonNull() .to(builder::port); map.from(proxy::getUsername) .whenHasText() .to(builder::username); map.from(proxy::getPassword) .whenHasText() .to(password -> builder.password(s -> password)); map.from(proxy::getNonProxyHostsPattern) .whenHasText() .to(builder::nonProxyHosts); return builder; }); } }; } @Bean public HttpClientProperties httpClientProperties() { return new HttpClientProperties(); } @Bean public NettyRoutingFilter routingFilter(HttpClient httpClient, ObjectProvider<List<HttpHeadersFilter>> headersFilters) { return new NettyRoutingFilter(httpClient, headersFilters); } @Bean public NettyWriteResponseFilter nettyWriteResponseFilter(GatewayProperties properties) { return new NettyWriteResponseFilter(properties.getStreamingMediaTypes()); } @Bean public ReactorNettyWebSocketClient reactorNettyWebSocketClient(@Qualifier("nettyClientOptions") Consumer<? super HttpClientOptions.Builder> options) { return new ReactorNettyWebSocketClient(options); } } //...... }
spring cloud gateway uses reactor's httpclient, which constructs options through the bean nettyClientOptions. The specific configuration is HttpClientProperties
HttpClientProperties
Configuration description
{ "sourceType": "org.springframework.cloud.gateway.config.HttpClientProperties", "name": "spring.cloud.gateway.httpclient", "type": "org.springframework.cloud.gateway.config.HttpClientProperties" }, { "sourceType": "org.springframework.cloud.gateway.config.HttpClientProperties", "name": "spring.cloud.gateway.httpclient.pool", "sourceMethod": "getPool()", "type": "org.springframework.cloud.gateway.config.HttpClientProperties$Pool" }, { "sourceType": "org.springframework.cloud.gateway.config.HttpClientProperties", "name": "spring.cloud.gateway.httpclient.proxy", "sourceMethod": "getProxy()", "type": "org.springframework.cloud.gateway.config.HttpClientProperties$Proxy" }, { "sourceType": "org.springframework.cloud.gateway.config.HttpClientProperties", "name": "spring.cloud.gateway.httpclient.ssl", "sourceMethod": "getSsl()", "type": "org.springframework.cloud.gateway.config.HttpClientProperties$Ssl" }
You can see that the main configurations are pool, proxy and ssl
Configuration class
spring-cloud-gateway-core-2.0.0.RC1-sources.jar!/org/springframework/cloud/gateway/config/HttpClientProperties.java
@ConfigurationProperties("spring.cloud.gateway.httpclient") public class HttpClientProperties { /** Pool configuration for Netty HttpClient */ private Pool pool = new Pool(); /** Proxy configuration for Netty HttpClient */ private Proxy proxy = new Proxy(); /** SSL configuration for Netty HttpClient */ private Ssl ssl = new Ssl(); //...... @Override public String toString() { return "HttpClientProperties{" + "pool=" + pool + ", proxy=" + proxy + '}'; } }
Pool
public static class Pool { public enum PoolType { ELASTIC, FIXED, DISABLED } /** Type of pool for HttpClient to use, defaults to ELASTIC. */ private PoolType type = PoolType.ELASTIC; /** The channel pool map name, defaults to proxy. */ private String name = "proxy"; /** Only for type FIXED, the maximum number of connections before starting pending acquisition on existing ones. */ private Integer maxConnections = PoolResources.DEFAULT_POOL_MAX_CONNECTION; /** Only for type FIXED, the maximum time in millis to wait for aquiring. */ private Long acquireTimeout = PoolResources.DEFAULT_POOL_ACQUIRE_TIMEOUT; //...... @Override public String toString() { return "Pool{" + "type=" + type + ", name='" + name + '\'' + ", maxConnections=" + maxConnections + ", acquireTimeout=" + acquireTimeout + '}'; } }
The following properties can be specified
- spring.cloud.gateway.httpclient.pool.type, the default is ELASTIC
- spring.cloud.gateway.httpclient.pool.name, the default is proxy
If the type is fixed, you can also specify the following two parameters
- spring.cloud.gateway.httpclient.pool.maxConnections, defaulting to poolresources.default.pool.max.connection
/** * Default max connection, if -1 will never wait to acquire before opening new * connection in an unbounded fashion. Fallback to * available number of processors. */ int DEFAULT_POOL_MAX_CONNECTION = Integer.parseInt(System.getProperty("reactor.ipc.netty.pool.maxConnections", "" + Math.max(Runtime.getRuntime() .availableProcessors(), 8) * 2));
- Spring.cloud.gateway.httpclient.pool.acquietimeout, defaulting to poolresources.default.pool.acquire.timeout
/** * Default acquisition timeout before error. If -1 will never wait to * acquire before opening new * connection in an unbounded fashion. Fallback to * available number of processors. */ long DEFAULT_POOL_ACQUIRE_TIMEOUT = Long.parseLong(System.getProperty( "reactor.ipc.netty.pool.acquireTimeout", "" + 45000));
Proxy
public class Proxy { /** Hostname for proxy configuration of Netty HttpClient. */ private String host; /** Port for proxy configuration of Netty HttpClient. */ private Integer port; /** Username for proxy configuration of Netty HttpClient. */ private String username; /** Password for proxy configuration of Netty HttpClient. */ private String password; /** Regular expression (Java) for a configured list of hosts * that should be reached directly, bypassing the proxy */ private String nonProxyHostsPattern; //...... @Override public String toString() { return "Proxy{" + "host='" + host + '\'' + ", port=" + port + ", username='" + username + '\'' + ", password='" + password + '\'' + ", nonProxyHostsPattern='" + nonProxyHostsPattern + '\'' + '}'; } }
You can configure the following parameters
- spring.cloud.gateway.httpclient.proxy.host
- spring.cloud.gateway.httpclient.proxy.port
- spring.cloud.gateway.httpclient.proxy.username
- spring.cloud.gateway.httpclient.proxy.password
- spring.cloud.gateway.httpclient.proxy.nonProxyHostsPattern
Ssl
public class Ssl { /** Installs the netty InsecureTrustManagerFactory. This is insecure and not suitable for production. */ private boolean useInsecureTrustManager = false; //TODO: support configuration of other trust manager factories public boolean isUseInsecureTrustManager() { return useInsecureTrustManager; } public void setUseInsecureTrustManager(boolean useInsecureTrustManager) { this.useInsecureTrustManager = useInsecureTrustManager; } @Override public String toString() { return "Ssl{" + "useInsecureTrustManager=" + useInsecureTrustManager + '}'; } }
It is mainly to configure the spring.cloud.gateway.httpclient.ssl.use-secure-trust-manager property. If it is set to true, the InsecureTrustManagerFactory.INSTANCE will be used
netty-handler-4.1.23.Final-sources.jar!/io/netty/handler/ssl/util/InsecureTrustManagerFactory.java
/** * An insecure {@link TrustManagerFactory} that trusts all X.509 certificates without any verification. * <p> * <strong>NOTE:</strong> * Never use this {@link TrustManagerFactory} in production. * It is purely for testing purposes, and thus it is very insecure. * </p> */ public final class InsecureTrustManagerFactory extends SimpleTrustManagerFactory { private static final InternalLogger logger = InternalLoggerFactory.getInstance(InsecureTrustManagerFactory.class); public static final TrustManagerFactory INSTANCE = new InsecureTrustManagerFactory(); private static final TrustManager tm = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String s) { logger.debug("Accepting a client certificate: " + chain[0].getSubjectDN()); } @Override public void checkServerTrusted(X509Certificate[] chain, String s) { logger.debug("Accepting a server certificate: " + chain[0].getSubjectDN()); } @Override public X509Certificate[] getAcceptedIssuers() { return EmptyArrays.EMPTY_X509_CERTIFICATES; } }; private InsecureTrustManagerFactory() { } @Override protected void engineInit(KeyStore keyStore) throws Exception { } @Override protected void engineInit(ManagerFactoryParameters managerFactoryParameters) throws Exception { } @Override protected TrustManager[] engineGetTrustManagers() { return new TrustManager[] { tm }; } }
Summary
The underlying layer of spring cloud gateway uses reactor's httpclient. You can specify relevant options through the configuration of spring.cloud.gateway.httpclient prefix. It is mainly divided into three categories: pool, proxy and ssl. The default type of pool is elastic. If it is fixed, you can also specify maxConnections and acquireTimeout parameters.