1-Flume中agent的source

news2024/11/18 7:35:14

Flume(1.11.0版本)

简介

概述

  1. Flume本身是由Cloudera公司开发的后来贡献给了Apache的一套针对日志数据进行收集(collecting)、汇聚(aggregating)和传输(moving)的机制

  2. Flume本身提供了简单且灵活的结构来完成日志数据的传输

    Flume结构

  3. Flume有两大版本:

    1. Flume0.X:又称之为Flume-og,依赖于Zookeeper部署,需要提供的格式文件相对复杂,所以现在市面上已经不使用了
    2. Flume1.X:又称之为Flume-ng,不依赖于Zookeeper部署,需要提供的格式文件结构明确且简单,所以是现在流通的版本

基本概念

  1. Event

    1. Flume会将收集到的每一条日志封装成一个Event

    2. Event本质上就是一个json串,即Flume会将收集到的日志封装成json的形式,Event中固定的包含两部分:headers和body

      {"headers":{},"body":""}
      
  2. Agent:Flume流动模型的基本组成结构,至少包含3部分

    1. Source:从数据源采集数据 - collecting
    2. Channel:临时存储数据 - aggregating
    3. Sink:将数据写出到目的地 - moving

流动模型

  1. 单级流动

    Flume结构

  2. 多级流动:又称之为串联流动

    多级流动

  3. 扇入流动:又称之为并联流动、聚集流动

    扇入流动

  4. 扇出流动:又称之为复用流动

    扇出流动

  5. 复杂流动:按照需求将多个流动进行组合,那么就是复杂流动

参数解释

参数解释
--name或者-n指定要运行的agent的名字
--conf或者-cFlume的原生配置
--conf-file或者-f执行的文件
-D指定运行其他的参数
flume.root.logger指定日志的打印级别,级别分为INFOWARNERROR,可以指定打印位置consolelogfile

Source

NetCat TCP Source

  1. Netcat TCP Source监听TCP请求,在使用的时候需要监听指定的主机和端口,从这个指定主机的指定端口来接收TCP请求,并且将TCP请求内容作为日志来进行收集

  2. 默认情况下,每一条数据大小不能超过512B,可以通过参数max-line-length来修改

    1. 在Flume中,所有的流动模型,不是通过代码来指定,而是通过格式文件来配置,所以实际过程中,往往会要求格式文件存放在统一的位置上。上课过程中,统一要求将格式文件放到/opt/software/flume-1.11.0/data

      cd /opt/software/flume-1.11.0/
      mkdir data
      cd data
      
    2. 编辑格式文件,文件名和后缀名可以自己定义 properties文件的 key = value 格式配置在vim会有颜色上的区分,便于阅读。

      vim basic.propertie
      

      在文件中添加

      # 给Agent起名   a1就是这个agent的名字
      # 给Source起名
      # 如果有多个Source,那么名字之间用空格隔开
      a1.sources = s1
      # 给Channel起名
      a1.channels = c1
      # 给Sink起名
      a1.sinks = k1
      
      # 配置Source
      a1.sources.s1.type = netcat
      a1.sources.s1.bind = 0.0.0.0
      a1.sources.s1.port = 8090
      
      # 配置Channel
      a1.channels.c1.type = memory
      a1.channels.c1.capacity = 1000
      a1.channels.c1.transactionCapacity = 1000
      
      # 配置Sink
      a1.sinks.k1.type = logger
      
      # 将Source和Channel绑定
      a1.sources.s1.channels = c1
      # 将Sink和Channel绑定
      a1.sinks.k1.channel = c1
      
    3. 执行

      flume-ng agent --name a1 --conf $FLUME_HOME/conf --conf-file basic.properties -Dflume.root.logger=INFO,console
      
    4. 复制窗口之后,发送TCP请求

      nc hadoop01 8090
      

Exec Source

  1. Exec Source运行指定命令,监听命令结果,将命令结果作为日志进行收集

  2. 案例:监听指定文件,如果文件中新添了数据,那么自动收集这个文件中的数据

    1. 构建空文件

      touch /opt/software/flume-1.11.0/data/a.txt
      
    2. 监听这个文件,如果这个文件中新添了数据,自动收集数据作为日志

      vim execsource.properties
      

      在文件中添加

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      # 配置Exec Source
      # Source的类型
      a1.sources.s1.type = exec
      # 监听指定的命令
      a1.sources.s1.command = tail -F /opt/software/flume-1.11.0/data/a.txt
      # 指定命令的脚本类型
      a1.sources.s1.shell = /bin/sh -c
      
      a1.channels.c1.type = memory
      
      a1.sinks.k1.type = logger
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      
    3. 执行命令

      flume-ng agent -n a1 -c $FLUME_HOME/conf -f execsource.properties -Dflume.root.logger=INFO,console
      
    4. 在新窗口中追加数据

      echo "testing" >> /opt/software/flume-1.11.0/data/a.txt
      echo "exec" >> /opt/software/flume-1.11.0/data/a.txt
      

      AVRO Source

      1. AVRO Source接收被AVRO序列化之后的数据,结合AVRO Sink,可以实现复杂的流动模型

      2. 案例

        1. 编辑文件

          cd /opt/software/flume-1.11.0/data/
          vim avrosource.properties 
          

          在文件中添加

          a1.sources = s1           
          a1.channels = c1
          a1.sinks = k1
          
          # 配置AVRO Source
          # 类型必须是avro
          a1.sources.s1.type = avro
          # 监听的主机
          a1.sources.s1.bind = 0.0.0.0
          # 监听的端口号
          a1.sources.s1.port = 6666
          
          a1.channels.c1.type = memory
          
          a1.sinks.k1.type = logger
          
          a1.sources.s1.channels = c1
          a1.sinks.k1.channel = c1
          
        2. 启动

          flume-ng agent -n a1 -c $FLUME_HOME/conf -f avrosource.properties -Dflume.root.logger=INFO,console
          
        3. 在新窗口中启动AVRO客户端

          flume-ng avro-client -H hadoop01 -p 6666 -F a.txt
          

      Spooling Directory Source

      1. 监听指定的目录,如果目录中产生了新的文件,那么自动的将新文件中的内容收集起来

      2. 默认情况下,这个文件如果被收集了,那么文件的后缀就是.COMPLETED

      3. 案例

        1. 创建目录

          mkdir /opt/flume_data
          
        2. 编辑文件

          vim spooldirsource.properties
          

          在文件中添加

          a1.sources = s1
          a1.channels = c1
          a1.sinks = k1
          
          # 配置Spooling Directory Source
          # 类型必须是spooldir
          a1.sources.s1.type = spooldir
          # 监听的目录
          a1.sources.s1.spoolDir = /opt/flume_data
          # 被收集过的文件后缀
          # 利用这条规则,可以过滤掉一部分不需要收集的文件
          a1.sources.s1.fileSuffix = .finished
          
          a1.channels.c1.type = memory
          
          a1.sinks.k1.type = logger
          
          a1.sources.s1.channels = c1
          a1.sinks.k1.channel = c1
          
        3. 执行

          flume-ng agent -n a1 -c $FLUME_HOME/conf -f spooldirsource.properties -Dflume.root.logger=INFO,console
          

      Taildir Source

      1. 可以用于监听一个或者一组文件,如果被监听的文件中添加了新数据,那么新添的数据会被自动收集

      2. Exec Source需要通过指定tail -F命令才能监听指定文件,Spooling Directory Source监听指定的目录,并不能确定文件中是否新添了数据

      3. 不同于Exec Source的地方在于,Taildir Source不需要指定命令,还可以监控一类文件,且Taildir Source通过记录偏移量实现断点续传效果

      4. 偏移量通过属性positionFile来决定,默认是~/.flume/taildir_position.json

      5. 需要注意的是,Taildir Source不支持在Windows中使用

      6. 案例:监听flume_data目录下所有的log和txt文件,如果文件被添加新数据,那么自动收集

        1. 编辑文件

          vim taildirsource.properties
          
        2. 在文件中添加

          a1.sources = s1
          a1.channels = c1
          a1.sinks = k1
          
          # 配置Taildir Source
          # 类型必须是TAILDIR
          a1.sources.s1.type = TAILDIR
          # 监听的一组文件的组名
          a1.sources.s1.filegroups = f1 f2
          # 文件组中的要监听的文件
          a1.sources.s1.filegroups.f1 = /opt/flume_data/.*log.*
          a1.sources.s1.filegroups.f2 = /opt/flume_data/.*txt.*
          # 偏移量的存储位置
          a1.sources.s1.positionFile = /opt/flume_data/taildir_position.json
          
          a1.channels.c1.type = memory
          
          a1.sinks.k1.type = logger
          
          a1.sources.s1.channels = c1
          a1.sinks.k1.channel = c1
          
        3. 执行

          flume-ng agent -n a1 -c $FLUME_HOME/conf -f taildirsource.properties -Dflume.root.logger=INFO,console
          

      Sequence Generator Source

      1. 序列产生器,从0开始递增到totalEvents,默认情况下totalEvents的值Long.MAX_VALUE

      2. 实际过程中,会利用这个Source测试流动模型是否搭建成功

      3. 案例

        a1.sources = s1
        a1.channels = c1
        a1.sinks = k1
        
        # 配置Sequence Generator Source
        # 类型必须是seq
        a1.sources.s1.type = seq
        # 最大值
        a1.sources.s1.totalEvents = 100
        
        a1.channels.c1.type = memory
        
        a1.sinks.k1.type = logger
        
        a1.sources.s1.channels = c1
        a1.sinks.k1.channel = c1
        

      HTTP Source

      1. 接收HTTP请求,并且将请求内容作为日志进行收集

      2. 只能接收GET和POST请求,其中GET请求接收只能用于实验,实际过程中使用HTTP Source来接收POST请求

      3. 案例

        1. 在文件中添加

          a1.sources = s1
          a1.channels = c1
          a1.sinks = k1
          
          # 配置HTTP Source
          # 类型必须是http
          a1.sources.s1.type = http
          # 监听端口
          a1.sources.s1.port = 8888
          
          a1.channels.c1.type = memory
          
          a1.sinks.k1.type = logger
          
          a1.sources.s1.channels = c1
          a1.sinks.k1.channel = c1
          
        2. 启动Flume

        3. 发送POST请求

          curl -X POST -d '[{"headers":{"class":"flume"},"body":"welcome~~~"}]' http://hadoop01:8888
          

      Custom Source

      1. Flume支持用户自定义Source。Flume针对Source提供了顶级接口Source,但是实际过程中,并不是实现Source接口,而是实现子接口之一:
        1. EventDrivenSource:事件驱动Source,本身是一个被动型Source,需要自己定义线程来获取数据以及封装数据
        2. PollableSource:拉取Source,本身是一个主动型Source,提供了线程来获取数据,只需要考虑数据怎么封装即可
      2. 由于在自定义Source的时候,还需要考虑获取格式文件中的参数值,所以还需要实现Configurable接口
      3. 实际过程中,考虑到要覆盖的方法比较多,所以继承AbstractSource
      pom依赖
      <!--Flume核心包-->
      <dependency>
          <groupId>org.apache.flume</groupId>
          <artifactId>flume-ng-core</artifactId>
          <version>1.11.0</version>
      </dependency>
      <!--Flume开发包-->
      <dependency>
          <groupId>org.apache.flume</groupId>
          <artifactId>flume-ng-sdk</artifactId>
          <version>1.11.0</version>
      </dependency>
      <!--Flume配置包-->
      <dependency>
          <groupId>org.apache.flume</groupId>
          <artifactId>flume-ng-configuration</artifactId>
          <version>1.11.0</version>
      </dependency>
      
      自定义EventDrivenSource
      代码
      import org.apache.flume.Context;
      import org.apache.flume.Event;
      import org.apache.flume.EventDrivenSource;
      import org.apache.flume.channel.ChannelProcessor;
      import org.apache.flume.conf.Configurable;
      import org.apache.flume.event.EventBuilder;
      import org.apache.flume.source.AbstractSource;
      
      import java.util.HashMap;
      import java.util.Map;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      
      // 自定义代码实现Sequence Generator Source,加深理解
      public class AuthDrivenSource extends AbstractSource implements EventDrivenSource, Configurable {
      private long start;
      private long end;
      private long step;
      private ExecutorService es;
      
      // 获取参数值
      @Override
      public void configure(Context context) {
          // 3 -> +4
          // 获取起始值
          // 如果用户没有指定,那么默认从0开始递增
          start = context.getLong("start", 0L);
          // 获取结束值
          // 如果不指定,递增到Long.MAX_VALUE
          end = context.getLong("end", Long.MAX_VALUE);
          // 获取步长
          // 如果不指定,那么默认每次递增1
          step = context.getLong("step", 1L);
          // 保证数据的合理性
          if (start > end || step < 1)
              throw new IllegalArgumentException();
      }
      
      // 启动Source
      @Override
      public synchronized void start() {
          // 线程池中准备5个线程
          es = Executors.newFixedThreadPool(5);
          // 获取ChannelProcessor
          ChannelProcessor cp = this.getChannelProcessor();
          // 提交任务
          es.submit(new Add(start, end, step, cp));
      }
      
      // 结束Source
      @Override
      public synchronized void stop() {
          if (es != null) es.shutdown();
      }}
      
      // 自增
      class Add implements Runnable {private final long start;
      private final long end;
      private final long step;
      private final ChannelProcessor cp;
      
      public Add(long start, long end, long step, ChannelProcessor cp) {
          this.start = start;
          this.end = end;
          this.step = step;
          this.cp = cp;
      }
      
      @Override
      public void run() {
      
          for (long i = start; i < end; i += step) {
              // 封装headers
              // 在headers中记录了数据产生的时间
              Map<String, String> headers = new HashMap<>();
              headers.put("time", String.valueOf(System.currentTimeMillis()));
              // 封装body
              byte[] body = String.valueOf(i).getBytes();
              // 将数据封装成Event
              Event e = EventBuilder.withBody(body, headers);
              // 将Event传递给Channel来存储
              cp.processEvent(e);
          }
      }
      }
      
      1. 将程序打成jar包(要求是JDK1.8,好多框架还不支持17版本),上传到Flume安装目录的lib目录下

        cd /opt/software/flume-1.11.0/lib/
        rz
        
      2. 回到格式文件目录下,编辑文件

        cd /opt/software/flume-1.11.0/data/
        vim authdrivensource.properties
        

        在文件中添加

        a1.sources = s1
        a1.channels = c1
        a1.sinks = k1
        
        # 配置自定义EventDrivenSource
        # 类型必须是类的全路径名
        a1.sources.s1.type = com.fesco.source.AuthDrivenSource
        # 起始值
        a1.sources.s1.start = 10
        # 结束值
        a1.sources.s1.end = 100
        # 步长
        a1.sources.s1.step = 5
        
        a1.channels.c1.type = memory
        
        a1.sinks.k1.type = logger
        
        a1.sources.s1.channels = c1
        a1.sinks.k1.channel = c1
        
      3. 启动Flume

      自定义PollableSource
      代码
      import org.apache.flume.Context;
      import org.apache.flume.Event;
      import org.apache.flume.PollableSource;
      import org.apache.flume.channel.ChannelProcessor;
      import org.apache.flume.conf.Configurable;
      import org.apache.flume.event.EventBuilder;
      import org.apache.flume.source.AbstractSource;
      
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      
      public class AuthPollableSource extends AbstractSource implements PollableSource, Configurable {
      private long min;
      private long max;
      private long step;
      
      // 获取配置
      @Override
      public void configure(Context context) {
          this.min = context.getLong("min", 0L);
          this.max = context.getLong("max", Long.MAX_VALUE);
          this.step = context.getLong("step", 1L);
          if (min > max || step < 1)
              throw new IllegalArgumentException();
      }
      
      // 封装数据,写出数据
      @Override
      public Status process() {
          // 定义List来临时存储数据
          List<Event> events = new ArrayList<>();
          // 获取ChannelProcessor
          ChannelProcessor cp = this.getChannelProcessor();
          for (long i = min; i < max; i += step) {
              // 封装headers
              Map<String, String> headers = new HashMap<>();
              headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
              // 封装body
              byte[] body = String.valueOf(i).getBytes();
              // 封装Event
              Event e = EventBuilder.withBody(body, headers);
              events.add(e);
              // 每50条数据写一次
              if (events.size() >= 50) {
                  // 写出数据。这个方法一次写出多个
                  cp.processEventBatch(events);
                  // 清空集合
                  events.clear();
              }
          }
          return Status.READY;
      }
      
      // PollableSource主动提供线程来获取数据
      // 如果线程暂时没有获取到数据,那么线程会临时休眠
      // 这个方法就是控制线程的休眠时间,单位是毫秒
      @Override
      public long getBackOffSleepIncrement() {
          return 1000;
      }
      
      @Override
      public long getMaxBackOffSleepInterval() {
          return 10000;
      }
      }
      
      1. 打成jar包,上传到lib目录下

        cd ../lib
        rz
        
      2. 回到格式文件目录下,编辑文件

        cd ../data/
        vim authpollablesource.properties
        

        在文件中添加

        a1.sources = s1
        a1.channels = c1
        a1.sinks = k1
        
        # 配置自定义PollableSource
        # 类型必须是类的全路径名
        a1.sources.s1.type = com.fesco.source.AuthPollableSource   //注意自己的全类名
        # 起始值
        a1.sources.s1.min = 10
        # 结束值
        a1.sources.s1.max = 1000
        # 步长
        a1.sources.s1.step = 5
        
        a1.channels.c1.type = memory
        
        a1.sinks.k1.type = logger
        
        a1.sources.s1.channels = c1
        a1.sinks.k1.channel = c1
        

      cd …/data/
      vim authpollablesource.properties

      
      在文件中添加
      
      ```properties
      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      # 配置自定义PollableSource
      # 类型必须是类的全路径名
      a1.sources.s1.type = com.fesco.source.AuthPollableSource   //注意自己的全类名
      # 起始值
      a1.sources.s1.min = 10
      # 结束值
      a1.sources.s1.max = 1000
      # 步长
      a1.sources.s1.step = 5
      
      a1.channels.c1.type = memory
      
      a1.sinks.k1.type = logger
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      
      1. 启动Flume

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

有道翻译实现接口加密解密

文章目录 目标简单逆向分析源码深度逆向分析参考文献目标 实现对网易有道 sign 等参数的加密 及 返回的密文数据解密实现 简单逆向分析 首先在右上角提前登录好账号信息。 输入中文:你好 要求翻译成:英文 全局搜索:你好 或 hello,结果没有发现什么。 切换 Fetch/XHR …

JAVA毕业设计131—基于Java+Springboot+Vue的餐厅点餐系统(源代码+数据库+4000字文档)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的餐厅点餐系统(源代码数据库4000字文档)131 一、系统介绍 本项目前后端分离&#xff0c;分为管理员、用户两种角色 1、用户&#xff1a; 注册、登录、点餐…

移动0【双指针】

移动零 cur每次走一步&#xff0c;dest走不走取决于cur有没有找到非0值&#xff0c;一旦找打非0值&#xff0c;交换。不是非0值&#xff0c;dest不动。》【非零&#xff0c;dest】【dest&#xff0c;0】 class Solution { public:void moveZeroes(vector<int>& num…

电脑不能读取移动硬盘,但是可以读取U盘解决方法

找到此电脑 右键设备管理器&#xff0c;找到其中的通用串行总线控制器。 注意&#xff0c;凡是插入到电脑当中不能读取的U盘或者移动硬盘&#xff0c;都会在通用串行总线控制器当中显示为USB大容量存储设备 鼠标选中“USB大容量存储设备”&#xff0c;右键卸载它。此时&#x…

[项目前置]websocket协议

websocket协议介绍 WebSocket 协议是一种在单个 TCP 连接上进行全双工通讯的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更简单&#xff0c;允许服务器主动向客户端推送数据。它在 2011 年成为国际标准&#xff0c;现在被所有现代浏览器支持。WebSocket 设计用于…

【蓝桥杯选拔赛真题72】python找路线 第十四届青少年组蓝桥杯python选拔赛真题 算法思维真题解析

目录 python找路线 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python找路线 第十四届蓝桥杯青少年组python比赛选拔赛真题 一、题目要求 …

mysql基础2多表查询

多表查询 多表关系: 一对多 案例: 部门 与 员工的关系 关系: 一个部门对应多个员工&#xff0c;一个员工对应一个部门 实现: 在多的一方建立外键&#xff0c;指向一的一方的主键 多对多 案例: 学生 与 课程的关系 关系: 一个学生可以选修多门课程&#xff0c;一门课程也可以…

鸿蒙实战开发:【7日天气预报】

先来看一下效果 本项目界面搭建基于ArkUI中TS扩展的声明式开发范式&#xff0c; 数据接口是[和风&#xff08;天气预报&#xff09;]&#xff0c; 使用ArkUI自带的网络请求调用接口。 我想要实现的一个功能是&#xff0c;查询当前城市的实时天气&#xff0c; 目前已实现的功…

阿里云服务器价格表2024,最新报价2核2G/2核4G/4核8G/8核16G/16核32G

2024年腾讯云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新的云服务器优惠券…

【嵌入式学习】Qtday03.24

一、思维导图 二、练习 QMovie *mv new QMovie(":/Logo/giphy (2).gif");ui->label_5->setMovie(mv);ui->label_5->setScaledContents(true);mv->start();this->setWindowIcon(QIcon(":/Logo/bdf48b5198c8417da0e4fef6b72c5657.png"));/…

mysql 存储引擎 基本介绍

目录 一 存储引擎概念介绍 &#xff08;一&#xff09;存储引擎概念 &#xff08;二&#xff09;MySQL常用的存储引擎 &#xff08;三&#xff09;存储引擎运作方式 二 MyISAM 存储引擎介绍 &#xff08;一&#xff09; MyISAM 存储引擎特点 1&#xff0c;不支持…

WorkPlus AI助理,为企业提供智能化客户服务,助力企业发展与竞争力

在当今竞争激烈的商业环境中&#xff0c;提供优质高效的客户服务是企业取得成功的关键。而AI智能客服的崛起&#xff0c;以其卓越的性能和功能&#xff0c;助力企业提升客户服务体验。WorkPlus AI助理作为一款领先的解决方案&#xff0c;能够实现智能化客户服务&#xff0c;满足…

SVN的branch分支合并完要不要删除

在 SVN 中&#xff0c;当一个分支&#xff08;branch&#xff09;的工作已经完成并成功合并回主干&#xff08;trunk&#xff09;后&#xff0c;通常不需要立即删除该分支。保留分支可以有一些好处&#xff0c;例如&#xff1a; 历史记录和追溯&#xff1a;保留分支可以帮助团…

蓝桥杯练习04学生成绩统计

学生成绩统计 介绍 随着大数据的发展&#xff0c;数据统计在很多应用中显得不可或缺&#xff0c;echarts作为一款基于JavaScript的数据可视化图表库&#xff0c;也成为了前端开发的必备技能&#xff0c;下面我们一起来用echarts开发一个学生数据统计的柱形图。 准备 开始答…

性能调优专题并发编程专题(持续更新)

一、性能调优专题 MySQL相关 一、深入理解MySQL索引底层数据结构与算法 索引概念&#xff1a;索引是帮助MySQL高效获取数据的排好序的数据结构 索引数据结构&#xff1a; 1、二叉树 缺点&#xff1a;当索引字段有序的时候&#xff0c;不会自动平衡二叉树&#xff0c;数据…

Spring Boot方法

Spring Boot方法 1、 equals&#xff1a;确保比较的是字符串的内容。这样可以避免潜在的错误&#xff0c;并确保正确地比较字符串的值。 1、 equals&#xff1a;确保比较的是字符串的内容。这样可以避免潜在的错误&#xff0c;并确保正确地比较字符串的值。

Echarts地图之——如何给地图添加背景图片

上期我们已经给地图添加了一个阴影3d的效果&#xff0c;但是背景纯色的感觉还是不怎么好看&#xff0c;希望能给地图加个背景图。 一般来说给地图加背景图的情况较少&#xff0c;加个渐变色或者根据数据的情况给某些省份设置不一样的背景色&#xff0c;这样的做法是比较多的。…

如何用联合(共用体)union验证系统大小端

一&#xff1a;思路 由联合体的特点&#xff0c;可知上图&#xff0c;char c 和 int i 共用四个字节&#xff0c;假设是小端&#xff0c;则由左到右是低地址到高地址&#xff0c;四个字节的内容如图所示01 00 00 00 代码展示&#xff1a; 如果第一个字节是1&#xff0c;则证明…

PostgreSQL关系型数据库介绍与部署

使用背景 在过去的几年中&#xff0c;PostgreSQL的使用量逐渐增加&#xff0c;而Oracle和MySQL的使用量则有所下降。这主要是由于以下几个原因&#xff1a;开源和免费、功能丰富、可扩展性强、安全性高、跨平台支持好、社区活跃、成熟稳定。这些因素使得PostgreSQL成为了许多开…

qt Qt Remote Object(QtRO)实现进程间通信

简介 Qt Remote Object简称QtRO&#xff0c;这是Qt5.9以后官方推出来的新模块&#xff0c;专门用于进程间通信&#xff08;IPC&#xff09;。是基于Socket来封装的&#xff0c;兼容LPC和RPC。LPC即Local Process Communication&#xff0c;而RPC是指Remote Process Communicat…