spring cloud gateway修改websocket的Max Frame length传输大小
参考:https://blog.csdn.net/wu_xijie/article/details/103166605待完成
参考:https://blog.csdn.net/wu_xijie/article/details/103166605
spring cloud版本:Greenwich.SR2
spring cloud gateway使用默认的netty
使用websocket,通过spring cloud gateway转发传送数据大于64kb时会报错,查看资料发现netty中默认websocket限制大小是64k
An exception has been observed post termination, use DEBUG level to see the full stack: io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException: Max frame length of 65536 has been exceeded.
排查原因
主要是在ReactorNettyWebSocketClient.java类中的方法execute中,一个
@Override
public Mono<Void> execute(URI url, HttpHeaders requestHeaders, WebSocketHandler handler) {
return getHttpClient()
.headers(nettyHeaders -> setNettyHeaders(requestHeaders, nettyHeaders))
.websocket(StringUtils.collectionToCommaDelimitedString(handler.getSubProtocols()))
.uri(url.toString())
.handle((inbound, outbound) -> {
HttpHeaders responseHeaders = toHttpHeaders(inbound);
String protocol = responseHeaders.getFirst("Sec-WebSocket-Protocol");
HandshakeInfo info = new HandshakeInfo(url, responseHeaders, Mono.empty(), protocol);
NettyDataBufferFactory factory = new NettyDataBufferFactory(outbound.alloc());
WebSocketSession session = new ReactorNettyWebSocketSession(inbound, outbound, info, factory);
if (logger.isDebugEnabled()) {
logger.debug("Started session '" + session.getId() + "' for " + url);
}
return handler.handle(session);
})
.doOnRequest(n -> {
if (logger.isDebugEnabled()) {
logger.debug("Connecting to " + url);
}
})
.next();
}
其中创建WebSocketSession对象的语句中,查看构造函数可以发现它有两个构造函数DEFAULT_FRAME_MAX_SIZE,默认是64KB,一个可以指定DEFAULT_FRAME_MAX_SIZE的大小
WebSocketSession session = new ReactorNettyWebSocketSession(inbound, outbound, info, factory);
//ReactorNettyWebSocketSession的构造函数
/**
* Constructor for the session, using the {@link #DEFAULT_FRAME_MAX_SIZE} value.
*/
public ReactorNettyWebSocketSession(WebsocketInbound inbound, WebsocketOutbound outbound,
HandshakeInfo info, NettyDataBufferFactory bufferFactory) {
this(inbound, outbound, info, bufferFactory, DEFAULT_FRAME_MAX_SIZE);
}
/**
* Constructor with an additional maxFramePayloadLength argument.
* @since 5.1
*/
public ReactorNettyWebSocketSession(WebsocketInbound inbound, WebsocketOutbound outbound,
HandshakeInfo info, NettyDataBufferFactory bufferFactory,
int maxFramePayloadLength) {
super(new WebSocketConnection(inbound, outbound), info, bufferFactory);
this.maxFramePayloadLength = maxFramePayloadLength;
}
解决
1、处理方式,编写子类继承ReactorNettyWebSocketClient.java,并且在execute方法中,使用ReactorNettyWebSocketSession另外一个构造函数,指定maxFramePayloadLength大小即可
ReactorNettyWebSocketSession(WebsocketInbound inbound, WebsocketOutbound outbound,
HandshakeInfo info, NettyDataBufferFactory bufferFactory,
int maxFramePayloadLength)
创建子类继承ReactorNettyWebSocketClient.java
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.socket.HandshakeInfo;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketSession;
import org.springframework.web.reactive.socket.adapter.ReactorNettyWebSocketSession;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.websocket.WebsocketInbound;
import java.net.URI;
public class MyReactorNettyWebSocketClient extends ReactorNettyWebSocketClient {
private static final Log logger = LogFactory.getLog(ReactorNettyWebSocketClient.class);
private final HttpClient httpClient;
/**
* websocket最大大小为10MB
*/
private static final int DEFAULT_FRAME_MAX_SIZE = 10 * 1024 * 1024;
/**
* Default constructor.
*/
public MyReactorNettyWebSocketClient() {
this(HttpClient.create());
}
/**
* Constructor that accepts an existing {@link HttpClient} builder.
* @since 5.1
*/
public MyReactorNettyWebSocketClient(HttpClient httpClient) {
Assert.notNull(httpClient, "HttpClient is required");
this.httpClient = httpClient;
}
/**
* Return the configured {@link HttpClient}.
*/
public HttpClient getHttpClient() {
return this.httpClient;
}
@Override
public Mono<Void> execute(URI url, WebSocketHandler handler) {
return execute(url, new HttpHeaders(), handler);
}
@Override
public Mono<Void> execute(URI url, HttpHeaders requestHeaders, WebSocketHandler handler) {
return getHttpClient()
.headers(nettyHeaders -> setNettyHeaders(requestHeaders, nettyHeaders))
.websocket(StringUtils.collectionToCommaDelimitedString(handler.getSubProtocols()))
.uri(url.toString())
.handle((inbound, outbound) -> {
HttpHeaders responseHeaders = toHttpHeaders(inbound);
String protocol = responseHeaders.getFirst("Sec-WebSocket-Protocol");
HandshakeInfo info = new HandshakeInfo(url, responseHeaders, Mono.empty(), protocol);
NettyDataBufferFactory factory = new NettyDataBufferFactory(outbound.alloc());
WebSocketSession session = new ReactorNettyWebSocketSession(inbound, outbound, info, factory, DEFAULT_FRAME_MAX_SIZE);
if (logger.isDebugEnabled()) {
logger.debug("Started session '" + session.getId() + "' for " + url);
}
return handler.handle(session);
})
.doOnRequest(n -> {
if (logger.isDebugEnabled()) {
logger.debug("Connecting to " + url);
}
})
.next();
}
private void setNettyHeaders(HttpHeaders httpHeaders, io.netty.handler.codec.http.HttpHeaders nettyHeaders) {
httpHeaders.forEach(nettyHeaders::set);
}
private HttpHeaders toHttpHeaders(WebsocketInbound inbound) {
HttpHeaders headers = new HttpHeaders();
io.netty.handler.codec.http.HttpHeaders nettyHeaders = inbound.headers();
nettyHeaders.forEach(entry -> {
String name = entry.getKey();
headers.put(name, nettyHeaders.getAll(name));
});
return headers;
}
}
2、排除GatewayAutoConfiguration的自动配置
@SpringBootApplication(exclude = {GatewayAutoConfiguration.class})//排除掉默认自动配置类
@EnableEurekaClient //启用eureka服务发现
public class GateWayApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class, args);
}
}
3、复制一份GatewayAutoConfiguration.java代码,自定义MyGatewayAutoConfiguration,并将其内部类NettyConfiguration
下的ReactorNettyWebSocketClient的bean 注入改为自定义的MyReactorNettyWebSocketClient,如下
@Bean
public ReactorNettyWebSocketClient reactorNettyWebSocketClient(
HttpClient httpClient) {
//return new ReactorNettyWebSocketClient(httpClient);
return new MyReactorNettyWebSocketClient(httpClient);
}
该bean主要提供给WebsocketRoutingFilter过滤器中的WebSocketClient
@Bean
public WebsocketRoutingFilter websocketRoutingFilter(WebSocketClient webSocketClient,
WebSocketService webSocketService,
ObjectProvider<List<HttpHeadersFilter>> headersFilters) {
return new WebsocketRoutingFilter(webSocketClient, webSocketService,
headersFilters);
}
添加依赖
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava-reactive-streams</artifactId>
<version>1.2.1</version>
</dependency>
指定bean的名称@Qualifier("webFluxValidator") Validator validator
@Bean
public WeightCalculatorWebFilter weightCalculatorWebFilter(@Qualifier("webFluxValidator") Validator validator,
ObjectProvider<RouteLocator> routeLocator) {
return new WeightCalculatorWebFilter(validator, routeLocator);
}
修改完毕后,完整的自定义MyGatewayAutoConfiguration.java
import java.security.cert.X509Certificate;
import java.util.List;
import com.netflix.hystrix.HystrixObservableCommand;
import io.netty.channel.ChannelOption;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.springframework.cloud.gateway.config.*;
import reactor.core.publisher.Flux;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.tcp.ProxyProvider;
import rx.RxReactiveStreams;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint;
import org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter;
import org.springframework.cloud.gateway.filter.ForwardPathFilter;
import org.springframework.cloud.gateway.filter.ForwardRoutingFilter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyRoutingFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter;
import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter;
import org.springframework.cloud.gateway.filter.WebsocketRoutingFilter;
import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter;
import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SecureHeadersProperties;
import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilter;
import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter;
import org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilter;
import org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.PrincipalNameKeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.CloudFoundryRouteServiceRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.WeightRoutePredicateFactory;
import org.springframework.cloud.gateway.route.CachingRouteLocator;
import org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator;
import org.springframework.cloud.gateway.route.CompositeRouteLocator;
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.RouteRefreshListener;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.cloud.gateway.support.StringToZonedDateTimeConverter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import org.springframework.validation.Validator;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
import org.springframework.web.reactive.socket.server.WebSocketService;
import org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService;
import static org.springframework.cloud.gateway.config.HttpClientProperties.Pool.PoolType.DISABLED;
import static org.springframework.cloud.gateway.config.HttpClientProperties.Pool.PoolType.FIXED;
@Configuration
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayLoadBalancerClientAutoConfiguration.class,
GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
public class MyGatewayAutoConfiguration {
@Bean
public StringToZonedDateTimeConverter stringToZonedDateTimeConverter() {
return new StringToZonedDateTimeConverter();
}
@Bean
public RouteLocatorBuilder routeLocatorBuilder(
ConfigurableApplicationContext context) {
return new RouteLocatorBuilder(context);
}
@Bean
@ConditionalOnMissingBean
public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(
GatewayProperties properties) {
return new PropertiesRouteDefinitionLocator(properties);
}
@Bean
@ConditionalOnMissingBean(RouteDefinitionRepository.class)
public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
return new InMemoryRouteDefinitionRepository();
}
@Bean
@Primary
public RouteDefinitionLocator routeDefinitionLocator(
List<RouteDefinitionLocator> routeDefinitionLocators) {
return new CompositeRouteDefinitionLocator(
Flux.fromIterable(routeDefinitionLocators));
}
@Bean
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
List<GatewayFilterFactory> GatewayFilters,
List<RoutePredicateFactory> predicates,
RouteDefinitionLocator routeDefinitionLocator,
@Qualifier("webFluxConversionService") ConversionService conversionService) {
return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates,
GatewayFilters, properties, conversionService);
}
@Bean
@Primary
// TODO: property to disable composite?
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
return new CachingRouteLocator(
new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
}
@Bean
public RouteRefreshListener routeRefreshListener(
ApplicationEventPublisher publisher) {
return new RouteRefreshListener(publisher);
}
@Bean
public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
return new FilteringWebHandler(globalFilters);
}
@Bean
public GlobalCorsProperties globalCorsProperties() {
return new GlobalCorsProperties();
}
@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(
FilteringWebHandler webHandler, RouteLocator routeLocator,
GlobalCorsProperties globalCorsProperties, Environment environment) {
return new RoutePredicateHandlerMapping(webHandler, routeLocator,
globalCorsProperties, environment);
}
@Bean
public GatewayProperties gatewayProperties() {
return new GatewayProperties();
}
// ConfigurationProperty beans
@Bean
public SecureHeadersProperties secureHeadersProperties() {
return new SecureHeadersProperties();
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.gateway.forwarded.enabled", matchIfMissing = true)
public ForwardedHeadersFilter forwardedHeadersFilter() {
return new ForwardedHeadersFilter();
}
// HttpHeaderFilter beans
@Bean
public RemoveHopByHopHeadersFilter removeHopByHopHeadersFilter() {
return new RemoveHopByHopHeadersFilter();
}
@Bean
@ConditionalOnProperty(name = "spring.cloud.gateway.x-forwarded.enabled", matchIfMissing = true)
public XForwardedHeadersFilter xForwardedHeadersFilter() {
return new XForwardedHeadersFilter();
}
// GlobalFilter beans
@Bean
public AdaptCachedBodyGlobalFilter adaptCachedBodyGlobalFilter() {
return new AdaptCachedBodyGlobalFilter();
}
@Bean
public RemoveCachedBodyFilter removeCachedBodyFilter() {
return new RemoveCachedBodyFilter();
}
@Bean
public RouteToRequestUrlFilter routeToRequestUrlFilter() {
return new RouteToRequestUrlFilter();
}
@Bean
public ForwardRoutingFilter forwardRoutingFilter(
ObjectProvider<DispatcherHandler> dispatcherHandler) {
return new ForwardRoutingFilter(dispatcherHandler);
}
@Bean
public ForwardPathFilter forwardPathFilter() {
return new ForwardPathFilter();
}
@Bean
public WebSocketService webSocketService() {
return new HandshakeWebSocketService();
}
@Bean
public WebsocketRoutingFilter websocketRoutingFilter(WebSocketClient webSocketClient,
WebSocketService webSocketService,
ObjectProvider<List<HttpHeadersFilter>> headersFilters) {
return new WebsocketRoutingFilter(webSocketClient, webSocketService,
headersFilters);
}
@Bean
public WeightCalculatorWebFilter weightCalculatorWebFilter(@Qualifier("webFluxValidator") Validator validator,
ObjectProvider<RouteLocator> routeLocator) {
return new WeightCalculatorWebFilter(validator, routeLocator);
}
@Bean
public AfterRoutePredicateFactory afterRoutePredicateFactory() {
return new AfterRoutePredicateFactory();
}
/*
* @Bean //TODO: default over netty? configurable public WebClientHttpRoutingFilter
* webClientHttpRoutingFilter() { //TODO: WebClient bean return new
* WebClientHttpRoutingFilter(WebClient.routes().build()); }
*
* @Bean public WebClientWriteResponseFilter webClientWriteResponseFilter() { return
* new WebClientWriteResponseFilter(); }
*/
// Predicate Factory beans
@Bean
public BeforeRoutePredicateFactory beforeRoutePredicateFactory() {
return new BeforeRoutePredicateFactory();
}
@Bean
public BetweenRoutePredicateFactory betweenRoutePredicateFactory() {
return new BetweenRoutePredicateFactory();
}
@Bean
public CookieRoutePredicateFactory cookieRoutePredicateFactory() {
return new CookieRoutePredicateFactory();
}
@Bean
public HeaderRoutePredicateFactory headerRoutePredicateFactory() {
return new HeaderRoutePredicateFactory();
}
@Bean
public HostRoutePredicateFactory hostRoutePredicateFactory() {
return new HostRoutePredicateFactory();
}
@Bean
public MethodRoutePredicateFactory methodRoutePredicateFactory() {
return new MethodRoutePredicateFactory();
}
@Bean
public PathRoutePredicateFactory pathRoutePredicateFactory() {
return new PathRoutePredicateFactory();
}
@Bean
public QueryRoutePredicateFactory queryRoutePredicateFactory() {
return new QueryRoutePredicateFactory();
}
@Bean
public ReadBodyPredicateFactory readBodyPredicateFactory() {
return new ReadBodyPredicateFactory();
}
@Bean
public RemoteAddrRoutePredicateFactory remoteAddrRoutePredicateFactory() {
return new RemoteAddrRoutePredicateFactory();
}
@Bean
@DependsOn("weightCalculatorWebFilter")
public WeightRoutePredicateFactory weightRoutePredicateFactory() {
return new WeightRoutePredicateFactory();
}
@Bean
public CloudFoundryRouteServiceRoutePredicateFactory cloudFoundryRouteServiceRoutePredicateFactory() {
return new CloudFoundryRouteServiceRoutePredicateFactory();
}
// GatewayFilter Factory beans
@Bean
public AddRequestHeaderGatewayFilterFactory addRequestHeaderGatewayFilterFactory() {
return new AddRequestHeaderGatewayFilterFactory();
}
@Bean
public AddRequestParameterGatewayFilterFactory addRequestParameterGatewayFilterFactory() {
return new AddRequestParameterGatewayFilterFactory();
}
@Bean
public AddResponseHeaderGatewayFilterFactory addResponseHeaderGatewayFilterFactory() {
return new AddResponseHeaderGatewayFilterFactory();
}
@Bean
public ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory() {
return new ModifyRequestBodyGatewayFilterFactory();
}
@Bean
public DedupeResponseHeaderGatewayFilterFactory dedupeResponseHeaderGatewayFilterFactory() {
return new DedupeResponseHeaderGatewayFilterFactory();
}
@Bean
public ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory() {
return new ModifyResponseBodyGatewayFilterFactory();
}
@Bean
public PrefixPathGatewayFilterFactory prefixPathGatewayFilterFactory() {
return new PrefixPathGatewayFilterFactory();
}
@Bean
public PreserveHostHeaderGatewayFilterFactory preserveHostHeaderGatewayFilterFactory() {
return new PreserveHostHeaderGatewayFilterFactory();
}
@Bean
public RedirectToGatewayFilterFactory redirectToGatewayFilterFactory() {
return new RedirectToGatewayFilterFactory();
}
@Bean
public RemoveRequestHeaderGatewayFilterFactory removeRequestHeaderGatewayFilterFactory() {
return new RemoveRequestHeaderGatewayFilterFactory();
}
@Bean
public RemoveResponseHeaderGatewayFilterFactory removeResponseHeaderGatewayFilterFactory() {
return new RemoveResponseHeaderGatewayFilterFactory();
}
@Bean(name = PrincipalNameKeyResolver.BEAN_NAME)
@ConditionalOnBean(RateLimiter.class)
@ConditionalOnMissingBean(KeyResolver.class)
public PrincipalNameKeyResolver principalNameKeyResolver() {
return new PrincipalNameKeyResolver();
}
@Bean
@ConditionalOnBean({ RateLimiter.class, KeyResolver.class })
public RequestRateLimiterGatewayFilterFactory requestRateLimiterGatewayFilterFactory(
RateLimiter rateLimiter, KeyResolver resolver) {
return new RequestRateLimiterGatewayFilterFactory(rateLimiter, resolver);
}
@Bean
public RewritePathGatewayFilterFactory rewritePathGatewayFilterFactory() {
return new RewritePathGatewayFilterFactory();
}
@Bean
public RetryGatewayFilterFactory retryGatewayFilterFactory() {
return new RetryGatewayFilterFactory();
}
@Bean
public SetPathGatewayFilterFactory setPathGatewayFilterFactory() {
return new SetPathGatewayFilterFactory();
}
@Bean
public SecureHeadersGatewayFilterFactory secureHeadersGatewayFilterFactory(
SecureHeadersProperties properties) {
return new SecureHeadersGatewayFilterFactory(properties);
}
@Bean
public SetRequestHeaderGatewayFilterFactory setRequestHeaderGatewayFilterFactory() {
return new SetRequestHeaderGatewayFilterFactory();
}
@Bean
public SetResponseHeaderGatewayFilterFactory setResponseHeaderGatewayFilterFactory() {
return new SetResponseHeaderGatewayFilterFactory();
}
@Bean
public RewriteResponseHeaderGatewayFilterFactory rewriteResponseHeaderGatewayFilterFactory() {
return new RewriteResponseHeaderGatewayFilterFactory();
}
@Bean
public SetStatusGatewayFilterFactory setStatusGatewayFilterFactory() {
return new SetStatusGatewayFilterFactory();
}
@Bean
public SaveSessionGatewayFilterFactory saveSessionGatewayFilterFactory() {
return new SaveSessionGatewayFilterFactory();
}
@Bean
public StripPrefixGatewayFilterFactory stripPrefixGatewayFilterFactory() {
return new StripPrefixGatewayFilterFactory();
}
@Bean
public RequestHeaderToRequestUriGatewayFilterFactory requestHeaderToRequestUriGatewayFilterFactory() {
return new RequestHeaderToRequestUriGatewayFilterFactory();
}
@Bean
public RequestSizeGatewayFilterFactory requestSizeGatewayFilterFactory() {
return new RequestSizeGatewayFilterFactory();
}
@Configuration
@ConditionalOnClass(HttpClient.class)
protected static class NettyConfiguration {
@Bean
@ConditionalOnMissingBean
public HttpClient httpClient(HttpClientProperties properties) {
// configure pool resources
HttpClientProperties.Pool pool = properties.getPool();
ConnectionProvider connectionProvider;
if (pool.getType() == DISABLED) {
connectionProvider = ConnectionProvider.newConnection();
}
else if (pool.getType() == FIXED) {
connectionProvider = ConnectionProvider.fixed(pool.getName(),
pool.getMaxConnections(), pool.getAcquireTimeout());
}
else {
connectionProvider = ConnectionProvider.elastic(pool.getName());
}
HttpClient httpClient = HttpClient.create(connectionProvider)
.tcpConfiguration(tcpClient -> {
if (properties.getConnectTimeout() != null) {
tcpClient = tcpClient.option(
ChannelOption.CONNECT_TIMEOUT_MILLIS,
properties.getConnectTimeout());
}
// configure proxy if proxy host is set.
HttpClientProperties.Proxy proxy = properties.getProxy();
if (StringUtils.hasText(proxy.getHost())) {
tcpClient = tcpClient.proxy(proxySpec -> {
ProxyProvider.Builder builder = proxySpec
.type(ProxyProvider.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 tcpClient;
});
HttpClientProperties.Ssl ssl = properties.getSsl();
if (ssl.getTrustedX509CertificatesForTrustManager().length > 0
|| ssl.isUseInsecureTrustManager()) {
httpClient = httpClient.secure(sslContextSpec -> {
// configure ssl
SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
X509Certificate[] trustedX509Certificates = ssl
.getTrustedX509CertificatesForTrustManager();
if (trustedX509Certificates.length > 0) {
sslContextBuilder.trustManager(trustedX509Certificates);
}
else if (ssl.isUseInsecureTrustManager()) {
sslContextBuilder
.trustManager(InsecureTrustManagerFactory.INSTANCE);
}
sslContextSpec.sslContext(sslContextBuilder)
.defaultConfiguration(ssl.getDefaultConfigurationType())
.handshakeTimeout(ssl.getHandshakeTimeout())
.closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
.closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout());
});
}
// TODO: add configuration to turn on wiretap
// httpClient = httpClient.wiretap(true);
return httpClient;
}
@Bean
public HttpClientProperties httpClientProperties() {
return new HttpClientProperties();
}
@Bean
public NettyRoutingFilter routingFilter(HttpClient httpClient,
ObjectProvider<List<HttpHeadersFilter>> headersFilters,
HttpClientProperties properties) {
return new NettyRoutingFilter(httpClient, headersFilters, properties);
}
@Bean
public NettyWriteResponseFilter nettyWriteResponseFilter(
GatewayProperties properties) {
return new NettyWriteResponseFilter(properties.getStreamingMediaTypes());
}
@Bean
public ReactorNettyWebSocketClient reactorNettyWebSocketClient(
HttpClient httpClient) {
//return new ReactorNettyWebSocketClient(httpClient);
return new MyReactorNettyWebSocketClient(httpClient);
}
}
@Configuration
@ConditionalOnClass({ HystrixObservableCommand.class, RxReactiveStreams.class })
protected static class HystrixConfiguration {
@Bean
public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(
ObjectProvider<DispatcherHandler> dispatcherHandler) {
return new HystrixGatewayFilterFactory(dispatcherHandler);
}
@Bean
public FallbackHeadersGatewayFilterFactory fallbackHeadersGatewayFilterFactory() {
return new FallbackHeadersGatewayFilterFactory();
}
}
@Configuration
@ConditionalOnClass(Health.class)
protected static class GatewayActuatorConfiguration {
@Bean
@ConditionalOnEnabledEndpoint
public GatewayControllerEndpoint gatewayControllerEndpoint(
RouteDefinitionLocator routeDefinitionLocator,
List<GlobalFilter> globalFilters,
List<GatewayFilterFactory> GatewayFilters,
RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) {
return new GatewayControllerEndpoint(routeDefinitionLocator, globalFilters,
GatewayFilters, routeDefinitionWriter, routeLocator);
}
}
}
---------------------------------
补充:spirng cloud 版本Hoxton.SR8的gateway需要2.2.5.RELEASE已经提供websocket的一次最大数据块配置,无需改源码
spring:
cloud:
# spring cloud gateway配置
gateway:
httpclient:
# spirng cloud 版本Hoxton.SR8的gateway需要2.2.5.RELEASE已经提供websocket的一次最大数据块配置,无需改源码
websocket:
max-frame-payload-length: 10485760 # 单次通信提交最大数据库设置成10MB
更多推荐
所有评论(0)