【运维知识大神篇】超详细的ELFK日志分析教程5(Logstash中Filter常用插件详解+实战练习)

本篇文章主要讲解logstash的有关内容,包括filter的grok、date、user_agent、geoip、mutate插件,多个输入输出方案(多实例+if多分支语句),每个知识点都涉及实战练习,在实战中学习,事半功倍!

Filter常用插件详解

一、grok使用官方模块采集nginx日志

参考官网链接:https://www.elastic.co/guide/en/logstash/7.17/plugins-filters-grok.html

1、删除缓存数据,删除后会重新读取文件,注意删除前先停掉logstash

[root@ELK102 ~]# ll /usr/share/logstash/data/plugins/inputs/file/.sincedb_
.sincedb_d527d4fe95e50e89070186240149c8bb
.sincedb_df5ae0d18161177fc305494571a52fca
.sincedb_e516aafddd2f065b257550d46b8c954c
[root@ELK102 ~]# rm -rf /usr/share/logstash/data/plugins/inputs/file/.sincedb_*

2、编写配置文件

[root@ELK102 ~]# cat /etc/logstash/conf.d/04-nginx-to-es.conf
input { 
  file {
    start_position => "beginning"
    path => ["/var/log/nginx/access.log*"]
  }
}  

filter{
  grok{
    match => {
      "message" => "%{COMMONAPACHELOG}"    #官方自带的Apache转换模块,与nginx格式一致
    }
  }
}

output { 
  elasticsearch {
    hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19200"]
    index => "koten-nginx-%{+yyyy.MM.dd}" 
  } 
  stdout {} 
}

3、执行logstash查看grok转换结果

[root@ELK102 ~]# logstash -rf /etc/logstash/conf.d/04-nginx-to-es.conf
......
{
       "@version" => "1",
        "message" => "10.0.0.1 - - [29/May/2023:11:26:09 +0800] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50\" \"-\"",
           "path" => "/var/log/nginx/access.log",
       "clientip" => "10.0.0.1",
           "host" => "ELK102",
        "request" => "/",
     "@timestamp" => 2023-05-29T03:26:20.756Z,
           "verb" => "GET",
       "response" => "304",
           "auth" => "-",
    "httpversion" => "1.1",
          "ident" => "-",
      "timestamp" => "29/May/2023:11:26:09 +0800",
          "bytes" => "0"
}

二、grok自定义正则案例

1、准备待匹配文本数据

[root@ELK102 ~]# cat /tmp/haha.log 
welcome to kotenedu linux, 2023

2、编写自定义的匹配模式

[root@ELK102 ~]# mkdir koten-patterns/koten-patterns
[root@ELK102 ~]# cat koten-patterns/koten.patterns 
SCHOOL [a-z]{8}
SUBJECT [a-z]{5}
YEAR [\d]{4}

3、编写grok的使用自定义匹配模式

[root@ELK102 ~]# cat config/05-file-grok-stdout.conf 
input { 
  file {
    start_position => "beginning"
    path => ["/tmp/haha.log"]
  }
}  

filter {
  # 基于正则匹配任意文本
  grok {
    # 加载自定义变量的存储目录
    patterns_dir => ["./koten-patterns/"]

    match => {
      "message" => "welcome to %{SCHOOL:school} %{SUBJECT:subject}, %{YEAR:year}"
    }
  }
}

output { 
  stdout {
    codec => rubydebug 
  } 
}

4、启动logstash,注意,启动logstasg案例,为防止写入时多个案例调用同一个id的文档,导致数据少写,官方限制了多个案例同时启动,需要单独指定数据路径

[root@ELK102 ~]# logstash -rf /etc/logstash/conf.d/05-nginx_file-grok-stdout.conf 
......
{
       "message" => "welcome to kotenedu linux, 2023",
        "school" => "kotenedu",
       "subject" => "linux",
          "year" => "2023",
    "@timestamp" => 2023-05-29T12:01:33.003Z,
          "host" => "ELK102",
      "@version" => "1",
          "path" => "/tmp/haha.log"
}

[root@ELK102 ~]# logstash -rf /etc/logstash/conf.d/05-nginx_file-grok-stdout.conf --path.data /tmp/new-data    #单独指定数据路径

三、date插件修改日期时间

参考官网链接:https://www.elastic.co/guide/en/logstash/7.17/plugins-filters-date.html

[root@ELK102 ~]# cat config/06-file-filter-es.conf
input { 
  file {
    start_position => "beginning"
    path => ["/var/log/nginx/access.log"]
  }
}  

filter {
  grok {
    match => "%{COMMONAPACHELOG}"
  }
}

output { 
  elasticsearch{
    hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19300"]
    index => "koten-nginx-access-%{+yyyy.MM.dd}"
  }
  stdout {
    codec => rubydebug 
  } 
}
[root@ELK102 ~]# logstash -rf config/06-file-filter-es.conf

由于在kinbana中,若更改索引名字有日期,添加索引模式,下拉时间戳字段会显示@timestamp 

@timestamp 字段是logstash读取到日志的时间

我们可以根据该时间进行筛选,但是该时间并不是日志的时间,有些时候我们想针对日志中的时间筛选,就需要date插件来定义日志中的时间

我们根据官网提供的时间符号来定义自己的时间格式

[root@ELK102 ~]# cat config/07-file-filter-es.conf
input { 
  file {
    start_position => "beginning"
    path => ["/var/log/nginx/access.log"]
  }
}  

filter {
  grok {
    match => {
      "message" => "%{COMMONAPACHELOG}"
    }
  }
  date {
    match => [ 
      # "28/May/2023:16:46:15 +0800"
      "timestamp", "dd/MMM/yyyy:HH:mm:ss Z"
    ]

    target => "koten-timestamp"
  }
}

output { 
  elasticsearch{
    hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19300"]
    index => "koten-nginx-access-%{+yyyy.MM.dd}"
  }
  stdout {
    codec => rubydebug 
  } 
}

 删除之前加入的索引和索引模式,删除logstash记录的添加收集记录,运行新的配置文件

[root@ELK102 ~]# rm -rf /usr/share/logstash/data/plugins/inputs/file/.sincedb_*
[root@ELK102 ~]# logstash -rf config/07-file-filter-es.conf
......
{
    "koten-timestamp" => 2023-05-29T03:22:53.000Z,        #格林威治时间
              "bytes" => "0",
               "verb" => "GET",
          "timestamp" => "29/May/2023:11:22:53 +0800",    #日志中的时间
         "@timestamp" => 2023-05-29T12:47:30.415Z,        #logstash读取到日志的时间
               "path" => "/var/log/nginx/access.log",
               "host" => "ELK102",
              "ident" => "-",
           "response" => "304",
           "@version" => "1",
        "httpversion" => "1.1",
            "request" => "/",
               "auth" => "-",
            "message" => "10.0.0.1 - - [29/May/2023:11:22:53 +0800] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50\" \"-\"",
           "clientip" => "10.0.0.1"
}

此时timestamp字段已经由text字段,子字段是keyword字段转换成了date字段

选择自己自定义的日志中的时间戳格式 

 观察字段发现右上角筛选日期变成了按照日志时间进行筛选

四、useragent插件

参考官网链接:https://www.elastic.co/guide/en/logstash/7.17/plugins-filters-useragent.html

分析"/tmp/nginx.log"日志,采集后写入ES,并分析2011~2021的访问量pv,设备类型

1、将一些nginx记录提前准备好,放到/tmp/下,命名为nginx.log

[root@ELK102 ~]# ll -h /tmp/nginx.log 
-rw-r--r-- 1 root root 63M May 29 20:57 /tmp/nginx.log
[root@ELK102 ~]# wc -l /tmp/nginx.log
294549 /tmp/nginx.log
[root@ELK102 ~]# head -1 /tmp/nginx.log
54.94.14.30 - - [15/Sep/2010:02:16:14 +0800] "POST /zhibo.html HTTP/1.1" 200 555 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" "-"

2、清空logstash缓存,方便其自动添加

[root@ELK102 ~]# rm -rf /usr/share/logstash/data/plugins/inputs/file/.since*

3、编写配置文件采集日志,并按照指定格式加入ES索引

[root@ELK102 ~]# cat config/08-file-filter-es.conf 
input { 
  file {
    start_position => "beginning"
    path => ["/tmp/nginx.log"]
  }
}  

filter {
  grok { #分析文本并解析提取需要的字段
    match => { #匹配文本字段,可以引用内置的正则变量
      "message" => "%{COMMONAPACHELOG}"
    }
  }
  date { #解析日期的字段
    match => [ #对时间进行格式化匹配并转换成ES的date字段
      # "28/May/2023:16:46:15 +0800"
      "timestamp", "dd/MMM/yyyy:HH:mm:ss Z"
    ]
    #将转换后的结果存储在指定字段,若不指定,则默认覆盖@timestamp字段
    target => "koten-timestamp"
  }
  # 分析客户端设备类型
  useragent {
      # 指定要分析客户端的字段
      source => "message"
      # 指定将分析的结果放在哪个字段中,若不指定,则放在顶级字段中。
      target => "koten-agent"
  }
}

output { 
  elasticsearch{
    hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19300"]
    index => "koten-nginx-access-%{+yyyy.MM.dd}"
  }
  #stdout {        #数据量过大,挨个输出到屏幕上浪费时间
  #  codec => rubydebug 
  #} 
}

4、运行logstash

[root@ELK102 ~]# logstash -rf config/08-file-filter-es.conf 

这些都是useragent插件生成的设备信息的字段

五、geoip插件

参考官网链接:https://www.elastic.co/guide/en/logstash/7.17/plugins-filters-geoip.html

写入地理位置测试数据到ES中,并在kibana中生成地图

1、在postman中创建索引并指定location字段

将location字段定义成geo_point类型

PUT http://10.0.0.101:19200/koten-map

{
  "mappings": {
    "properties": {
      "location": { 
        "type": "geo_point"
      }
    }
  }
}

2、写入一些测试数据

POST http://10.0.0.101:19200/_bulk

{ "create" : { "_index" : "koten-map" } }
{ "location": { "lat": 24,"lon": 121 }}
{ "create" : { "_index" : "koten-map" } }
{ "location": { "lat": 36.61,"lon": 114.488 }}
{ "create" : { "_index" : "koten-map" } }
{ "location": { "lat": 39.914,"lon": 116.386 }}

3、kibana添加地图

创建索引模式--->菜单栏 ---> Maps ---> 添加图层 ---> 文档 ---> 选择已添加的索引

 

 

添加图形好后可以做很多图形设置,配置好后点击保存并关闭

我们可以在地图上看到我们的数据所在的大概位置,数据根据经纬度显示在地图上,可以拖拽地图,可以进行缩放

六、geoip插件分析Nginx日志

提取nginx.log中的公网ip,由logstash转成经纬度,写入ES中并在kibana中以地图形式显示

(如果跟着我的操作做的话,请先看第6步)

1、删除先前生成的索引,并删除logstash的提交记录

[root@ELK102 ~]# rm -rf /usr/share/logstash/data/plugins/inputs/file/.since*

2、编辑配置文件提交我们的nginx.log数据

[root@ELK102 ~]# cat config/09-file-filter-es.conf
input { 
  file {
    start_position => "beginning"
    path => ["/tmp/nginx.log"]
  }
}  

filter {
  grok { #分析文本并解析提取需要的字段
    match => { #匹配文本字段,可以引用内置的正则变量
      "message" => "%{COMMONAPACHELOG}"
    }
  }
  date { #解析日期的字段
    match => [ #对时间进行格式化匹配并转换成ES的date字段
      # "28/May/2023:16:46:15 +0800"
      "timestamp", "dd/MMM/yyyy:HH:mm:ss Z"
    ]
    #将转换后的结果存储在指定字段,若不指定,则默认覆盖@timestamp字段
    target => "koten-timestamp"
  }
  # 分析客户端设备类型
  useragent {
      # 指定要分析客户端的字段
      source => "message"
      # 指定将分析的结果放在哪个字段中,若不指定,则放在顶级字段中。
      target => "koten-agent"
  }
  #基于IP地址分析地理位置
  geoip{
    #指定基于哪个字段分析IP地理位置 
    source => "clientip"
  }
}

output { 
  elasticsearch{
    hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19300"]
    index => "koten-nginx-access-%{+yyyy.MM.dd}"
  }
 # stdout {
 #   codec => rubydebug 
 # } 
}

3、执行logstash,写入ES数据

[root@ELK102 ~]# logstash -rf config/09-file-filter-es.conf

4、创建索引模式,创建地图图层,发现索引模式不包含任何地理空间字段

5、原因是字段类型并没有修改,解决办法是创建索引模板

location下的经纬度默认是浮点数

 创建索引模板

6、添加模板后重复上面删除索引,运行logstash的操作,创建索引模式,再次创建地图图层,成功将数据显示在地图上(因为索引映射一旦确定不能更改,只能删除索引重新添加)

添加好图层后可以看到地图上显示了我们索引中文档的数据

右上角可以保存地图 

保存并添加到库,也可以保存到仪表板,我还没有创建就先不添加了,以后想看可以在库中随时调用出来。

七、mutate插件

参考官网链接:https://www.elastic.co/guide/en/logstash/7.17/plugins-filters-mutate.html

当我们的日志中的字段是按照指定字符分割开来时,就需要用到该插件了,mutate插件适合对字段的信息进行分割,通过分割可以很方便的定义添加字段,虽然用grok写正则表达式也可以实现匹配字段,但是写很多表达式还是很麻烦的。

1、编写生成日志的脚本,模拟公司产品的日志

cat > generate_log.py  <<EOF
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import datetime
import random
import logging
import time
import sys

LOG_FORMAT = "%(levelname)s %(asctime)s [com.koten.%(module)s] - %(message)s "
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

# 配置root的logging.Logger实例的基本配置
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT, filename=sys.argv[1]
, filemode='a',)
actions = ["浏览页面", "评论商品", "加入收藏", "加入购物车", "提交订单", "使用优惠券", "领取优惠券",
 "搜索", "查看订单", "付款", "清空购物车"]

while True:
    time.sleep(random.randint(1, 5))
    user_id = random.randint(1, 10000)
    # 对生成的浮点数保留2位有效数字.
    price = round(random.uniform(15000, 30000),2)
    action = random.choice(actions)
    svip = random.choice([0,1])
    logging.info("DAU|{0}|{1}|{2}|{3}".format(user_id, action,svip,price))
EOF

2、生成测试的日志

[root@ELK102 ~]# python generate_log.py  /tmp/app.log
[root@ELK102 ~]# cat /tmp/app.log 
INFO 2023-05-29 23:34:52 [com.koten.generate_log] - DAU|3849|提交订单|1|15990.11 
INFO 2023-05-29 23:34:57 [com.koten.generate_log] - DAU|189|查看订单|0|26263.25 
INFO 2023-05-29 23:34:58 [com.koten.generate_log] - DAU|8444|领取优惠券|0|25803.03 
INFO 2023-05-29 23:35:03 [com.koten.generate_log] - DAU|5440|搜索|0|20433.35 
INFO 2023-05-29 23:35:08 [com.koten.generate_log] - DAU|2913|提交订单|1|22605.35 
INFO 2023-05-29 23:35:11 [com.koten.generate_log] - DAU|3708|提交订单|1|28590.17 
INFO 2023-05-29 23:35:15 [com.koten.generate_log] - DAU|9296|使用优惠券|0|16057.25 
INFO 2023-05-29 23:35:20 [com.koten.generate_log] - DAU|6150|评论商品|1|20976.35 
INFO 2023-05-29 23:35:23 [com.koten.generate_log] - DAU|8145|提交订单|0|15477.72 
INFO 2023-05-29 23:35:24 [com.koten.generate_log] - DAU|689|搜索|1|24395.35 
INFO 2023-05-29 23:35:28 [com.koten.generate_log] - DAU|1439|领取优惠券|1|15574.72 
......

3、使用mutate组件分析日志,编辑配置文件

[root@ELK102 ~]# cat config/10-file-filter-es.conf
input { 
  file {
    start_position => "beginning"
    path => ["/tmp/app.log"]
  }
}  

filter {
   # 对文本数据进行处理
   mutate {
      # 对message字段按照"|"进行切割
      split => { "message" => "|" }
   }
  
   mutate {
     # 添加字段
     add_field => {
        user_id => "%{[message][1]}"
        action => "%{[message][2]}"
        svip => "%{[message][3]}"
        price => "%{[message][4]}"
     }
   }
  
   mutate {
     # 进行数据类型转换,将指定字段换成为期望的数据类型
     convert => {
       "user_id" => "integer"
       "svip" => "boolean"
       "price" => "float"
     }
   }

   mutate {
     # 对字段进行重命名
     rename => { "path" => "filepath" }
   }

   mutate {
     # 移除指定的字段
     remove_field => [ "@version","message" ]
   }
}

output { 
  elasticsearch{
    hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19300"]
    index => "koten-nginx-access-%{+yyyy.MM.dd}"
  }
 # stdout {
 #   codec => rubydebug 
 # } 
}

4、启用logstash,观察屏幕输出的日志是否按照自定义字段输出

[root@ELK102 ~]# rm -rf /usr/share/logstash/data/plugins/inputs/file/.sincedb_*
[root@ELK102 ~]# logstash -rf config/10-file-filter-es.conf 

5、kibana查看数据并创建可视化

创建数据图表:菜单栏 ---> Visualize library ---> 创建可视化 ---> Lens ---> 根据字段选择即可。

 

 

 

创建聚合图形:菜单栏 ---> Visualize library ---> 创建可视化 --->  基于聚合  ---> 指标(其他同理) ---> 选择索引  

 可以修改标签,更新显示,同样右上角可以保存

 创建仪表板:Overview--->仪表板--->创建新的仪表板--->从库中添加--->保存仪表板

可以添加库中的图形 

右上角保存仪表板

 下次再打开Overview就显示了,可以打开直接看

八、if多分支语句

if多分支语句与--path.data一样,是多个输入多个输出的一种方式

1、准备读入文件

[root@ELK102 ~]# cat /tmp/haha.log
welcome to kotenedu linux, 2023
[root@ELK102 ~]# cat /tmp/app.log 
INFO 2023-05-29 23:34:52 [com.koten.generate_log] - DAU|3849|提交订单|1|15990.11 
INFO 2023-05-29 23:34:57 [com.koten.generate_log] - DAU|189|查看订单|0|26263.25 
INFO 2023-05-29 23:34:58 [com.koten.generate_log] - DAU|8444|领取优惠券|0|25803.03 
INFO 2023-05-29 23:35:03 [com.koten.generate_log] - DAU|5440|搜索|0|20433.35 
INFO 2023-05-29 23:35:08 [com.koten.generate_log] - DAU|2913|提交订单|1|22605.35 
INFO 2023-05-29 23:35:11 [com.koten.generate_log] - DAU|3708|提交订单|1|28590.17 
INFO 2023-05-29 23:35:15 [com.koten.generate_log] - DAU|9296|使用优惠券|0|16057.25 
INFO 2023-05-29 23:35:20 [com.koten.generate_log] - DAU|6150|评论商品|1|20976.35 
INFO 2023-05-29 23:35:23 [com.koten.generate_log] - DAU|8145|提交订单|0|15477.72 
INFO 2023-05-29 23:35:24 [com.koten.generate_log] - DAU|689|搜索|1|24395.35 
INFO 2023-05-29 23:35:28 [com.koten.generate_log] - DAU|1439|领取优惠券|1|15574.72 
......

2、准备正则表达式

[root@ELK102 ~]# cat config/koten-patterns/koten-patterns
SCHOOL [a-z]{8}
SUBJECT [a-z]{5}
YEAR [\d]{4}

3、编辑配置文件

[root@ELK102 ~]# cat config/11-file-filter-es.conf
input { 
  file {
    start_position => "beginning"
    path => ["/tmp/haha.log"]
    type => "haha"
  }

  file {
    start_position => "beginning"
    path => ["/tmp/app.log"]
    type => "app"
  }
}  


filter {
   if [type] == "haha" {
      grok {
        patterns_dir => ["./koten-patterns/"]
        match => {
          "message" => "welcome to %{SCHOOL:school} %{SUBJECT:subject}, %{YEAR:year}"
        }
      }

   } else if [type] == "app" {
       mutate {
          split => { "message" => "|" }
       }

       mutate {
         add_field => {
            user_id => "%{[message][1]}"
            action => "%{[message][2]}"
            svip => "%{[message][3]}"
            price => "%{[message][4]}"
         }
       }

       mutate {
         convert => {
           "user_id" => "integer"
           "svip" => "boolean"
           "price" => "float"
         }
       }

       mutate {
         rename => { "path" => "filepath" }
       }

       mutate {
         remove_field => [ "@version","message" ]
       }

  }
}



output { 
  if [type] == "haha" {
    elasticsearch {
      hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19200"]
      index => "koten-if-haha-%{+yyyy.MM.dd}"
    } 
  } else if [type] == "app" {
    elasticsearch {
      hosts => ["10.0.0.101:19200","10.0.0.102:19200","10.0.0.103:19200"]
      index => "koten-if-app-%{+yyyy.MM.dd}"
    } 
  }

  stdout {
    codec => rubydebug 
  } 
}

4、运行logstash,可以观察到两者输入输出的区别,更名的字段等等

[root@ELK102 ~]# rm -rf /usr/share/logstash/data/plugins/inputs/file/.sinced*
[root@ELK102 ~]# logstash -rf config/11-file-filter-es.conf
......
{
          "type" => "app",
      "filepath" => "/tmp/app.log",
       "user_id" => 9389,
          "svip" => false,
          "host" => "ELK102",
    "@timestamp" => 2023-05-29T16:31:25.353Z,
         "price" => 26972.71,
        "action" => "付款"
}
{
          "path" => "/tmp/haha.log",
          "type" => "haha",
       "subject" => "linux",
      "@version" => "1",
          "host" => "ELK102",
          "year" => "2023",
    "@timestamp" => 2023-05-29T16:31:25.240Z,
       "message" => "welcome to kotenedu linux, 2023",
        "school" => "kotenedu"
}
......

Logstash常用filter插件总结

1、grok:正则匹配任意文本

2、date:处理时间字段

3、user_agent:分析客户端设备

4、geoip:分析客户端IP地理位置

5、mutate:对字符串文本进行处理,转换,字母大小写,切分,重命名,添加字段,删除字段

运行多个输入和输出的方案:

多实例:需要单独指定数据路径,--data.path

if分支语句:

if [type] == "xxx" {

} else if [type] == "xxx" {

} else {

}

pipline:logstash运行时默认就有一个main pipline


我是koten,10年运维经验,持续分享运维干货,感谢大家的阅读和关注!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/196237.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mysql 高级日志binlog、undoLog、redoLog 详解

数据更新流程与日志记录&#xff1a; undoLog&#xff1a; binLog&#xff1a; redoLog&#xff1a;

Leetcode—160.相交链表【简单】

2023每日刷题&#xff08;四十一&#xff09; Leetcode—160.相交链表 算法思想 两个链表的节点之和是相等的 如果两个链表相交&#xff0c;那么相交点之后的长度是相同的 我们需要做的事情是&#xff0c;让两个链表从同距离末尾同等距离的位置开始遍历。这个位置只能是较短…

建筑红模板尺寸规格

红模板是建筑施工中常用的一种模板材料&#xff0c;具有较好的承重能力和稳定性。在建筑工程中&#xff0c;正确选择合适的红模板尺寸规格对于施工质量和效率至关重要。本文将介绍一些关于红模板尺寸规格的信息&#xff0c;帮助您更好地了解和选择适合的红模板。 以下是关于红模…

论如何让Spring Boot在高压力环境下依然与众不同

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容调优线程池优化线程池配置多样化设备支持分布式控制同步编程 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客…

FlowJo 10 v10.4(流式细胞分析软件)

FlowJo是一款广泛应用的流式细胞数据分析软件&#xff0c;它功能强大&#xff0c;简单易用&#xff0c;是流式领域最受推荐的一款专业分析软件&#xff0c;也是各高影响力科学期刊使用最多的软件&#xff0c;已经成了行业的一个标准。 FlowJo具有全面专业的分析功能&#xff0…

《数据结构、算法与应用C++语言描述》-线索二叉树的定义与C++实现

_23Threaded BinaryTree 可编译运行代码见&#xff1a;GIithub::Data-Structures-Algorithms-and-Applications/_24Threaded_BinaryTree 线索二叉树定义 在普通二叉树中&#xff0c;有很多nullptr指针被浪费了&#xff0c;可以将其利用起来。 首先我们要来看看这空指针有多少…

分享一套MES源码,可以直接拿来搞钱的好项目

目前国内智能制造如火如荼&#xff0c;工厂信息化、数字化是大趋势。如果找到一个工厂&#xff0c;搞定一个老板&#xff0c;搞软件的朋友就能吃几年。 中国制造业发达&#xff0c;工厂林立&#xff0c;但是普遍效率不高&#xff0c;需要信息化提高效率。但是矛盾的地方在于&a…

pdf文件能扫码查看吗?一键做文本二维码

pdf格式是常用的一种文件格式&#xff0c;很多资料、展示性的内容都会选择这种格式&#xff0c;现在很多人都需要将文件生成二维码图片后分享给他人&#xff0c;那么文件存入二维码展示的方法有哪些呢&#xff1f;下面给大家分享一招使用二维码生成器来生成二维码图片的操作方法…

skywalking告警UI界面有告警信息,webhook接口没有回调,400错误

400错误就是回调接口返回数据的属性对应不上 PostMapping(“/webhook”) public void webhook(RequestBody List alarmMessageList) 自定义的实体类AlarmMessage有问题 只能去官网找了 告警实体类官网 Getter EqualsAndHashCode RequiredArgsConstructor NoArgsConstructor(fo…

系列二十一、Spring中bean的创建顺序

一、概述 我们知道启动IOC容器时&#xff0c;Spring会为我们创建各种各样的bean&#xff0c;那么思考一个问题&#xff0c;bean的创建顺序是由什么决定的呢&#xff1f;答&#xff1a;bean的创建顺序是由BeanDefinition的注册信息决定的&#xff0c;这个其实很好理解&#xff0…

解析d3dcompiler_47.dll缺失怎么修复,4种方法修复d3dcompiler_47.dll文件

d3dcompiler_47.dll缺失怎么修复&#xff1f;其实在我们使用计算机操作的过程中&#xff0c;有时会遇到一些由dll文件错误导致的问题&#xff0c;其中d3dcompiler_47.dll丢失就是这样一种。那么究竟d3dcompiler_47.dll缺失是什么意思&#xff0c;为何它会发生丢失&#xff0c;以…

Unity WebGL通过URL的形式接收参数执行初始化

参考博客&#xff1a; http://t.csdnimg.cn/QnfhK 问题背景&#xff1a; 需要在外面的网页指定WebGL的打开初始化逻辑。 步骤&#xff1a; 1.配置jslib&#xff0c;用文本文件创建即可&#xff0c;"__Internal.jslib"。 2.加入一段代码&#xff1a; mergeInto(…

2023-简单点-机器学习中常用的特殊函数,激活函数[sigmoid tanh ]

机器学习中的特殊函数 Sigmoidsoftplus函数tanhReLu(x)Leaky-ReluELUSiLu/ SwishMish伽玛函数beta函数Ref Sigmoid 值域: 【0,1】 定义域&#xff1a;【负无穷,正无穷】 特殊点记忆&#xff1a; 经过 [0 , 0.5] 关键点[0,0.5]处的导数是 0.025 相关导数&#xff1a; softplu…

鹅厂终于开始收割韭菜了!!!获取手机号需要收费 ,吃相难看~

微信于2023年8月26日起对手机号验证能力收费&#xff0c;在规则生效时会给予每个小程序1000次免费验证&#xff0c;超出次数则需要到微信小程序官方后台进行充值&#xff0c;费用由微信官方收取。 这一做法&#xff0c;现在让越来越多的老板很头疼了&#xff0c; 如果你要修…

ArkUI开发进阶—@Builder函数@BuilderParam装饰器的妙用与场景应用【鸿蒙专栏-05】

ArkUI开发进阶—@Builder函数@BuilderParam装饰器的妙用与场景应用 HarmonyOS,作为一款全场景分布式操作系统,为了推动更广泛的应用开发,采用了一种先进而灵活的编程语言——ArkTS。ArkTS是在TypeScript(TS)的基础上发展而来,为HarmonyOS提供了丰富的应用开发工具,使开…

ELK高级搜索,深度详解ElasticStack技术栈-上篇

前言 1、黑马视频地址&#xff1a;java中级教程-ELK高级搜索&#xff0c;深度详解ElasticStack技术栈 2、本内容仅用于个人学习笔记&#xff0c;如有侵扰&#xff0c;联系删除 1. 课程简介 1.1 课程内容 ELK是包含但不限于Elasticsearch&#xff08;简称es&#xff09;、Lo…

嵌入式常见协议---IIC协议

1.IIC&#xff08;IC&#xff09;协议是什么&#xff1f; 全称 Inter-Integrated Circuit ,字面意思是集成电路之间&#xff0c;是IC BUS简称&#xff0c;中文应该叫集成电路总线&#xff0c;是一种串行通信总线&#xff08;同步串行半双工&#xff09;&#xff0c;使用多主从…

配置 Mantis 在 Windows 上的步骤

配置 Mantis Bug Tracker 在 Windows 上的步骤 Mantis Bug Tracker 是一款开源的缺陷跟踪系统&#xff0c;用于管理软件开发中的问题和缺陷。在 Windows 环境下配置 Mantis 可以帮助开发者更方便地进行项目管理。以下是一个详细的教程&#xff0c;包含了 EasyPHP Devserver 和…

app上架一直显示审核中状态要怎么处理?

当你提交一个应用到App Store上时&#xff0c;它会经历一个审核过程。在这个过程中&#xff0c;苹果的审核人员会检查你的应用是否符合苹果的规定和标准。这个过程通常需要几天的时间&#xff0c;但是如果你的应用一直显示“审核中”状态&#xff0c;那么可能会有一些原因。 1…

如何使用Cloudreve将个人电脑打造为私有云盘并实现远程访问

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 云存储概念兴起后&#xff0c;现在市面上也已经有了很多公有云盘。但一段时间后…