调用如下代码:RegionUtil.getRegion(ip) 方法。持续最高5个并发请求。平均比不加多了大约1.5s。
public class RegionUtil
{
private static final Logger log = LoggerFactory.getLogger(RegionUtil.class);
private static final String JAVA_TEMP_DIR = "java.io.tmpdir";
// file(完全基于文件的查询),vectorIndex(缓存VectorIndex索引),content(缓存整个xdb数据)
// 本工具类仅支持使用“缓存整个xdb数据”方式处理。(file和vectorIndex方式非线程安全,需要将工具类优化为不同线程不同对象方式解决。)
private static final String SEARCHER_TYPE = "content";
static Searcher searcher = null;
/**
* 初始化IP库
*/
static
{
try
{
// 因为jar无法读取文件,复制创建临时文件
String dbPath = RegionUtil.class.getResource("/ip2region/ip2region.xdb").getPath();
File file = new File(dbPath);
if (!file.exists())
{
String tmpDir = System.getProperties().getProperty(JAVA_TEMP_DIR);
dbPath = tmpDir + "ip2region.xbd";
file = new File(dbPath);
ClassPathResource cpr = new ClassPathResource("ip2region" + File.separator + "ip2region.xdb");
InputStream resourceAsStream = cpr.getInputStream();
if (resourceAsStream != null)
{
FileUtils.copyInputStreamToFile(resourceAsStream, file);
}
}
if ("file".equals(SEARCHER_TYPE)) {
searcher = Searcher.newWithFileOnly(dbPath);
} else {
byte[] cBuff;
if ("vectorIndex".equals(SEARCHER_TYPE)) {
cBuff = Searcher.loadVectorIndexFromFile(dbPath);
searcher = Searcher.newWithVectorIndex(dbPath, cBuff);
} else if ("content".equals(SEARCHER_TYPE)) {
cBuff = Searcher.loadContentFromFile(dbPath);
searcher = Searcher.newWithBuffer(cBuff);
} else {
throw new IOException("invalid cache policy `" + SEARCHER_TYPE + "`, options: file/vectorIndex/content");
}
}
log.info("bean [{}]", searcher);
}
catch (Exception e)
{
log.error("init ip region error:{}", e);
}
}
/**
* 解析IP
*
* @param ip
* @return
*/
public static String getRegion(String ip)
{
try
{
if (searcher == null || StringUtils.isEmpty(ip))
{
log.error("Searcher is null");
return StringUtils.EMPTY;
}
long startTime = System.currentTimeMillis();
// 检查ip
Searcher.checkIP(ip);
String result = searcher.search(ip);
long endTime = System.currentTimeMillis();
log.debug("region use time[{}] result[{}]", endTime - startTime, result);
return result;
}
catch (Exception e)
{
log.error("error:{}", e);
}
return StringUtils.EMPTY;
}
}
仔细检查你的代码逻辑,问题很明显,你先打个日志确保逻辑如你所构思的。
xdb文件在jar里面就先读取出来,整个xdb buffer起来。
或者直接丢到jar外面。
大佬,初始化ip的地方加了三个打印,验证执行顺序。小弟不理解的是xdb于第一次访问的时候缓存起来了,请求也正常,就是部分外网访问的时候慢。
static
{
try
{
// 因为jar无法读取文件,复制创建临时文件
String dbPath = RegionUtil.class.getResource("/ip2region/ip2region.xdb").getPath();
File file = new File(dbPath);
if (!file.exists())
{
log.info("==============11111111111111==============");
String tmpDir = System.getProperties().getProperty(JAVA_TEMP_DIR);
dbPath = tmpDir + "ip2region.xbd";
file = new File(dbPath);
ClassPathResource cpr = new ClassPathResource("ip2region" + File.separator + "ip2region.xdb");
InputStream resourceAsStream = cpr.getInputStream();
if (resourceAsStream != null)
{
log.info("==============222222222222==============");
FileUtils.copyInputStreamToFile(resourceAsStream, file);
}
}
if ("file".equals(SEARCHER_TYPE)) {
searcher = Searcher.newWithFileOnly(dbPath);
} else {
byte[] cBuff;
if ("vectorIndex".equals(SEARCHER_TYPE)) {
cBuff = Searcher.loadVectorIndexFromFile(dbPath);
searcher = Searcher.newWithVectorIndex(dbPath, cBuff);
} else if ("content".equals(SEARCHER_TYPE)) {
log.info("==============33333333333333==============");
cBuff = Searcher.loadContentFromFile(dbPath);
searcher = Searcher.newWithBuffer(cBuff);
} else {
throw new IOException("invalid cache policy `" + SEARCHER_TYPE + "`, options: file/vectorIndex/content");
}
}
log.info("bean [{}]", searcher);
}
catch (Exception e)
{
log.error("init ip region error:{}", e);
}
}
日志:
11:27:18.639 [schedule-pool-1] INFO c.h.c.u.RegionUtil - [,43] - ==============11111111111111==============
11:27:18.639 [schedule-pool-1] INFO c.h.c.u.RegionUtil - [,51] - ==============222222222222==============
11:27:18.761 [schedule-pool-1] INFO c.h.c.u.RegionUtil - [,64] - ==============33333333333333==============
11:27:18.774 [schedule-pool-1] INFO c.h.c.u.RegionUtil - [,71] - bean [org.lionsoul.ip2region.xdb.Searcher@57f30478]
11:27:18.775 [schedule-pool-1] INFO c.h.c.u.RegionUtil - [getRegion,99] - region use time[0] result[0|0|0|ĚIP|ĚIP]
11:27:18.779 [schedule-pool-1] INFO sys-user - [run,55] - [10.81.4.91]0 ĚIP[admin][Logout][͋³ö³ɹ¦]
11:27:41.400 [schedule-pool-1] INFO c.h.c.u.RegionUtil - [getRegion,99] - region use time[0] result[0|0|0|ĚIP|ĚIP]
11:27:41.400 [schedule-pool-1] INFO sys-user - [run,55] - [10.81.4.91]0 ĚIP[admin][Success][µǂ¼³ɹ¦]
11:27:41.475 [http-nio-8080-exec-3] INFO c.h.c.u.RegionUtil - [getRegion,99] - region use time[0] result[0|0|0|ĚIP|ĚIP]
11:28:36.928 [schedule-pool-2] INFO c.h.c.u.RegionUtil - [getRegion,99] - region use time[0] result[0|0|0|ĚIP|ĚIP]
11:28:36.928 [schedule-pool-2] INFO sys-user - [run,55] - [10.81.4.91]0 ĚIP[admin][Logout][͋³ö³ɹ¦]
11:28:54.813 [schedule-pool-1] INFO c.h.c.u.RegionUtil - [getRegion,99] - region use time[0] result[0|0|0|ĚIP|ĚIP]
11:28:54.814 [schedule-pool-1] INFO sys-user - [run,55] - [10.81.4.91]0 ĚIP[admin][Success][µǂ¼³ɹ¦]
11:28:54.834 [http-nio-8080-exec-17] INFO c.h.c.u.RegionUtil - [getRegion,99] - region use time[0] result[0|0|0|ĚIP|ĚIP]
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
第一,你这里是有个 bug 吧:
String tmpDir = System.getProperties().getProperty(JAVA_TEMP_DIR);
dbPath = tmpDir + "ip2region.xbd";
file = new File(dbPath);
检测用的 xdb,临时文件怎么又变成了 xbd 了。
第二,getRegion方法对于 基于文件 和 vector 索引的方法都是 非线程安全的 ,文档有明确说明,你这每一次拷贝一个 xdb 怎么快的起来。
仔细想清楚自己的使用逻辑在具体产品中的执行情况,我觉得这个问题与项目本身无关
大佬, 我这边 知道文件和vector是非线程安全的,所以配置的是content。文件和vector只是暂时写了判断,但是没有构思具体以后时候使用。( 明确项目里一直使用的content方式 ),xbd这个bug确实没发现,感谢大佬,有无可能是这个bug导致查询慢,我去验证一下。
// file(完全基于文件的查询),vectorIndex(缓存VectorIndex索引),content(缓存整个xdb数据)
// 本工具类仅支持使用“缓存整个xdb数据”方式处理。(file和vectorIndex方式非线程安全,需要将工具类优化为不同线程不同对象方式解决。)
private static final String SEARCHER_TYPE = "content";
登录 后才可以发表评论