enhancement: wehotel(#175)

This commit is contained in:
hongqiaowei
2021-05-12 16:16:34 +08:00
parent ecd8f986eb
commit 0296224d23
8 changed files with 196 additions and 234 deletions

View File

@@ -71,11 +71,7 @@ DEFAULT_JAVA_OPTS="-XX:+AggressiveOpts \
-Xloggc:${APP_LOG_DIR}/${START_DATE_TIME}.gc \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=${APP_LOG_DIR}/dump.logs \
-Dorg.jboss.netty.epollBugWorkaround=true \
-Dio.netty.leakDetectionLevel=PARANOID -Dio.netty.leakDetection.targetRecords=60 \
-Dio.netty.allocator.type=unpooled \
-Dio.netty.noPreferDirect=true \
-Dio.netty.noUnsafe=true "
-Dorg.jboss.netty.epollBugWorkaround=true "
MEM_OPTS=${JAVA_MEM_OPTS:-$DEFAULT_JAVA_MEM_OPTS}

View File

@@ -86,7 +86,7 @@ log:
stat:
# switch for push access stat data
open: true
open: false
send-log:
# switch for push log data
open: true

View File

@@ -17,12 +17,7 @@
package we.config;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.AdaptiveRecvByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.channel.PreferHeapByteBufAllocator;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import org.slf4j.Logger;
@@ -34,8 +29,9 @@ import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.resources.LoopResources;
import we.util.JacksonUtils;
import java.time.Duration;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
/**
@@ -46,13 +42,13 @@ public abstract class WebClientConfig {
protected static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);
private String name;
private int maxConnections = 2_000;
private Duration maxIdleTime = Duration.ofMillis(40_000);
private Duration pendingAcquireTimeout = Duration.ofMillis(6_000);
// private String name;
//
// private int maxConnections = 2_000;
//
// private Duration maxIdleTime = Duration.ofMillis(40_000);
//
// private Duration pendingAcquireTimeout = Duration.ofMillis(6_000);
private long connReadTimeout = 20_000;
@@ -64,39 +60,39 @@ public abstract class WebClientConfig {
private boolean chSoKeepAlive = true;
private boolean compress = false;
private boolean compress = true;
public String getName() {
return name;
}
public void setName(String name) {
this.name = "wc-" + name;
}
public int getMaxConnections() {
return maxConnections;
}
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
public Duration getMaxIdleTime() {
return maxIdleTime;
}
public void setMaxIdleTime(long maxIdleTime) {
this.maxIdleTime = Duration.ofMillis(maxIdleTime);
}
public Duration getPendingAcquireTimeout() {
return pendingAcquireTimeout;
}
public void setPendingAcquireTimeout(long pendingAcquireTimeout) {
this.pendingAcquireTimeout = Duration.ofMillis(pendingAcquireTimeout);
}
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// }
//
// public int getMaxConnections() {
// return maxConnections;
// }
//
// public void setMaxConnections(int maxConnections) {
// this.maxConnections = maxConnections;
// }
//
// public Duration getMaxIdleTime() {
// return maxIdleTime;
// }
//
// public void setMaxIdleTime(long maxIdleTime) {
// this.maxIdleTime = Duration.ofMillis(maxIdleTime);
// }
//
// public Duration getPendingAcquireTimeout() {
// return pendingAcquireTimeout;
// }
//
// public void setPendingAcquireTimeout(long pendingAcquireTimeout) {
// this.pendingAcquireTimeout = Duration.ofMillis(pendingAcquireTimeout);
// }
public long getConnReadTimeout() {
return connReadTimeout;
@@ -146,55 +142,18 @@ public abstract class WebClientConfig {
this.compress = compress;
}
private ConnectionProvider getConnectionProvider() {
String cpName = name + "-cp";
ConnectionProvider cp = ConnectionProvider.builder(cpName).maxConnections(maxConnections)
.pendingAcquireTimeout(pendingAcquireTimeout)
.maxIdleTime(maxIdleTime)
.build();
log.info(cpName + ' ' + cp);
return cp;
}
@Resource
ReactorResourceFactory reactorResourceFactory;
private LoopResources getLoopResources() {
String elPrefix = name + "-el";
// LoopResources lr = LoopResources.create(elPrefix, 1, Runtime.getRuntime().availableProcessors(), true);
LoopResources lr = LoopResources.create(elPrefix, Runtime.getRuntime().availableProcessors(), true);
lr.onServer(false);
log.info(name + "-lr " + lr);
return lr;
}
protected ReactorResourceFactory reactorResourceFactory() {
ReactorResourceFactory fact = new ReactorResourceFactory();
fact.setUseGlobalResources(false);
fact.setConnectionProvider(getConnectionProvider());
fact.setLoopResources(getLoopResources());
fact.afterPropertiesSet();
return fact;
}
// @Resource
// ReactorClientHttpConnector reactorClientHttpConnector;
public WebClient webClient() {
log.info(this.toString());
// return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build())
// .clientConnector(new ReactorClientHttpConnector(reactorResourceFactory(), httpClient -> {
// return httpClient.compress(compress).tcpConfiguration(tcpClient -> {
// return tcpClient.doOnConnected(connection -> {
// connection.addHandlerLast(new ReadTimeoutHandler( connReadTimeout, TimeUnit.MILLISECONDS))
// .addHandlerLast(new WriteTimeoutHandler( connWriteTimeout, TimeUnit.MILLISECONDS));
// }).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, chConnTimeout)
// .option(ChannelOption.TCP_NODELAY, chTcpNodelay)
// .option(ChannelOption.SO_KEEPALIVE, chSoKeepAlive)
// .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT);
// });
// })).build();
ConnectionProvider cp = getConnectionProvider();
LoopResources lr = getLoopResources();
ConnectionProvider cp = reactorResourceFactory.getConnectionProvider();
LoopResources lrs = reactorResourceFactory.getLoopResources();
HttpClient httpClient = HttpClient.create(cp).compress(compress).tcpConfiguration(
tcpClient -> {
return tcpClient.runOn(lr, false)
// .runOn(lr)
return tcpClient.runOn(lrs)
// .bootstrap(
// bootstrap -> (
// bootstrap.channel(NioSocketChannel.class)
@@ -209,27 +168,28 @@ public abstract class WebClientConfig {
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, chConnTimeout)
.option(ChannelOption.TCP_NODELAY, chTcpNodelay)
.option(ChannelOption.SO_KEEPALIVE, chSoKeepAlive)
// .option(ChannelOption.ALLOCATOR, PreferHeapByteBufAllocator.DEFAULT);
// .option(ChannelOption.ALLOCATOR, PreferHeapByteBufAllocator.DEFAULT)
// .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT);
// .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
;
}
);
return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build())
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
return WebClient.builder().exchangeStrategies(
ExchangeStrategies.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1))
.build()
)
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
@Override
public String toString() {
return " {name=" + name +
", maxConnections=" + maxConnections +
", maxIdleTime=" + maxIdleTime +
", pendingAcquireTimeout=" + pendingAcquireTimeout +
", connReadTimeout=" + connReadTimeout +
return "{ connReadTimeout=" + connReadTimeout +
", connWriteTimeout=" + connWriteTimeout +
", chConnTimeout=" + chConnTimeout +
", chTcpNodelay=" + chTcpNodelay +
", chSoKeepAlive=" + chSoKeepAlive +
", compress=" + compress +
'}';
", chConnTimeout=" + chConnTimeout +
", chTcpNodelay=" + chTcpNodelay +
", chSoKeepAlive=" + chSoKeepAlive +
", compress=" + compress +
" }";
}
}

View File

@@ -21,6 +21,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.resources.LoopResources;
import we.util.JacksonUtils;
/**
* @author hongqiaowei
@@ -36,6 +38,7 @@ public class AggrWebClientConfig extends WebClientConfig {
@Bean(aggrWebClient)
public WebClient webClient() {
log.info(aggrWebClient + ": " + this);
return super.webClient();
}
}

View File

@@ -21,6 +21,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.resources.LoopResources;
import we.util.JacksonUtils;
/**
* @author hongqiaowei
@@ -36,6 +38,7 @@ public class ProxyWebClientConfig extends WebClientConfig {
@Bean(proxyWebClient)
public WebClient webClient() {
log.info(proxyWebClient + ": " + this);
return super.webClient();
}
}

View File

@@ -17,24 +17,28 @@
package we.config;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import io.netty.channel.ChannelOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.reactive.ReactorResourceFactory;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.resources.LoopResources;
import java.time.Duration;
/**
* @author hongqiaowei
*/
@@ -46,98 +50,89 @@ public class WebFluxConfig {
private static final Logger log = LoggerFactory.getLogger(WebFluxConfig.class);
// private ConnectionProvider getConnectionProvider() {
// String cpName = "fizz-cp";
// ConnectionProvider cp = ConnectionProvider.builder(cpName).maxConnections(10_000)
// .pendingAcquireTimeout(Duration.ofMillis(6_000)).maxIdleTime(Duration.ofMillis(40_000)).build();
// log.info(cpName + ' ' + cp);
// return cp;
// }
@NacosValue(value = "${server.connection-pool.max-connections:500}", autoRefreshed = true)
@Value( "${server.connection-pool.max-connections:500}" )
private int maxConnections;
// private LoopResources getLoopResources() {
// String elPrefix = "fizz-el";
// LoopResources lr = LoopResources.create(elPrefix, 1, Runtime.getRuntime().availableProcessors(), true);
// lr.onServerSelect(false);
// lr.onServer(false);
// log.info("fizz-lr " + lr);
// return lr;
// }
@NacosValue(value = "${server.connection-pool.max-idle-time:30000}", autoRefreshed = true)
@Value( "${server.connection-pool.max-idle-time:30000}" )
private long maxIdleTime;
// @Bean
// public ReactorResourceFactory reactorResourceFactory() {
// ReactorResourceFactory fact = new ReactorResourceFactory();
// fact.setUseGlobalResources(false);
// // fact.setConnectionProvider(getConnectionProvider());
// fact.setLoopResources(getLoopResources());
// // fact.afterPropertiesSet();
// return fact;
// }
private ConnectionProvider connectionProvider() {
ConnectionProvider connectionProvider = ConnectionProvider.builder("fizz-cp")
.maxConnections(maxConnections)
.maxIdleTime(Duration.ofMillis(maxIdleTime))
.pendingAcquireMaxCount(-1)
.build();
log.info("server connection provider: maxConnections={}, maxIdleTime={}", maxConnections, maxIdleTime);
return connectionProvider;
}
// public static EventLoopGroup acceptorGroup;
// public static EventLoopGroup workerGroup;
// static {
// if (SystemUtils.IS_OS_WINDOWS) {
// acceptorGroup = new NioEventLoopGroup(1, new DefaultLoopResources.EventLoopFactory(true, "fizz-acceptor", new AtomicLong(0)));
// workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors(), new DefaultLoopResources.EventLoopFactory(true, "fizz-worker", new AtomicLong(0)));
// } else {
// // DefaultLoop defaultLoop = DefaultLoopNativeDetector.getInstance();
// // EventLoopGroup newEventLoopGroup = defaultLoop.newEventLoopGroup(
// // selectCount,
// // threadFactory(this, "select-" + defaultLoop.getName()));
// acceptorGroup = new EpollEventLoopGroup(1, new DefaultLoopResources.EventLoopFactory(true, "fizz-acceptor", new AtomicLong(0)));
// workerGroup = new EpollEventLoopGroup(Runtime.getRuntime().availableProcessors(), new DefaultLoopResources.EventLoopFactory(true, "fizz-worker", new AtomicLong(0)));
// }
// }
private LoopResources loopResources() {
LoopResources loopResources = LoopResources.create("fizz-lrs");
log.info("server loop resources: " + loopResources);
return loopResources;
}
@Bean
public NettyReactiveWebServerFactory nettyReactiveWebServerFactory(ServerProperties serverProperties/*, ReactorResourceFactory reactorResourceFactory*/) {
NettyReactiveWebServerFactory httpServerFactory = new NettyReactiveWebServerFactory();
httpServerFactory.setResourceFactory(null);
// httpServerFactory.setResourceFactory(reactorResourceFactory);
LoopResources lr = LoopResources.create("fizz-el", 1, Runtime.getRuntime().availableProcessors(), true);
httpServerFactory.addServerCustomizers(
httpServer -> (
httpServer.tcpConfiguration(
tcpServer -> {
return (
tcpServer
// .runOn(workerGroup)
.runOn(lr, false)
// .runOn(lr)
// .selectorOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
// .port(7777)
.bootstrap(
serverBootstrap -> (
serverBootstrap
// .group(parentGroup, childGroup)
// .channel(NioServerSocketChannel.class)
// .handler(new LoggingHandler(LogLevel.DEBUG))
// .childHandler(new ChannelInitializer<SocketChannel>() {
// @Override
// public void initChannel(final SocketChannel socketChannel) {
// socketChannel.pipeline().addLast(new BufferingInboundHandler());
// }
// })
// .channel(NioServerSocketChannel.class)
.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
// .option(ChannelOption.SO_BACKLOG, 8192)
.childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
)
)
);
}
)
)
);
return httpServerFactory;
public ReactorResourceFactory reactorServerResourceFactory() {
ReactorResourceFactory rrf = new ReactorResourceFactory();
rrf.setUseGlobalResources(false);
rrf.setLoopResources(loopResources());
rrf.setConnectionProvider(connectionProvider());
log.info("server reactor resource factory: " + rrf);
return rrf;
}
// @Bean
// public NettyReactiveWebServerFactory nettyReactiveWebServerFactory(ServerProperties serverProperties/*, ReactorResourceFactory reactorResourceFactory*/) {
// NettyReactiveWebServerFactory httpServerFactory = new NettyReactiveWebServerFactory();
// httpServerFactory.setResourceFactory(null);
// // httpServerFactory.setResourceFactory(reactorResourceFactory);
// // LoopResources lr = LoopResources.create("fizz-el", 1, Runtime.getRuntime().availableProcessors(), true);
// httpServerFactory.addServerCustomizers(
// httpServer -> (
// httpServer.tcpConfiguration(
// tcpServer -> {
// return (
// tcpServer
// // .runOn(lr, true)
// // .runOn(lr)
// // .selectorOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
// // .port(7777)
// .bootstrap(
// serverBootstrap -> (
// serverBootstrap
// // .group(parentGroup, childGroup)
// // .channel(NioServerSocketChannel.class)
// // .handler(new LoggingHandler(LogLevel.DEBUG))
// // .childHandler(new ChannelInitializer<SocketChannel>() {
// // @Override
// // public void initChannel(final SocketChannel socketChannel) {
// // socketChannel.pipeline().addLast(new BufferingInboundHandler());
// // }
// // })
// // .channel(NioServerSocketChannel.class)
// // .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
// // .option(ChannelOption.SO_BACKLOG, 8192)
// // .childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
// .childOption(ChannelOption.SO_KEEPALIVE, true)
// .childOption(ChannelOption.TCP_NODELAY, true)
// )
// )
// );
// }
// )
// )
// );
//
// return httpServerFactory;
// }
@Configuration
@EnableWebFlux
public static class FizzWebFluxConfigurer implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().maxInMemorySize(-1);

View File

@@ -300,58 +300,61 @@ public class ApiConfigService {
private Mono<Object> canAccess(ServerWebExchange exchange, String app, String ip, String timestamp, String sign, String service, HttpMethod method, String path) {
String api = ThreadContext.getStringBuilder().append(service).append(Constants.Symbol.BLANK).append(method.name()).append(Constants.Symbol.BLANK + path).toString();
ApiConfig ac = getApiConfig(app, service, method, path);
if (ac == null) {
if (SystemConfig.DEFAULT_GATEWAY_TEST_PREFIX0.equals(WebUtils.getClientReqPathPrefix(exchange))) {
if (systemConfig.aggregateTestAuth) {
return logAndResult(api + " no route config", Access.ROUTE_NOT_FOUND);
} else {
return Mono.just(Access.YES);
}
}
if (!needAuth) {
return Mono.just(Access.YES);
} else {
return logAndResult(api + " no route config", Access.ROUTE_NOT_FOUND);
}
if (SystemConfig.DEFAULT_GATEWAY_TEST_PREFIX0.equals(WebUtils.getClientReqPathPrefix(exchange))) {
if (systemConfig.aggregateTestAuth) {
return logAndResult(getApiString(service, method, path) + " no route config", Access.ROUTE_NOT_FOUND);
} else {
return Mono.just(Access.YES);
}
}
if (!needAuth) {
return Mono.just(Access.YES);
} else {
return logAndResult(getApiString(service, method, path) + " no route config", Access.ROUTE_NOT_FOUND);
}
} else if (!ac.checkApp) {
return allow(api, ac);
return allow(getApiString(service, method, path), ac);
} else if (app != null) {
if (ac.access == ApiConfig.ALLOW) {
App a = appService.getApp(app);
if (a.useWhiteList && !a.allow(ip)) {
return logAndResult(ip + " not in " + app + " white list", Access.IP_NOT_IN_WHITE_LIST);
} else if (a.useAuth) {
if (a.authType == App.AUTH_TYPE.SIGN) {
return authSign(ac, a, timestamp, sign);
} else if (a.authType == App.AUTH_TYPE.SECRETKEY) {
return authSecretkey(ac, a, sign);
} else if (customAuth == null) {
return logAndResult(app + " no custom auth", Access.NO_CUSTOM_AUTH);
} else {
return customAuth.auth(exchange, app, ip, timestamp, sign, a).flatMap(v -> {
if (v == Access.YES) {
return Mono.just(ac);
} else {
return Mono.just(Access.CUSTOM_AUTH_REJECT);
}
});
}
} else {
return Mono.just(ac);
}
if (ac.access == ApiConfig.ALLOW) {
App a = appService.getApp(app);
if (a.useWhiteList && !a.allow(ip)) {
return logAndResult(ip + " not in " + app + " white list", Access.IP_NOT_IN_WHITE_LIST);
} else if (a.useAuth) {
if (a.authType == App.AUTH_TYPE.SIGN) {
return authSign(ac, a, timestamp, sign);
} else if (a.authType == App.AUTH_TYPE.SECRETKEY) {
return authSecretkey(ac, a, sign);
} else if (customAuth == null) {
return logAndResult(app + " no custom auth", Access.NO_CUSTOM_AUTH);
} else {
return logAndResult("cant access " + api, Access.CANT_ACCESS_SERVICE_API);
return customAuth.auth(exchange, app, ip, timestamp, sign, a).flatMap(v -> {
if (v == Access.YES) {
return Mono.just(ac);
} else {
return Mono.just(Access.CUSTOM_AUTH_REJECT);
}
});
}
} else {
return Mono.just(ac);
}
} else {
return logAndResult("cant access " + getApiString(service, method, path), Access.CANT_ACCESS_SERVICE_API);
}
} else {
return logAndResult(app + " not in " + api + " legal apps", Access.APP_NOT_IN_API_LEGAL_APPS);
return logAndResult(app + " not in " + getApiString(service, method, path) + " legal apps", Access.APP_NOT_IN_API_LEGAL_APPS);
}
}
private String getApiString(String service, HttpMethod method, String path) {
return ThreadContext.getStringBuilder().append(service).append(Constants.Symbol.BLANK).append(method.name()).append(Constants.Symbol.BLANK).append(path).toString();
}
private Mono authSign(ApiConfig ac, App a, String timestamp, String sign) {
if (StringUtils.isAnyBlank(timestamp, sign)) {
return logAndResult(a.app + " lack timestamp " + timestamp + " or sign " + sign, Access.NO_TIMESTAMP_OR_SIGN);

View File

@@ -36,6 +36,8 @@ public class ServiceConfig {
private static final String gg2acs = "$gg2acs";
private static final String acs = "$acs";
public String id;
@JsonIgnore
@@ -139,7 +141,7 @@ public class ServiceConfig {
if (matchGatewayGroup2apiConfigs.isEmpty()) {
return Collections.emptyList();
} else {
List<ApiConfig> lst = new ArrayList<>(8);
List<ApiConfig> lst = ThreadContext.getArrayList(acs, ApiConfig.class);
for (GatewayGroup2apiConfig gatewayGroup2apiConfig : matchGatewayGroup2apiConfigs) {
Set<ApiConfig> apiConfigs = gatewayGroup2apiConfig.get(gatewayGroup);
if (apiConfigs != null) {