Code refactor and refinement for FileInJarReadableDataSource
Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
882a06007d
commit
df27e3ef9d
|
|
@ -31,6 +31,7 @@
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
<finalName>sentinel-demo-dynamic-file-rule</finalName>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
|
|
||||||
|
|
@ -39,24 +39,24 @@ import java.util.List;
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author dingq
|
* @author dingq
|
||||||
* @date 2019-03-30
|
|
||||||
*/
|
*/
|
||||||
public class JarFileDataSourceDemo {
|
public class JarFileDataSourceDemo {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
JarFileDataSourceDemo demo = new JarFileDataSourceDemo();
|
JarFileDataSourceDemo demo = new JarFileDataSourceDemo();
|
||||||
demo.listenRules();
|
demo.listenRules();
|
||||||
|
|
||||||
/*
|
// Start to require tokens, rate will be limited by rule of FlowRule.json in jar.
|
||||||
* Start to require tokens, rate will be limited by rule in FlowRule.json
|
|
||||||
*/
|
|
||||||
FlowQpsRunner runner = new FlowQpsRunner();
|
FlowQpsRunner runner = new FlowQpsRunner();
|
||||||
runner.simulateTraffic();
|
runner.simulateTraffic();
|
||||||
runner.tick();
|
runner.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listenRules() throws Exception {
|
private void listenRules() throws Exception {
|
||||||
String jarPath = System.getProperty("user.dir") + "/sentinel-demo/sentinel-demo-dynamic-file-rule/target/sentinel-demo-dynamic-file-rule-1.5.1-SNAPSHOT.jar";
|
// Modify the path with your real path.
|
||||||
// eg: if flowRuleInJarName full path is 'sentinel-demo-dynamic-file-rule-1.5.1-SNAPSHOT.jar!/classes/FlowRule.json',
|
String jarPath = System.getProperty("user.dir") + "/sentinel-demo/sentinel-demo-dynamic-file-rule/target/"
|
||||||
|
+ "sentinel-demo-dynamic-file-rule.jar";
|
||||||
|
// eg: if flowRuleInJarName full path is 'sentinel-demo-dynamic-file-rule.jar!/classes/FlowRule.json',
|
||||||
// your flowRuleInJarName is 'classes/FlowRule.json'
|
// your flowRuleInJarName is 'classes/FlowRule.json'
|
||||||
String flowRuleInJarPath = "FlowRule.json";
|
String flowRuleInJarPath = "FlowRule.json";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@
|
||||||
package com.alibaba.csp.sentinel.datasource;
|
package com.alibaba.csp.sentinel.datasource;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||||
import java.io.FileNotFoundException;
|
import com.alibaba.csp.sentinel.util.AssertUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
@ -25,65 +26,66 @@ import java.util.jar.JarFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* A {@link ReadableDataSource} based on jarfile. This class can only read file when it
|
* A {@link ReadableDataSource} based on jar file. This class can only read file initially when it loads file.
|
||||||
* run but will not automatically refresh if it is changed.
|
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* Limitations: Default read buffer size is 1 MB. If file size is greater than
|
* Limitations: Default read buffer size is 1 MB, while max allowed buffer size is 4MB.
|
||||||
* buffer size, exceeding bytes will be ignored. Default charset is UTF-8.
|
* File size should not exceed the buffer size, or exception will be thrown. Default charset is UTF-8.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author dingq
|
* @author dingq
|
||||||
* @date 2019-03-30
|
* @author Eric Zhao
|
||||||
|
* @since 1.6.0
|
||||||
*/
|
*/
|
||||||
public class FileInJarReadableDataSource<T> extends AutoRefreshDataSource<String, T> {
|
public class FileInJarReadableDataSource<T> extends AbstractDataSource<String, T> {
|
||||||
private static final int MAX_SIZE = 1024 * 1024 * 4;
|
|
||||||
private static final long DEFAULT_REFRESH_MS = 3000;
|
private static final int MAX_SIZE = 1024 * 1024 * 4;
|
||||||
private static final int DEFAULT_BUF_SIZE = 1024 * 1024;
|
private static final int DEFAULT_BUF_SIZE = 1024 * 1024;
|
||||||
private static final Charset DEFAULT_CHAR_SET = Charset.forName("utf-8");
|
private static final Charset DEFAULT_CHARSET = Charset.forName("utf-8");
|
||||||
|
|
||||||
private byte[] buf;
|
|
||||||
private JarEntry jarEntry;
|
|
||||||
private JarFile jarFile;
|
|
||||||
private final Charset charset;
|
private final Charset charset;
|
||||||
private final String jarName;
|
private final String jarName;
|
||||||
private final String fileInJarName;
|
private final String fileInJarName;
|
||||||
|
|
||||||
|
private byte[] buf;
|
||||||
|
private JarEntry jarEntry;
|
||||||
|
private JarFile jarFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param jarName the jar to read
|
* @param jarName the jar to read
|
||||||
* @param fileInJarName the file in jar to read
|
* @param fileInJarName the file in jar to read
|
||||||
* @param configParser the config decoder (parser)
|
* @param configParser the config decoder (parser)
|
||||||
* @throws FileNotFoundException
|
* @throws IOException if IO failure occurs
|
||||||
*/
|
*/
|
||||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser)
|
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
this(jarName, fileInJarName, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, DEFAULT_CHAR_SET);
|
this(jarName, fileInJarName, configParser, DEFAULT_BUF_SIZE, DEFAULT_CHARSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser, int bufSize)
|
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser,
|
||||||
throws IOException {
|
int bufSize) throws IOException {
|
||||||
this(jarName, fileInJarName, configParser, DEFAULT_REFRESH_MS, bufSize, DEFAULT_CHAR_SET);
|
this(jarName, fileInJarName, configParser, bufSize, DEFAULT_CHARSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser, Charset charset)
|
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser,
|
||||||
throws IOException {
|
|
||||||
this(jarName, fileInJarName, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, charset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser, long recommendRefreshMs, int bufSize,
|
|
||||||
Charset charset) throws IOException {
|
Charset charset) throws IOException {
|
||||||
super(configParser, recommendRefreshMs);
|
this(jarName, fileInJarName, configParser, DEFAULT_BUF_SIZE, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileInJarReadableDataSource(String jarName, String fileInJarName, Converter<String, T> configParser,
|
||||||
|
int bufSize, Charset charset) throws IOException {
|
||||||
|
super(configParser);
|
||||||
|
AssertUtil.assertNotBlank(jarName, "jarName cannot be blank");
|
||||||
|
AssertUtil.assertNotBlank(fileInJarName, "fileInJarName cannot be blank");
|
||||||
if (bufSize <= 0 || bufSize > MAX_SIZE) {
|
if (bufSize <= 0 || bufSize > MAX_SIZE) {
|
||||||
throw new IllegalArgumentException("bufSize must between (0, " + MAX_SIZE + "], but " + bufSize + " get");
|
throw new IllegalArgumentException("bufSize must between (0, " + MAX_SIZE + "], but " + bufSize + " get");
|
||||||
}
|
}
|
||||||
if (charset == null) {
|
AssertUtil.notNull(charset, "charset can't be null");
|
||||||
throw new IllegalArgumentException("charset can't be null");
|
|
||||||
}
|
|
||||||
this.buf = new byte[bufSize];
|
this.buf = new byte[bufSize];
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
this.jarName = jarName;
|
this.jarName = jarName;
|
||||||
this.fileInJarName = fileInJarName;
|
this.fileInJarName = fileInJarName;
|
||||||
refreshJar();
|
initializeJar();
|
||||||
firstLoad();
|
firstLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,29 +95,14 @@ public class FileInJarReadableDataSource<T> extends AutoRefreshDataSource<String
|
||||||
// Will throw FileNotFoundException later.
|
// Will throw FileNotFoundException later.
|
||||||
RecordLog.warn(String.format("[FileInJarReadableDataSource] File does not exist: %s", jarFile.getName()));
|
RecordLog.warn(String.format("[FileInJarReadableDataSource] File does not exist: %s", jarFile.getName()));
|
||||||
}
|
}
|
||||||
InputStream inputStream = null;
|
try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
|
||||||
try {
|
|
||||||
inputStream = jarFile.getInputStream(jarEntry);
|
|
||||||
if (inputStream.available() > buf.length) {
|
if (inputStream.available() > buf.length) {
|
||||||
throw new IllegalStateException(jarFile.getName() + " file size=" + inputStream.available()
|
throw new IllegalStateException(String.format("Size of file <%s> exceeds the bufSize (%d): %d",
|
||||||
+ ", is bigger than bufSize=" + buf.length + ". Can't read");
|
jarFile.getName(), buf.length, inputStream.available()));
|
||||||
}
|
}
|
||||||
int len = inputStream.read(buf);
|
int len = inputStream.read(buf);
|
||||||
return new String(buf, 0, len, charset);
|
return new String(buf, 0, len, charset);
|
||||||
} finally {
|
|
||||||
if (inputStream != null) {
|
|
||||||
try {
|
|
||||||
inputStream.close();
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isModified() {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void firstLoad() {
|
private void firstLoad() {
|
||||||
|
|
@ -123,17 +110,16 @@ public class FileInJarReadableDataSource<T> extends AutoRefreshDataSource<String
|
||||||
T newValue = loadConfig();
|
T newValue = loadConfig();
|
||||||
getProperty().updateValue(newValue);
|
getProperty().updateValue(newValue);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
RecordLog.info("loadConfig exception", e);
|
RecordLog.warn("[FileInJarReadableDataSource] Error when loading config", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
super.close();
|
|
||||||
buf = null;
|
buf = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshJar() throws IOException {
|
private void initializeJar() throws IOException {
|
||||||
this.jarFile = new JarFile(jarName);
|
this.jarFile = new JarFile(jarName);
|
||||||
this.jarEntry = jarFile.getJarEntry(fileInJarName);
|
this.jarEntry = jarFile.getJarEntry(fileInJarName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue