* sentinel-transport-netty-http will also retry when port specified has been used * LogBase support variable arguments * Remove duplicated JVM properties overriding in SentinelConfig * Add VersionUtil to get version from jarmaster
@@ -58,6 +58,7 @@ | |||
<maven.deploy.version>2.8.2</maven.deploy.version> | |||
<maven.gpg.version>1.6</maven.gpg.version> | |||
<maven.jacoco.version>0.8.1</maven.jacoco.version> | |||
<maven.jar.version>3.1.0</maven.jar.version> | |||
</properties> | |||
<modules> | |||
@@ -182,6 +183,15 @@ | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
<pluginManagement> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-jar-plugin</artifactId> | |||
<version>${maven.jar.version}</version> | |||
</plugin> | |||
</plugins> | |||
</pluginManagement> | |||
</build> | |||
<profiles> | |||
@@ -24,5 +24,19 @@ | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-jar-plugin</artifactId> | |||
<configuration> | |||
<archive> | |||
<manifestEntries> | |||
<Implementation-Version>${project.version}</Implementation-Version> | |||
</manifestEntries> | |||
</archive> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -20,6 +20,7 @@ import com.alibaba.csp.sentinel.node.DefaultNode; | |||
import com.alibaba.csp.sentinel.node.EntranceNode; | |||
import com.alibaba.csp.sentinel.slotchain.StringResourceWrapper; | |||
import com.alibaba.csp.sentinel.slots.system.SystemRule; | |||
import com.alibaba.csp.sentinel.util.VersionUtil; | |||
/** | |||
* @author qinan.qn | |||
@@ -28,7 +29,7 @@ import com.alibaba.csp.sentinel.slots.system.SystemRule; | |||
*/ | |||
public final class Constants { | |||
public static final String SENTINEL_VERSION = "0.2.1"; | |||
public static final String SENTINEL_VERSION = VersionUtil.getVersion("0.2.1"); | |||
public final static int MAX_CONTEXT_NAME_SIZE = 2000; | |||
public final static int MAX_SLOT_CHAIN_SIZE = 6000; | |||
@@ -77,15 +77,6 @@ public class SentinelConfig { | |||
for (Object key : fileProps.keySet()) { | |||
SentinelConfig.setConfig((String)key, (String)fileProps.get(key)); | |||
try { | |||
String systemValue = System.getProperty((String)key); | |||
if (!StringUtil.isEmpty(systemValue)) { | |||
SentinelConfig.setConfig((String)key, systemValue); | |||
} | |||
} catch (Exception e) { | |||
RecordLog.info(e.getMessage(), e); | |||
} | |||
RecordLog.info(key + " value: " + SentinelConfig.getConfig((String)key)); | |||
} | |||
} | |||
} catch (Throwable ioe) { | |||
@@ -94,7 +85,13 @@ public class SentinelConfig { | |||
// JVM parameter override file config. | |||
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) { | |||
SentinelConfig.setConfig(entry.getKey().toString(), entry.getValue().toString()); | |||
String configKey = entry.getKey().toString(); | |||
String configValue = entry.getValue().toString(); | |||
String configValueOld = getConfig(configKey); | |||
SentinelConfig.setConfig(configKey, configValue); | |||
if (configValueOld != null) { | |||
RecordLog.info("JVM parameter overrides {0}: {1} -> {2}", configKey, configValueOld, configValue); | |||
} | |||
} | |||
} | |||
@@ -32,18 +32,20 @@ public class CommandCenterLog extends LogBase { | |||
logHandler = makeLogger(FILE_NAME, heliumRecordLog); | |||
} | |||
public static void info(String msg) { | |||
LoggerUtils.disableOtherHandlers(heliumRecordLog, logHandler); | |||
heliumRecordLog.log(Level.INFO, msg); | |||
public static void info(String detail, Object... params) { | |||
log(heliumRecordLog, logHandler, Level.INFO, detail, params); | |||
} | |||
public static void info(String detail, Throwable e) { | |||
log(heliumRecordLog, logHandler, Level.INFO, detail, e); | |||
} | |||
public static void info(String msg, Throwable e) { | |||
LoggerUtils.disableOtherHandlers(heliumRecordLog, logHandler); | |||
heliumRecordLog.log(Level.INFO, msg, e); | |||
public static void warn(String detail, Object... params) { | |||
log(heliumRecordLog, logHandler, Level.WARNING, detail, params); | |||
} | |||
public static void warn(String msg, Throwable e) { | |||
LoggerUtils.disableOtherHandlers(heliumRecordLog, logHandler); | |||
heliumRecordLog.log(Level.WARNING, msg, e); | |||
public static void warn(String detail, Throwable e) { | |||
log(heliumRecordLog, logHandler, Level.WARNING, detail, e); | |||
} | |||
} |
@@ -61,6 +61,26 @@ public class LogBase { | |||
} | |||
return logDir; | |||
} | |||
protected static void log(Logger logger, Handler handler, Level level, String detail, Object... params) { | |||
if (detail == null) { | |||
return; | |||
} | |||
LoggerUtils.disableOtherHandlers(logger, handler); | |||
if (params.length == 0) { | |||
logger.log(level, detail); | |||
} else { | |||
logger.log(level, detail, params); | |||
} | |||
} | |||
protected static void log(Logger logger, Handler handler, Level level, String detail, Throwable throwable) { | |||
if (detail == null) { | |||
return; | |||
} | |||
LoggerUtils.disableOtherHandlers(logger, handler); | |||
logger.log(level, detail, throwable); | |||
} | |||
/** | |||
* Get log file base directory path, the returned path is guaranteed end with {@link File#separator} | |||
@@ -32,24 +32,20 @@ public class RecordLog extends LogBase { | |||
static { | |||
logHandler = makeLogger(FILE_NAME, heliumRecordLog); | |||
} | |||
public static void info(String detail) { | |||
LoggerUtils.disableOtherHandlers(heliumRecordLog, logHandler); | |||
heliumRecordLog.log(Level.INFO, detail); | |||
public static void info(String detail, Object... params) { | |||
log(heliumRecordLog, logHandler, Level.INFO, detail, params); | |||
} | |||
public static void info(String detail, Throwable e) { | |||
LoggerUtils.disableOtherHandlers(heliumRecordLog, logHandler); | |||
heliumRecordLog.log(Level.INFO, detail, e); | |||
log(heliumRecordLog, logHandler, Level.INFO, detail, e); | |||
} | |||
public static void warn(String detail) { | |||
LoggerUtils.disableOtherHandlers(heliumRecordLog, logHandler); | |||
heliumRecordLog.log(Level.WARNING, detail); | |||
public static void warn(String detail, Object... params) { | |||
log(heliumRecordLog, logHandler, Level.WARNING, detail, params); | |||
} | |||
public static void warn(String detail, Throwable e) { | |||
LoggerUtils.disableOtherHandlers(heliumRecordLog, logHandler); | |||
heliumRecordLog.log(Level.WARNING, detail, e); | |||
log(heliumRecordLog, logHandler, Level.WARNING, detail, e); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.util; | |||
import com.alibaba.csp.sentinel.log.RecordLog; | |||
/** | |||
* Get Sentinel version from MANIFEST.MF | |||
* | |||
* @author jason | |||
* @since 0.2.1 | |||
*/ | |||
public class VersionUtil { | |||
public static String getVersion(String defaultVersion) { | |||
try { | |||
String version = VersionUtil.class.getPackage().getImplementationVersion(); | |||
return version == null || version.length() == 0 ? defaultVersion : version; | |||
} catch (Throwable e) { | |||
RecordLog.warn("return default version, ignore exception", e); | |||
return defaultVersion; | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
package com.alibaba.csp.sentinel.util; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
public class VersionUtilTest { | |||
@Test | |||
public void versionTest() { | |||
String version = VersionUtil.getVersion("1.0"); | |||
/** | |||
* manifest cannot be load before package | |||
*/ | |||
Assert.assertEquals("1.0", version); | |||
} | |||
} |
@@ -20,5 +20,10 @@ | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>fastjson</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -18,14 +18,17 @@ package com.alibaba.csp.sentinel.transport.command.netty; | |||
import java.util.Map; | |||
import java.util.Map.Entry; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.concurrent.TimeUnit; | |||
import com.alibaba.csp.sentinel.transport.config.TransportConfig; | |||
import com.alibaba.csp.sentinel.command.CommandHandler; | |||
import com.alibaba.csp.sentinel.log.CommandCenterLog; | |||
import com.alibaba.csp.sentinel.log.RecordLog; | |||
import com.alibaba.csp.sentinel.transport.config.TransportConfig; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
import io.netty.bootstrap.ServerBootstrap; | |||
import io.netty.channel.Channel; | |||
import io.netty.channel.ChannelFuture; | |||
import io.netty.channel.EventLoopGroup; | |||
import io.netty.channel.nio.NioEventLoopGroup; | |||
import io.netty.channel.socket.nio.NioServerSocketChannel; | |||
@@ -33,6 +36,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; | |||
/** | |||
* @author Eric Zhao | |||
*/ | |||
@SuppressWarnings("rawtypes") | |||
public final class HttpServer { | |||
private static final int DEFAULT_PORT = 8719; | |||
@@ -60,13 +64,40 @@ public final class HttpServer { | |||
} catch (Exception e) { | |||
throw new IllegalArgumentException("Illegal port: " + TransportConfig.getPort()); | |||
} | |||
channel = b.bind(port).sync().channel(); | |||
int retryCount = 0; | |||
ChannelFuture channelFuture = null; | |||
// loop for an successful binding | |||
while (true) { | |||
int newPort = getNewPort(port, retryCount); | |||
try { | |||
channelFuture = b.bind(newPort).sync(); | |||
TransportConfig.setRuntimePort(newPort); | |||
break; | |||
} catch (Exception e) { | |||
TimeUnit.MILLISECONDS.sleep(30); | |||
RecordLog.warn("netty server bind error, port={0}, retry={1}", newPort, retryCount); | |||
retryCount ++; | |||
} | |||
} | |||
channel = channelFuture.channel(); | |||
channel.closeFuture().sync(); | |||
} finally { | |||
workerGroup.shutdownGracefully(); | |||
bossGroup.shutdownGracefully(); | |||
} | |||
} | |||
/** | |||
* increase port number every 3 tries | |||
* | |||
* @param basePort | |||
* @param retryCount | |||
* @return | |||
*/ | |||
private int getNewPort(int basePort, int retryCount) { | |||
return basePort + retryCount / 3; | |||
} | |||
public void close() { | |||
channel.close(); | |||
@@ -52,6 +52,7 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
private static final int DEFAULT_SERVER_SO_TIMEOUT = 3000; | |||
private static final int DEFAULT_PORT = 8719; | |||
@SuppressWarnings("rawtypes") | |||
private static final Map<String, CommandHandler> handlerMap = new HashMap<String, CommandHandler>(); | |||
private ExecutorService executor = Executors.newSingleThreadExecutor( | |||
@@ -61,6 +62,7 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
private ServerSocket socketReference; | |||
@Override | |||
@SuppressWarnings("rawtypes") | |||
public void beforeStart() throws Exception { | |||
// Register handlers | |||
Map<String, CommandHandler> handlers = CommandHandlerProvider.getInstance().namedHandlers(); | |||
@@ -94,54 +96,56 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
@Override | |||
public void run() { | |||
int repeat = 0; | |||
int tmpPort = port; | |||
boolean success = false; | |||
while (true) { | |||
ServerSocket serverSocket = null; | |||
try { | |||
serverSocket = new ServerSocket(tmpPort); | |||
} catch (IOException ex) { | |||
CommandCenterLog.info( | |||
String.format("IO error occurs, port: %d, repeat times: %d", tmpPort, repeat), ex); | |||
tmpPort = adjustPort(repeat); | |||
try { | |||
TimeUnit.SECONDS.sleep(5); | |||
} catch (InterruptedException e1) { | |||
break; | |||
} | |||
repeat++; | |||
} | |||
if (serverSocket != null) { | |||
CommandCenterLog.info("[CommandCenter] Begin listening at port " + serverSocket.getLocalPort()); | |||
socketReference = serverSocket; | |||
executor.submit(new ServerThread(serverSocket)); | |||
success = true; | |||
break; | |||
} | |||
ServerSocket serverSocket = getServerSocketFromBasePort(port); | |||
if (serverSocket != null) { | |||
CommandCenterLog.info("[CommandCenter] Begin listening at port " + serverSocket.getLocalPort()); | |||
socketReference = serverSocket; | |||
executor.submit(new ServerThread(serverSocket)); | |||
success = true; | |||
port = serverSocket.getLocalPort(); | |||
} | |||
if (!success) { | |||
tmpPort = PORT_UNINITIALIZED; | |||
port = PORT_UNINITIALIZED; | |||
} | |||
TransportConfig.setRuntimePort(tmpPort); | |||
TransportConfig.setRuntimePort(port); | |||
executor.shutdown(); | |||
} | |||
/** | |||
* Adjust the port to settle down. | |||
*/ | |||
private int adjustPort(int repeat) { | |||
int mod = repeat / 5; | |||
return port + mod; | |||
} | |||
}; | |||
new Thread(serverInitTask).start(); | |||
} | |||
/** | |||
* Get a server socket from an avaliable port from a base port.<br> | |||
* Increasement on port number will happen when the port has already been | |||
* used.<br> | |||
* | |||
* @param basePort | |||
* @return | |||
*/ | |||
private static ServerSocket getServerSocketFromBasePort(int basePort) { | |||
int tryCount = 0; | |||
while (true) { | |||
try { | |||
ServerSocket server = new ServerSocket(basePort + tryCount / 3, 100); | |||
server.setReuseAddress(true); | |||
return server; | |||
} catch (IOException e) { | |||
tryCount ++; | |||
try { | |||
TimeUnit.MILLISECONDS.sleep(30); | |||
} catch (InterruptedException e1) { | |||
break; | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
@Override | |||
public void stop() throws Exception { | |||
@@ -204,10 +208,12 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
} | |||
} | |||
@SuppressWarnings("rawtypes") | |||
public static CommandHandler getHandler(String commandName) { | |||
return handlerMap.get(commandName); | |||
} | |||
@SuppressWarnings("rawtypes") | |||
public static void registerCommands(Map<String, CommandHandler> handlerMap) { | |||
if (handlerMap != null) { | |||
for (Entry<String, CommandHandler> e : handlerMap.entrySet()) { | |||
@@ -216,6 +222,7 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
} | |||
} | |||
@SuppressWarnings("rawtypes") | |||
public static void registerCommand(String commandName, CommandHandler handler) { | |||
if (StringUtil.isEmpty(commandName)) { | |||
return; | |||