ES 7.7.0 版本
ik分词字典更新,按照官方文档,采用本地词库+热更新方式
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">my_stars__sogou.dic;my_luxury_sogou.dic;</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">http://192.168.0.200:8085/ik/customerDict.txt</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
配置中的两个dic文件,是从sogou拼音官方下载的两个词库,然后使用"深蓝词库转换 imewlconverter"转换成纯文本文件。
热更新文件customerDict.txt
中每行一个词,以换行符\n
结尾。
测试的时候遇到一个奇怪的问题,达到108行的时候,就会更新失败。log中显示如下:
[2021-11-23T03:58:58,578][WARN ][stderr ] [ubuntuaben1] Nov 23, 2021 3:58:58 AM org.apache.http.impl.execchain.RetryExec execute
[2021-11-23T03:58:58,578][WARN ][stderr ] [ubuntuaben1] INFO: I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to {}->http://192.168.0.200:8085: The target server failed to respond
[2021-11-23T03:58:58,578][WARN ][stderr ] [ubuntuaben1] Nov 23, 2021 3:58:58 AM org.apache.http.impl.execchain.RetryExec execute
[2021-11-23T03:58:58,578][WARN ][stderr ] [ubuntuaben1] INFO: Retrying request to {}->http://192.168.0.200:8085
[2021-11-23T05:31:49,175][WARN ][stderr ] [ubuntuaben1] Nov 23, 2021 5:31:49 AM org.apache.http.impl.execchain.RetryExec execute
[2021-11-23T05:31:49,175][WARN ][stderr ] [ubuntuaben1] INFO: I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.0.200:8085: Connection reset
热更新的服务是放在nginx下的。正常情况下, 请求返回的header是:
Accept-Ranges: bytes
Content-Length: 992
Content-Type: text/plain; charset=utf-8
Date: Tue, 23 Nov 2021 05:41:40 GMT
ETag: "619c66ae-3e0"
Last-Modified: Tue, 23 Nov 2021 03:57:34 GMT
Server: nginx
异常时, 返回的是:
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Date: Tue, 23 Nov 2021 05:42:19 GMT
ETag: W/"619c7f33-413"
Last-Modified: Tue, 23 Nov 2021 05:42:11 GMT
Server: nginx
Transfer-Encoding: chunked
Vary: Accept-Encoding
so, 很明显了, 这是nginx启用了gzip压缩导致的,而ik
7.7.0版本的插件尚不支持gzip。
要么在nginx中关闭gzip, 但是nginx不支持指定站点设置gzip off
,蛋疼ing....
看来就剩一条路了:改源码,使其支持gzip
网上有改源码,直接去连接mysql
经过测试, ES7.15.2中已经解决了此问题, 下图是插件主要修改的地方
值得注意的是,在数据没有变更(就是返回304状态,可以从nginx的access日志中看到)时,ES7.7版本的ik也是会出现前面的异常,目前测试来看只是请求的间隔时间从1分钟延长到了2分钟,7分钟,2分钟。。。。。
旧版本的问题归结为2个:
- 服务端启用了gzip的问题
- 服务端返回304的问题
新版本7.15.2
也还是有304
的问题.
但是在源码src\main\java\org\wltea\analyzer\dic\Monitor.java
的方法runUnprivileged
中有做了处理啊:
/**
* 监控流程:
* ①向词库服务器发送Head请求
* ②从响应中获取Last-Modify、ETags字段值,判断是否变化
* ③如果未变化,休眠1min,返回第①步
* ④如果有变化,重新加载词典
* ⑤休眠1min,返回第①步
*/
public void runUnprivileged() {
//超时设置
RequestConfig rc = RequestConfig.custom().setConnectionRequestTimeout(10*1000)
.setConnectTimeout(10*1000).setSocketTimeout(15*1000).build();
HttpHead head = new HttpHead(location);
head.setConfig(rc);
//设置请求头
if (last_modified != null) {
head.setHeader("If-Modified-Since", last_modified);
}
if (eTags != null) {
head.setHeader("If-None-Match", eTags);
}
CloseableHttpResponse response = null;
try {
response = httpclient.execute(head);
//返回200 才做操作
if(response.getStatusLine().getStatusCode()==200){
if (((response.getLastHeader("Last-Modified")!=null) && !response.getLastHeader("Last-Modified").getValue().equalsIgnoreCase(last_modified))
||((response.getLastHeader("ETag")!=null) && !response.getLastHeader("ETag").getValue().equalsIgnoreCase(eTags))) {
// 远程词库有更新,需要重新加载词典,并修改last_modified,eTags
Dictionary.getSingleton().reLoadMainDict();
last_modified = response.getLastHeader("Last-Modified")==null?null:response.getLastHeader("Last-Modified").getValue();
eTags = response.getLastHeader("ETag")==null?null:response.getLastHeader("ETag").getValue();
}
}else if (response.getStatusLine().getStatusCode()==304) {
//没有修改,不做操作
//noop
}else{
logger.info("remote_ext_dict {} return bad code {}" , location , response.getStatusLine().getStatusCode() );
}
} catch (Exception e) {
logger.error("remote_ext_dict {} error!",e , location);
}finally{
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
TODO....