• 【Elastic2】SpringBoot整合ELK、SpringBoot写ES


    ELK相关TODO

    Kafka相关TODO

    前言

    ​ 快速开始文档中,讲解了ELK三个组件的下载、安装、配置、启动等过程。只要按照文章走一下,就可以看到一个单机版的ELK三件套。本文会带你整合SpringBoot、ELK、Kafka,组成最常见的日志系统。当然,这套组合不仅能作为日志系统,也能作为大数据流处理的前半部分(数据的收集)。后面也会带来大数据相关的随笔文章。本文也会附带相关源码,链接如下:

    Github:https://github.com/MrLing1997/elasticsearch-study

    依赖导入

    ​ 虽然整合的是SpringBoot,但是为了方便前期学习、理解,我们就不用SpringData Elasticsearch的starter了。在熟悉了ES官方提供的Java客户端后,可以再使用SpringData Elasticsearch,其提供了很多非常方便的注解。除了注解,还有starter提供的自动配置等功能。更多相关功能和用法可以自行去查看Spring Data官方文档或相关博客。

    ​ 这里我们只导入ES提供的Java客户端,然后手动去初始化ES。注意导入的版本,最好和服务器的ES版本保持一致。但是由于前段时间log4j的漏洞,导致7.14之前的版本全都被遗弃了,所以这里最低只能导入7.14版本。不过只要版本差距不大,一般不会有问题。

    <!-- Elasticsearch服务 -->
    <!-- 生成环境中,依赖版本最好和服务器的ES的版本保持一致,因为log4j的漏洞,7.14.0之前的部分依赖被遗弃无法成功下载-->
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>7.14.0</version>
    </dependency>
    <!-- Elasticsearch Java高级客户端 -->
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.14.0</version>
    </dependency>
    

    初始化ES客户端

    ​ 首先去yml或properties添加配置信息。这个配置key不是上面的jar包提供的,而是我们自己自定义的,然后通过@Value注解获取值。所以你的key不一定要和我一样。配置如下:

    elasticsearch:
      host: ip
      port: port
    

    ​ 然后初始化RestHighLevelClient即可:

    @Configuration
    @Slf4j
    public class ElasticSearchConfig{
        @Value("${elasticsearch.host}")
        private String host;
        @Value("${elasticsearch.port}")
        private int port;
    
        @Bean
        public RestHighLevelClient restHighLevelClient() {
            RestHighLevelClient restHighLevelClient = null;
            try {
                log.info("elasticsearch start init...");
                restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost(host, port, "http")));
                log.info("elasticsearch init success!");
            }catch (Exception e){
                log.error("elasticsearch init had exception:{}", ExceptionUtils.getStackTrace(e));
            }
            return restHighLevelClient;
        }
    }
    

    造数据

    ​ 自己手动编两个数据总觉得不带劲,一是数据量太少,二是太麻烦。我这里推荐一个开源的,自动生成数据的工具,依赖如下,记得排除snakeyaml,可能会和你的springboot中的yaml产生冲突。

    				<dependency>
                <groupId>com.github.javafaker</groupId>
                <artifactId>javafaker</artifactId>
                <version>1.0.2</version>
                <exclusions>
                    <exclusion>
                        <artifactId>snakeyaml</artifactId>
                        <groupId>org.yaml</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    ​ 造数据的工具类和实体类很简单,直接贴一下代码:

    @Data
    @Accessors(chain = true)
    public class User {
        private Long id;
        private String traceId;
        private String name;
        private String birthday;
        private String job;
        private String address;
        private String company;
    }
    
    public class GenerateUserUtil {
        private static final Faker faker = new Faker();
    
        public static User generate(){
            return new User()
                    .setId(System.currentTimeMillis())
                    .setTraceId(UUID.randomUUID().toString())
                    .setName(faker.name().name())
                    .setBirthday(DateFormat.format(faker.date().birthday(18,60)))
                    .setJob(faker.job().title())
                    .setAddress(faker.address().fullAddress())
                    .setCompany(faker.company().name());
        }
    }
    

    往ES写数据

    ​ 往ES写数据之前,需要新建索引、定义mapping。根据你的实体类然后定义mapping即可。下面一共有三个类,ESConstant中定义了索引常量字符串和mapping。ESUtil封装了RestHighLevelClient,向外提供了创建索引和添加文档两个方法。WriteLogService模拟业务的服务类,不停产生数据和写日志。

    public class ESConstant {
        public static final String ES_USER_INDEX_PREFIX = "user";
    
        public static final String MAPPING ="{\n" +
                "        \"properties\": {\n" +
                "          \"id\":{\n" +
                "            \"type\": \"long\"\n" +
                "          },\n" +
                "          \"traceId\":{\n" +
                "            \"type\": \"keyword\"\n" +
                "          },\n" +
                "          \"name\":{\n" +
                "            \"type\": \"text\"\n" +
                "            , \"analyzer\": \"standard\"\n" +
                "          },\n" +
                "          \"birthday\":{\n" +
                "            \"type\": \"date\"\n" +
                "          },\n" +
                "          \"job\":{\n" +
                "            \"type\": \"text\"\n" +
                "            , \"analyzer\": \"standard\"\n" +
                "          },\n" +
                "          \"address\":{\n" +
                "            \"type\": \"text\"\n" +
                "            , \"analyzer\": \"standard\"\n" +
                "          },\n" +
                "          \"company\":{\n" +
                "            \"type\": \"text\"\n" +
                "            , \"analyzer\": \"standard\"\n" +
                "          }\n" +
                "        }\n" +
                "    }";
    
    }
    
    @Component
    public class ESUtil {
        @Autowired
        RestHighLevelClient restHighLevelClient;
    
        public void createIndex(String indexName,String mapping,int shards,int replicas) throws IOException {
            CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
            //设置索引的配置,1个分片1个副本。由于我们是单机ES,这个配置无关紧要,正式的线上环境记得要配置
            HashMap<String,String> indexOption = new HashMap<>();
            indexOption.put("index.number_of_shards",String.valueOf(shards));
            indexOption.put("index.number_of_replicas",String.valueOf(replicas));
            createIndexRequest.settings(indexOption);
            //设置索引mapping,即字段的定义
            createIndexRequest.mapping(mapping, XContentType.JSON);
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        }
    
        public void addDocument(String document,String indexName) throws IOException {
            IndexRequest indexRequest = new IndexRequest(indexName);
            indexRequest.source(document,XContentType.JSON);
            restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        }
    }
    
    @Service
    @Slf4j
    public class WriteLogService implements CommandLineRunner{
        @Autowired
        RestHighLevelClient restHighLevelClient;
        @Autowired
        ESUtil esUtil;
    
        private static final Gson gson = new GsonBuilder().serializeNulls().create();
    
        @Override
        public void run(String... args) {
            try {
                //运行前检查索引是否存在,不存在就新建一个
                if (!restHighLevelClient.indices().exists(new GetIndexRequest(ES_USER_INDEX_PREFIX), RequestOptions.DEFAULT)) {
                    esUtil.createIndex(ES_USER_INDEX_PREFIX, MAPPING, 1, 1);
                }
                while (true) {
                    String user = gson.toJson(GenerateUserUtil.generate());
                    log.info("generate user:{}", user);
                    esUtil.addDocument(user, ES_USER_INDEX_PREFIX);
                    Thread.sleep(1000);
                }
            }catch (Exception e){
                log.error("service had exception:{}", ExceptionUtils.getStackTrace(e));
            }
        }
    }
    

    ​ 写入成功之后,就可以去Kibana的index Manager中添加user索引了。

  • 相关阅读:
    过滤器判断请求参数中是否含有某一字段
    vscode开发vue项目实现pc端自适应_cssrem_rem_reset.scss,pc端媒体查询常用设置
    element_ui的datePicker修改样式
    TCP/IP 卷一 APR、RAPR、ICMP
    TCP/IP 卷一:协议(IP层)
    常见负载均衡策略
    TCP/IP 卷一:协议(链路层)
    TCP/IP 卷一:协议(概述)
    RokcetMQ
    Zookeeper集群
  • 原文地址:https://www.cnblogs.com/lbhym/p/15948064.html
Copyright © 2020-2023  润新知