vue使用uuid,请求头headers设置uuid

下载uuid,导入文件 npm install uuid 使用 在src包下创建utils包,存放uuid_token.js文件.在uuid_token文件下进行配置 调用 import { v4 as uuidv4 } from 'uuid'; 引用 uuidv4() import { v4 as uuidv4 } from 'uuid'; // 要生成一个随机字符串,且每次执行不能发生变化,游客身份持久存储 export const getUUID = () => { // 先从本地存储获取uuod let uuid_token = localStorage.getItem('UUIDTOKEN'); // 如果没有则生成 if (!uuid_token) { // 生成游客临时身份 uuid_token = uuidv4(); // 本地存储一次 localStorage.setItem('UUIDTOKEN', uuid_token); } // 切记要有返回值,没有则是undefined return uuid_token; } 在其他文件中引用uuid 本次我是把生成的uuid放在store中的detail包下,所以后面将uuid放在请求头中会出现调用此包的代码 // 游客身份的模块,生成随机字符串,不能再改变 import { getUUID } from "

使用 IDEA 将本地jar上传到本地maven仓库

文章目录 前言IDEA中的操作步骤创建一个 Maven 运行配置编辑 Maven 配置 运行 前言 应用场景: 在日常开发中,有时候会用到别人的 jar 包,但是又想用 Maven 管理。 就需要将该 jar 上传到 maven 仓库。 本文主要讲一下使用开发工具 IDEA 上传的操作步骤。【首先,需要确认你的项目空间是配置了 maven 的】 IDEA中的操作步骤 创建一个 Maven 运行配置 在开发工具的导航栏中,点击选择配置: 选择编辑配置: 在配置界面点击左上角的加号,随后选择增加一个maven运行配置: 编辑 Maven 配置 上图中的含义: Name 对应的是本配置的名字、用处或功能。 Working directory 表示运行命令的位置,一般选择项目的根路径(即pom.xml 文件所在的位置)。 Command line 表示命令行参数。 本次上传 jar 到 maven 仓库,用到的命令行参数如下(所有参数以空格隔开,这里为了方便讲解,做了换行处理): install:install-file -Dfile=C:/Users/FengJinSong/Downloads/kuaishou-merchant-open-sdk-release_open_kwaishop_sdk-1.0.150.jar -DgroupId=kuaishou -DartifactId=kuaishou-merchant-open-sdk-release_open_kwaishop_sdk -Dversion=1.0.150 -Dpackaging=jar 其中的含义是: ● -Dfile 表示当前要上传的jar包所在的位置 ● -DgroupId 表示当前 jar 对应的 groupId ● -DartifactId 表示的是当前 jar 对应的 artifactId

linux系统添加中文输入法

1)配置阿里云镜像源 下载新的 CentOS-Base.repo 到 /etc/yum.repos.d/ wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo 运行 yum makecache 生成缓存 yum makecache 非阿里云ECS用户会出现 Couldn’t resolve host ‘mirrors.cloud.aliyuncs.com’ 信息,不影响使用。用户也可自行修改相关配置: eg: sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo 具体参考阿里云官网:https://developer.aliyun.com/mirror/centos 2)安装中文输入安装包 yum search pinyin yum install ibus-libpinyin.x86_64 -y 3)linux在设置中添加中文 设置完后,按shift就可以切换中英文了

SQL 入门之第一讲——MySQL 8.0.29安装教程(windows 64位)

1.先去官网直接下载解压包进行安装 https://dev.mysql.com/downloads/mysql/ 下载完成后,进行解压到想要的目录下 2.进行配置初始化的my.ini文件的文件 解压后的目录是没有这个ini文件,自己新建一个my.ini(新建文本文件,将文件类型改为的.ini) 写入基本配置: [mysqld] # 设置3306端口 port=3306 # 设置mysql的安装目录 basedir=D:\program Files\MySQL\mysql-8.0.29-winx64 # 允许最大连接数 max_connections=200 # 允许连接失败的次数。 max_connect_errors=10 # 服务端使用的字符集默认为utf8mb4 character-set-server=utf8mb4 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # 默认使用“mysql_native_password”插件认证 #mysql_native_password default_authentication_plugin=mysql_native_password [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8mb4 [client] # 设置mysql客户端连接服务端时默认使用的端口 port=3306 default-character-set=utf8mb4 需要注意的是,配置文件里的路径要和实际存放的路径一致 3.初始化MySQL 在安装时,需要使用管理员身份运行CMD,否则在安装时会报错 右键管理员模式打开后,进入mysql的bin目录 在MySQL目录下的bin目录下执行命令: mysqld --initialize --console 注意保存初始化的密码和账号 其中root 为账号,localhost为主机地址,Erev<uASDg0J? 为密码(注意不要复制空格)在没有更改密码前,需要记住这个密码,后续登录需要用到。复制密码先保存起来!!! 4.安装MySQL服务 + 启动MySQL 服务 执行下面的命令: mysqld --install [服务名] ###(服务名可以不加默认为mysql) 这个是不是以管理员模式启动的cmd,会提示无权限进行更改 这个是以管理员模式启动的cmd,直接成功 服务安装成功之后通过命令进行启动服务 net start mysql 安装到启动主要三个步骤: 1.初始化MySQL2.创建服务3.启动服务 到这里MySQL已经是安装好了! 5.

unity中return返回

return在方法中使用,直接跳出当前方法; 如:执行以下方法最终输出结果:“从5返回”; float test1 = 10; string TestReturn() { if (test1 == 10) { if (test1 - 5 == 5) { Debug.Log("从5返回"); } } Debug.Log("从10返回"); return "10"; } 如果if判断中,调用方法A,方法A内部有return,执行if判断时,不受方法A内部的return影响; 如:执行以下方法最终输出结果:“从5返回”,“从10返回”; float test1 = 10; string TestReturn() { if (test1 == 10) { //if (test1 - 5 == 5) //{ // Debug.Log("从5返回"); //} TestReturn2(); } Debug.Log("从10返回"); return "10"; } string TestReturn2() { if (test1 - 5 == 5) { Debug.Log("从5返回"); return "

Http-超文本传输协议-详解

一、HTTP基本概念 1.1、Http是什么? HTTP是 超文本传输协议 分为三个部分 超文本 它就是超越了普通文本的文本,它是文字、图片、视频等的混合体,最关键有超链接,能从一个超文本跳转到另外一个超文本。 传输 所谓的「传输」,很好理解,就是把一堆东西从 A 点搬到 B 点,或者从 B 点 搬到 A 点。允许中间有中转或接力 HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。 协议 HTTP 是一个用在计算机世界里的协议。它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范(两个以上的参与者),以及相关的各种控制和错误处理方式(行为约定和规范)。 HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。 1.2、HTTP常见 的状态码有哪些? 1xx :状态属于提示信息,是协议处理中的一种中间状态,实际上用的比较少 2xx :表示服务器成功处理了客户端的请求,也是我们希望看到的状态 200:成功状态码,一切ok;204: 也是成功状态码,但无响应的body数据;206:应用于 HTTP 分块下载 或 断点续传,表示响应返回的 body 数据 并不是资源的全部,而是一部分,也是成功状态码; 3xx:表示客户端请求的资源发送了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。 301:表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。 302 :表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。 301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。 304 :不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。 4xx:表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。 400:表示客户端请求的报文有错误,但只是个笼统的错误。403 :表示服务器禁止访问资源,并不是客户端的请求出错。404:表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。 5xx:表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。 500:与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。501:表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。502:通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。503:表示服务器当前很忙,暂时无法响应服务器,类似“网络服务正忙,请稍后重试”的意思。 1.3、HTTP常见的字段有哪些 host 客户端发送请求时,用来指定服务器的域名。 ---- Host: www.

CentOS7搭建Zookeeper集群

目录 一、CenOS7安装Zookeeper单节点 二、Zookeeper集群搭建 1、同一台服务器搭建伪Zookeeper集群 2、3台服务器搭建Zookeeper集群 首先,zookeeper安装依赖jdk环境,可以参考:CentOS7安装jdk1.8-源码安装、openjdk安装、docker安装 一、CenOS7安装Zookeeper单节点 Zookeeper的下载地址为:https://dlcdn.apache.org/zookeeper/,根据自己的需要选择对应的版本,这里将几个版本进行了下载(但是一定下载-bin.tar.gz 的包): 如果可以不连外网,则可以使用上面的安装包先上传到对饮服务器位置;如果可以连外网则,先下载安装包: wget https://dlcdn.apache.org/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz 解压安装包:tar -zxvf apache-zookeeper-3.7.0-bin.tar.gz 跳转到解压包下的config目录下,将sample的配置包复制一份: cp zoo_sample.cfg zoo.cfg 修改配置的信息: tickTime =2000 zookeeper与客户端的心跳时间; initLimit=10 LF初始通信时限; syncLimit =5 LF同步通信时限; dataDir=/tmp/zookeeper/ 数据文件目录+数据持久化路径; clientPort=2181 客户端连接端口; 原则上不用修改了,配置已经为如下所示: 记得开启CentOS7防火墙端口或关闭防火墙,如果是阿里云、华为云服务器等自行在 安全规则组中添加对应端口 启动zookeeper:./zkServer.sh start 关闭zookeeper:./zkServer.sh stop 二、Zookeeper集群搭建 Zookeeper集群为了防止脑裂,需要将节点树设置为奇数,这里建议设置为3台。 info:脑裂就是为了防止因为网络等问题照成两个集群同时工作照成使用数据错误的问题,这样的结果本身比Zookeeper集群不能对外工作更严重,如果是集群则在Zap协议选举时,需要半数以上的节点投票,则不可能出现脑裂的情况 1、同一台服务器搭建伪Zookeeper集群 类似上面单体服务一样,上传并且解压后得到的目录如下: 此时可以进入下面的conf目录,复制 zoo.cfg配置文件,这样下面再copy节点后都有配置文件了 将解压文件负责三分作为三个节点: cp -R apache-zookeeper-3.7.0-bin zookeeper-1 cp -R apache-zookeeper-3.7.0-bin zookeeper-2 cp -R apache-zookeeper-3.7.0-bin zookeeper-3 分别在三个节点下创建data数据目录,如下: mkdir /home/mosty/zookeeper/zookeeper-1/data mkdir /home/mosty/zookeeper/zookeeper-2/data mkdir /home/mosty/zookeeper/zookeeper-3/data 然后分别在三个数据节点目录下创建文件 myid, 并且写入对应的值服务id,比如节点3如下:

SQL入门之第十一讲——OUTER JOIN 外连接

外连接是左外连接(LEFT OUTER JOIN),右外连接(RIGHT OUTER JOIN),全外连接(FULL OUTER JOIN)的统称。 一般情况下直接忽视掉OUTER就可以,直接统称: 左外连接为:左连接(LEFT JOIN)右外连接为:右连接(RIGHT JOIN)全外连接为:全连接(FULL JOIN) 左连接和右连接,在结果中除了交集,还包含左/右表中的全部记录。 具体查看图片会比较清楚点: 1. 左连接(LEFT JOIN) 定义:左连接就是将JOIN前面的表中所有记录都展示出来。 实例1:将学生表和教师表通过教师编号Tid连接起来 select * from teachers as t left join students as s on t.Tid = s.Tid 执行结果: 从结果上看,将教师表中全部的教师都查询出来了,对于学生表中对应不上的,以Null填充 2 . 右连接(RIGHT JOIN) 定义:右连接就是将JOIN后面的表中所有记录都展示出来。跟左连接是对应互通的。 例如,还是将第一个实例中的teachers 表 和 students 表 进行互换,再将LEFT JOIN 改成RIGHT JOIN,可以看到执行的结果,输出的记录是一样的。 实例2:将学生表和教师表通过教师编号Tid连接起来 select * from students as s right join teachers as t on s.Tid = t.Tid 执行结果: 可以看到所输出的记录是一样的,唯一的区别是在右连接中: students 表中的(Sid、Sname)在前面Teachers表中的(Tid、Tname)在后面 3 .

(数字ic)CDC跨时钟域可能出现的问题及解决办法总结

CDC跨时钟域可能出现的问题及解决办法总结 1、CDC基本概念2、SOC中有哪些跨时钟域的问题? 1、CDC基本概念 时钟域(Clock Domain):时钟域为由单个时钟或具有恒定相位关系的时钟驱动的设计部分。换句话说,时钟域就是时钟信号的势力范围 且一个时钟域中只能存在一个时钟信号,而一个时钟信号最多可以对应两个时钟域。 多个时钟来自不同的来源,而由这些时钟驱动的逻辑单元部分为时钟域,这些异步时钟域之间的接口信号称为时钟域交叉(CDC)路径。 如图一,divCLK是由CLK分频得到的,所以divCLK和CLK为同步时钟,也是属于同一个时钟域的。 如图二,DA信号被认为是一个异步信号进入时钟领域,即CLKA和CLKB之间不存在恒定的相位和时间关系。 2、SOC中有哪些跨时钟域的问题? problem1:亚稳态 problem2:快时钟域到慢时钟域数据保持的问题 problem3:重新聚合问题(Reconvergence of Synchronized Signals)(数据恢复问题) problem4:多比特数据同步问题 problem5:异步复位 同步释放 solution1: (比如从AHB总线传输信号到APB总线,由于各个接口的时钟频率不同,因此可能会存在跨时钟域的问题) 产生原因: 在同步系统中,输入信号总是系统时钟同步,能够达到寄存器的时序要求,所以亚稳态不会发生。亚稳态问题通常发生在一些跨时钟域信号传输以及异步信号采集上。 1)在跨时钟域信号传输时,由于源寄存器时钟和目的寄存器时钟相移未知,所以源寄存器数据发出数据,数据可能在任何时间到达异步时钟域的目的寄存器,所以无法保证满足目的寄存器Tsu和Th的要求; 2)在异步信号采集中,由于异步信号可以在任意时间点到达目的寄存器,所以也无法保证满足目的寄存器Tsu和Th的要求; solution2: 将快时钟域的数据延迟相应的拍数(快时钟域比慢时钟域快的频率),如problem2图中,clkA是clkB的2倍,那么就要将数据A扩展成两个周期,即加入一个寄存器。 solution3: 产生原因: 如果多个信号从一个时钟域进入另外一个时钟域,然后这些信号在目标时钟域中又聚合到一起,那么就有可能因为信号 的重新聚合导致电路功能上的异常。如图,一旦同步完成,同步器之外的结构仍然很重要。设计必须确保同步信号不重新聚合(若聚合会产生功能错误),后同步逻辑可能会导致DB信号出现Glitch。原本IN1和IN2转换时钟域后,期望得到的值是2’b00和2’b11,但由于IN1和IN2到达CLKB时钟域的时间有差异,实际得到的值是2’b00、2’b10和2’b11,最终导致后继电路功能出现问题。 信号X和信号Y进行跨时钟域传输两者同时从0变1,由于delay A和delayB的不同,可能在目的时钟域的第一个寄存器采样X为1,采样Y为0,第二个周期时,第一个寄存器采样X为1,Y为1,那么打两拍之后,X比Y提前一个周期为1的状态就会一直传递下去(如图),但实际上在原时钟域X和Y是同时从0到1翻转的。所以在跨时钟域传输多bit数据时,一次我们只允许数据的1bit发生翻转。不允许多bit发生翻转 solution4: Handshake:(MUX同步)即源时钟域发出一个1bit的请求信号(req),然后经过同步化处理后,将源时钟域的信号传输至目的时钟域,然后目的时钟域接受到数据后,反馈出一个完成信号(res)。多bit数据同步仅将一个信号a_en做两级同步,使得输出的b_en作为使能信号,若为1,才将多比特数据d[0]-d[7]传输过去,若为0,就不传输,这样就不用每一个比特都加两级触发器了。 FIFO:适用于大数量的多比特数据传输 solution5: 异步复位同步释放优缺点: 同步复位:当时钟上升沿检测到复位信号,执行复位操作(有效的时钟沿是前提)。always @ ( posedge clk ); 优点: a、有利于仿真器的仿真; b、可以使所设计的系统成为 100% 的同步时序电路,有利于时序分析,而且可综合出较高的 Fmax; c、由于只在时钟有效电平到来时才有效,所以可以滤除高于时钟频率的复位毛刺。 缺点: a、复位信号的有效时长必须大于时钟周期,才能真正被系统识别并完成复位任务。同时还要考虑诸如 clk skew 、组合逻辑路径延时 、复位延时等因素(所以复位信号有时需要脉冲展宽,用以保证时钟有效期间有足够的复位宽度); b、由于大多数的逻辑器件的目标库内的 DFF 都只有异步复位端口,所以,倘若采用同步复位的话,综合器就会在寄存器的数据输入端口插入组合逻辑,这样就会一方面额外增加FPGA内部的逻辑资源,另一方面也增加了相应的组合逻辑门时延。 异步复位:它是指无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。always @ ( posedge clk or negedge rst_n );

18.Java POI下载和简介

简单介绍一下POI: POI是Apache软件基金会的开放源码函式库 提供API给Java程序对Microsoft Office格式档案读和写的功能。 下载相关jar包方法 : 打开POI的官网: Apache POI - the Java API for Microsoft Documents 进入下载页下滑,可以看到两个版本的POI Binary Distribution是二进制包,也就是已经编译完成以后的包。 Source Distribution是源码包,也就是可以查看jar包的具体源代码。 可以选择喜欢的压缩模式,这里下载的是Binary包的zip压缩版,点击进入内页。 可以看到三个下载方法,前两个是下载。 点击链接后等待下载完成即可

2022年美赛S奖得主的三次完赛经历

三次建模 三次比赛:美赛,mathorcup,北京市大学生计算机应用与建模 队友:美赛和mathorcup 我在大学最好的好兄弟,我心动过的人 我的好兄弟的好兄弟,也是我曾经心动过的人 第三次 管我的人 & 编程碾压我的人 成绩:美赛S奖,其他未出 美赛 2022.2.18 E题 论文内容:我们给出了一个政策,在不损害经济又增大碳吸收的前提下,选择树种并分配种植面积。难点在于计算经济利益和碳吸收量。这之所以难,是因为我们考虑了不同树种的价钱、伐龄、销量,这些数据不好找;种植面积应该是多少没有条件;计算碳吸收量的公式只有方精云90年代发表的我看得懂。 如何提升:看论文,了解各种题目的思路、数据、如何把问题抽象成数学式子。此外,老哥的课除了算参数和拟合、层次分析,其他的到底有什么用? 经验:思路全靠自己。如果队友想放弃会很累。如果队友不及时跟你沟通进展会很累。我不是说累是我没获奖的原因,但累会影响积极性,这比没实力更可怕。 实际:我准备蓝桥杯直到4.9 mathorcup 4.14 A题 论文内容:1.判断可能的相似点,以此排除非细节点 2.观察得出,若两指纹相似,相似细节点占所有点的比例普遍比较大 3.计算没被排除的细节点的距离 4.根据2,3的值得到一个公式算出相似度评分,这个公式是队友提供的,我选的参数 5批量比较,验证方法可信度 经验:思路全靠自己。队友想放弃让我很累。跟队友沟通进展而他们不认为我在做有意义的事情很累。累会影响积极性,这比没实力更可怕。 如何提升:等大家都会编程了再说吧 第三次: 被拉进统计建模比赛,老师让我们先参加建模。 我一个人用excel完成了比赛。 通过拟合新增感染人数预测了奥密克戎消失时间。 感想:奥密克戎与我有关,我爱瞪眼法分析数据,我爱excel!为了荣誉参加比赛不符合得奖法则,迟早遭报应。道不同,不相为谋,好在统计建模没报上。 如何提升:学好excel,数学和编程;熟悉各种模型

二叉树非递归遍历算法分析

以前没有学习过树的相关算法,只是了解一些皮毛,最近开始认真学习它。看视频或者网上查资料,可以知道怎么去遍历一棵树,但是算法为什么是这样的呢?少有讲到。如果有一天,我忘记了这个算法,我需要重新去看视频,看文档,这不是我想要的。我想要的是,知道这个算法是怎么设计出来的。下次我忘记的时候,我需要一支笔,一张纸,重新设计出这个算法,而不是去找资料看视频。我想要知道的是,为什么如此,而不是仅仅知道如此而已。 一、三种遍历顺序 怎么记住三种遍历顺序:前序、中序、后序;前、中、后指的是什么。一棵树是怎么发展起来的:me,my->left_child,my->right_child,这是最基本的关系,me是中心,left和right跟me建立了一种联系,left和right再各自发展自己的child,于是一棵树就越来越庞大了。遍历过程,就是要把所有节点走一遍,而最基本的就是me/left/right这三者,所以根据访问它们的顺序,划分出了三种顺序,首先是先左后右,其次是me放在哪个位置,根据me的位置对遍历顺序进行命名,me在前即前序,在中即中序,在后即后序。 二、递归遍历的实现 递归是符合我们的思维习惯的,一个复杂的问题总是可以分解为若干简单的问题。无论一棵树多么庞大,我从它的根节点出发,看到的是最多3个节点:我自己,我的左孩子,我的右孩子。我自己可以直接访问,然后是访问左孩子和右孩子。访问左孩子和右孩子的方法是一样的,访问它们自己节点,以及它们的左右孩子。这就是递归,这就是分治,把一个问题分解为几个子问题,分别考虑每个子问题,如果子问题跟我的处理逻辑一样,那么就成了递归。 // 这里以前序遍历为例,中序/后序只需要调整visit(node)所在位置即可 void traverse(node_t *node) { visit(node); traverse(node->left); traverse(node->right); } 但是递归存在一个问题:如果树很深,那么函数的栈可能溢出。通常情况下栈的大小是固定的,不会动态扩展(go语言除外,它的栈可以伸缩,所以用go写递归,不用考虑栈溢出的问题)。每调用一个函数,就消耗一定的函数栈空间,如果这个函数没有结束,那么它会一直占用栈空间;在这个函数内部调用一个函数,又开辟了新的栈空间,如果树太深,那么栈就可能耗尽,然后访问越界,发生踩内存,coredump等未知问题。 所以,我们需要非递归,至少我们可以仿照函数栈的方式,自己实现栈,组织树的节点,完成遍历。当树太深的时候,我们可以动态扩展栈的空间,最终完成树的遍历。怎么实现栈的动态扩展,网上可以找到很多相关介绍。我的另外一篇博客实现了一种栈扩展的方法。在这里,只需要知道栈怎么用的:push/pop,后进先出,不考虑栈空间的扩展问题(假设它已经可以自动扩展了)。 三、怎么设计出非递归遍历算法 函数栈实现了递归,我们需要用自己的栈替换掉函数的栈,组织树的节点。一开始,我尝试分析函数栈的过程,发现太复杂了。函数栈很通用,一个节点会反复的入栈出栈,栈中的元素带了状态信息,这些状态信息就是我们的栈变量,所以每次处理当前栈顶元素的时候,总是可以知道应该做什么。以上面的前序递归函数为例,执行函数traverse(node),首先需要访问node这个节点,于是开辟新的函数栈调用函数visit(node),当visit结束后,重新回到traverse(node),这时候pc指针已经指向了visit之后的代码,会调用traverse(node->left)。如果我们要用这种方式,那么需要压栈的时候,不仅把node入栈,还需要把node已经完成了多少工作也压栈,即 typedef enum { STATE_INIT, // 刚刚开始 STATE_VISITED_MYSELF, // 已经访问了自己 STATE_LEFT_HANDLED, // 已经处理了左孩子 STATE_RIGHT_HANDLED, // 已经处理了右孩子 } node_state_t; typedef struct { node_t *node; node_state_t state; } node_info_t; 也就是说,每次入栈的元素是node_info_t,每次处理之后修改state信息,直到node_info_t处理完之后从栈里面弹出销毁。我没有继续走下去,我认为这么做是可以行得通的,但是比较复杂,显然我们知道的非递归遍历算法,只是把node压栈了,没有这么多信息入栈,所以需要寻找更简单的方法。我放弃了分析函数栈推导非递归算法这条路。 梳理一下思路:实现非递归遍历算法,需要用到栈,人工遍历是可以知道结果的。所以,我需要一张纸,一支笔,人工遍历,如果走到某一步发现走不下去了,看看可以怎么利用栈来帮我记录信息,然后重新开始,最终,应该可以找到一种方法,利用栈,实现非递归遍历。 设计遍历算法的步骤是: 1、明确遍历的顺序:前序、中序、还是后序; 2、人工遍历; 3、发现人工遍历进行不下去的时候,回头看看,怎么利用栈保存需要的信息;这一步可以总结出一些规则; 4、根据步骤3总结的规则,从步骤2重新开始,如此反复几次,应该就可以归纳出遍历的方法,最终完成遍历,并设计出一种算法。 四、推导非递归算法——前序遍历 (没有画图,感兴趣的朋友,可以自己找一张纸,一支笔,在纸上画画。下面的树只是用文字简单描述一下形状。) <00> /\ <01> <02> /\ /\ <03> <04> <05> <06> /\ /\ /\ /\ <07> <08> <09> <10> <11> <12> <13> <14> 明确遍历顺序:我->左->右。

LC5--ftp服务器密码检测

lc5下载: 链接:https://pan.baidu.com/s/1Ljg3aJiaarf2vYHEJ91fiQ 提取码:xxmt 目录 实验目的: 实验任务: 实验原理: 实验环境: 实验步骤: 实验目的: 1.掌握FTP服务器的搭建方法 2.理解FTP的使用。 3.学习LC5破解密码工具的配置和使用方法。 实验任务: 1、架设一个简单的FTP服务器,分配用户,并按实验内容设置密码。 2、LC5破解工具。 实验原理: 一般入侵者常常采用下面几种方法获取用户的口令,包括弱口令扫描,Sniffer密码嗅探,暴力破解,打探、套取或合成口令等手段。 有关系统用户帐号口令的破解主要是基于字符串匹配的破解方法,最基本的方法有两个,穷举法和字典法。穷举法是效率最低的办法,将字符或数字按照穷举的规则生成口令字符串,进行遍历尝试。在口令组合稍微复杂的情况下,穷举法的破解速度很低。字典法相对来说效率较高,它用口令字典中事先定义的常用字符去尝试匹配口令。口令字典是一个很大的文本文件,可以通过自己编辑或者由字典工具生成,里面包含了单词或者数字的组合。如果你的口令就是一个单词或者是简单的数字组合那么破解者就可以很轻易的破解口令。 客户机操作系统:Windows 2000 /windows xp IP地址为 192.168.2.1服务器操作系统:Windows 2000 Advance Server / windows xp IP地址为 192.168.2.2实验时,如果没有两台机器,可以使用虚拟机,在虚拟机下安装服务器Windows 2000 Advance Server / windows xp。也可以把客户机和服务器同时安装到虚拟机下。 实验环境: 客户机操作系统:Windows 2000 /windows xp IP地址为 192.168.2.1 服务器操作系统:Windows 2000 Advance Server / windows xp IP地址为 192.168.2.2 实验时,如果没有两台机器,可以使用虚拟机,在虚拟机下安装服务器Windows 2000 Advance Server / windows xp。也可以把客户机和服务器同时安装到虚拟机下。 实验步骤: 1、首先搭建IIS服务器,同时选择角色服务为FTP服务器,点击下一步进行安装。 2、然后在服务器上搭建FTP服务,选择添加FTP站点,右击选择属性。 进行IP地址设置(绑定服务器的IP地址192.168.192.175) 3、之后创建用户xiaoxiukun(用于后续ftp远程登录实验) 4、在客户机上连接服务器的FTP服务:在客户机上启动wireshark(由于未下载到可用的Sniffer嗅探器,此处使用wireshark进行抓包监控),然后在DOS命令下使用FTP指令连接服务器的FTP服务器。(当未知密码时) 利用抓包工具wireshark查看抓取的FTP过程(推荐使用Sniffer):

Win10系统怎么注销微软账户

问题描述: 今天领得公共电脑准备干活,电脑上面还留着前人的Microsoft账户在那挂着,显示管理员账户,账户页面只有管理按键没有删除按键,导致无法删除掉,试了很多方法才删除掉,把成功的方法记录在下面。 解决办法: 1.假设你的微软账号是:xxx@xx.com,win+R打开运行,在运行输入框输入regedit,点击确定打开注册表编辑器,搜索微软账号名:xxx@xx.com。 2.一般是HKEY_CURRENT_USER\Software\Microsoft\IdentityCRL\UserExtendedProperties\xxx@xx.com和HKEY_USERS\.DEFAULT\Software\Microsoft\IdentityCRL\StoredIdentities\xxx@xx.com,然后删除注册表xxx@xx.com项,开始菜单里注销微软账户。 3.再次登录后,显示是本地账号,但是微软账号依然存在,删除HKEY_CURRENT_USER\Software\Microsoft\IdentityCRL和HKEY_USERS\.DEFAULT\Software\Microsoft\IdentityCRL项,再次在开始菜单里注销账户; 4.重新登录后,在设置-账户-电子邮件和应用账户下,单击微软账户xxx@xx.com,点击“删除”即可 因为要修改注册表,为了安全起见最好还是先备份一下!

SQL入门之第十讲——INNER JOIN 内连接

在实际的业务当中,往往需要多张表连接查询,这就会涉及到JOIN 连接 1. JOIN 连接的类型 INNER JOIN :内连接, 可以只写JOIN ,只有连接的两个表中,都存在连接标准的数据才会保留下来,相当于两个表的交集。如果前后连接的是同一个表,也叫自连接。LEFT JOIN :左连接,也叫左外连接。操作符左边表中符合WHERE子句中的所有记录将会被返回,操作右边表中如果没有符合ON后面连接的条件时,那么右边表指定选择的列将会返回NULL。RIGHT JOIN:右连接,也叫右外连接。返回右边表所有符合WHERE语句的记录,左表中匹配不上的字段值用NULL来代替。FULL JOIN:全连接。返回所有表中符合WHERE语句条件的所有记录。如果表中指定字段没有符合条件的值的话,用NULL来代替。 2. INNER JOIN 内连接 通过JOIN语句就可以将几个表通过那几个列连接起来INNER JOIN,可以省略掉 'INNER ’ 只写JOIN就可以 基本语法: select <字段名> from <表a> JOIN <表b> ON a.<字段名> = b.<字段名>; 实例1:将学生表和教师表通过教师编号Tid连接起来 select * from students AS s join teachers AS t on s.Tid = t.Tid; 执行结果: 查看输出结果,from后面的students表会作为基础表放在前面,后面在根据关联的Tid,去拼接是哪个join后面的teachers 表。 如果将两个表进行调换下位置,那么teachers表将会作为基础表放在前面 select * from teachers AS t join students AS s on t.Tid = s.Tid; 执行结果: 查看结果时发现,teachers表中一个有6个老师,现在只输出了4个老师,这是因为没出现的2个老师在students里没有对应的学生,所以内连接,只会输出两个表中相互匹配的数据,2个表的交集

SQL入门之第九讲——DELETE删除语句

定义:DELETE 语句是用于删除表中的一条或多条记录。 基本语法: DELETE FROM <表名> WHERE <筛选条件>; 1.DELETE删除语句 如果省略WHERE条件时,这回收DELETE 语句就会删除整个表的数据记录。需要注意的是:这里不会删除表结构,只是将表中所有的数据全部清除掉勒 实例1:删除教师表中所有记录。 delete from teachers; 执行结果: 删除语句执行后,可以看到表中的列名还是存在,但是表中数据已经没有了 只有加上WHERE条件时,就会执行删除符合条件的记录。 实例2:删除学生表中,生日为:1992-01-11的这一条记录 delete from students where Sage = '1992-01-11'; 执行结果: select * from students where Sage = '1992-01-11'; 可以看到已经查询不到一条记录了 2.恢复数据库 DROP DATABASE school; 删除之后在创建数据库即可

numpy array转 python list

主要调用numpy的tolist()方法,可参考下面的例子: import numpy as np arr=np.array([0,1,2,3,4,5,6,7,8,9]) lst=arr.tolist() type(lst) #<class 'list'> print(lst) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

SQL入门之第八讲——UPDATE更新语句

定义:UPDATE更新语句是用来修改表中一条数据或者多条数据记录 基本语法: UPDATE <表名> SET <字段名=值> WHERE <筛选条件>; 1. 更新单行数据 实例1:在学生表中,将学生编号Sid为6的学生姓名Sname修改为:杨红梅 update students set Sname='杨红梅' where Sid = 6; 执行结果: SET后面除了带文本之外,还可以是数学表达式 实例2:在学生表中,将学生编号Sid为10的学生姓名对应的Tid加100 update students set Tid=Tid+100 where Sid=10; 执行结果: 2. 更新多行数据 让where 条件筛选更多的记录,就会同时更改多条数据记录了 实例3:在学生表中,将性别为 ‘女’ 的学生,学生编号加500 update students set Sid=Sid+500 where Ssex = '女'; 执行结果: 3. UPDATE语句与子查询的搭配使用 子查询的定义:子查询是查询语句里面嵌套的查询语句,子查询的结果将作为主查询的查询条件,来完成更加复杂的数据检索那UPDATE语句是如何与子查询来进行搭配使用的呢,本质上就是将子查询与where子句结合来使用 实例4:在学生表中,将查询出班主任为:高静的学生性别修改为:女生 解析:在学生表中只有教师编号Tid,并没有教师姓名Tname, 所以需要先在教师表中查询出高静的id update students set Ssex = '女生' where Tid = (select Tid from teachers where Tname = '高静'); 执行结果:

SpringCloud Alibaba实战第三课 Gateway、Sentinel实战

09 服务门户:Spring Cloud Gateway 如何把好微服务的大门 上一讲我们学习了 Dubbo 是如何与 Nacos 协同作业。通过对比 RESTful 与 RPC,我们介绍了两种通信方式的区别,再通过实例讲解如何将 Dubbo 与 Nacos 进行整合。但你是否发现无论是基于 OpenFeign 的 RESTful 通信,还是基于 Dubbo 的 RPC 通信,它们都在强调的是微服务间的信息传递,属于微服务架构内部的事情。而对于用户端从外侧访问微服务如何有效管理,微服务又是如何将接口暴露给用户呢?这就需要通过 API 网关实现需求了,本讲咱们就针对 API 网关学习三方面知识: 介绍 API 网关的用途与产品; 讲解 Spring Cloud Gateway 的配置技巧; 讲解 Gateway执行原理与自定义过滤器(Filter)。 API 网关的作用 如下图所示,对于整个微服务来说如果将每一个微服务的接口直接暴露给用户是错误的做法,这里主要体现出三个问题: 服务将所有 API 接口对外直接暴露给用户端,这本身就是不安全和不可控的,用户可能越权访问不属于它的功能,例如普通的用户去访问管理员的高级功能。 后台服务可能采用不同的通信方式,如服务 A 采用 RESTful 通信,服务 B 采用 RPC 通信,不同的接入方式让用户端接入困难。尤其是 App 端接入 RPC 过程更为复杂。 在服务访问前很难做到统一的前置处理,如服务访问前需要对用户进行鉴权,这就必须将鉴权代码分散到每个服务模块中,随着服务数量增加代码将难以维护。 用户端直接访问微服务 为了解决以上问题,API 网关应运而生,加入网关后应用架构变为下图所示。 引入 API 网关后的微服务架构 当引入 API 网关后,在用户端与微服务之间建立了一道屏障,通过 API 网关为微服务访问提供了统一的访问入口,所有用户端的请求被 API 网关拦截并在此基础上可以实现额外功能,例如:

Ubuntu 20.04下配置 HAL 汇编开发环境教程

目录 安装解压配置环境变量测试 案例 安装 环境:Ubuntu 20.04 安装包:linux64.hla.tar.gz 这里安装的是64位的,具体与linux.hla.tar.gz有什么不同,没研究过。 解压 可任选目录,本文在我的用户目录/home/nqw下解压。 $ tar -xvf linux64.hla.tar.gz 解压后会自动创建子目录/usr/hla,文件都保存在这个目录下。其中code文件夹是笔者自己添加的,用来保存以后编写的代码。 配置环境变量 $ gedit ~/.bashrc 在打开的文件末尾,添加如下内容,主要是配置hla的可执行文件路径、库路径、头文件路径等。 PATH=/home/nqw/usr/hla:$PATH export PATH hlalib=/home/nqw/usr/hla/hlalib export hlalib hlainc=/home/nqw/usr/hla/include export hlainc hlacode=/home/nqw/usr/hla/code export hlacode 保存,退出。 执行如下指令生效。 $ source ~/.bashrc 测试 检测hla版本,看是否安装成功。 $ hla -v 得到如下信息,表示安装成功。 $ hla -v HLA (High Level Assembler) Use '-license' to see licensing information. Version 2.16 build 4409 (prototype) ELF output OBJ output using HLA Back Engine -test active HLA Lib Path: /hla/usr/hla/hlalib/hlalib.

vue 路由的三种模式

路由模式解析 这里要讲vue-router的路由模式,首先要了解的一点就是路由是由多个URL组成的,使用不同的URL可以相应的导航到不同的位置。如果有进行过服务器开发或者对http协议有所了解就会知道,浏览器中对页面的访问是无状态的,所以我们在切换不同的页面时都会重新进行请求。而实际使用vue和vue-router开发就会明白,在切换页面时是没有重新进行请求也没有重新刷新页面,使用起来就好像页面是有状态的,这是什么原因呢。这其实是借助了浏览器的History API来实现的,这样可以使得页面跳转而不刷新,页面的状态就被维持在浏览器中了。 hash模式 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载,其显示的网路路径中会有 “#” 号,有一点点丑。这是最安全的模式,因为他兼容所有的浏览器和服务器。 history模式 美化后的hash模式,会去掉路径中的 “#”。依赖于Html5 的history,pushState API,所以要担心IE9以及一下的版本,感觉不用担心。并且还包括back、forward、go三个方法,对应浏览器的前进,后退,跳转操作。就是浏览器左上角的前进、后退等按钮进行的操作。 history.go(-2);//后退两次 history.go(2);//前进两次 history.back(); //后退 hsitory.forward(); //前进 但是history也是有缺点的,不怕前进后退跳转,就怕刷新(如果后端没有准备的话),因为刷新是实实在在地去请求服务器了。 abstract 路由模式 abstract 是vue路由中的第三种模式,本身是用来在不支持浏览器API的环境中,充当fallback,而不论是hash还是history模式都会对浏览器上的url产生作用,本文要实现的功能就是在已存在的路由页面中内嵌其他的路由页面,而保持在浏览器当中依旧显示当前页面的路由path,这就利用到了abstract这种与浏览器分离的路由模式。 路由示例 export const routes = [ { path: "/", redirect: "abstract-route", }, { path: "/embed-route", name: "embedded", component: () => import(/* webpackChunkName: "embed" */ "../views/embed.vue"), }, { path: "/abstract-route", name: "abstract", component: () => import(/* webpackChunkName: "abstract" */ "../views/abstract.vue"), }, ]; const router = new VueRouter({ mode: "

树莓派DS18B20温度采样上报服务器

目录 流程图 初始化部分 命令行解析 各个模块初始化 while循环部分 连接检查 采样判断 流程图 客户端功能: *1.判断是否存在数据库db文件和表,不存在就创建,存在就不创建 *2.支持命令行传ip地址,端口号,域名,产品序列号,间隔时间,等参数 *3.客户端网络断开时自动保存断开时数据 *4.连接服务器时判断是否有断电时保留的数据 *5.有保留的数据就将数据发送给服务器 *6.在服务器网络恢复时自动重连服务器 *7.保证在发送数据库数据时能够精确采样数据 初始化部分 命令行解析 void useage(char *progname) { printf("%s useage:\n",progname); printf("-i(--ipaddr):specify server IP address or Domain name\n");//服务器IP地址或域名 printf("-p(--port):specify server port\n");//服务器端口 printf("-h(--help):print this help information\n");//打印帮助信息 printf("-d(--daemon):Let the Program run in the background\n");//进入后台运行 printf("-s(--sn):product ID\n");//指定产品序列号 printf("-t(--time):Sampling interval time\n");//指定采样间隔 printf("for example:proname -i 127.0.0.0 -p 1111 (-s [int i]) (-d) (-t [int i]) "); return; } //命令行解析 while((opt = getopt_long(argc,argv,"

百度网盘启动没响应解决办法

百度网盘启动的时候没响应,打开任务管理器看看是不是有一个BaiduNetdiskUpdate(好像是,我已经更新好了,就没有这个了)。那就是你的百度网盘在更新,等会就自动启动了。

Stream流中collect方法

Stream流中collect方法 一、收集Stream流到集合和指定集和中1、示例2、结果 二、收集 Stream 流中的数据到数组中1、示例2、结果 三、Stream流中数据聚合/分组/分区/拼接操作1、聚合操作2、分组操作3、多级分组操作4、分区操作5、拼接操作 一、收集Stream流到集合和指定集和中 Stream 流提供了一个 collect() 方法,可以收集流中的数据到【集合】或者【数组】中去。 //1.收集数据到list集合中 stream.collect(Collectors.toList()) //2.收集数据到set集合中 stream.collect(Collectors.toSet()) //3.收集数据到指定的集合中 stream.collect(Collectors.toCollection(Supplier<C> collectionFactory)) 1、示例 public void test2() { //Stream 流 Stream<String> stream = Stream.of("aaa", "bbb", "ccc", "bbb"); //收集流中的数据到集合中 //1.收集流中的数据到 list List<String> list = stream.collect(Collectors.toList()); System.out.println(list); //Stream 流 stream = Stream.of("aaa", "bbb", "ccc", "bbb"); //2.收集流中的数据到 set Set<String> collect = stream.collect(Collectors.toSet()); System.out.println(collect); //Stream 流 stream = Stream.of("aaa", "bbb", "ccc", "bbb"); //3.收集流中的数据(ArrayList)(不收集到list,set等集合中,而是)收集到指定的集合中 ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new)); System.out.println(arrayList); //Stream 流 stream = Stream.

K8S:Namespace详解

Namespace概念 Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群,这些虚拟集群被称为命名空间。 命名空间 namespace 是 k8s 集群级别的资源,可以给不同的用户、租户、环境或项目创建对应的命名空间。 在创建pod的时候可以指定pod到namespace。 命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有少数项目人员的集群则不需要使用namespace。 在你部署完k8s集群后,会提供几个默认的namespace,kube-system主要用于运行系统级资源,存放k8s一些组件的。 default为那些未指定名称空间的资源操作提供一个默认值,即你在创建pod时如果没有指定namespace,则会默认使用default这个namespace。 Namespace指令 kubectl get namespace 该命令用于查看k8s集群中的所有名称空间 kubectl describe namespace +名称空间的名字 该命令用于查看指定名称空间的详细信息 kubectl create namespace +名称空间的名字 该命令用于创建新的namespace 查看namespace,发现其中有我们新建的test,表示我们创建成功 kubectl delete namespace +名称空间的名字 该命令用于删除指定的namespace,注意,删除namespace时,它所包含的所有资源也会被一并被删除,所以在删除时要确定是自己没有用的资源在进行删除。并且如果意外删除到系统的namespace,则会导致整个集群down kubectl api-resources --namespaced=true 该命令用于查看属于namespace级别的资源

PWM生成原理与控制输出

PWM生成原理与控制输出 PWM生成原理与控制输出参考 PWM生成原理与控制输出 PWM生成原理 PWM实现DA转换,通过产生数字信号模拟输出模拟信号 基本原理: PWM简称脉冲宽度调制,一个周期内存在不同极性电平状态。PWM频率:一秒钟从高电平再到低电平,再从低电平到高电平的瞬间次数。PWM周期:一秒钟从高电平到低电平时间 T= f/1(s)。PWM占空比:一周期高电平时间和总时间比值。 PWM产生: PWM实现通过锯齿波/三角波同所需合成波形(调制波)比较,确定输出极性,锯齿波从比较器反向段输出,大于参考电压输出与锯齿波相反极性锯齿波同相端输入,大于参考电压时输出与锯齿波相同极性。 反相端接锯齿波,大于参考电压输出为0,而小于参考电压为1,通过改变参考电压的值,从而产生了不同占空比的信号。 FPGA实现控制PWM输出 PWM调控:计数+译码,计数器从0开始到period-1,是整个pwm周期。译码器实现,计数值 < max 输出高电平,否则输出低电平,实现可调节占空比。 针对低电平传输标志信号,并调用相应的器件如蜂鸣器对控制信号进行输出,实现控制pwm输出。 根据周期变化,调节占空比,实现不同占空比的方波输出。 参考 PWM的基本原理及如何产生PWM

DBeaver数据导出CSV格式有科学计数法

DBeaver数据导出CSV格式,数值太长有科学计数法,看我如何完美解决!! 解决前 — 导出的CSV文件解决后 — 导出的CSV文件解决方案 解决前 — 导出的CSV文件 从上图可以看到,身份证号一列,由于数值超长已经转化成了科学计数法。 解决后 — 导出的CSV文件 从上图可以看到,身份证号一列,不再是科学计数法的显示方式。而是作为文本的格式展现出来。 那么,在使用DBeaver导出的时候,该如何配置呢? 请看下图所示: 解决方案 交流三连击 你学废了吗? 哪里还不懂? 评论区留言吧!猿史天尊,随时关注!!!

java代码中发送Post/Get请求

目录 1、通过HttpURLConnection发送GET和POST请求 2、通过Apache HttpClient发送GET和POST请求 1、通过HttpURLConnection发送GET和POST请求 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; public class HttpURLConnectionDemo { public String doPost(String URL){ OutputStreamWriter out = null; BufferedReader in = null; StringBuilder result = new StringBuilder(); HttpURLConnection conn = null; try{ URL url = new URL(URL); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); //发送POST请求必须设置为true conn.setDoOutput(true); conn.setDoInput(true); //设置连接超时时间和读取超时时间 conn.setConnectTimeout(30000); conn.setReadTimeout(10000); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Accept", "application/json"); //获取输出流 out = new OutputStreamWriter(conn.getOutputStream()); //参数 String jsonStr = "

前端基本知识介绍

目录 一.前端三剑客 1.前导 2.三剑客的分工 二.VsCode的介绍与配置 1.vscode的介绍 2.vscode的下载安装 3.vscode的使用 3.1 图形界面操作 3.3 常用插件 三.HTML基础标签 HTML基础知识 1.HTML为何物? 2.标签介绍 3.HTML属性 4.HTML标签骨架 基本的HTML标签 1.HTML标题标签 2.换行与空格 3.HTML段落 4.字体加粗与倾斜及删除效果 5.图片标签 6.超链接 7.列表 8.布局标签 9.表格标签 10.表单标签 四.CSS基础选择器 CSS介绍 CSS样式表介绍 CSS基础语法 CSS选择器 选择器介绍 基础选择器 复合选择器 CSS引入方式 CSS引入方式介绍 内部样式表(嵌入式) 行内样式表 外部样式表 五.JS基础 Javascript介绍 1.js的介绍 2.js的由来 3.JavaScript组成 JavaScript基本语法 1.JavaScript的引入方式 2.js注释 3.js的输入输出方法 4.变量 5.数据类型 6.数据类型转换 7.更多JS基础 六.JS之DOM 1.DOM简介 什么是DOM? DOM树 2.获取元素 根据ID获取 根据类名获取 根据标签名获取 通过选择器获取 通过选择器获取(多个) 定位body标签 定位html标签 3.事件基础 事件基础介绍

Cannal组件

1.Cannal入门 什么是canal 当mysql发生新增,修改,我们可以利用cancal监控到这个修改的数据,并将这个数据写到消息队列,供实时计算框架使用。 cancal主要支持了MYSQL的Binlog解析,解析完成后才利用Cancal Client来处理获得的相关数据 什么是mysql的binlog MYSQL的二进制日志可以说是MYSQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句),以事件形式记录,还包含语句执行的消耗时间。 二进制有两个重要的使用场景: 1.主从数据同步 2.数据恢复 binlog分类 binlog的格式有三种,分别是STATEMENT.MIXED,ROW statement:语句级,binlog会记录每一次执行写操作的语句row:行级,binlog会记录每次操作后每行记录的变化,保持数据的绝对一致性。占用空间较大mixed:statement的升级版,默认情况还是statement,但是当函数中包含了uuid(),自增字段的表被更新,执行插入语句时,会按照row方式处理。节省空间,同事兼顾了一定的一致性 2.Cannal工作原理 1.MySQL主从复制过程 Master主库将改变记录,写到二进制日志中Slave从库向MySQL Master发送dump协议,将Master主库的binary log events拷贝到它的中继日志(relay log)Slave从库读取并重做中继日志中的事件,将改变的数据同步到自己的数据库 canal 工作原理 把自己伪装成Slave,假装从Master复制数据 2.使用场景 1.原始场景:阿里Otter中间件的一部分 Otter是阿里用于进行异地数据库之间的同步框架,Canal是其中一部分 2.更新缓存 3.抓取业务表的新增变化数据,用于制作实时统计 步骤: 修改mysql配置文件my.cnf中的binlog_format为row模式,指定需同步的数据库binlog-do-db给canal赋予只读权限配置mysql服务器地址及用户名密码 TCP模式 客户端,服务端模式 自己编写客户端代码 kafka模式 采集后直接发送到消息队列中 canal数据结构

如何在Android中使用Google FireBase?

我这里引用Firese的目的主要是检测到底有多少用户在使用相关产品,用的是Firebase的免费版本。看官方教程还是被一些地方给卡住了,特别是检测是否成功时。比较幸运的是Google团队还是比较靠谱,咨询相关问题都能给出及时反馈和建议。 如需了解更多,请访问:https://www.emperinter.info/2022/05/06/how-to-use-google-firebase-in-android/ 注册 登录并启用https://console.firebase.google.com/ 使用 添加APP 按引导流程下载配置相关文件,操作流程安排挺清楚的,注意细节就行了。 这里就说关键的一点,那就是必需在代码中也配置一些相关信息,这个是教程中没提到的,我这里没添加是没有任何有效检测的的,最后加上后就好了。 ... public class GameActivity extends AppCompatActivity { private FirebaseAnalytics mFirebaseAnalytics; protected void onCreate(@Nullable Bundle savedInstanceState) { // Obtain the FirebaseAnalytics instance. mFirebaseAnalytics = FirebaseAnalytics.getInstance(this); mFirebaseAnalytics.setAnalyticsCollectionEnabled(true); Bundle bundle = new Bundle(); bundle.putString("start", "yes"); mFirebaseAnalytics.logEvent("share", bundle); ... } } Firebase DebugView 配置 进入adb目录,一般在你配置的SDK路径下,比如windwos就是 D:\SoftWare\Android\SDK\platform-tools 启用调试模式,注意package_name替换成你自己的应用package_name. adb shell setprop debug.firebase.analytics.app package_name 查看 Android Studio 调试日志中的事件。 如需了解更多,请访问:https://www.emperinter.info/2022/05/06/how-to-use-google-firebase-in-android/

Mac(M1 ARM)安装lightgbm记录

2022-5-6上午一客户说他的Mac笔记本安装python-lightgbm库报错: 电话指导客户安装TODESK并开启权限开始远程协助处理故障: 1.进入客户anaconda环境 pip install lightgbm 成功 2.执行代码故障依旧。 3.CSDN搜索一个方案进入系统终端执行brew install lightgbm (libomp自动安装) 4.执行代码故障依旧。 5.继续CSDN搜索方案,通过brew安装cmake和gcc brew install cmake brew install gcc --without-multilib brew会查找最新的gcc版本进行安装,安装过程中要仔细观察安装的gcc版本,接下来会用到,很重要,如果没注意安装过程并且不小心关掉了终端的话可以到这个路径进行查看: find /opt -name gcc 6.安装的是gcc11 下面进入终端到下载目录用cmake进行编译: git clone --recursive https://github.com/Microsoft/LightGBM cd LightGBM export CXX=g++-11 CC=gcc-11 mkdir build cd build cmake .. make -j4 7.激活anaconda环境,进入编译的lightgbm目录LightGBM/python-package/下 执行: sudo python setup.py install --precompile 输入密码就完成lightgbm安装,pip list 可以看到版本是3.3. 执行代码故障依旧。不过这次出现新提示;  (mach-o file, but is an incompatible architecture (have 'arm64', need 'x86_64') 8.检查客户自己安装的anconda是X_86的版本。。。。。而M1是arm版本

@NoArgsConstructor、@AllArgsConstructor、@RequiredArgsConstructor的区别以及在springboot常用地方

文章目录 1. 先说结论2. 代码解析区别1. @AllArgsConstructor2. @RequiredArgsConstructor 3. 场景使用---代替@Autowired注入bean对象1. @AllArgsConstructor2. @RequiredArgsConstructor3. @RequiredArgsConstructor 与 @AllArgsConstructor 在注入bean上的区别 4. 总结 1. 先说结论 区别: @NoArgsConstructor:生成无参的构造方法。 @AllArgsConstructor:生成该类下全部属性的构造方法。 @RequiredArgsConstructor:生成该类下被final修饰或者non-null字段生成一个构造方法。场景: 在springboot中,对于一个bean类,注入其他bean的时候,常见的是使用@Autowired,实际上也可以使用构造函数注入,这个时候就可以使用@AllArgsConstructor或者@RequiredArgsConstructor来代替。 2. 代码解析区别 @NoArgsConstructor 默认都知道。若不知道怎么查看java反编译字节码内容,可以看一下: Java 如何进行反编译生成.java文件(javap、jad下载安装使用) 1. @AllArgsConstructor @AllArgsConstructor public class demo { private String name; // 被final修饰 private final String age; @NonNull private String sex; } 根据反编译查看代码: public class demo { // 默认 只要是该类下的字段,无论什么修饰,都会被参与构造 public demo(String name, String age, String sex) { if(sex == null) { throw new NullPointerException("

java 基本IO操作

1.JAVA IO IO指的是输入与输出,Input和Output java将输入与输出比作流: 流可以理解为是 顺着同一个方向移动的过程,即:流动的概念 输入流:想象为是一个"管道",链接着我们写的java程序与另一端的管道,而流动的方向 是从另一端移动到我们的程序的过程,是一个获取的过程,操作为"读" 输出流:方向从我们写的程序到另一端的方向,操作为:"写" java为了规范流的行为,定义了两个超类: java.io.InputStream和java.io.OutputStream java.io.InputStream是所有字节输入流的超类(同时是抽象类) 定义了几个常见的抽象方法: int read():读取一个字节 int read(byte[] data):块读取操作 java.io.OutputStream是所有字节输出流的超类(同时是抽象类) void write(int d):写出一个字节 void write(byte[] data):块写操作 void write(byte[] data,int off,int len):块写部分数据。 文件流: java.io.FileInputStream和FileOutputStream 文件流继承自java.io.InputStream和OutputStream 这对流是用来读写文件的流 public class FOSDemo { public static void main(String[] args) throws IOException { /* 常见构造器: FileOutputStream(String pathname) 参数为写出的文件的路径 FileOutputStream(File file) 参数为写出的文件所对应的File实例 创建文件输出流时,如果指定的文件不存在文件流会自动将该文件创建出来 但是如果指定的文件所在的目录不存在时,实例化会抛出异常: java.io.FileNotFoundException 即:文件没找到异常 */ //向当前目录下的fos.dat文件中写入数据 /* 相对路径中"./"可以忽略不写,默认就是从"./"开始的 比如: "./fos.dat"等价与"fos.dat" "./demo/fos.dat"等价于"demo/fos.dat" */ FileOutputStream fos = new FileOutputStream("

基础java文件操作

File : 文件 io:input输入 output输出 path : 路径 java.io.File File的每一个实例用于表示硬盘上的一个文件或目录(实际上表示的是一个抽象路径) File可以: 1:可以访问其表示的文件或目录的属性信息(文件名,大小,修改时间等等) 2:创建或删除文件及目录 3:访问一个目录(文件夹)中的所有子项 File不能访问文件数据!!!! public class FileDemo { public static void main(String[] args) { //访问当前项目下的demo.txt文件 /* File常用构造器: File(String pathname) 指定一个路径,使当前File对象表达该位置对应的文件或目录。 这里路径使用一个字符串,路径有两种写法: 绝对路径:从操作系统定义的"根"开始,比如windows中硬盘上的根从c盘,d盘等盘符开始 绝对路径的有点在于清晰明了,但是缺点就是太绝对,不能更好适应跨平台。 相对路径:相对路径写法常见的为"./",即:当前目录 相对路径有更好的适应性,适合跨平台使用,缺点是不够清晰,具体位置的 判断要视当前程序的运行环境而定。 比如在IDEA中执行当前程序时,IDEA规定的"./"就是当前项目目录 */ // D:/Robin/jsd2203_se/demo.txt // File file = new File("D:/Robin/jsd2203_se/demo.txt"); File file = new File("./demo.txt"); /* File常见方法: 1:String getName() 获取File对象表示的文件或目录的名字 2:long length() 获取当前File对象表示的文件或目录占用的硬盘空间,单位为字节 11:27回来 */ String name = file.getName(); System.out.println(name); long len = file.

Pytorch框架学习

Pytorch学习 Pycharm、console、jupyter运行区别Pytorch加载数据Dataset代码实战Tensorboard的使用Transforms使用常见的Transforms使用torchvision使用DataLoader使用神经网络nn.module使用卷积操作(conv2函数)神经网络卷积层最大池化非线性激活线性层及其他层介绍神经网络Sequential使用损失函数与反向传播优化器现有模型修改和使用模型保存与加载模型训练(cuda) Pycharm、console、jupyter运行区别 介绍: Pycharm:代码是以块为一个整体运行的话,python文件的块是所有行的代码。 Console:以每一行为块运行。 Jupyter:以任意行为块运行的。 优点: Pycharm:通用,传播方便,适用于大型项目。 Console:显示每个变量的属性。 Jupyter:利于代码的阅读及修改。 缺点: Pycharm:需要从头运行。 Console:不利于代码的阅读及修改。 Jupyter:环境需要配置。 Pytorch加载数据 Dataset 提供一种方式去获取数据及其label。其主要实现以下两个功能: 1.如何获取每一个数据及其label。 2.告诉我们总共有多少的数据。 Dataloader 为后面的网络提供不同的数据形式。 Dataset代码实战 from PIL import Image #导入Image包 img_path="C:\\Users\\myn\\Pytorch_Learning\\datasets\\train\\ants\\0013035.jpg" #图片路径 img=Image.open(img_path) #读取图片,在变量中可以看到图片的属性 img.size #获取图片的大小 img.show() dir_path="datasets/train/ants" import os #python中的一个系统库 img_path_list=os.listdir(dir_path) #文件名列表 img_path_list[0] root_dir="datasets/train" label_dir="ants" path=os.path.join(root_dir,label_dir) #将路径拼接 Tensorboard的使用 Tensorborad是一种很好的可视化工具,可以绘制函数、显示图像等功能。 控制台连接Tensorboard: (base)C:\Users\myn\Pytorch_Learning>tensorboard --logdir=logs --port=6007 # Tensorboard使用 from torch.utils.tensorboard import SummaryWriter #导入Tensorboard相应的库 import numpy as np from PIL import Image writer = SummaryWriter("

链表的应用-多项式的加法

写在前面—— 本章是链表的一个实践,即运用链表来进行多项式的计算。本篇的预备知识——单链表的基本运用。 代码实现如下: 1.(闵版) typedef struct LinkNode{ int coefficient; int exponent; struct LinkNode *next; } *LinkList, *NodePtr; //初始化表 LinkList initLinkList(){ LinkList tempHeader = (LinkList)malloc(sizeof(struct LinkNode)); tempHeader->coefficient = 0; tempHeader->exponent = 0; tempHeader->next = NULL; return tempHeader; } //打印函数(1) void printList(LinkList paraHeader){ NodePtr p = paraHeader->next; while (p != NULL) { printf("%d * 10^%d + ", p->coefficient, p->exponent); p = p->next; } printf("\r\n"); } //打印函数(2) void printNode(NodePtr paraPtr, char paraChar){ if (paraPtr == NULL) { printf("

Visual Studio Code 正则表达式搜索

引言 VS Code 的全局搜索,可快速查找旧项目代码,或者函数名称但是不是所有时候,都知道想要的函数名字,直接搜索是搜不到的所以,要引入模糊搜索的概念在只知道部分信息的情况下,利用正则表达式,匹配目标代码块 VS CODE 的正则规则 通配符说明.匹配换行外的任意字符\w字母 or 数字 or 下划线 or 汉字\s空白符\d数字\b单词的开始或者结束\W不是 字母 or 数字 or 下划线 or 汉字\S不是 空白符\D不是 数字\B不是 单词的开始或者结束[^x]匹配除X外的任意字符^字符串的开始$字符串的结束*重复0 or 多次+重复1 or 多次?重复0 or 1次{n}重复n次{n,}重复n or 多次{n, m}重复n - m次

Node+Express+Compression部署Vue项目

背景: 在一个Vue项目开发完成后,经过 yarn build 或者 npm run build 打包文件,此时会在文件夹下生成一个 dist 文件夹,那怎么让这个文件夹运行起来可以预览开发完成的项目呢?在此使用 Node 搭建简易的服务器,将 dist 文件夹托管为静态资源。实现步骤如下。 一、新建文件夹 创建一个新的文件夹,通过 npm init -y 初始化 Node.js 项目,生成的默认的 package.json ,将 dist 文件夹拷贝到当前文件目录下,如下图所示。 二、安装依赖 1、通过 npm run express 或者 yarn add express 安装 express ,该中间件是 Node 项目运行起来的关键。 2、通过 npm run compression 或者 yarn add compression 安装 compression ,该中间件是启用 Gzip 资源压缩功能的关键。 PS:资源压缩一般是前端打包项目的时候启用 Gzip 压缩,如果是在服务器进行压缩的话会造成性能浪费, compression 在此的作用是当前端请求的时候,返回已经压缩好的 GZ 文件,而不是对请求的文件进行压缩后再返回给前端。关于Vue项目webpack打包如何启用Gzip压缩可以看我另外一篇文章: Vue项目打包启用图片、JS和CSS文件的Gzip压缩 三、新建app.js文件 新建 app.js 文件作为 Node.js 项目的入口文件,主要代码如下: const express = require('express'); const compression = require('compression'); const app = express(); // compression的使用写到静态资源托管之前 app.

Scala基础教程--07--继承与抽象类

Scala第七章节 章节目标 掌握继承和抽象类相关知识点掌握匿名内部类的用法了解类型转换的内容掌握动物类案例 1. 继承 1.1 概述 实际开发中, 我们发现好多类中的内容是相似的(例如: 相似的属性和行为), 每次写很麻烦. 于是我们可以把这些相似的内容提取出来单独的放到一个类中(父类), 然后让那多个类(子类)和这个类(父类)产生一个关系, 从而实现子类可以访问父类的内容, 这个关系就叫: 继承. 因为scala语言是支持面向对象编程的,我们也可以使用scala来实现继承,通过继承来减少重复代码。 1.2 语法 scala中使用extends关键字来实现继承可以在子类中定义父类中没有的字段和方法,或者重写父类的方法类和单例对象都可以有父类 语法 class/object A类 extends B类 { .. } 叫法 上述格式中, A类称之为: 子类, 派生类.B类称之为: 父类, 超类, 基类. 1.3 类继承 需求 已知学生类(Student)和老师类(Teacher), 他们都有姓名和年龄(属性), 都要吃饭(行为), 请用所学, 模拟该需求. 方式一: 非继承版. object ClassDemo01 { //1. 定义老师类. class Teacher{ var name = "" var age = 0 def eat() = println("老师喝牛肉汤!...") } //2. 定义学生类. class Student{ var name = "

为什么不建议给MySQL设置Null值?《死磕MySQL系列 十八》

大家好,我是咔咔 不期速成,日拱一卒 之前ElasticSearch系列文章中提到了如何处理空值,若为Null则会直接报错,因为在ElasticSearch中当字段值为null时、空数组、null值数组时,会将其视为该字段没有值,最终还是需要使用exists或者null_value来处理空值 大多数ElasticSearch的数据都来自于各类数据库,这里暂且只针对于MySQL,各个开源软件中都默认兼容各种Null值,空数组等等 若从根源上截断就可以省很多事,直到现在很多开发小伙伴还是坚韧不拔的给字段的默认值还是Null 本期就来聊一聊为什么不建议给字段的默认值设置为Null 本期环境为:MySQL8.0.26 一、案例数据 创建表user CREATE TABLE `user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `age` tinyint(4) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci 添加数据,共计10条数据,有两条数据的name值为Null INSERT INTO `user` (`name`, `age`) VALUES ('kaka', 26); INSERT INTO `user` (`name`, `age`) VALUES ('niuniu', 26); INSERT INTO `user` (`name`, `age`) VALUES ('yangyang', 26); INSERT INTO `user` (`name`, `age`) VALUES ('dandan', 26); INSERT INTO `user` (`name`, `age`) VALUES ('liuliu', 26); INSERT INTO `user` (`name`, `age`) VALUES ('yanyan', 26); INSERT INTO `user` (`name`, `age`) VALUES ('leilie', 26); INSERT INTO `user` (`name`, `age`) VALUES ('yao', 26); INSERT INTO `user` (`name`, `age`) VALUES (NULL, 26); INSERT INTO `user` (`name`, `age`) VALUES (NULL, 26); 一、count数据丢失 在这期 MySQL统计总数就用count,别花里胡哨的《死磕MySQL系列 十》 文章中,已经对count的使用说的非常明白了。

重看计算机网络——数据链路层

自用记录,写的不是很详细。 数据链路层 数据链路层属于计算机网络的低层,使用的信道主要有以下两种类型: (1)点对点信道:使用一对一的点对点通信方式,使用的协议是PPP协议 (2)广播信道:使用一对多的广播通信方式,因此过程比较复杂。采用的协议是以太网协议。 数据链路层解决的问题是:在同一个局域网中,分组怎样从一台主机传送到另一台主机,但并不经过路由器转发。 数据链路层的三个基本问题:封装成帧、透明传输、差错检验。 1、使用点对点信道的数据链路层 基本概念: 链路:从一个结点到相邻结点的一段物理线路(无线或有线),而中间没有任何其他的交换结点。在进行数据通信时,两台计算机之间的通信路程往往要经过许多段这样的链路。链路只是一个路径的组成部分。数据链路:当需要在一条线路上传送数据时,除了必须要有一条物理线路外,还必须要有一些必要的通信协议来控制这些数据的传输。因此数据链路就是链路加通信协议。目前通过网络适配器来实现这些协议。帧:数据链路层的协议数据单元。数据链路层把网络层交下来的数据构成帧发送到链路上,以及把接收到的帧中的数据取出并上交给网络层。网络层的协议数据单元为IP数据报(简称为数据报、分组或包)。 帧 = 首部+IP数据报+尾部 点对点信道的数据链路层进行通信时的步骤为: (1)结点A 将网络层交下来的IP数据报添加首部和尾部封装成帧 (2)结点A将帧发送给结点B的数据链路层 (3)若结点B收到的帧无差错,则从收到的帧中提取出IP数据报交给上面的网络层,否则丢弃这个帧。 针对数据链路层的点对点通信的三个基本问题:封装成帧,透明传输和差错检验进行对应处理 (1)封装成帧 封装成帧就是在IP数据报前后加上首部和尾部,因此接收端在收到物理层上交的比特流后,就能根据首部和尾部的标记,从收到的比特流中识别帧的开始与结束。 首部和尾部的作用为:帧定界,即确定帧的界限,此外首部和尾部还包括许多必要的控制信息。 首部为控制字符SOH,表示帧的开始,其ASCII码为0x01;尾部为控制字符EOT,其ASCII码为0x04,表示帧的结束。PPP帧中必须同时包括SOH和EOT,否则认为帧不完整,要被丢弃。 帧的组成: 帧开始符SOH + 数据部分 + 帧结束符EOT (其中数据部分有长度上限——最大传输单元MTU) (2)透明传输 所谓透明传输,指的是无论什么样的比特组合的数据,都能够按照原样没有差错地通过这个数据链路层,因此对数据而言,这个数据链路层是无妨碍的,也就是透明的。 由于封装成帧时在首部和尾部加控制字符,控制字符决定了一个帧是否完整,如果在数据部分也出现控制字符SOH或EOT,那么会导致接收端错误判断帧的界限,把部分帧收下,而误以为收下的是完整的帧,而把剩下的数据丢弃。 因此规定,如果数据部分的二进制代码中出现SOH或EOT,就在前面加一个转义字符”ESC”,其ASCII码为1B。如果数据部分的二进制代码出现了转义符,那就在这个转义符前再加一个转义符。当接收端接收到帧时,就会把每次出现的第一个转义字符删除。以上的操作称为字符填充或字节填充。 (3)差错检测 比特差错:比特流在传输过程中可能会出现差错,比如0变成1,1变成0.实际的通信链路并非是理想的,比特差错不可避免,目前数据链路层广泛使用的差错检测方法为循环冗余检测(CRC)。 CRC原理: 在发送端,首先会把数据划分为组,假定每组k个比特。比如现假定待传送的数据M=101001,即k=6。CRC会在数据M后加n位冗余码,然后构成一个帧发送出去,一共发送(k+n)位。 冗余码的获得:首先数据M乘2^n,相当于在M后补了n个0,然后设定一个除数P,P的位数为n+1位,这个P是发送端和接收端共同规定的,则有: M*2nP=Q….R 其中,Q为商,没有用,R为余数,R即为要获得的冗余码,称为FCS(帧检验序列) M和R进行拼接,就获得了最终PPP帧中的数据部分。 而在接收端,收到这个帧后,获得数据部分,然后用数据部分的二进制码除以P,若余数为0,则说明没有差错,反之,有差错,这个帧被丢弃。 从上述描述可以发现,CRC只检测是否有差错,而不能知道差错在哪。 差错检测能确保接收端接收到的帧是无差错的,但不能保证数据链路层的可靠传输。因为差错检测只能解决最基本的比特差错,但无法检测帧的差错,比如帧丢失,帧重复和帧失序。 因此数据链路层的CRC检测只能保证无比特差错,但不能保证无传输差错。 对于实现数据链路层的可靠传输,以前的方式是在CRC的基础上增加帧编号、确认和重传机制。由于现在的通信线路的质量大大提高,由通信线路质量不好引起差错的概率大大降低,为了提高效率,互联网采用区别对待的方式: 对于通信质量良好的有线传输链路,数据链路层协议不使用确认和重传机制。如果在数据链路层传输数据时出现差错,并需要改正时,就由上层(如TCP)来解决。对于通信质量较差的无线链路,数据链路层采用确认和重传机制。 PPP协议的帧格式: (1)封装成帧 首部四个字段: F:0x7E 定界符,表示帧开始或结束 A:地址字段,默认0xFF,无实际意义 C:控制字段,默认0x03,无实际意义 协议:2个字节,表示数据部分属于上层的哪个协议 数据部分:不超过1500字节 尾部:FCS + F(7E),即帧检验序列和定界符 (2)字节填充:解决透明传输问题 PPP协议使用异步传输时,将转义符定为0x7D,并使用字节填充。 0x7E -> 0x7D,0x5E0x7d -> 0x7D,0x5D对ASCII码中数值小于0x20的字符,如0x03变为 0x7D,0x23 接收端会对填充后的字节进行反变换获得原始的字节

NetEq(一) 延迟估计

总体框图 四个buffer 抖动缓冲区(packet buffer) 暂存从网络获得的音频数据包 解码缓冲区 (dec buffer ) 抖动缓冲区中的数据包通过解码器解码成为PCM原始音频数据,暂存到解码缓冲区 算法缓冲区 (algorithm buffer) NetEQ将解码缓冲区中的数据进行拉伸、平滑处理后将结果暂存到DSP算法缓冲区 语音缓冲区 (speech buffer) 算法缓冲区中的数据会被塞到语音缓冲区中,声卡每隔一段时间会从语音缓冲区中提取固定长度的语音数据播放 当需要加速,加速,丢包补偿,融合等操作时,需要经过一些算法处理解码后的数据,经过算法处理后的数据放入算法缓冲区。 延迟估计 有两个延迟需要估计,网络延迟和抖动延迟,涉及两个线程,一个线程负责接收网络发来的数据包并估计网络时延,另一个线程负责解码,算法处理,解码数据放入syncBuffer中。 网络延迟 当每一帧数据包到来时,会进入NetEq的InsertPacket,首先把数据包保存到packet_buffer中。 const int ret = packet_buffer_->InsertPacket(*packet, &stats_); 目前配置的packet_buffer最多能缓存50包数据,如果packet_buffer写"爆了",会清空packet_buffer. // Get an iterator pointing to the place in the buffer where the new packet // should be inserted. The list is searched from the back, since the most // likely case is that the new packet should be near the end of the list.

vscode正则匹配非注释中的关键字

前言 平时在用vscode开发中,会搜索代码中的关键字,但是直接搜索的话,很多comments中的关键字也会出现在搜索结果中了,如下: 可以用正则表达式,*^((?!//).)schedule,匹配只出现在代码正文中的关键字,

Apache Druid历险记

1. Druid简介 1. 1 概述 Druid是一个快速的列式分布式的支持实时分析的数据存储系统。它在处理PB级数据、毫秒级查询、数据实时处理方面,比传统的OLAP系统有了显著的性能改进。 OLAP分析分为关系型联机分析处理(ROLAP)、多维联机分析处理(MOLAP)两种,MOLAP需要数据预计算好为一个多维数组,典型方式就是Cube,而ROLAP就是数据本身什么样就是什么样,查询时通过MPP提高分布式计算能力。 Druid是ROLAP路线,实时摄取数据,实时出结果,不像Kylin一样,有一个显式的预计算过程。 1.1.2 补充 MPP:俗称大规模并行处理,数据库集群中,每个节点都有独立的磁盘存储系统跟内存系统,业务数据根据数据库模型跟应用特点被划分到各个节点,MPP就是将任务并行分散到多个节点,每个节点计算完毕后将结果汇总下来得到最终结果。 Lambda架构:该 架构的设计是为了在处理大规模数据时,同时发挥流处理和批处理的优势。通过批处理提供全面、准确的数据,通过流处理提供低延迟的数据,从而达到平衡延迟、吞吐量和容错性的目的。为了满足下游的即席查询,批处理和流处理的结果会进行合并。一般有三层。 Batch Layer:批处理层,对离线的历史数据进行预计算。 Speed Layer:加速处理层,处理实时的增量数据。 Serving Layer:合并层,计算历史数据和实时数据都有了。 注意:阿里巴巴也曾创建过一个开源项目叫作Druid(简称阿里Druid),它是一个数据库连接池的项目。阿里Druid和本文讨论的Druid没有任何关系,它们解决完全不同的问题。 1.2 Druid 特点 低延迟交互式查询:Druid提供低延迟实时数据摄取(⼊库),典型的lambda架构。并采⽤预聚合、列式存储、位图索引等⼿段使得海量数据分析能够亚秒级响应。 ⾼可⽤性( High Available ):Druid 使⽤用 HDFS/S3 作为 Deep Storage,Segment 会在多个Historical 节点上进行加载,摄取数据时也可以多副本摄取,保证数据可⽤性和容错性。 可伸缩( Horizontal Scalable ):Druid 部署架构都可以⽔平扩展,增加大量服务器来加快数据摄取,以保证亚秒级的查询服务。集群扩展和缩小,只需添加或删除服务器,集群将在后台自动重新平衡,无需任何停机时间。 并行处理( Parallel Processing ): Druid 可以在整个集群中进行大规模的并行处理查询(MPP)。 丰富的查询能力( Rich Query ):Druid支持时间序列、 TopN、 GroupBy等查询,同时提供了2种查询方式:API 和 SQL(功能较少)。 1.3 Druid 适用 & 不适用场景 ⼀句话总结,Druid适合带时间维度、海量数据的实时/准实时分析 带时间字段的数据,且时间维度为分析的主要维度。 快速交互式查询,且亚秒级快速响应。 多维度海量数据,能够预先定义维度。 适用于清洗好的记录实时录入,但不需要更新操作。 适用于支持宽表,不用Join的方式(换句话说就是一张单表)。 适用于可以总结出基础的统计指标,用一个字段表示。 适用于对数据质量的敏感度不高的场景(原生版本非精确去重)。 Druid 不适合的场景

用laravel写一个API

目的 用Laravel写一个API,查询所有的用户信息,示例如下 最起码要跑起来 [ { "id": 1, "name": "Sinmu", "phone": null, "email": "sinmu@example.com", "email_verified_at": "2022-03-14T10:58:59.000000Z", "weixin_openid": null, "weixin_unionid": null, "created_at": "2022-03-14T10:58:59.000000Z", "updated_at": "2022-04-01T17:56:04.000000Z", "avatar": "https://cdn.learnku.com/uploads/images/201710/14/1/ZqM7iaP4CR.png", "introduction": null, "notification_count": 0, "last_actived_at": null }, . . . . ] 步骤 下载Laravel 我这里是通过composer 来下载一个laravel项目,composer create-project laravel/laravel projectname_laravel_API 约定 项目按照路径同意会用{path} 来代替。 比如我们的项目文件路径:{path}/projectname_laravel_API 修改配置文件并添加controller 进入项目文件路径下的 .env文件编辑文件内容,修改数据库的参数 通过php artisan make:controller Api/UserController创建一个文件,此时我们可以看到这里多了一个文件 我们在里面添加一些方法 <?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Models\User; class UserController extends Controller { public function index(){ return 'index'; } public function show(){ return User::all(); } } 在return User::all();的意思是会返回我们数据库中user表中的所有数据

PDF 缩略图无法正常显示 解决办法

先交代一下配置:win10 + 福晰阅读器+Adobe Acrobat DC 有时候PDF无法显示缩略图,像下面这样子 提前设置好两个点: 1.从不显示缩略图的复选框的勾 ,取消, 如图所示。 . 2.在Adobe Acrobat DC 中 设置 如下 把pdf默认打开软件改成 adobe ,至此 问题应该差不多解决了。 但是我遇到的问题是,我习惯用福晰阅读器看pdf,每次看pdf的时候都得先默认用adobe 让他出缩略图,然后再默认成福晰阅读器,这样很不方便。于是我又找了下面一个办法, 先对福晰阅读器的设置, 然后安装 ,SumatraPDF-3.1.2-64-install.exe,以后也不要升级到 3.2的版本!!! 注意安装的时候 选择让windows 显示 pdf 文件的预览,一下然后清理一下系统的缩略图,重启。 完。 其他: pdf 缩率图旁边白色过多,显得图标变胖,解决办法 在偏好设置--辅助工具中,去掉在操作系统中打开缩略图前面的勾号,然后清理系统缩略图,重启。

####好好好###图神经网络系统介绍与总结分析

图神经网络算法将深度神经网络的运算(如卷积、梯度计算)与迭代图传播结合在一起:每个顶点的特征都是由其邻居顶点的特征结合一组深度神经网络来计算。 但是, 现有的深度学习框架不能扩展和执行图传播模型,因此缺乏高效训练图神经网络的能力,并且现有框架一般采用数据/模型并行来分布式训练深度神经网络,这种并行计算方法难以直接应用于图神经网络,因此限制了训练大规模图神经网络的能力。 而现有的图处理系统虽然能够表示迭代图传播模型,并能有效支持大规模图的迭代计算,但是缺乏支持神经网络计算的关键能力,如张量抽象、自动微分等。 因此,为了支持图神经网络在大规模图上的应用,以及对更复杂图神经网络结构的探索,开发针对图神经网络的训练系统是十分有必要的。 图神经网络系统介绍与总结分析​ mp.weixin.qq.com/s/q0V5vHqQzijTKzXIk0TNOw正在上传…重新上传取消 目前具有代表性的图神经网络框架:DGL、PyTorch Geometric、NeuGraph、EnGN、Euler、PSGraph、AliGraph、Roc、AGL、PGL. DGL是易于使用,高性能且可扩展的Python库,用于图结构的深度学习,能够与主流的深度学习框架集成,例如Tensorflow、PyTorch、MXNet。 PyTorch Geometric是基于PyTorch构建的深度学习库,用于处理非结构化数据的深度学习。 NeuGraph是一种将数据流系统和图处理系统结合起来训练图神经网络的框架, 它构建在现有的数据流引擎之上,使用Python和C++作为开发语言。 EnGN是一种以边为中心,专门用于大规模图神经网络训练的加速器。 Euler与PSGraph是一个与深度学习工具集成的大规模分布式图学习框架,支持用户在数十亿点数百亿边的图上进行模型训练。 AliGraph是由阿里巴巴团队开发的采样建模训练一体化的图神经网络平台。 Roc是一种用于快速图神经网络训练的分布式多GPU框架。 AGL是用于工业用途图学习的集成系统, 利用传统基础架构(MapReduce、参数服务器)实现了容错性和一致性。 PGL (paddle graph learning)是由百度开发的基于PaddlePaddle的高效灵活的图学习框架。 1. 图神经网络系统介绍 1.1 DGL DGL是用于图结构深度学习的Python库,通过与主流的深度学习框架集成,能够实现从传统的张量运算到图运算的自由转换。DGL提供基于消息传递的编程模型来完成图上的计算,结合消息融合等优化技术使系统达到了比较好的性能。 DGL的API主要有两部分,一是消息函数: 二是累和函数: 其中, 代表边k的属性向量, 代表顶点i的属性向量,是边k的源顶点属性向量, 是边k的目的顶点属性向量, 代表边k上的消息,t代表迭代次数。 是一个消息函数,定义在边上,通过将边的特征与两端的顶点特征组合来生成“消息”。 是在每个顶点上定义的更新函数,通过使用reduce操作汇总其传入的消息来更新顶点特征。在图神经网络中,这些功能由神经网络模块进行参数化,⊕可以是求和运算,也可以是均值,最大值、最小值或LSTM网络,s.t. rk=i表示对目的顶点为i的所有消息进行聚合操作。 消息张量的大小正比于图中边的数量,因而当图增大时,消息张量消耗的内存空间也会显著上升。为了避免生成消息张量带来的额外存储开销,DGL实现了消息融合技术,将send函数和recv函数合并成了 sendandrecv 。 1.2 PyTorch Geometric PyTorch Geometric,是一个基于PyTorch构建的深度学习库,可以对非结构化数据进行建模和训练。该库利用专用CUDA内核实现了高性能训练。 PyTorch Geometric提供一个简单的消息传递API,将卷积算子推广到不规则域,具体表示为: 其中, ⊕表示可微置换不变函数,如求和、均值或最大值。整个模型可以通过gather和scatter顶点特征以及对其进行矢量化的元素计算来实现。 通过这个消息传递模型,用户只需要定义消息函数和更新函数,以及选择聚合方案⊕,就可以设计新的图神经网络模型。该库采用COO格式编码边索引,一个维度表示源顶点,另一个维度表示目标顶点,这种存储格式非常适用于消息传递模型,能够快速获取顶点对应的源顶点的信息。与通过矩阵乘法实现的方法相比,使用消息传递模型能够达到更好的性能。 1.3 NeuGraph NeuGraph提出了一种新的框架,根据图神经网络是将标准神经网络与迭代图传播结合起来的这一特点,NeuGraph在数据流中引入以顶点为中心的消息传递模型,将图模型和数据流模型结合,来支持并行图神经网络计算。NeuGraph还将图计算的优化方法如数据分区、调度,引入到了数据流框架中,来支持高效的图神经网络训练。 NeuGraph提出了一种新的处理模型SAGA-NN,它将数据流和顶点编程模式相结合来表示图神经网络的计算。SAGA-NN将前向计算分为4个阶段: Scatter、ApplyEdge、Gather和ApplyVertex。 ApplyEdge和ApplyVertex提供了两个用户定义函数,供用户在边和顶点上声明神经网络计算。ApplyEdge函数定义每个边上的计算,以edge和W作为输入,其中edge是指边数据,W包含图神经网络模型的可学习参数。ApplyVertex函数定义了顶点的计算,它以顶点张量、顶点聚合累积量和可学习参数W作为输入,并在应用神经网络模型后返回新的顶点表示。Scatter和Gather执行数据传播和收集,由系统隐式触发和执行。 SAGA-NN中的顶点程序采用以顶点为中心的编程模型来表达图神经网络的计算,对图神经网络中的通用阶段进行建模,并在图计算和数据流调度中实现优化。 NeuGraph在数据流抽象的基础上引入了特定的图分区方法,可以解决GPU内存的物理限制问题。通过2D图分区方法,NeuGraph将顶点数据分割成P个大小相等的不相交顶点块,并将邻接矩阵分为P×P个边块。通过将图数据分割成块,在逐个处理边块信息时,只需要边块所对应的源顶点块和目标顶点块即可。在训练过程中, 与顶点块或边块相关的一些中间特征数据将用于反向传播。 为了节省GPU内存,它们在前向计算期间交换到主机内存,在反向传播期间交换回。NeuGraph为降低主机和GPU内存之间的数据传输做了一系列优化:在处理边块E时,NeuGraph设计了一个过滤器,来过滤每个顶点块内的必要顶点,并将其传输到GPU中;通过一种局部感知的图划分算法,NeuGraph将连接同一顶点的边尽可能地压缩到一个块内,通过这种方法,NeuGraph可以获得更好的顶点数据访问局部;NeuGraph设计流水线调度进一步重叠数据传输和计算,以隐藏传输延迟。 1.4 EnGN EnGN是一种处理大规模图神经网络的专用加速器架构,并且EnGN提出了一种使用专用架构的以边为中心的数据流模型。EnGN将常见的图神经网络计算模式抽象为特征提取,聚合和更新3个阶段。 在特征提取阶段,神经网络来压缩图中每个顶点的属性。聚合阶段通过聚合在特征提取中生成的每个顶点的邻居属性,来产生统一的输出特征,其中聚合函数的选择包括各种算术运算,例如max,min和add。在传播迭代结束时,更新阶段会利用学习到的参数进一步压缩聚合阶段中获得的输出特征,并在输出之前将非线性激活函数或GRU/LSTM函数应用于图的每个顶点。 在以边为中心的数据路模型基础上,EnGN集成了一个神经图处理单元(NGPU),能够在统一的体系结构中执行特征提取,聚合和更新操作。它具有一个PE数组,每个PE单元都包含一个本地寄存器,用于存储临时结果并充当PE间通信的中介。 EnGN提出了图属性感知(GPA)数据流,来分离顶点的输入属性和硬件计算结构。以这种方式,PE阵列的同一列中的每个PE负责顶点属性的单个维,而同一行中的每个PE处理单个顶点。输入顶点属性的尺寸变得独立于硬件体系结构,并且可以连续地注入到PE阵列中,而与阵列大小和属性尺寸无关。通过这种方式,处理单元可以处理具有任意尺寸属性的顶点。RER (ring-edge-reduce)阵列同一列中的每个PE连接到环形网络中的邻居,同一列中的每个PE仅与其两个最近的邻居(北, 南)通信。PE将其数据发送到北部邻居,并接收从南部邻居发送的数据以进行汇总。以此方式,PE可以基于环型数据流从边解析的控制信号来选择要聚合的相关顶点。