请选择 进入手机版 | 继续访问电脑版

elk+rabbitmq+springboot快速搭建日志系统

[复制链接]
小甜心 发表于 2021-1-1 18:32:58 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
elk+rabbitmq+springboot日志系统搭建说明

一、情况摆设

1、使用工具(xshell等)远程毗连到110服务器,首先摆设好 elk (ElasticSearch,logstash,kibana) 和 rabbitmq
  elk和rabbitmq我先前已经在110服务器用docker摆设好了,详细摆设步调自行查阅资料。(110服务器只是我当时使用的服务器地点,不消在意。)
2、进入logstash举行设置
  如果创建logstash容器时使用 -v 绑定了某个卷,则不需要进入logstash容器内部。


  • 使用下令进入容器 (“logstash”是创建该容器时自界说的容器名字)
  1. docker exec -it logstash bash
复制代码


  • 乐成进入后,进入config内查看 pipelines.yml 文件(7.0以下的旧版设置不在这里,发起使用新版)



  • pipelines.yml文件中告诉了我们它启动是根据哪个路径的设置文件运行,我们找到对应的这个路径。



  • 进入后我们看到此中有个默认的启动设置文件 logstash.conf(我已经给它加了个.backup后缀)



  • 我们添加自己需要的设置,我这里已经添加好了 (logstash-mq.conf)
  1. #日志信息会在项目中发送到mq中(下面会有在项目中的设置),我们要从mq中拿到日志信息input {   #平凡利用日志在下面设置的队列   rabbitmq {       type =>"operation"       durable => true       exchange => "log.exchange.direct"       exchange_type => "direct"       key => "log_operation"       host => "172.17.0.1"       port => 5672       user => "superadmin"       password => "admin2020"       queue => "QUEUE_LOG_OPERATION"       auto_delete => false  } #上送指令的日志存在了下面设置的队列 rabbitmq {       type =>"upmsg"       durable => true       exchange => "log.exchange.direct"       exchange_type => "direct"       key => "log_up_msg"       host => "172.17.0.1"       port => 5672       user => "superadmin"       password => "admin2020"       queue => "QUEUE_LOG_UP_MSG"       auto_delete => false  } #下发指令的日志存在了下面设置的队列 rabbitmq {       type =>"downmsg"       durable => true       exchange => "log.exchange.direct"       exchange_type => "direct"       key => "log_down_msg"       host => "172.17.0.1"       port => 5672       user => "superadmin"       password => "admin2020"       queue => "QUEUE_LOG_DOWN_MSG"       auto_delete => false  }}#我们要输出到es,把日志信息存在es中,差别日志发到差别的索引中output {    #下发指令    if "downMsg" in [message]{        elasticsearch {                hosts => ["172.17.0.1:9200"]                index => "downmsg-log-%{+YYYY.MM.dd}"        }    }    #上送指令    else if "upMsg" in [message] {         elasticsearch {                hosts => ["172.17.0.1:9200"]                index => "upmsg-log-%{+YYYY.MM.dd}"         }    }    #平凡利用指令    else {        elasticsearch {                hosts => ["172.17.0.1:9200"]                index => "operation-log-%{+YYYY.MM.dd}"         }    }}
复制代码
【说明】

  • input就是logstash是设置好的队列的消费者,从队列拿到数据后 output 输出到es中,它会把数据放到动态生成的索引中,你可以把索引当成数据库。logstash可以用来过滤数据, input -> filter -> output,固然我这里没有设置,以后有空我会写个更加详细的说明,更多花里胡哨的利用可以阅读logstash官方文档。
  • 这里的 ip地点 172.17.0.1 你可以当作 110服务器中的docker容器之间沟通的地点,你也可以配成可以访问的ip加端口。
  • 【message】字段存放的就是推送到mq中详细的日志信息,这个 “upMsg” in [message]就是判断这个字段中有没有“upMsg”字符串,反面我会说这个字符串那里来的,通过这个我们将差别范例的日志放到差别索引中;”%{+YYYY.MM.dd}"这个很显着就是获取当天的日期了。天天的日志存在一个索引中。
    (ps:你大概想说,这个判断能不能缩小范围,这样写似乎重复了挺多代码,答案是不能,原因我还未找到。你还想说,这个“upmsg”索引名不是驼峰定名,那就注意了:es中的索引名只能小写。)
  • 更多详细设置后续需要可以自行更改,例如 output 那里可以设置数据到了多少条批量输出到es。


  • 之后我们使用exit下令退出容器并重启容器(restart),进入mq的管理界面,队列、互换机等都会自动生成给我们,固然你自己事先添加也可以。当数据量够了,就会在es中找到大概生成我们设置的索引并存放数据。
二、集成到SpringBoot项目

【添加设置】

1、logback依赖,在maven项目中引入下面这个依赖就会帮我们引入logback相关依赖,详细可以点进入去搜索一下。
  1.     org.springframework.boot    spring-boot-starter-parent    2.3.2.RELEASE
复制代码
2、现在我们已经搭建好了底子情况,我们现在要把项目中的日志信息发送到mq中,我们需要添加一个设置
文件 logback-spring.xml,该文件在项目中的 common-web 模块的resource下(这只是我当时编写时的地方,不消在意),下面是日志写入mq的详细设置,这里的 appender 设置项要和刚才 input 中的设置信息相同。
  1.                                        ${serverName}                                                        ${CONSOLE_LOG_PATTERN}            ${LOG_CHARSET}                                          ${LOG_PATTERN}            ${LOG_CHARSET}                        192.168.0.110:5672        36        true        log_up_msg        superadmin        admin2020        true        direct                log.exchange.direct                log_up_msg        true        UTF-8        true        NON_PERSISTENT        true        false                                        ${LOG_PATTERN}              ${LOG_CHARSET}                        192.168.0.110:5672        36        true        log_down_msg        superadmin        admin2020        true        direct        log.exchange.direct        log_down_msg        true        UTF-8        true        NON_PERSISTENT        true        false                            ${LOG_PATTERN}            ${LOG_CHARSET}                        192.168.0.110:5672        36        true        log_operation        superadmin        admin2020        true        direct        log.exchange.direct                log_operation        true        UTF-8        true        NON_PERSISTENT        true        false                                                                                       
复制代码
【说明】
1、主要看 appender 标签,这个标签体现你的日志要去那里, logger 标签体现你的日志在项目的什么地方拿的,比如你在某个类写个日志 log.info(“xxx”),你可以在 logger的name属性指定该类的包,大概直接指定这个类,然后用 appender-ref 子标签体现你想让这个类的日志输出到哪个appender,我们这里的 appender 设置了mq,这样日志就会发送到你指定的队列了。至于 root 标签,只要你在 logger 标签中指明 additivity=“true” ,那这个logger就成了 root标签的儿子,会把拿到的日志继承输出到 root标签指定的 appender中。
2、这个 appender的name属性值会添加到每条推送到这个appender的日志消息中,也就是上述message字段会存在这个name属性。
3、你可以在某个控制层大概业务层中的方法中用切面添加详细的日志(log.info(“x请求了x服务”),然后用logger指向这个切面类,你可以把差别范例的日志放到差别切面类中,然后用logger的name属性来指定。固然也可以不消切面,直接用logger的name指定某包下大概某类下的日志收集为一种日志范例。
【测试】

1、设置好后,我们做一些测试。我们在springboot项目中添加一个测试类,可以看到我在项目启动时会输出102条日志信息。(这个类在 org.zzz包下,对应上面 logger标签界说的name属性,这样会发送到三个队列中,)
  1. @Component@Slf4jpublic class Init implements ApplicationRunner {    @Override    public void run(ApplicationArguments args) throws Exception {        for (int i = 0; i < 102; i++) {            log.info("我只是一条无聊的测试日志,我要去mq,然后再去logstash,然后再去es");        }    }}
复制代码
2、启动乐成后,我们打开192.168.0.110:9100(管理工具es-head,摆设在110的docker),毗连到9200端口的es,可以看到索引已经创建 ,此中的文档数据,就是logstash从队列中拿过来然后放在这的。
因为我们把这个日志发到了三个差别队列,一开始我们在logstash设置的input是从这三个队列中拿的日志数据,output就是差别队列的日志创建或找到差别的索引;可以看到本日的(2020.12.31)在一个新的索引,昨天的(2020.12.30)是另一个索引。

3、我们点击 根本查询 ,选择想要查找的索引,must match_all是查询全部

4、点击搜索,此中的 message字段就是 日志信息。

5、我们进入 192.168.0.110:5601 kibana的管理界面,进入 菜单中的dev tools

6、我们可以通过 rest 请求 来利用和查看es中的详细数据,中括号中的字段就是一个查询条件的写法,可以自行学习es官方文档。log_mq就是一个索引名,你可以把它当成我要查哪个数据库。

【说明】kibana是个强大的工具,我这里就不详细说明白,可以自行学习。
【添加es的工具类,在项目中查看或利用】

1、添加依赖(版本号随引入的springboot的依赖版本)
  1.              org.springframework.boot            spring-boot-starter-data-elasticsearch
复制代码
2、我们在application.yml设置文件中添加es的uri(有许多设置的方式,只要你能连上es就行)
  1. spring:   elasticsearch:    rest:      uris: 192.168.0.110:9200
复制代码
3、接下我们使用 ElasticsearchRestTemplate 来举行利用,实际底层也是request response的请求响应而已。
  1. @Componentpublic class ElasticSearchUtil {    @Autowired    private ElasticsearchRestTemplate elasticsearchRestTemplate;    /**     * @Description: 创建索引(可批量)     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:53     * @param indexName     * @return {@link boolean}     */    public boolean createIndex(String... indexName) {        return elasticsearchRestTemplate.indexOps(IndexCoordinates.of(indexName)).create();    }    /**     * @Description: 建索引相当于给实体类建库,实体类要加上注解 @Document(indexName = "test")     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 11:18     * @param clazz     * @return {@link boolean}     */    public  boolean createIndex(Class clazz) {        return elasticsearchRestTemplate.indexOps(clazz).create();    }    /**     * @Description: 删除索引     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:53     * @param indexName     * @return {@link boolean}     */    public boolean deleteIndex(String... indexName) {        return elasticsearchRestTemplate.indexOps(IndexCoordinates.of(indexName)).delete();    }    /**     * @Description: 删除实体类上指明的索引     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:53     * @param clazz     * @return {@link boolean}     */    public  boolean deleteIndex(Class clazz) {        return elasticsearchRestTemplate.indexOps(clazz).delete();    }    /**     * @Description: 索引是否存在     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:53     * @param indexName     * @return {@link boolean}     */    public boolean isIndexExists(String indexName) {        return elasticsearchRestTemplate.indexOps(IndexCoordinates.of(indexName)).exists();    }    /**     * @Description: 该实体类指明的索引是否存在     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:52     * @param clazz     * @return {@link boolean}     */    public  boolean isIndexExists(Class clazz) {        return elasticsearchRestTemplate.indexOps(clazz).exists();    }    /**     * @Description: 获取指定索引和id的一条纪录,可以用map来接,即可以传入Map.class     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:38     * @param clazz     * @param id     * @param indexName     * @return {@link T}     */    public  T getById(Class clazz, String id, String indexName) {        return elasticsearchRestTemplate.get(id, clazz, IndexCoordinates.of(indexName));    }    /**     * @Description: 获取实体类上的指定的索引根据id查询的一条纪录     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:38     * @param clazz (该实体类指明白哪个索引,用@Document(indexName = "索引名") 体现 )     * @param id 要查询的id     * @return {@link T}     */    public  T getById(Class clazz, String id) {        return getById(clazz, id, elasticsearchRestTemplate.getIndexCoordinatesFor(clazz).getIndexName());    }    /**     * @Description: 类似于 where fieldName = fieldValue 的条件查询,     * 返回与文档纪录(相当于关系型数据库的一行行数据)对应实体类聚集;     * 实体类上有指明哪个索引 (类上加上注解 @Document(indexName = "test"))     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:23     * @param clazz     * @param fieldName     * @param fieldValue     * @return {@link List}     */    public  List getByFieldName(Class clazz,String fieldName,String fieldValue,int page, int size) {        return getByFieldName(clazz, fieldName, fieldValue,                elasticsearchRestTemplate.getIndexCoordinatesFor(clazz).getIndexName(),page,size);    }    /**     * @Description: 类似于 where fieldName = fieldValue 的条件查询,把返回的数据映射在对类上     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 14:43     * @param clazz 条件查询后返回数据对应的类     * @param fieldName 字段     * @param fieldValue 字段值     * @param indexName 索引名,要查询哪个索引下的数据     * @return {@link List}     */    public  List getByFieldName(Class clazz,String fieldName,String fieldValue,String indexName,int page, int size) {        //匹配查询        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder(fieldName,fieldValue);        return doSearch(clazz, matchQueryBuilder, indexName, page, size);    }    /**     * @Description: 获取指定索引的所有纪录,通报分页参数来分页     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 15:37     * @param clazz     * @param indexName     * @param page     * @param size     * @return {@link List}     */    public  List getAllDocuments(Class clazz, String indexName, int page, int size) {        //条件查询        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();        //必须匹配全部,即获取全部的意思而已        boolQueryBuilder.must(new MatchAllQueryBuilder());        return doSearch(clazz, boolQueryBuilder, indexName, page, size);    }    /**     * @Description: 通用查询(有分页)     * @Author: Chenhuanxing     * @Date: 2020/12/29 0029 15:48     * @param clazz     * @param queryBuilder     * @param indexName     * @param page     * @param size     * @return {@link List}     */    private  List doSearch(Class clazz,QueryBuilder queryBuilder,String indexName,int page,int size) {        NativeSearchQuery query = new NativeSearchQuery(queryBuilder);        query.setPageable(PageRequest.of(page, size));        SearchHits search = elasticsearchRestTemplate.search(query, clazz,IndexCoordinates.of(indexName));        //只获取对应的实体类聚集        return search.stream().parallel().map(SearchHit::getContent).collect(Collectors.toList());    }}
复制代码
【说明】
1、可以看到获取指定索引的全部文档的方法里
  1.                 //条件查询        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();        //必须匹配全部,即获取全部的意思而已        boolQueryBuilder.must(new MatchAllQueryBuilder());        return doSearch(clazz, boolQueryBuilder, indexName, page, size);
复制代码
可以看到这些什么什么queryBuilder,实际上就是和rest请求如下那些查询字段一样的,可以先去相识es的rest请求利用。
  1. "query": {"bool": {"must": [{"match_all": {}}]}}
复制代码
2、后续可以根据自己的需要,参考我的写法,在工具类中添加更多方法,仔细看下来并不难。固然这个也只是我根据elasticsearchRestTemplate的方法参数编写的工具类,根本上是我的个人明白,仅供参考。
【我们测试一下】
1、编写一个测试类
  1. @SpringBootTest(classes = {QuartzApplication.class})@RunWith(SpringJUnit4ClassRunner.class)@Slf4jpublic class TestES {    @Autowired    private ElasticSearchUtil searchUtil;    @Test    public void test1() {        searchUtil.getAllDocuments(testAA.class, "downmsg-log-2020.12.31", 0, 10).                forEach(System.out::println);    }    @Data    class testAA{        private String message;    }}
复制代码
2、输出效果

可以看到这testAA实体类的message字段对应该索引的message字段,也就是详细的日志信息,这个 粉紫色的 "downMsg"就是我们设置的 appender的name属性值,在output中我就是根据这个来区分差别日志创建或找到差别索引的,如果后续有更好的方法,可以自己完善一下,我这样写确实扩展性不高。
3、固然你也可以hashmap来接响应的数据,字段和值就是key和value。
4、你可以在在实体类上 用@Document 指明是哪个索引,可以少传一个参数,你在工具类添加个重载方法就行。
  1. @Data@Document(indexName = "downmsg-log-2020.12.31")class testAA{    private String message;}
复制代码
【大部分的个人观点和明白仅供参考】

来源:https://blog.csdn.net/m0_46859537/article/details/112008290
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )