当前位置: 首页 > news >正文

executor行为相关Spark sql参数源码分析

0、前言

参数名和默认值
spark.default.parallelism=Default number of partitions in RDDs
spark.executor.cores=1 in YARN mode 一般默认值
spark.files.maxPartitionBytes=134217728(128M)
spark.files.openCostInBytes=4194304 (4 MiB)
spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version=1 不同版本算法task提交数据

【重点】在spark sql中有对应参数为:

spark.sql.files.maxPartitionBytes=134217728(128M)  本次重点源码分析
spark.sql.files.openCostInBytes=4194304  (4 MiB) 本次重点源码分析
spark.default.parallelism = math.max(totalCoreCount.get(), 2)

对应源码位置如下:

org.apache.spark.scheduler.cluster.CoarseGrainedSchedulerBackend#defaultParallelism

org.apache.spark.sql.internal.SQLConf#FILES_MAX_PARTITION_BYTES

org.apache.spark.sql.internal.SQLConf#FILES_OPEN_COST_IN_BYTES

1、 环境准备

create database bicoredata;CREATE TABLE bicoredata.dwd_start_log_dm(
`device_id` string,
`area` string,
`uid` string,
`app_v` string,
`event_type` string,
`os_type` string,
`channel` string,
`language` string,
`brand` string,
`entry` string,
`action` string,
`error_code` string
)
comment 'dwd用户启动日志信息'
partitioned by (`dt` string)
stored as orc
tblproperties("orc.compress"="ZLIB")
location '/bicoredata/dwd_start_log_dm';-- 解析ods日志到dwd表insert overwrite table bicoredata.dwd_start_log_dm
partition(dt='20220721')
select get_json_object(line, '$.attr.device_id'),
get_json_object(line, '$.attr.area'),
get_json_object(line, '$.attr.uid'),
get_json_object(line, '$.attr.app_v'),
get_json_object(line, '$.attr.event_type'),
get_json_object(line, '$.attr.os_type'),
get_json_object(line, '$.attr.channel'),
get_json_object(line, '$.attr.language'),
get_json_object(line, '$.attr.brand'),
get_json_object(line, '$.app_active.json.entry'),
get_json_object(line, '$.app_active.json.action'),
get_json_object(line, '$.app_active.json.error_code')
from 
(
select split(str, ' ')[7] as  line
from biods.ods_start_log
where dt='20220721'
)t

2、 代码准备

package org.example.sparksqlimport org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSessionobject SparkSqlHive {def main(args: Array[String]): Unit = {System.setProperty("HADOOP_USER_NAME", "root")// 动态分配参数必须 在 yarn环境下才能生效,client/clusterval ss = SparkSession.builder().master("yarn").appName("the test of SparkSession").config("spark.deploy.mode","cluster").config("yarn.resourcemanager.hostname", "hadoop2")// 注意只有设置为true,才是文件读取算子,否则是表读取算子。.config("spark.sql.hive.convertMetastoreOrc", "true").config("spark.sql.files.maxPartitionBytes","34008864")  //注意不是spark.files.maxPartitionBytes.config("spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version","2").config("spark.dynamicAllocation.enabled","true").config("spark.shuffle.service.enabled","true").config("spark.driver.host","192.168.150.1").enableHiveSupport().getOrCreate()ss.sql("DROP TABLE IF EXISTS temp.temp_ods_start_log");val df = ss.sql("insert overwrite table bicoredata.dwd_start_log_dm " +"partition(dt='20210721') " +"select get_json_object(line, '$.attr.device_id')," +"get_json_object(line, '$.attr.area')," +"get_json_object(line, '$.attr.uid')," +"get_json_object(line, '$.attr.app_v')," +"get_json_object(line, '$.attr.event_type')," +"get_json_object(line, '$.attr.os_type')," +"get_json_object(line, '$.attr.channel')," +"get_json_object(line, '$.attr.language')," +"get_json_object(line, '$.attr.brand')," +"get_json_object(line, '$.app_active.json.entry')," +"get_json_object(line, '$.app_active.json.action')," +"get_json_object(line, '$.app_active.json.error_code') " +"from " +"(" +"select split(str, ' ')[7] as  line " +"from biods.ods_start_log " +"where dt='20210721'" +")t")Thread.sleep(1000000)ss.stop()}
}

输入:
hdfs中该日期分区存有2个文件,大小分别为245M和94M
请添加图片描述
输出:
最终结果分区中,有6个文件。
请添加图片描述

可见缩小spark.sql.files.maxPartitionBytes值,增大了读取task数量。

3 、源码分析

3.1 、物理执行计划如下

Execute InsertIntoHadoopFsRelationCommand hdfs://hadoop1:9000/bicoredata/dwd_start_log_dm, Map(dt -> 20210721), false, [dt#55], ORC, Map(orc.compress -> ZLIB, serialization.format -> 1, partitionOverwriteMode -> dynamic), Overwrite, CatalogTable(
Database: bicoredata
Table: dwd_start_log_dm
Owner: root
Created Time: Sun Dec 11 17:47:33 CST 2022
Last Access: UNKNOWN
Created By: Spark 2.2 or prior
Type: MANAGED
Provider: hive
Comment: dwd????????
Table Properties: [orc.compress=ZLIB, transient_lastDdlTime=1670752053]
Location: hdfs://hadoop1:9000/bicoredata/dwd_start_log_dm
Serde Library: org.apache.hadoop.hive.ql.io.orc.OrcSerde
InputFormat: org.apache.hadoop.hive.ql.io.orc.OrcInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat
Storage Properties: [serialization.format=1]
Partition Provider: Catalog
Partition Columns: [`dt`]
Schema: root|-- device_id: string (nullable = true)|-- area: string (nullable = true)|-- uid: string (nullable = true)|-- app_v: string (nullable = true)|-- event_type: string (nullable = true)|-- os_type: string (nullable = true)|-- channel: string (nullable = true)|-- language: string (nullable = true)|-- brand: string (nullable = true)|-- entry: string (nullable = true)|-- action: string (nullable = true)|-- error_code: string (nullable = true)|-- dt: string (nullable = true)
), org.apache.spark.sql.execution.datasources.CatalogFileIndex@df5f9368, [device_id, area, uid, app_v, event_type, os_type, channel, language, brand, entry, action, error_code, dt]
+- Project [ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.device_id) as string) AS device_id#43, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.area) as string) AS area#44, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.uid) as string) AS uid#45, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.app_v) as string) AS app_v#46, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.event_type) as string) AS event_type#47, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.os_type) as string) AS os_type#48, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.channel) as string) AS channel#49, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.language) as string) AS language#50, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.attr.brand) as string) AS brand#51, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.app_active.json.entry) as string) AS entry#52, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.app_active.json.action) as string) AS action#53, ansi_cast(get_json_object(split(str#1,  , -1)[7], $.app_active.json.error_code) as string) AS error_code#54, 20210721 AS dt#55]+- *(1) ColumnarToRow+- FileScan orc biods.ods_start_log[str#1,dt#2] Batched: true, DataFilters: [], Format: ORC, Location: InMemoryFileIndex[hdfs://hadoop1:9000/bi/ods/ods_start_log/dt=20210721], PartitionFilters: [isnotnull(dt#2), (dt#2 = 20210721)], PushedFilters: [], ReadSchema: struct<str:string>

如上所示,本质上分三部分:
(1)读取表
FileScan orc biods.ods_start_log
(2)转换
Project [ansi_cast(get_json_object(split(str#1, , -1)[7]
(3)写入目标表
Execute InsertIntoHadoopFsRelationCommand

3.2 、FileScan和InsertIntoHadoopFsRelationCommand 算子

从InsertIntoHadoopFsRelationCommand 开始源码分析如下:

org.apache.spark.sql.execution.datasources.InsertIntoHadoopFsRelationCommand#run

org.apache.spark.sql.execution.datasources.FileFormatWriter$#write

org.apache.spark.sql.execution.FileSourceScanExec#inputRDD

FileSourceScanExec#createNonBucketedReadRDD

org.apache.spark.sql.execution.FileSourceScanExec#createNonBucketedReadRDD
首次出现3个相关参数

private def createNonBucketedReadRDD(readFile: (PartitionedFile) => Iterator[InternalRow],selectedPartitions: Array[PartitionDirectory],fsRelation: HadoopFsRelation): RDD[InternalRow] = {// 对应spark.sql.files.openCostInBytes 参数 val openCostInBytes = fsRelation.sparkSession.sessionState.conf.filesOpenCostInBytes// 基于3个参数计算出来val maxSplitBytes =FilePartition.maxSplitBytes(fsRelation.sparkSession, selectedPartitions)logInfo(s"Planning scan with bin packing, max size: $maxSplitBytes bytes, " +s"open cost is considered as scanning $openCostInBytes bytes.")// 逻辑分割orc文件,返回分区的文件对象PartitionedFileval splitFiles = selectedPartitions.flatMap { partition =>partition.files.flatMap { file =>// getPath() is very expensive so we only want to call it once in this block:val filePath = file.getPath// orc文件是可以分割的,对应org.apache.spark.sql.hive.orc.OrcFileFormat#isSplitable函数,返回trueval isSplitable = relation.fileFormat.isSplitable(relation.sparkSession, relation.options, filePath)PartitionedFileUtil.splitFiles(sparkSession = relation.sparkSession,file = file,filePath = filePath,isSplitable = isSplitable,maxSplitBytes = maxSplitBytes,partitionValues = partition.values)}}.sortBy(_.length)(implicitly[Ordering[Long]].reverse)// 基于分区文件对象,最大分割尺寸,返回文件分区FilePartition对象(逻辑层面)val partitions =FilePartition.getFilePartitions(relation.sparkSession, splitFiles, maxSplitBytes)// 返回rddnew FileScanRDD(fsRelation.sparkSession, readFile, partitions)
}
FilePartition和PartitionedFile区别(1)FilePartition对象:会被单个任务读取的PartitionedFile集合
对应源码在 org.apache.spark.sql.execution.datasources.FilePartition
--》特点是,一个FilePartition对应1个task(2)PartitionedFile对象:用于读取的单个文件的部分,包含文件路径,开始偏移量,读取长度偏移量
-->特点是,一个PartitionedFile对应1个文件的部分,有对应的开始偏移量和读取偏移量

FilePartition#maxSplitBytes

org.apache.spark.sql.execution.datasources.FilePartition#maxSplitBytes
综合以上3个关键参数,计算出最大分割大小。

def maxSplitBytes(sparkSession: SparkSession,selectedPartitions: Seq[PartitionDirectory]): Long = {// 对应 spark.sql.files.maxPartitionBytes 参数,默认128Mval defaultMaxSplitBytes = sparkSession.sessionState.conf.filesMaxPartitionBytes// 对应spark.sql.files.openCostInBytes 参数 ,默认4Mval openCostInBytes = sparkSession.sessionState.conf.filesOpenCostInBytes// 对应 spark.default.parallelism参数,默认应该会取到2(yarn cluster集群默认环境下测试结果)val defaultParallelism = sparkSession.sparkContext.defaultParallelismval totalBytes = selectedPartitions.flatMap(_.files.map(_.getLen + openCostInBytes)).sumval bytesPerCore = totalBytes / defaultParallelismMath.min(defaultMaxSplitBytes, Math.max(openCostInBytes, bytesPerCore))
}

org.apache.spark.scheduler.cluster.CoarseGrainedSchedulerBackend#defaultParallelism

override def defaultParallelism(): Int = {conf.getInt("spark.default.parallelism", math.max(totalCoreCount.get(), 2))
}

PartitionedFileUtil#splitFiles

org.apache.spark.sql.execution.PartitionedFileUtil#splitFiles

def splitFiles(sparkSession: SparkSession,file: FileStatus,filePath: Path,isSplitable: Boolean,maxSplitBytes: Long,partitionValues: InternalRow): Seq[PartitionedFile] = {if (isSplitable) {(0L until file.getLen by maxSplitBytes).map { offset =>val remaining = file.getLen - offsetval size = if (remaining > maxSplitBytes) maxSplitBytes else remainingval hosts = getBlockHosts(getBlockLocations(file), offset, size)// 基于偏移量,size构造分区file对象PartitionedFile(partitionValues, filePath.toUri.toString, offset, size, hosts)}} else {Seq(getPartitionedFile(file, filePath, partitionValues))}
}

逻辑分割结果,11个文件,降序排列:
请添加图片描述

FilePartition#getFilePartitions

org.apache.spark.sql.execution.datasources.FilePartition#getFilePartitions

def getFilePartitions(sparkSession: SparkSession,partitionedFiles: Seq[PartitionedFile],maxSplitBytes: Long): Seq[FilePartition] = {val partitions = new ArrayBuffer[FilePartition]val currentFiles = new ArrayBuffer[PartitionedFile]var currentSize = 0L/** Close the current partition and move to the next. */def closePartition(): Unit = {if (currentFiles.nonEmpty) {// 将PartitionedFile文件数组封装成1个FilePartition对象val newPartition = FilePartition(partitions.size, currentFiles.toArray)partitions += newPartition}currentFiles.clear()currentSize = 0}val openCostInBytes = sparkSession.sessionState.conf.filesOpenCostInBytes// Assign files to partitions using "Next Fit Decreasing"partitionedFiles.foreach { file =>if (currentSize + file.length > maxSplitBytes) {closePartition()}// Add the given file to the current partition.currentSize += file.length + openCostInBytescurrentFiles += file}// 处理最后1个分区文件closePartition()partitions
}

总体调用流程

请添加图片描述
InsertIntoHadoopFsRelationCommand为物理逻辑计划的最后1个算子,其run方法,包含写入数据和更新元数据过程;其中写入数据又包含生成FileScanRDD(11个分区)和提交job过程。

请添加图片描述
stage0的初始rdd,即为FileScanRDD。

由于FileScanRDD包含11个FilePartition,所以 最终生成11个task
请添加图片描述
请添加图片描述

4、疑问

4.1、预期11 个task 大小均匀分布 32M左右,但为什么实际存在一些task空跑,其他task输入大小为62M多?

经了解发现,以hdfs://hadoop1:9000/bi/ods/ods_start_log/dt=20210721/000000_1orc文件为例,其由4个stripe组成,大小刚好为62.5M,62.5M,62.5M,58.6M,且不可分割,这就与task中大小和数量不谋而合。

orc原理参考: https://www.jianshu.com/p/0ba4f5c3f113

查看orc文件的stripe个数等信息

hive --orcfiledump hdfs://hadoop1:9000/bi/ods/ods_start_log/dt=20210721/000001_0 | less

结果如下
请添加图片描述

4.2、测试sql中不涉及join,group by等shuffle操作,为什么会溢出到内存,甚至磁盘?

请添加图片描述

下面是exectuor中,spark task运行的线程dump中,可以发现有堆内存溢出的操作。

猜测:可能有shuffle或者排序,因为如果是纯map task任务,如果excutor内存不足,会直接报oom错误。

请添加图片描述

org.apache.spark.sql.execution.SortExec#doExecute

//task执行过程中,会到这一步。
protected override def doExecute(): RDD[InternalRow] = {val peakMemory = longMetric("peakMemory")val spillSize = longMetric("spillSize")val sortTime = longMetric("sortTime")child.execute().mapPartitionsInternal { iter =>val sorter = createSorter()val metrics = TaskContext.get().taskMetrics()// Remember spill data size of this task before execute this operator so that we can// figure out how many bytes we spilled for this operator.val spillSizeBefore = metrics.memoryBytesSpilled// 说明sort过程会 溢出数据到内存val sortedIterator = sorter.sort(iter.asInstanceOf[Iterator[UnsafeRow]])sortTime += NANOSECONDS.toMillis(sorter.getSortTimeNanos)peakMemory += sorter.getPeakMemoryUsagespillSize += metrics.memoryBytesSpilled - spillSizeBeforemetrics.incPeakExecutionMemory(sorter.getPeakMemoryUsage)sortedIterator}

sortExec工作原理 : https://zhuanlan.zhihu.com/p/582664919
当没有足够的内存来存储指针阵列列表或分配的内存页,或者UnsafeInMemorySorter的行数大于或等于溢出阈值numElementsForSpillThreshold时,内存中的数据将被分割到磁盘。

为什么会有sortExec算子?

在 InsertIntoHadoopFsRelationCommand 命令,提交job之前。

org/apache/spark/sql/execution/datasources/FileFormatWriter.scala:170

// 查看requiredChildOrderings针对排序有特殊需求的添加SortExec节点
val rdd = if (orderingMatched) {empty2NullPlan.execute()
} else {// SPARK-21165: the `requiredOrdering` is based on the attributes from analyzed plan, and// the physical plan may have different attribute ids due to optimizer removing some// aliases. Here we bind the expression ahead to avoid potential attribute ids mismatch.val orderingExpr = bindReferences(requiredOrdering.map(SortOrder(_, Ascending)), outputSpec.outputColumns)// 这里绑定上了sortexec 算子,返回的是rdd,并非已经开始计算了SortExec(orderingExpr,global = false,child = empty2NullPlan).execute()
}val rddWithNonEmptyPartitions = if (rdd.partitions.length == 0) {sparkSession.sparkContext.parallelize(Array.empty[InternalRow], 1)} else {rdd}val jobIdInstant = new Date().getTimeval ret = new Array[WriteTaskResult](rddWithNonEmptyPartitions.partitions.length)
// 然后这里才提交了jobsparkSession.sparkContext.runJob(rddWithNonEmptyPartitions,(taskContext: TaskContext, iter: Iterator[InternalRow]) => {executeTask(description = description,jobIdInstant = jobIdInstant,sparkStageId = taskContext.stageId(),sparkPartitionId = taskContext.partitionId(),sparkAttemptNumber = taskContext.taskAttemptId().toInt & Integer.MAX_VALUE,committer,iterator = iter)},rddWithNonEmptyPartitions.partitions.indices,(index, res: WriteTaskResult) => {committer.onTaskCommit(res.commitMsg)ret(index) = res})

参考:https://developer.aliyun.com/article/679260

4.3、resulttask

不涉及shuffle的sql 最终生成的只有resultTask, 当然也只有resultstage。

org.apache.spark.rdd.RDDCheckpointData$
请添加图片描述

请添加图片描述

executetask即 传入 rdd上执行的func

org.apache.spark.scheduler.ResultTask#runTask

请添加图片描述

org.apache.spark.sql.execution.datasources.FileFormatWriter#executeTask

里面包含提交task的过程

参考:https://blog.csdn.net/weixin_42588332/article/details/122440644#:~:text=%E5%AF%B9%E4%BA%8E%20Aggregate%20%E6%93%8D%E4%BD%9C%EF%BC%8CSpark%20UI%20%E4%B9%9F%E8%AE%B0%E5%BD%95%E7%9D%80%E7%A3%81%E7%9B%98%E6%BA%A2%E5%87%BA%E4%B8%8E%E5%B3%B0%E5%80%BC%E6%B6%88%E8%80%97%EF%BC%8C%E5%8D%B3%20Spill%20size%20%E5%92%8C,%E7%9A%84%E5%B3%B0%E5%80%BC%E6%B6%88%E8%80%97%EF%BC%8C%E8%AF%81%E6%98%8E%E5%BD%93%E5%89%8D%203GB%20%E7%9A%84%20Executor%20Memory%20%E8%AE%BE%E7%BD%AE%EF%BC%8C%E5%AF%B9%E4%BA%8E%20Aggregate%20%E8%AE%A1%E7%AE%97%E6%9D%A5%E8%AF%B4%E6%98%AF%E7%BB%B0%E7%BB%B0%E6%9C%89%E4%BD%99%E7%9A%84%E3%80%82

https://zhuanlan.zhihu.com/p/431015932

https://blog.csdn.net/chongqueluo2709/article/details/101006130

相关文章:

executor行为相关Spark sql参数源码分析

0、前言 参数名和默认值spark.default.parallelismDefault number of partitions in RDDsspark.executor.cores1 in YARN mode 一般默认值spark.files.maxPartitionBytes134217728(128M)spark.files.openCostInBytes4194304 (4 MiB)spark.hadoop.mapreduce.fileoutputcommitte…...

双通道5.2GSPS(或单通道10.4GSPS)射频采样FMC+模块

概述 FMC140是一款具有缓冲模拟输入的低功耗、12位、双通道&#xff08;5.2GSPS/通道&#xff09;、单通道10.4GSPS、射频采样ADC模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.1规范&#xff0c;该模块可以作为一个理想的IO单元耦合至FPGA前端&#xff0c;8通道的JE…...

理解java反射

是什么Java反射是Java编程语言的一个功能&#xff0c;它允许程序在运行时&#xff08;而不是编译时&#xff09;检查、访问和修改类、对象和方法的属性和行为。使用反射创建对象相比直接创建对象有什么优点使用反射创建对象相比直接创建对象的主要优点是灵活性和可扩展性。当我…...

EasyRcovery16免费的电脑照片数据恢复软件

电脑作为一种重要的数据储存设备&#xff0c;其中保存着大量的文档&#xff0c;邮件&#xff0c;视频&#xff0c;音频和照片。那么&#xff0c;如果电脑照片被删除了怎么办&#xff1f;今天小编给大家介绍&#xff0c;误删除的照片从哪里可以找回来&#xff0c;误删除的照片如…...

若依微服务版在定时任务里面跨模块调用服务

第一步 在被调用的模块中添加代理 RemoteTaskFallbackFactory.java: package com.ruoyi.rpa.api.factory;import com.ruoyi.common.core.domain.R; import com.ruoyi.rpa.api.RemoteTaskService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springf…...

SpringMVC简单配置

1、pom.xml配置 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.12.RELEASE</version></dependency></dependencies><build><…...

xcat快速入门工作流程指南

目录一、快速入门指南一、先决条件二、准备管理节点xcatmn.mydomain.com三、第1阶段&#xff1a;添加你的第一个节点并且用带外BMC接口控制它四、第 2 阶段 预配节点并使用并行 shell 对其进行管理二&#xff1a;工作流程指南1. 查找 xCAT 管理节点的服务器2. 在所选服务器上安…...

C++回顾(十九)—— 容器string

19.1 string概述 1、string是STL的字符串类型&#xff0c;通常用来表示字符串。而在使用string之前&#xff0c;字符串通常是 用char * 表示的。string 与char * 都可以用来表示字符串&#xff0c;那么二者有什么区别呢。 2、string和 char * 的比较 &#xff08;1&#xff09…...

Hadoop入门

数据分析与企业数据分析方向 数据是什么 数据是指对可观事件进行记录并可以鉴别的符号&#xff0c;是对客观事物的性质、状态以及相互关系等进行记载的物理符号或这些物理符号的组合&#xff0c;它是可以识别的、抽象的符号。 他不仅指狭义上的数字&#xff0c;还可以是具有一…...

高校如何通过校企合作/实验室建设来提高大数据人工智能学生就业质量

高校人才培养应该如何结合市场需求进行相关专业设置和就业引导&#xff0c;一直是高校就业工作的讨论热点。亘古不变的原则是&#xff0c;高校设置不能脱离市场需求太远&#xff0c;最佳的结合方式是&#xff0c;高校具有前瞻性&#xff0c;能领先市场一步&#xff0c;培养未来…...

提升学习 Prompt 总结

NLP现有的四个阶段&#xff1a; 完全有监督机器学习完全有监督深度学习预训练&#xff1a;预训练 -> 微调 -> 预测提示学习&#xff1a;预训练 -> 提示 -> 预测 阶段1&#xff0c;word的本质是特征&#xff0c;即特征的选取、衍生、侧重上的针对性工程。 阶段2&…...

JavaScript学习笔记(2.0)

BOM--&#xff08;browser object model&#xff09; 获取浏览器窗口尺寸 获取可视窗口高度&#xff1a;window.innerWidth 获取可视窗口高度:window.innerHeight 浏览器弹出层 提示框&#xff1a;window.alert(提示信息) 询问框&#xff1a;window.confirm(提示信息) 输…...

直击2023云南移动生态合作伙伴大会,聚焦云南移动的“价值裂变”

作者 | 曾响铃 文 | 响铃说 2023年3月2日下午&#xff0c;云南移动生态合作伙伴大会在昆明召开。云南移动党委书记&#xff0c;总经理葛松海在大会上提到“2023年&#xff0c;云南移动将重点在‘做大平台及生态级新产品&#xff0c;做优渠道转型新动能&#xff0c;做强合作新…...

STM32F1开发实例-振动传感器(机械)

振动(敲击)传感器 振动无处不在&#xff0c;有声音就有振动&#xff0c;哒哒的脚步是匆匆的过客&#xff0c;沙沙的夜雨是暗夜的忧伤。那你知道理科工程男是如何理解振动的吗&#xff1f;今天我们就来讲一讲本节的主角&#xff1a;最简单的机械式振动传感器。 下图即为振动传…...

2023最新ELK日志平台(elasticsearch+logstash+kibana)搭建

去年公司由于不断发展&#xff0c;内部自研系统越来越多&#xff0c;所以后来搭建了一个日志收集平台&#xff0c;并将日志收集功能以二方包形式引入自研系统&#xff0c;避免每个自研系统都要建立一套自己的日志模块&#xff0c;节约了开发时间&#xff0c;管理起来也更加容易…...

2023-3-10 刷题情况

打家劫舍 IV 题目描述 沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。 由于相邻的房屋装有相互连通的防盗系统&#xff0c;所以小偷 不会窃取相邻的房屋 。 小偷的 窃取能力 定义为他在窃取过程中能从单间房屋中窃取的 最大…...

如何建立一个成功的MES?

制造执行系统&#xff08;MES&#xff09;是一种为制造业企业提供实时生产过程控制、管理和监视的信息系统。一个成功的MES系统可以帮助企业提高生产效率&#xff0c;降低成本&#xff0c;提高产品质量&#xff0c;提高客户满意度等。下面是一些关键步骤来建立一个成功的MES系统…...

Kafka生产者幂等性/事务

Kafka生产者幂等性/事务幂等性事务Kafka 消息交付可靠性保障&#xff1a; Kafka 默认是&#xff1a;至少一次最多一次 (at most once) : 消息可能会丢失&#xff0c;但绝不会被重复发送至少一次 (at least once) : 消息不会丢失&#xff0c;但有可能被重复发送精确一次 (exact…...

JavaWeb--案例(Axios+JSON)

JavaWeb--案例&#xff08;AxiosJSON&#xff09;1 需求2 查询所有功能2.1 环境准备2.2 后端实现2.3 前端实现2.4 测试3 添加品牌功能3.1 后端实现3.2 前端实现3.3 测试1 需求 使用Axios JSON 完成品牌列表数据查询和添加。页面效果还是下图所示&#xff1a; 2 查询所有功能 …...

css制作动画(动效的序列帧图)

相信 animation 大家都用过很多&#xff0c;知道是 CSS3做动画用的。而我自己就只会在 X/Y轴 上做位移旋转&#xff0c;使用 animation-timing-function 规定动画的速度曲线&#xff0c;常用到的 贝塞尔曲线。但是这些动画效果都是连续性的。 今天发现个新功能 animation-timi…...

【设计模式】装饰器模式

装饰器模式 以生活中的场景来举例&#xff0c;一个蛋糕胚&#xff0c;给它涂上奶油就变成了奶油蛋糕&#xff0c;再加上巧克力和草莓&#xff0c;它就变成了巧克力草莓蛋糕。 像这样在不改变原有对象的基础之上&#xff0c;将功能附加到原始对象上的设计模式就称为装饰模式(D…...

Nginx配置实例-反向代理案例一

实现效果&#xff1a;使用nginx反向代理&#xff0c;访问 www.suke.com 直接跳转到本机地址127.0.0.1:8080 一、准备工作 Centos7 安装 Nginxhttps://liush.blog.csdn.net/article/details/125027693 1. 启动一个 tomcat Centos7安装JDK1.8https://liush.blog.csdn.net/arti…...

Java中IO流中字节流(FileInputStream(read、close)、FileOutputStream(write、close、换行写、续写))

IO流&#xff1a;存储和读取数据的解决方案 纯文本文件&#xff1a;Windows自带的记事本打开能读懂 IO流体系&#xff1a; FileInputStream&#xff1a;操作本地文件的字节输入流&#xff0c;可以把本地文件中的数据读取到程序中来 书写步骤&#xff1a;①创建字节输入流对象 …...

C#完全掌握控件之-combbox

无论是QT还是VC&#xff0c;这些可视化编程的工具&#xff0c;掌握好控件的用法是第一步&#xff0c;C#的控件也不例外&#xff0c;尤其这些常用的控件。常见控件中较难的往往是这些与数据源打交道的&#xff0c;比如CombBox、ListBox、ListView、TreeView、DataGridView. 文章…...

STL的空间配置器(allocator)

简答&#xff1a; 在CSTL中&#xff0c;空间配置器便是用来实现内存空间(一般是内存&#xff0c;也可以是硬盘等空间)分配的工具&#xff0c;他与容器联系紧密&#xff0c;每一种容器的空间分配都是通过空间分配器alloctor实现的。 解析: 1.两种C类对象实例化方式的异同在c中&a…...

linux系统莫名其妙的环境变量问题

今天使用Ubuntu20.04系统&#xff0c;使用less命令查看日志&#xff0c;发现日志中的“中文”显示为乱码&#xff1b; 使用vim命令查看该日志文件也显示为乱码&#xff1b; 使用more命令查看该日志文件则显示正常。 首先查询系统的字符集编码&#xff0c;发现编码正常支持中…...

使用 Microsoft Dataverse 简化的连接快速入门

重复昨天本地部署dynamics实例将其所有的包删除之后&#xff0c;再次重新下载回来。运行填写跟之前登陆插件一样的信息点击login 然后查看控制台&#xff0c;出现这样就说明第一个小示例就完成了。查看你的dy365平台下的 “我的活动”就可以看到刚刚通过后台代码创建的东西了。…...

PLSQL Developer 安装指南

PLSQL Developer 是 Oracle 的客户端。 下面以64位破解版的PLSQL Developer为例&#xff0c;进行PLSQL Developer 安装讲解。 0. 下载 PLSQL Developer https://download.csdn.net/download/Shipley_Leo/87557938 1. 根据操作系统选择对应“plsqldev.exe”可执行文件&#xff…...

腾讯云企业网盘2.5版本全新发布啦!!!

腾讯云企业网盘又又又更新啦&#xff01;本期重点打磨管理协同、企业安全守护能力&#xff0c;同时也不断强化自身产品体验&#xff0c;助力企业高效办公~那么&#xff0c;此次更新具体有什么安全可靠的新功能呢&#xff1f;今天就带大家一起解锁~01协同管理&#xff0c;提升工…...

Excel职业版本(4)

图表 图表基本结构 组成元素 图表的分类 柱状图 介绍&#xff1a;在竖直方向比较不同类型的数据 适用场景&#xff1a;用于二维数据集&#xff0c;对于不同类型的数据进行对比&#xff0c;也可用于同一类型的数据在不同的时间维度的数据对比&#xff0c;通过柱子的高度来反…...

3-2 SpringCloud快速开发入门:Ribbon 实现客户端负载均衡

接上一章节Ribbon 是什么&#xff0c;这里讲讲Ribbon 实现客户端负载均衡 Ribbon 实现客户端负载均衡 由于 Spring Cloud Ribbon 的封装&#xff0c; 我们在微服务架构中使用客户端负载均衡调用非常简单&#xff0c; 只需要如下两步&#xff1a; 1、启动多个服务提供者实例并…...

ChatGPT,乌合之众的疯狂

最近ChatGPT有多火爆就不用我说了。公司里&#xff0c;从CEO到技术人员&#xff0c;乃至于门口的保安、食堂的大婶&#xff0c;没有一个不会聊两句ChatGPT的。连我20年未见的小学同学、三线城市警官&#xff0c;都问我这东西能不能给领导写汇报材料。 用不了多久&#xff0c;家…...

代码随想录刷题-数组-长度最小的子数组

文章目录长度最小的子数组习题暴力解法滑动窗口长度最小的子数组 本节对应代码随想录中&#xff1a;代码随想录&#xff0c;讲解视频&#xff1a;拿下滑动窗口&#xff01; | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili 习题 题目链接&#xff1a;209. 长度最小的子数…...

成功解决安装MySQL5.7提示公钥GPG密钥配置为file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

前言 大家好,我是沐风晓月,今天做MySQL5.7安装的时候遇到问题了,我们一起来复盘下这个问题,如果你使用我的方法没有解决,一定要留言给我,我们一起来排查和学习和完善。 本文收录于csdn 我是沐风晓月的专栏 【日常遇到的疑难问题和bug解决】 ,若点击无法跳转,请在csdn …...

vue配置环境变量

目录 创建配置文件 .env.development 文件 .env.production 文件 .env.dev 文件 使用变量 配置 package.json 文件 例子&#xff1a;在 api.js 使用 可以继续添加 创建配置文件 在根目录与 package.json 同级创建文件 .env.development、 .env.production、.env.dev 文件…...

js学习3(数组)

目录 结构图 数组操作 每日一练 结构图 数组操作 ## 数组中可以存储任何类型元素 ## 创建&#xff1a; 字面量([...])、创建对象(new Array(arr_len)) ## 遍历&#xff1a; 循环遍历、forEach(callback)、map(callback)、filter(callback)、every(callback)、some(callback)、…...

不用写代码也能开发,产品经理是怎么做到的?

产品经理再也不用求开发了……就在前几天&#xff0c;我做的小程序上线了&#xff01; 从产品原型设计&#xff0c;前端开发后端开发&#xff0c;产品部署到运维&#xff0c;都是由我1个人完成的。 我是啥时候学会写代码的呢&#xff1f;不瞒你说&#xff0c;我一行代码都没写…...

Android源码分析 - Parcel 与 Parcelable

0. 相关分享 Android-全面理解Binder原理 Android特别的数据结构&#xff08;二&#xff09;ArrayMap源码解析 1. 序列化 - Parcelable和Serializable的关系 如果我们需要传递一个Java对象&#xff0c;通常需要对其进行序列化&#xff0c;通过内核进行数据转发&#xff0c;…...

数字孪生与 UWB 技术创新融合:从单点测量到全局智能化

人员定位是指利用各种定位技术对人员在特定场所的位置进行准确定位的技术。人员定位技术主要应用于需要实时监控、管理和保障人员安全的场所&#xff0c;如大型厂区、仓库、医院、学校、商场等。人员定位技术的应用范围非常广泛&#xff0c;例如&#xff1a;-在工厂生产线上&am…...

蓝桥杯嵌入式PWM_IN(打开中断)

1.原理图 2.配置 3.代码 关键函数 HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1) HAL_TIM_IC_CaptureCallback(TIM_HandTypeDef *htim)//回调函数 HAL_TIM_GET_COUNTER(&htim3) __HAL_TIM_SetCounter(&htim3,0)void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef …...

蓝桥杯集训·每日一题Week1

前缀和&#xff08;Monday&#xff09; AcWing 3956. 截断数组&#xff08;每日一题&#xff09; 思路&#xff1a; 首先可以预处理出前缀和。判断数组长度如果小于 333 或者前 nnn 项不是 333 的倍数&#xff0c;则可以直接输出 000。 否则就枚举所有 s[i]s[n]3s[i] \cfrac…...

25k的Java开发常问的ThreadLocal问题有哪些?

前言:ThreadLocal问的比较多的是和Synchronized的区别、ThreadLocal被设计弱引用、存储元素的过程、实现线程隔离的原理。 文章目录 ThreadLocalThreadLocal定义ThreadLocal与Synchronized的区别ThreadLocal底层实现ThreadLocalMap存储元素的过程ThreadLocal实现线程隔离的原理…...

R语言基础(四):数据类型

R语言基础(一)&#xff1a;注释、变量 R语言基础(二)&#xff1a;常用函数 R语言基础(三)&#xff1a;运算 5.数据类型 5.1 基本数据类型 R语言基本数据类型大致有六种&#xff1a; 整数Integer、浮点数Numeric、文本(字符串)Character、逻辑(布尔)Logical、复合类型Complex、…...

批处理命令--总结备忘「建议收藏」

批处理命令--总结备忘「建议收藏」 前言1、基础语法:2、批处理基本命令3、实例3.1 打开虚拟目录3.2 以当前时间为文件名,建文件夹3.3 备份postgresql数据库前言 最近用批处理命令做了一些postgresql数据库的备份,打开虚拟环境。。。发现批处理处理一些常用重复工作时真的很…...

面试知识点梳理及相关面试题(十一)-- docker

1. Docker和虚拟机的区别 容器不需要捆绑一整套操作系统&#xff0c;它只需要满足软件运行的最小内核就行了。 传统虚拟机技术是虚拟出一整套硬件后&#xff0c;在其上运行一个完成操作系统&#xff0c;在该系统上再运行所需应用进程容器内的应用进程直接运行于宿主的内核&am…...

k8s--services(微服务)

文章目录一、k8s网络通信service和iptables的关系二、services1.简介2.默认3.IPVS模式的service4.clusterip5.headless6.从外部访问service的三种方式&#xff08;1&#xff09;nodeport&#xff08;2&#xff09;loadbalancer7.metallb一、k8s网络通信 k8s通过CNI接口接入其他…...

【Java开发】设计模式 01:单例模式

1 单例模式介绍单例模式&#xff08;Singleton Pattern&#xff09;是Java中最为基础的设计模式。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有单个对…...

10、go工程化与标准库

目录一、用go mod管理工程二、包引入规则三、init调用链四、可见性五、标准库1 - 时间函数2 - 数学计算3 - I/O操作4 - 编码一、用go mod管理工程 初始化项目&#xff1a;go mod init $module_name&#xff0c;$module_name和目录名可以不一样。上述命令会生成go.mod文件 mod…...

【Selenium自动化测试】鼠标与键盘操作

在 WebDriver 中&#xff0c;与鼠标操作相关的方法都封装在ActionChains 类中&#xff0c;与键盘操作相关的方法都封装在Keys类中。下面介绍下这两个类中的常用方法。 鼠标操作 ActionChains类鼠标操作常用方法&#xff1a; context_click()&#xff1a;右击double_click()&…...

自定义javax.validation校验枚举类

枚举类单一情况 package com.archermind.cloud.phone.dto.portal.external.validation.validator;import com.archermind.cloud.phone.dto.portal.external.validation.constraints.EnumValidation; import lombok.extern.slf4j.Slf4j;import javax.validation.ConstraintVali…...