2016-12-28 19:34:33

Elasticsearch 2.X

elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。使用elasticsearch可以快速的构建一个全文检索集群帮助你实时搜索。

一、安装环境

JDK环境安装

Elasticsearch 默认需要安装jdk1.7+版本,首先需要下载 jdk7 选择与当前操作系统相适应的JDK版本下载Java SE Development Kit(JDK).

Linux:

选择Accept License Agreement,然后登陆Oracle账号就可以下载目前JDK7最新版的jdk-7u80-linux-x64.rpm 安装:

rpm -ivh jdk-7u80-linux-x64.rpm

环境变量:

vim ~/.bash_profile 在文件末尾添加

export JAVA_HOME=/usr/java/jdk1.7.0_80
export CLASS_PATH=./:$JAVA_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin

Windows:

根据操作操作系统位数选择对应的版本,这里下载jdk-7u80-windows-x64.exe进行安装.


安装好JDK后需要再配置环境变量,右键我的电脑->属性->高级->环境变量

新建变量:

1. JAVA_HOME指向JDK安装路径 C:\Program Files\Java\jdk1.7.0_80
2. CLASS_PATH指向%JAVA_HOME%\lib
3. 编辑原有的PATH,在末尾加上;%JAVA_HOME%\bin


Elasticsearch 安装

wget -c https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/zip/elasticsearch/2.0.0/elasticsearch-2.0.0.zip
unzip elasticsearch-2.0.0.zip

单机配置:

启动:

./bin/elasticsearch(windows下双击elasticsearch.bat)
后台方式启动:
./bin/elasticsearch -d

启动成功后会监听:9200(web api端)、9300(socket api)、54328(zen discovery udp广播).

建议修改掉elasticsearch默认端口9200和9300,这里修改为6200和6300这两个端口都不在nmap的常用1000个端口列表内.


elasticsearch 锁定内存配置

如果要修改ES锁定固定的内存大小需要在环境变量里设置,新建个ESHEAPSIZE。可以理解成指定一块固定的内存大小给elasticsearch使用。但是这个内存大小不要大于32G。

windows 新建环境变量:

ES_HEAP_SIZE=32G

linux:

export ES_HEAP_SIZE=32G

Windows 服务elasticsearch安装

需要注意的是一定记得用全路径,如:

d:/elasticsearch-x.x.x/bin/elasticsearch.bat install data-01

以前在本地测试多开ES的时候发现无法锁定内存,这样安装服务后可以避免无法读取ES_HEAP_SIZE问题。


二:中文分词

在默认情况下elasticsearch是不支持中文分词的,所以需要自行安装分词器以便于检索中文字符。这里采用elasticsearch-analysis-ik或者mmseg用于中文分词索引。

在elasticsearch安装目录新建文件夹:plugins

1、下载并安装Maven

Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。(Maven最新版3.3.9需要JDK7+版本支持)。

wget -c http://apache.fayea.com/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.zip

Linux:

  1. 配置环境变量:

    vim ~/.bash_profile

  2. 末尾添加:

export M2_HOME=/data/apache-maven-3.3.9
PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
Windows:
1. 新建环境变量M2_HOME指向JDK安装路径 C:\apache-maven-3.3.9\
2. 编辑原有的PATH,在末尾加上;%M2_HOME%\bin
2、安装elasticsearch-analysis-ik插件

Github: elasticsearch-analysis-ik

下载 elasticsearch-analysis-ik

解压elasticsearch-analysis-ik-master.zip

  1. 执行:mvn package (新版的ik在linux下可能会因为编码问题构建失败,用windows试试)

  2. 解压 target/releases/elasticsearch-analysis-ik-{version}.zip 并复制解压后的文件到elasticsearch安装文件夹,如:/data/elasticsearch-2.0.0/plugins/ik

  3. 复制elasticsearch-analysis-ik-master/config目录下的ik文件夹到 elasticsearch 的config文件夹,如:/data/elasticsearch-2.0.0/config/ik

3、安装elasticsearch-analysis-mmseg

Github: elasticsearch-analysis-mmseg

下载 elasticsearch-analysis-mmseg

解压elasticsearch-analysis-mmseg-master.zip

  1. 执行:mvn package

  2. 在elasticsearch安装目录下的plugins目录新建文件夹mmseg

  3. 构建完成后复制target目录下生成的elasticsearch-analysis-mmseg-1.5.0.jar、plugin-descriptor.properties到elasticsearch安装目录的plugins/mmseg文件夹。复制elasticsearch-analysis-mmseg-master/config/mmseg文件夹到elasticsearch安装目录的config文件夹。

三:Nginx HttpBasic认证

Elasticsearch启动后默认监听9200(netty-web端口)、9300(socket transport)。9200端口提供了RESTFUL查询支持比较方便。这里配置nginx代理为es的web接口添加负载和基础认证。

1、安装nginx

yum -y install nginx 
service nginx start
chkconfig nginx on
2、访问配置
vim /etc/nginx/conf.d/es.conf
添加:
server {
    server_name es.xxx.com;
    access_log  logs/es.access.log  main;
    listen 80;
    location / {
        proxy_pass http://localhost:6200;
        auth_basic "secret";
        auth_basic_user_file /etc/nginx/conf.d/es.db;
    }

    location /status {
        stub_status on;
        auth_basic "NginxStatus";
    }
}
下载htpasswd脚本,根据提示生成db文件:
wget http://p2j.cn/tools/htpasswd.sh

如此配置只能保证6200端口需授权访问,但是6300依旧可能直接访问。加上iptables或者安装elasticsearch Shield 插件。如果确认只对内网开放可以配置(network.bind_host为内网IP)。

四:集群

Elasticsearch会根据集群名称自动加入新的集群,所以只要保证集群名一样就行了。

1、集群配置

核心配置文件: config/elasticsearch.yml

node.name: "es-01"
cluster.name: "web-search"
node.master: true 是否设置为主节点,设置es-01为主节点。不设置也会自动选举。
elasticsearch 2.0版本开始network.host默认变成了127.0.0.1和::1,也就是说需要配置network.host才允许对外访问.如果要做内网集群这里需要写一个内外网IP地址.


可在elasticsearch.yml末尾加上一些优化配置:

bootstrap.mlockall: true
index.cache.field.type: soft
index.cache.field.max_size: 50000
index.cache.field.expire: 10m

复制已配置好的elasticsearch-2.0.0目录为elasticsearch-2.0.0-2(或者复制已配置好的elasticsearch-2.0.0目录到内网其他服务器)

修改: elasticsearch-2.0.0-2/config/elasticsearch.yml

修改节点配置:

node.name: "es-02"
cluster.name: "es-doc"
注释掉:#node.master: true
elasticsearch 1.x版本开始用多播来发现子网内的节点服务器,但是在elasticsearch 2.0版本开始已移除了集群多播自动发现(discovery-multicast).不过可以在elasticsearch.yml手动配置节点的IP地址.可以加端口,但端口是transport端口6300.
discovery.zen.ping.unicast.hosts: ["192.168.12.1", "192.168.12.2"]

当然2.0.0版本的用户也可以以插件的形式去安装discovery-multicast

sudo bin/plugin install discovery-multicast

2.0.0版本以上的用户可能会遇到如下错误:

ERROR: Plugin [${elasticsearch.plugin.name}] is incompatible with Elasticsearch [2.1.0]. Was designed for version [2.0.0]

五:测试

启动两个elasticsearch,如果配置了基础认证访问elasticsearch.yml的时候记得带上密码。

1、查看集群状态

http://账号:密码@localhost:6200/_cluster/health?pretty


可以看到:

{
        cluster_name: "web-search", 集群名字是web-search
        status: "green",    集群状态良好green
        timed_out: false,
        number_of_nodes: 2, 节点数2个
        number_of_data_nodes: 2,    存储节点2个
        active_primary_shards: 5,   主分片数5个
        active_shards: 10,  分片总数10个
        relocating_shards: 0,
        initializing_shards: 0,
        unassigned_shards: 0,   未分配的分片
        delayed_unassigned_shards: 0,
        number_of_pending_tasks: 0,
        number_of_in_flight_fetch: 0,
        task_max_waiting_in_queue_millis: 0,
        active_shards_percent_as_number: 100
}
2、创建索引
curl -XPUT http://localhost:6200/test
3、创建映射
curl -XPOST http://localhost:6200/test/fulltext/_mapping -d'
{
    "fulltext": {
        "_all": {
            "analyzer": "ik_max_word",
            "search_analyzer": "ik_max_word",
            "term_vector": "no",
            "store": "false"
        },
        "properties": {
            "content": {
                "type": "string",
                "store": "no",
                "term_vector": "with_positions_offsets",
                "analyzer": "ik_max_word",
                "search_analyzer": "ik_max_word",
                "include_in_all": "true",
                "boost": 8
            }
        }
    }
}'
4、添加索引
curl -XPOST http://localhost:6200/test/fulltext/1 -d'
{"content":"美国留给伊拉克的是个烂摊子吗"}'
curl -XPOST http://localhost:6200/test/fulltext/2 -d'
{"content":"公安部:各地校车将享最高路权"}'
curl -XPOST http://localhost:6200/test/fulltext/3 -d'
{"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"}'
curl -XPOST http:// localhost:6200/test/fulltext/4 -d'
{"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"}
5、搜索和搜索结果高亮
curl -XPOST http://localhost:6200/test/fulltext/_search  -d'
{
    "query" : { "term" : { "content" : "中国" }},
    "highlight" : {
        "pre_tags" : ["", ""],
        "post_tags" : ["", ""],
        "fields" : {
            "content" : {}
        }
    }
}
'

六:Java客户端

1、批量导入 添加elasticsearch-2.0.0.jar和lucene-core-5.2.1.jar

测试HtmlDoc.java:


import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.javaweb.utils.HttpRequestUtils;


public class HtmlDoc {
  
  public static void addIndex(Set<map<string,string>> ls){
    try {
      Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", "es-doc").put("client.transport.sniff", true).build();
      Client client = new TransportClient(settings).addTransportAddress(new InetSocketTransportAddress("localhost",6300));
      BulkRequestBuilder bulkRequest = client.prepareBulk();
      
      for(Map<string,string> doc:ls){
        bulkRequest.add(client.prepareIndex("domain", "documents").setSource(JSONObject.fromObject(doc).toString()));
      }
      
      BulkResponse bulkResponse = bulkRequest.execute().actionGet();
      if (bulkResponse.hasFailures()) {
        System.out.println("导入失败...");
      }else{
        System.out.println("导入成功...");
      }
      client.close();
    } catch (Exception e) {
      System.out.println(e.toString()+",导入异常.");
    }
  }
}
发表回复