2-Flume之Sink与Channel

news2024/10/5 12:54:54

Flume

Sink

HDFS Sink

  1. 将数据写到HDFS上。数据以文件形式落地到HDFS上,文件名默认是以FlumeData开头,可以通过hdfs.filePrefix来修改

  2. HDFS Sink默认每隔30s会滚动一次生成一个文件,因此会导致在HDFS上生成大量的小文件,实际过程中,需要通过hdfs.rollInterval来修改,一般设置为3600s或者86400s。如果设置为0,那么表示不滚动,只生成1个文件 。

  3. HDFS Sink默认每1024B会滚动一次生成一个文件,同样会导致产生更多的小文件,实际过程中,需要通过hdfs.rollSize来修改,一般设置为134217728B。如果设置为0,那么表示不滚动,只生成1个文件

  4. HDFS Sink默认每10条数据会滚动一次生成一个文件,同样会导致产生更多的小文件。实际过程中,需要通过hdfs.rollCount来修改。如果设置为0,那么表示不滚动,只生成1个文件

    //不是每次生成文件才一次全部写入。每次启动,就会先创建文件,然后一条一条的写入Event,当达到设置的任一条件时,产生新的文件,并向新的文件写入。

  5. HDFS Sink支持三种文件类型:SequenceFile(序列文件,不能直接cat查看), DataStream(文本文件) or CompressedStream(压缩文件),默认使用的是SequenceFile。如果将文件类型设置为CompressedStream,那么还需要指定属性hdfs.codeC,支持gzip, bzip2, lzo, lzop, snappy

  6. 案例

    1. 格式文件

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      a1.sources.s1.type = netcat
      a1.sources.s1.bind = 0.0.0.0
      a1.sources.s1.port = 8090
      
      a1.channels.c1.type = memory
      
      # 配置HDFS Sink
      # 类型必须是
      a1.sinks.k1.type = hdfs
      # 数据在HDFS上的存储路径。路径不存在会自动创建
      a1.sinks.k1.hdfs.path = hdfs://hadoop01:9000/flume_data
      # 文件滚动间隔时间
      a1.sinks.k1.hdfs.rollInterval = 3600
      # 文件滚动大小
      a1.sinks.k1.hdfs.rollSize = 134217728
      # 文件滚动条数
      a1.sinks.k1.hdfs.rollCount = 1000000000
      # 文件类型
      a1.sinks.k1.hdfs.fileType = DataStream
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      
      1. 启动
      flume-ng agent -n a1 -c $FLUME_HOME/conf -f hdfssink.properties -Dflume.root.logger=INFO,console
      
      1. 在新的窗口中通过nc来发送数据
      nc hadoop01 8090
      

Logger Sink

  1. 将数据以日志写入到指定目的地,支持consolefile。实际开发过程中,使用的比较少,一般是教学阶段使用较多
  2. Logger Sink默认要求Event的body部分不能超过16个字节,可以通过maxBytesToLog来调节
  3. Logger Sink对中文支持不好

File Roll Sink

  1. 将数据以文本文件形式存储到本地的磁盘上。可以通过属性sink.serializer来修改,支持TEXTavro_event

  2. 类似于HDFS Sink,File Roll Sink默认也是每隔30s滚动一次生成一个文件,可以通过属性sink.rollInterval来修改

  3. 案例

    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8090
    
    a1.channels.c1.type = memory
    
    # 配置File Roll Sink
    # 类型必须是file_roll
    a1.sinks.k1.type = file_roll
    # 数据在本地的存储路径
    a1.sinks.k1.sink.directory = /opt/flume_data
    # 文件滚动间隔时间
    a1.sinks.k1.sink.rollInterval = 3600
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1
    

AVRO Sink

  1. 将数据经过AVRO序列化之后来写出,结合AVRO Source来实现流动模型

  2. 多级流动

    多级流动

    1. 第一个节点

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      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
      
      //数据发送到hadoop02的7000端口
      a1.sinks.k1.type = avro
      a1.sinks.k1.hostname = hadoop02
      a1.sinks.k1.port = 7000
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      
    2. 第二个节点

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      //监听本机7000端口的数据
      a1.sources.s1.type = avro
      a1.sources.s1.bind = 0.0.0.0
      a1.sources.s1.port = 7000
      
      a1.channels.c1.type = memory
      
      a1.sinks.k1.type = avro
      
      a1.sinks.k1.hostname = hadoop03
      a1.sinks.k1.port = 7000
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      
    3. 第三个节点

      
      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      a1.sources.s1.type = avro
      a1.sources.s1.bind = 0.0.0.0
      a1.sources.s1.port = 7000
      
      a1.channels.c1.type = memory
      
      a1.sinks.k1.type = logger
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      

    启动顺序:hadoop03 hadoop02 hadoop01

  3. 扇入流动

    扇入流动

    1. 第一个节点

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      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 = avro
      a1.sinks.k1.hostname = hadoop03
      a1.sinks.k1.port = 6666
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      
    2. 第二个节点

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      a1.sources.s1.type = netcat
      a1.sources.s1.bind = 0.0.0.0
      a1.sources.s1.port = 8000
      
      a1.channels.c1.type = memory
      
      a1.sinks.k1.type = avro
      a1.sinks.k1.hostname = hadoop03
      a1.sinks.k1.port = 6666
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      
    3. 第三个节点

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      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
      
  4. 扇出流动

    扇出流动

    1. 注意:在Flume中,可以从同一个数据源采集数据,放到不同的仓库(Channel)存储,但是每一个Sink只能对应1个Channel。一个Channel可对应多个Sink

    2. 第一个节点

      a1.sources = s1
      a1.channels = c1 c2
      a1.sinks = k1 k2
      
      a1.sources.s1.type = netcat
      a1.sources.s1.bind = 0.0.0.0
      a1.sources.s1.port = 8000
      
      a1.channels.c1.type = memory
      a1.channels.c2.type = memory
      
      a1.sinks.k1.type = avro
      a1.sinks.k1.hostname = hadoop02
      a1.sinks.k1.port = 7000
      
      a1.sinks.k2.type = avro
      a1.sinks.k2.hostname = hadoop03
      a1.sinks.k2.port = 7000
      
      a1.sources.s1.channels = c1 c2
      a1.sinks.k1.channel = c1
      a1.sinks.k2.channel = c2
      
    3. 第二个和第三个节点

      a1.sources = s1
      a1.channels = c1
      a1.sinks = k1
      
      a1.sources.s1.type = avro
      a1.sources.s1.bind = 0.0.0.0
      a1.sources.s1.port = 7000
      
      a1.channels.c1.type = memory
      
      a1.sinks.k1.type = logger
      
      a1.sources.s1.channels = c1
      a1.sinks.k1.channel = c1
      

自定义Sink

  1. 自定义Sink的时候,需要定义一个类继承AbstractSink,实现Sink接口,最好还要实现Configurable接口来获取配置。注意,自定义Sink的过程中,需要关注事务问题。依赖和笔记1中用的一样。

  2. public class AuthSinks extends AbstractSink implements Sink , Configurable {
    
    
    
        String path ;
        //打印流,打印到文件或者Flume的窗口。sout调用的就是这个类中的方法
        PrintStream ps;
    
        @Override
        public void configure(Context context) {
    
            //从flume中的格式文件中获取路径信息
            path = context.getString("path");
            if(path == null || "".equals(path) || !path.startsWith("/"))
                throw new IllegalArgumentException();
        }
    
        @Override
        public synchronized void start() {
    
            if(!path.endsWith("/"))
                path = path + "/";
            path += String.valueOf(System.currentTimeMillis());
            try {
                ps =  new PrintStream(path);
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    
        @Override
        public Status process() throws EventDeliveryException {
            Channel channel = this.getChannel();
            Transaction ts = channel.getTransaction();
            ts.begin();
            Event e;
            try {
                while ((e = channel.take()) != null) {
                    ps.println("headers:");
                    Map<String, String> map = e.getHeaders();
                    for (Map.Entry<String, String> header : map.entrySet()) {
                        ps.println(header.getKey() + "-" + header.getValue());
                    }
                    ps.println("bodys:");
                    byte[] body = e.getBody();
                    ps.println("\t" + new String(body));
    
                }
                ts.commit();
                return Status.READY;
            } catch (Exception e1) {
                ts.rollback();
                return Status.BACKOFF;
            } finally {
                ts.close();
            }
        }
    
        @Override
        public synchronized void stop() {
            if(ps != null) ps.close();
        }
    }
    
  3. 打成jar包放到lib目录下

    cd /opt/software/flume-1.11.0/lib/
    rz
    
  4. 编辑格式文件

    cd ../data/
    vim authsink.properties
    

    在文件中添加

    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = http
    a1.sources.s1.port = 8888
    
    a1.channels.c1.type = memory
    
    # 配置自定义Sink
    # 类型必须是类的全路径名
    a1.sinks.k1.type = com.fesco.sink.AuthSink
    # 存储路径
    a1.sinks.k1.path = /opt/flume_data
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1
    
  5. 启动Flume

  6. 发送HTTP请求

    curl -X POST -d '[{"headers":{"class":"big data","sinktype":"auth"},"body":"testing~~~"}]' http://hadoop01:8888
    

事务

事务流程
  1. Source会先执行doPut操作,将数据放入PutList中,PutList本质上是一个Deque
  2. PutList会试图将数据传输给Channel,如果成功,执行doCommit操作,如果失败,那么执行doRollback
  3. Channel收到数据之后,会试图将数据推送到TakeList,然后由TakeList将数据试图推送给Sink。TakeList本质上也是一个Deque
  4. 如果TakeList成功将数据推送给Sink,那么执行doCommit操作;反之,如果失败,那么执行doRollback操作

Channel

Memory Channel

  1. Memory Channel将数据临时存储到内存队列中,队列默认容量是100,即队列默认最多能存储100条数据,如果队列被放满,那么后续的操作会被阻塞。可以通过属性capacity来调节,实际过程中一般会设置为100000~300000
  2. transactionCapacity:事务容量。每次PutList向Channel推送的数据条数或者Channel向TakeList添加的数据条数,默认是100。实际过程中,这个值一般会调节为1000~3000
  3. 需要注意的是,Memory Channel是将数据临时存储到内存中,所以读写速度相对较快,但是不可靠,因此适应于要求速度但是不要求可靠性的场景

File Channel

  1. File Channel将数据临时存储到磁盘上,所以读写速度相对慢一些,但是可靠,因此适应于要求可靠性但不要求速度的场景

  2. File Channel默认会将数据临时存储到~/.flume/file-channel/data目录下,可以通过属性dataDirs来修改,如果指定了多个数据目录,那么目录之间用逗号隔开

  3. File Channel支持断点续传,默认情况下,会将偏移量记录到~/.flume/file-channel/checkpoint目录下,可以通过属性checkpointDir来修改

  4. 默认File Channel能够存储1000000条数据,可以通过属性capacity来条件

  5. File Channel最多能占用2146435071B的磁盘,可以通过maxFileSize修改

  6. File Channel的transactionCapacity的默认值是10000

  7. 案例

    a1.sources = s1
    a1.channels = c1
    a1.sinks = k1
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8090
    
    # 配置File Channel
    # 类型必须是file
    a1.channels.c1.type = file
    # 偏移量的存储位置
    a1.channels.c1.checkpointDir = /opt/flume_data/checkpoint
    # 数据临时存储位置
    a1.channels.c1.dataDirs = /opt/flume_data/data
    
    a1.sinks.k1.type = logger
    
    a1.sources.s1.channels = c1
    a1.sinks.k1.channel = c1
    

其他Channel

  1. JDBC Channel:将数据临时存储到数据库,但是JDBC Channel目前只支持Derby数据库。基于Derby(微型、文件型、单连接)的特性,所以实际开发过程中,不适用这个Channel
  2. Spillable Memory Channel:内存溢出Channel。内存中维系一个队列,如果队列被放满,不会阻塞,而是会将数据临时存储到磁盘上,这个Channel目前还在实验阶段,不推荐在生产场景中使用

Selector

概述

  1. Selector并不是一个单独的组件,而是附属于Source的子组件
  2. Selector支持三种模式:
    1. replicating:复制/复用模式。节点收集到数据之后,会将数据复制,然后分发给每一个节点,此时每一个节点收到的数据都是相同的
    2. load balancing:负载均衡模式。节点收集到数据之后,会平均分发到其他的节点上。此时被扇出的节点接收到的数据条数大致相等,但是数据不相同。这种模式是Flume1.10提供的,然后不稳定
    3. multiplexing:路由/分发模式。节点收集到数据之后,会根据headers中的指定键和值,将数据分发给对应的节点来处理,此时每一个节点收到的数据都是不同的
  3. 扇出结构中,如果不指定,默认使用的是replicating模式

multiplexing

  1. 实际过程中,如果需要对数据进行分类处理,那么可以考虑使用路由/分发模式

  2. 案例

    a1.sources = s1
    a1.channels = c1 c2
    a1.sinks = k1 k2
    
    a1.sources.s1.type = http
    a1.sources.s1.port = 8000
    # 指定Selector的类型
    a1.sources.s1.selector.type = multiplexing
    # 指定监听的字段
    a1.sources.s1.selector.header = kind
    # 根据kind字段的值分发给对应的Channel
    
    //如果请求头中的kind的值是video就传输给c1 通道
    a1.sources.s1.selector.mapping.video = c1
    a1.sources.s1.selector.mapping.music = c2
    a1.sources.s1.selector.default = c2
    
    
    a1.channels.c1.type = memory
    a1.channels.c2.type = memory
    
    a1.sinks.k1.type = avro
    a1.sinks.k1.hostname = hadoop02
    a1.sinks.k1.port = 7000
    
    a1.sinks.k2.type = avro
    a1.sinks.k2.hostname = hadoop03
    a1.sinks.k2.port = 7000
    
    a1.sources.s1.channels = c1 c2
    a1.sinks.k1.channel = c1
    

a1.sinks.k2.channel = c2


启动Flume之后,发送请求

```sh
curl -X POST -d '[{"headers":{"kind":"video"},"body":"video log"}]' http://hadoop01:8000
curl -X POST -d '[{"headers":{"kind":"music"},"body":"music log"}]' http://hadoop01:8000
curl -X POST -d '[{"headers":{"kind":"txt"},"body":"txt log"}]' http://hadoop01:8000

Sink Processor

概述

  1. Sink Processor本质上就是Sink Group,是将一个或者多个Sink绑定到一个组中来使用
  2. 目前,官网支持三种模式
    1. default:默认模式。一个Sink就对应一个Sinkgroup,有几个Sink就对应了几个Sinkgroup
    2. Load Balancing:负载均衡。将多个Sink绑定到一个组中,然后将这个组接收到数据平均的发送给每一个Sink。支持round_robin(轮询)和random(随机)。同样,Flume提供的负载均衡模式并不好(能)用
    3. Failover:崩溃恢复。将多个Sink绑定到一个组中,如果现在工作的Sink宕机,同组中的其他Sink可以实现相同的功能,从而避免了单点故障

Failover

  1. 将多个Sink绑定到一个组中,同组的Sink需要配置优先级,数据会优先发送给优先级较高的Sink,如果高优先级的Sink宕机,那么才会发送给低优先级的Sink。当优先级高的Sink恢复后,那么数据又会重新回来。

  2. 案例

    a1.sources = s1
    a1.channels = c1 c2
    a1.sinks = k1 k2
    
    # 给Sinkgroup起名
    a1.sinkgroups = g1
    # 给Sinkgroup绑定Sink
    a1.sinkgroups.g1.sinks = k1 k2
    # 指定Sinkgroup的类型
    a1.sinkgroups.g1.processor.type = failover
    # 给Sink指定优先级
    a1.sinkgroups.g1.processor.priority.k1 = 7
    a1.sinkgroups.g1.processor.priority.k2 = 5
    # 发送超时时间
    # 默认是30000ms->30s   。这个属性的作用不是很理解
    a1.sinkgroups.g1.processor.maxpenalty = 10000
    
    a1.sources.s1.type = netcat
    a1.sources.s1.bind = 0.0.0.0
    a1.sources.s1.port = 8000
    
    a1.channels.c1.type = memory
    a1.channels.c2.type = memory
    
    a1.sinks.k1.type = avro
    a1.sinks.k1.hostname = hadoop02
    a1.sinks.k1.port = 7000
    
    a1.sinks.k2.type = avro
    a1.sinks.k2.hostname = hadoop03
    a1.sinks.k2.port = 7000
    
    a1.sources.s1.channels = c1 c2
    a1.sinks.k1.channel = c1
    a1.sinks.k2.channel = c2
    

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

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

相关文章

人工智能 框架 paddlepaddle 飞桨 使用指南 使用例子 线性回归模型demo 1

安装过程&使用指南&线性回归模型 使用例子 本来预想 是安装 到 conda 版本的 11.7的 但是电脑没有gpu 所以 安装过程稍有变动,下面简单讲下 conda create -n paddle_env117 python=3.9 由于想安装11.7版本 py 是3.9 所以虚拟环境名称也是 paddle_env117 activa…

各种排序介绍

1.排序的概念 排序 &#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性 &#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排…

【沐风老师】3DMAX样条线皮肤SplineSkin插件使用方法详解

3DMAX样条线皮肤SplineSkin插件使用方法 3DMAX样条线皮肤插件SplineSkin&#xff0c;将3D物体一键转化为样条线包裹形状的插件&#xff0c;适用于科研绘图和艺术设计等相关领域。 【适用版本】 3dMax2015及更高版本&#xff08;教程编写于2024&#xff0c;但适用不仅限于此范围…

LeetCode 面试经典150题 392.判断子序列

题目&#xff1a; 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde"…

SQL复习专题

请结合B站-技术蛋老师 视频学习 核心语法 一、增&#xff1a;数据库/表格 create create database 数据库名&#xff1b;#创建表&#xff08;列名类型&#xff09; mysql> create table eggs_record(-> id int,-> egg_name varchar(10),-> sold date-> ); 这…

【前端】代码案例

1.猜数字 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>猜数字</title> </head> <…

Flutter 旋转动画 线性变化的旋转动画

直接上代码 图片自己添加一张就好了 import dart:math;import package:flutter/material.dart;import package:flutter/animation.dart;void main() > runApp(MyApp()); //旋转动画 class MyApp extends StatelessWidget {overrideWidget build(BuildContext context) {re…

Luminar Neo:重塑图像编辑新纪元,Mac与Win双平台畅享创意之旅

在数字时代的浪潮中&#xff0c;图像编辑软件已成为摄影师和设计师们不可或缺的创作工具。Luminar Neo&#xff0c;作为一款专为Mac与Windows双平台打造的图像编辑软件&#xff0c;正以其卓越的性能和创新的编辑功能&#xff0c;引领着图像编辑的新潮流。 Luminar Neo不仅继承…

SOC 子模块---中断控制器

中断控制器对soc 中的各个外设进行中断管理&#xff0c;进行优先权排队&#xff0c;并送出IQR信号给CPU&#xff1b; 中断控制器在整个系统中的结构&#xff1a; IRQ<n>来源于不同的中断源&#xff0c;比如&#xff1a;I2C,SPI等&#xff0c;INTC收集这些中断&#xff0…

word文件如何转PDF格式?word转PDF的方法

在当今数字化时代&#xff0c;文档格式的转换已成为日常生活和工作中不可或缺的一部分。其中&#xff0c;将Word文档转换为PDF格式更是受到了广大用户的青睐。本文将详细介绍Word转PDF的方法&#xff0c;帮助读者轻松实现文档格式的转换&#xff0c;并探讨转换过程中的注意事项…

P6技巧:对计划执行纠偏措施

前言 对施工计划的滞后原因分析&#xff0c;通常采取由大到小、由高到低的方法。即首先查看总体进度偏差&#xff0c;再分析其偏差主要来源于哪部分。 项目进度评估与偏差控制 项目实施过程中&#xff0c;项目控制人员应对进度实施情况进行跟踪、采集数据&#xff0c;并根据…

图解Kafka架构学习笔记(二)

kafka的存储机制 https://segmentfault.com/a/1190000021824942 https://www.lin2j.tech/md/middleware/kafka/Kafka%E7%B3%BB%E5%88%97%E4%B8%83%E5%AD%98%E5%82%A8%E6%9C%BA%E5%88%B6.html https://tech.meituan.com/2015/01/13/kafka-fs-design-theory.html https://feiz…

数据可视化基础与应用-04-seaborn库从入门到精通01-02

总结 本系列是数据可视化基础与应用的第04篇seaborn&#xff0c;是seaborn从入门到精通系列第1-2篇。本系列的目的是可以完整的完成seaborn从入门到精通。主要介绍基于seaborn实现数据可视化。 参考 参考:数据可视化-seaborn seaborn从入门到精通01-seaborn介绍与load_datas…

CharacterController.Move called on inactive controller

【问题背景】 Unity3D中开发物体的移动&#xff0c;实现代码如下&#xff1a; public class TargetController : MonoBehaviour {private CharacterController character;private float speedRate 4f;private void Start(){character GetComponent<CharacterController&…

等保测评密评对照:一文看懂两者差异

最近&#xff0c;在去几个客户的办公室交流的方案的时候&#xff0c;都会被重点问到网络安全问题,在方案中“等保”是如何体现和落实的。而且有些客户的领导也会提到“密评”与“等保”如何衔接&#xff0c;是否有先后顺序&#xff0c;可否同时进行测评等问题。 关于“等保”与…

网络原理(7)——以太网数据帧和DNS协议(数据链路层和应用层)

目录 一、以太网数据帧&#xff08;数据链路层&#xff09; 二、DNS协议(域名解析系统&#xff0c;应用层协议) 一、以太网数据帧&#xff08;数据链路层&#xff09; 以太网横跨了数据链路层和物理层&#xff0c;这里只做简单介绍&#xff0c;因为普通程序员用不到这一块&am…

UI自动化_id 元素定位

## 导包selenium from selenium import webdriver import time1、创建浏览器驱动对象 driver webdriver.Chrome() 2、打开测试网站 driver.get("你公司的平台地址") 3、使浏览器窗口最大化 driver.maximize_window() 4、在用户名输入框中输入admin driver.find_ele…

hbase启动错误-local host is“master:XXXX“ destination is:master

博主的安装前提&#xff1a; zookeeper安装完成&#xff0c;且启动成功 hdfs高可用安装&#xff0c;yarn高可用安装&#xff0c;且启动成功 报错原因&#xff1a;端口配置不对 解决方案&#xff1a; 输入&#xff1a;hdfs getconf -confKey fs.default.name 然后把相应的…

WM8978 —— 带扬声器驱动程序的立体声编解码器(7)

接前一篇文章&#xff1a;WM8978 —— 带扬声器驱动程序的立体声编解码器&#xff08;6&#xff09; 十、音频接口 WM8978具有一个标准的音频接口&#xff0c;支持立体声数据在芯片之间的传输。该接口是一个3线标准音频接口&#xff0c;支持多种音频数据格式&#xff0c;包括I…

C++ 简单模拟实现 STL 中的 list 与 queue

目录 一&#xff0c;list 1&#xff0c; list 的节点与迭代器 2&#xff0c;list 的数据结构、一些简单的功能、构造函数 3&#xff0c;list 的对元素操作 4&#xff0c;C 11 的一些功能 5&#xff0c;完整代码&#xff1a; 二&#xff0c;queue 一&#xff0c;list std…