• ElasticStack系列之七 & IK自动热更新原理与实现


    一、热更新原理

      elasticsearch开启加载外部词典功功能后,会每60s间隔进行刷新字典。具体原理代码如下所示:

    public void loadDic(HttpServletRequest req,HttpServletResponse response){
        String eTag =req.getParameter("If-None-Match");
        try {
            OutputStream out= response.getOutputStream();
            List<String> list=new ArrayList<String>();
            list.add("中华人民共和国");
            list.add("我爱你爱我");
            String oldEtag = list.size() + "";
            StringBuffer sb=new StringBuffer();
            if (oldEtag != eTag) {
                for (String str : list) {
                    if(StringUtils.isNotBlank(str)){
                        sb.append("
    ");
                    }
                    sb.append(str+"
    ");
                }
            }
            String data=sb.toString();
    
            response.setHeader("Last-Modified", String.valueOf(list.size()));
            response.setHeader("ETag",String.valueOf(list.size()));
            response.setContentType("text/plain; charset=gbk");
            out.write(data.getBytes());
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    二、配置说明

      我们公司以及用户常用的分词器为 IK 分词器,其中它有一个对应的核心配置文件名为:IKAnalyzer.cfg.xml,具体内容:

    <?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">custom/mydict.dic;custom/single_word_low_freq.dic</entry>  
         <!--用户可以在这里配置自己的扩展停止词字典-->  
        <entry key="ext_stopwords">custom/ext_stopword.dic</entry>  
        <!--用户可以在这里配置远程扩展字典 -->  
        <entry key="remote_ext_dict">location</entry>  
        <!--用户可以在这里配置远程扩展停止词字典-->  
        <entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>  
    </properties>

      热更新 IK 分词使用方法,目前该插件支持热更新 IK 分词,通过上文在 IK 配置文件中提到的如下配置

    <!--用户可以在这里配置远程扩展字典 -->  
    <entry key="remote_ext_dict">location</entry>  
    <!--用户可以在这里配置远程扩展停止词字典-->  
    <entry key="remote_ext_stopwords">location</entry> 

      其中 location 是指一个 url,比如 http://yoursite.com/getCustomDict,该请求只需满足以下两点即可完成分词热更新。
      该 http 请求需要返回两个头部(header)

      1. 一个是 Last-Modified,

      2. 一个是 ETag

      这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。
      该 http 请求返回的内容格式是一行一个分词,换行符用 即可。

      满足上面两点要求就可以实现热更新分词了,不需要重启 ES 实例。还需要注意的是获取词典的url,必须支持head访问

    下面自己做的访问远程扩展词典的web api 服务接口(这一步可以直接忽略,看第三个即可,这里只是想说明也可以使用下面这种方式)

    [HttpHead, HttpGet, HttpPost]  
    public async Task<HttpResponseMessage> GetDictionary(string path)  
    {  
        var response = this.Request.CreateResponse(HttpStatusCode.OK);  
        var content = File.ReadAllText(path);  
        response.Content = new StringContent(content, Encoding.UTF8);  
        response.Headers.Age = TimeSpan.FromHours(1);  
        response.Headers.ETag = EntityTagHeaderValue.Parse($""{content.ToMD5()}"");  
        return response;  
    }

    三、Tomcat 服务器自动更新

     1、部署http服务

      在这使用 tomcat8 作为 web 容器,先下载一个 tomcat8.5.16,然后上传到某一台服务器上(192.168.80.100)。

      再执行以下命令

    tar -zxvf apache-tomcat-8.5.16.tar.gz
    cd apache-tomcat-8.5.16/webapp/ROOT
    vim hot_ext.dic
    智能移动机器人
    vim hot_stopwords.dic
    项目

      之后验证一下这个文件是否可以正常访问   http://192.168.80.100:8080/hot.dic

      2、修改ik插件的配置文件

      修改 IK 核心配置文件 IKAnalyzer.cfg.xml 中的配置

    <?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">custom/mydict.dic;custom/single_word_low_freq.dic</entry>  
         <!--用户可以在这里配置自己的扩展停止词字典-->  
        <entry key="ext_stopwords">custom/ext_stopword.dic</entry>  
        <!--用户可以在这里配置远程扩展字典 -->  
        <entry key="remote_ext_dict">http://192.168.80.100:8080/hot_ext.dic</entry>  
        <!--用户可以在这里配置远程扩展停止词字典-->  
        <entry key="remote_ext_stopwords">http://192.168.80.100:8080/hot_stopwords.dic</entry>  
    </properties>

     3、验证

      重启es,会看到如下日志信息,说明远程的词典加载成功了。

      

      在浏览器中输入如下命令:http://localhost:9200/patent/_analyze?analyzer=ik_smart&text=智能移动机器人

      正常情况下会分出很多次,这次发现只有这一个词,不会被分词,说明刚才配置远程的词库生效了,那么我们再换一个:北京雾霾,正常情况下可能会被分成两个词:北京、雾霾,如果我直接修改 tomcat 下的 hot_ext.dic 词库文件,增加一个关键词:北京雾霾,文件保存之后,查看es的日志会看到如下日志信息:

      

      此时,再执行下面命令查看分词效果:http://localhost:9200/patent/_analyze?analyzer=ik_smart&text=北京雾霾

      结果就是只有一个词,不会被分词了。

      到这为止,可以实现动态添加自定义词库实现词库热更新。~~

      

  • 相关阅读:
    《The One!》团队作业4:基于原型的团队项目需求调研与分析
    《TheOne团队》团队作业三:团队项目原型设计与开发
    《The One 团队》第二次作业:团队项目选题
    《The One!团队》第一次作业:团队亮相
    实验十 团队作业6:团队项目系统设计改进与详细设计
    易校园——项目系统设计与数据库设计
    易校园--项目需求分析
    软工实践——团队上机作业
    团队编程第一次作业
    《发际线总是和我作队》第六次作业:团队项目系统设计改进与详细设计
  • 原文地址:https://www.cnblogs.com/liang1101/p/7282744.html
Copyright © 2020-2023  润新知