文章目录 前言一、软件定时器结构体二、软件定时器的工作机制三、创建软件定时器四、启动软件定时器五、软件定时器如何知道什么时候被调用总结 前言 除了有硬件定时器,还有软件定时器,那么这篇文章将带大家学习一下软件定时器是如何工作的,以及分析软件定时器的内部源码。
一、软件定时器结构体 软件定时器的本质其实也是一个结构体,在FreeRTOS中会使用一个结构体来管理软件定时器。
软件定时器结构体:
typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { const char * pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management.
一、I2C 简介 物理连接 I2C总线由时钟线SCL、数据线SDA两根线构成,连接在其上的设备分为主机和从机两种,I2C上的通信全部由主机发起。
I2C设备对总线的输出采用开漏输出结构,即它只有在总线和GND之间的NMOS管,没有总线和VDD之间的PMOS管。输出0时通过开启NMOS管将总线与GND短接;输出1时无法像推挽输出那样开启PMOS管将总线与VDD短接,而是只能通过关闭NMOS从而由外接的上拉电阻将总线拉到高电平。
由于上拉电阻阻值一般比较大(10K欧姆),因此如果此时有其他I2C设备输出0,总线会被拉到低电平。只有当总线上的所有设备都不输出0时,总线才是高电平;只要有一个设备输出0,总线就是低电平,这也就是所谓的“线与”。这是I2C总线应答与多主机通信的基础。 协议格式 0、空闲时总线上所有设备都不驱动总线,即都不开启NMOS管,总线由外部上拉电阻拉到高电平。
1、I2C上的通信全部由主机发起,主机通过发送起始位启动传输,起始位由SCL为高时SDA线上的下降沿产生。
2、起始位后面跟7位地址和1位读写方向指示(0表示主机向从机写入,1表示主机从从机读取),主机发送完这8位后停止驱动总线,总线由外部上拉电阻拉到高电平,被寻址的从机输出0将总线拉低。主机检测到这个低电平,就知道从机可以相应主机请求,可以进行数据传输。
3、数据传输阶段,若R/W=0,则主机发送数据,从机发送响应;若R/W=1,则从机发送数据,主机发送响应,每传输一个字节数据,后面都跟一个响应位。
4、数据传输完成后,主机发送停止位终止传输,终止位由SCL为高时SDA线上的上升沿产生。
5、由于SCL为高时,SDA的上升沿、下降沿均有特殊含义,因此I2C中数据传输时,SDA只在SCL为低时变化,在SCL为高时保持不变。即发送方在SCL为低时改变SDA状态,接收方在SCL上升沿读取SDA状态。
二、SWM341 I2C 接口 功能框图 SWM341 I2C 的核心是一个双向移位寄存器,发送时,数据通过TXDATA寄存器写入移位寄存器,然后按位移除到SDA引脚;接收时,将SDA引脚状态移入移位寄存器,通过RXDATA寄存器读出。
移位寄存器的移位节拍来自内部I2C时钟分频器(主机模式下)或SCL引脚(从机模式下),主机模式下时钟分频器产生的时钟同时输出到SCL引脚,驱动总线上的I2C从机的移位寄存器。
使用示例:读写 EEPROM AT24C024 int main(void)
{
uint32_t i;
uint8_t ack;
SystemInit();
SerialInit();
I2CMstInit();
while(1==1)
{
/*************** EEPROM Write ***************/ ack = I2C_Start(I2C0, (SLV_ADDR << 1) | 0, 1);
if(ack == 0)
{
printf("Slave send NACK for address\r\n");
goto nextloop;
}
ack = I2C_Write(I2C0, MEM_ADDR, 1);
if(ack == 0)
SSML 的语音服务实现基于万维网联合会的语音合成标记语言版本 1.0。 语音服务支持的元素可能与 W3C 标准不同。
每个 SSML 文档是使用 SSML 元素(或标记)创建的。 这些元素用于调整语音、风格、音节、韵律、音量等。
下面是 SSML 文档的基本结构和语法的子集:
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="string"> <mstts:backgroundaudio src="string" volume="string" fadein="string" fadeout="string"/> <voice name="string" effect="string"> <audio src="string"></audio> <bookmark mark="string"/> <break strength="string" time="string" /> <emphasis level="value"></emphasis> <lang xml:lang="string"></lang> <lexicon uri="string"/> <math xmlns="http://www.w3.org/1998/Math/MathML"></math> <mstts:audioduration value="string"/> <mstts:express-as style="string" styledegree="value" role="string"></mstts:express-as> <mstts:silence type="string" value="string"/> <mstts:viseme type="string"/> <p></p> <phoneme alphabet="string" ph="string"></phoneme> <prosody pitch="value" contour="value" range="value" rate="value" volume="value"></prosody> <s></s> <say-as interpret-as="
半导体主要由四个组成部分组成:
集成电路(约占81%),光电器件(约占10%),分立器件(约占6%),传感器(约占3%), 因此通常将半导体和集成电路等价。
目录
公众号
效果图
交叉折线图之间分色填充概念介绍
应用领域
优点
缺点
结论
绘图工具函数
函数输入参数:
使用方法
案例 1
编辑
案例 2
编辑
案例 3
公众号 效果图 交叉折线图之间分色填充概念介绍 交叉折线图之间的分色填充是一种高级数据可视化技巧,它涉及在两条或多条在一定区间内交叉或重叠的折线图之间应用不同的颜色填充。此技术主要用于图形化地表示两组或多组数据之间的比较和对比,特别是它们随时间或其他变量的变化。
应用领域 金融市场分析:展现不同金融工具或指数在时间序列中的表现,突出市场波动或趋势。
生物医学研究:比较不同治疗方法或条件下的生物标志物变化。
环境监测:可视化不同环境因素(如温度、湿度)随时间的变化及其相互作用。
市场调研:对比不同消费群体的购买习惯或品牌偏好随时间的变化。
优点 增强数据解释性:通过颜色差异,使得数据集间的比较更加直观和易于理解。
强调数据动态:特别适用于展现数据随时间或其他变量的动态变化。
视觉吸引力:相比于传统的折线图,颜色填充增加了图表的视觉吸引力,提高了观众的关注度。
缺点 颜色选择的重要性:不当的颜色选择可能导致误解或视觉混淆,特别是在色盲观众中。
数据解读的准确性:过度依赖颜色填充可能会忽视数据的其他重要方面,如统计显著性。
图表复杂性:过多的数据集或颜色可能使图表过于复杂,难以解读。
结论 交叉折线图之间的分色填充通过颜色的视觉对比强化了数据间的差异和关系。正确使用时,它可以有效地传达复杂信息,并帮助观众理解数据动态。然而,为了保持图表的有效性和易读性,需要仔细考虑颜色选择和图表设计。
绘图工具函数 function fillArea(x1, y1, x2, y2, fillColor1, fillColor2, alphaValue) %-------------------------------------------------------------------------- % @Author: 好玩的Matlab && 猪猪 % @公众号:好玩的Matlab % @Created: 09,18,2023 % @Email: 2377389590@qq.com % 尊重劳动成果,转载请备注推文链接和公众号名,严禁商用。 %-------------------------------------------------------------------------- plot(x1,y1,'color','none','HandleVisibility','off'); plot(x2,y2,'color','none','HandleVisibility','off'); % 调用函数 x1 = x1(:); y1 = y1(:); x2 = x2(:); y2 = y2(:); % 查找交点 [xi, yi] = polyxpoly(x1, y1, x2, y2); % 裁剪到共同的 x 轴范围 xRange = [max(min(x1), min(x2)), min(max(x1), max(x2))]; yRange = [min(min(y1), min(y2)), max(max(y1), max(y2))]; %边界交叉点 [xa1,ya1]=polyxpoly(x1, y1,[xRange(1),xRange(1)],yRange); [xb1,yb1]=polyxpoly(x1, y1,[xRange(2),xRange(2)],yRange); [xa2,ya2]=polyxpoly(x2, y2,[xRange(1),xRange(1)],yRange); [xb2,yb2]=polyxpoly(x2, y2,[xRange(2),xRange(2)],yRange); % 交叉点 [x1,y1]=insertData(x1, y1, xi, yi);[x2,y2]=insertData(x2, y2, xi, yi); % 边界点插入 [x1, y1] = insertData(x1, y1, xa1, ya1);[x1, y1] = insertData(x1, y1, xb1, yb1); [x2, y2] = insertData(x2, y2, xa2, ya2);[x2, y2] = insertData(x2, y2, xb2, yb2); % 提取范围数据 xNew1 = x1(x1 >= xRange(1) & x1 <= xRange(2));yNew1 = y1(x1 >= xRange(1) & x1 <= xRange(2)); xNew2 = x2(x2 >= xRange(1) & x2 <= xRange(2));yNew2 = y2(x2 >= xRange(1) & x2 <= xRange(2)); [X1, Y1, X2, Y2] = equaLen(xNew1, yNew1, xNew2, yNew2); disp(char([20844 20247 21495 58 22909 29609 30340 77 97 116 108 97 98])) hold on for i = 1:length(X1) - 1 % 确定填充颜色 if Y1(i) > Y2(i) || (Y1(i) == Y2(i) && Y1(i+1) > Y2(i+1)) color = fillColor1; else color = fillColor2; end % 填充 fill([X1(i) X1(i+1) X1(i+1) X1(i)], [Y1(i) Y1(i+1) Y2(i+1) Y2(i)], .
EasyExcel读取Excel空数据行问题 原因解决写在最后 原因 项目Excel导入使用的EasyExcel工具,为什么会出现空白行的问题呢;在进行Excel导入时都会提前设定一个Excel模版,Excel导入时在Excel模版中设置了单元的样式,但没有给单元格设值。在读取数据时没有判断这一步,所以会出现直接读取到整行数据均为null的情况;
解决 自定义监听器
/* * 模版读取 */ @Slf4j public class DemoReadListener<T> extends AnalysisEventListener<T> { /* * 每一条数据解析都会来调用 */ @Override public void invoke(T data, AnalysisContext context) { //设置忽略空白行参数,ignoreEmptyRow默认true-忽略空的行, //此处设置为false,不忽略,然后根据读取到数据做校验 analysisContext.readworkbookHolder().setIgnoreEmptyRow(false); if (CellDatalypeEnum.EMPTY.name().equals(analysisContext.readSheetHolder().getTempCellData().getType().name())){ return; } else { //数据处理,数据值是否为空,也可以放在此处校验 } } @Override public void doAfterAllAnalysed(AnalysisContext context) { //所有数据解析完成了调用 } } 重启项目,导入原来有问题的Excel表格吧,数据读取是没问题的,也不会有空白行的问题了,如果是要校验一条数据字段是否为空,也是放在invoke中做校验的;
写在最后 可以在实体中绑定Excel模版定义的表头,如果发现导入某些字段为空,也可能是这个问题导致的;
//value值与Excel导入模版中定义保持一致 @ExcelProperty("名称") private String name;
linux start nginx 开启 /usr/sbin/nginx(直接启动)
nginx -s stop 停止
/usr/local/nginx/sbin/nginx -s stop
nginx -s quit 安全停止,保存信息
nginx -s reload 当配置信息修改,需要重新载入这些配置时使用此命令
nginx -s reopen 重新启动
nginx -v 查看Nginx版本
nginx -t 查看配置是否正确
netstat -ntlp 端口情况
windows 1、启动:
start nginx 或 nginx.exe
2、停止:
nginx.exe -s stop 或 nginx.exe -s quit
注:stop是快速停止nginx,可能并不保存相关信息;quit是完整有序的停止nginx,并保存相关信息。
3、重新载入Nginx(重新加载配置文件):
nginx.exe -s reload
在redis安装目录新建 redis.bat
@echo off redis-server.exe 再新建 redis.vbe
set ws=wscript.createobject("wscript.shell") ws.run "redis.bat /start",0 双击 redis.vbe 文件,redis服务就已经在后台安安静静地提供服务了。虽然双击后没有交互响应,但可以在任务管理器中查看
一、配置好你的Jetson Tx2 NX
1、电脑安装Ubuntu虚拟机18.04,切记一定不要用virtualbox!!!因为vmware可以选usb连接。
【玩转Jetson TX2 NX】(一)win10安装VMware14 Workstation Pro创建Ubuntu18.04虚拟环境(详细教程+错误解决)_鲁棒最小二乘支持向量机的博客-CSDN博客2
2、烧录系统(直接分配100g)
SDKmanager登录不进去就选新版本,我用的2.0.0,烧录的jetpack4.6.4
宿主机可以不要勾选安装
可以先烧录系统os,然后将系统转到固态硬盘上面,然后再烧录sdk包,防止原硬盘空间不足,烧sdk包可以不用跳线帽了,直接开机在里面ifconfig找到ip地址就行
【玩转Jetson TX2 NX】(二)TX2 NX刷机+烧录系统和SDK(详细教程+错误解决)_鲁棒最小二乘支持向量机的博客-CSDN博客【玩转Jetson TX2 NX】(三)TX2 NX挂载 M.2 固态硬盘+移动系统(详细教程)-CSDN博客
直接nvcc -v,有了cuda信息就说明安装好了
3、装TensorFlow,找对版本,我用的2.7.0版本,注意轮子是aarch64格式的,离线安装靠谱些
官方教程里面的改pip3操作,不改比较好
官方教程的测试,我是测试没通过过,不知道装好了没
【玩转Jetson TX2 NX】(四)TX2 NX安装TensorFlow GPU(详细教程+错误解决)_tx2 安装tensorflow-CSDN博客
4、装tensorrt,jetson-inference这个库确实是早上和深夜下载比较合适
摄像头物理颠倒没去弄,网上教程用google net去识别一只鸟测试通过了
【玩转Jetson TX2 NX】(五)TX2 NX TensorRT环境搭建及实时图像识别(详细教程+错误解决)_jetson安装tensorrt_鲁棒最小二乘支持向量机的博客-CSDN博客
5、试一下detectnet和YOLOv4
【玩转Jetson TX2 NX】(六)TX2 NX DetectNet+板载摄像头实时检测目标(详细教程)_鲁棒最小二乘支持向量机的博客-CSDN博客
【玩转Jetson TX2 NX】(七)TX2 NX YoLoV4环境搭建+板载摄像头实时目标检测(详细教程+错误解决)_jetson tx2 yolo-CSDN博客
参考着yolov4,使用命令行运行gpu版本的yolov8
6、装vscode和pycharm
vscode属实用不习惯,不支持3.7以下的python,jetpack自带的python是3.6.9
pycharm教程找不到了,最好有了archiconda再用
【玩转Jetson TX2 NX】(八)TX2 NX Visual Studio Code(VSCode)安装(详细教程)_tx2安装vscode-CSDN博客
7、装onnx-tensorrt,也不知道用上了没有,反正是装了
【玩转Jetson TX2 NX】(九)TX2 NX 安装onnx-tensorrt工具(详细教程+错误解决)_jetson安装tensorrt_鲁棒最小二乘支持向量机的博客-CSDN博客8
**单片机设计介绍,基于51单片机的音乐喷泉设计
文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的音乐喷泉设计是一种将音乐和水喷射效果相结合的创意设计。下面是一个简要的设计介绍:
硬件设计:
水泵模块:选择合适的水泵来提供水流动力,用于实现水喷射效果。喷头模块:设计一个喷头系统,可以控制水流的喷射方向和高度,以形成不同的喷射效果。RGB LED模块:选用RGB LED灯模块,用于展示不同颜色的光效,与音乐进行呼应。音频模块:选择一个合适的音频模块,用于播放音乐,可以是可编程的音频芯片或者MP3解码模块。传感器模块:选择一个合适的音频输入传感器,用于实时获取音乐的节拍和强弱等信息。 软件设计:
系统初始化:在单片机启动时,进行必要的初始化,包括引脚配置、定时器设置等。音频处理:通过音频模块实时读取音乐信号,并进行处理,获取音乐的节拍和强弱等信息。传感器数据处理:通过音频输入传感器获取音乐的节拍信息,将其与音频处理得到的信息进行关联。控制算法:根据传感器数据和音频处理结果,设计一个控制算法,确定水喷射和灯光变化的时机和强度。控制水泵和LED:根据控制算法的结果,控制水泵和LED模块,实现喷水和灯光的变化效果。喷泉节奏与音乐同步:将喷泉的喷水节奏和LED的灯光变化与音乐的节奏同步,使得整个系统能够与音乐呼应。 以上只是一个简单的基于51单片机的音乐喷泉设计的介绍,实际的设计还需要根据具体需求进行详细的设计和实现,包括电路连接、传感器校准、控制算法优化等。同时,对于水泵和喷头的设计,需要考虑水流控制、喷射距离和角度等因素。
二、功能设计 本设计由STC89C52单片机电路+水泵控制电路+ADC0832采样电路+LM386功率放大器电路+LED灯显示电路+电源电路组成。
1、本设计可以播放电脑、手机、MP3里面的音乐。
2、通过ADC0832芯片对音频信号的采集,转换为数字信号给单片机,然后PWM脉冲宽度调制控制水泵水柱对的高低。
3、同事有流水灯表示音乐大小情况。
设计思路 设计思路
文献研究法:搜集整理相关单片机系统相关研究资料,认真阅读文献,为研究做准备;
调查研究法:通过调查、分析、具体试用等方法,发现单片机系统的现状、存在问题和解决办法;
比较分析法:比较不同系统的具体原理,以及同一类传感器性能的区别,分析系统的研究现状与发展前景;
软硬件设计法:通过软硬件设计实现具体硬件实物,最后测试各项功能是否满足要求。
三、 软件设计 本系统原理图设计采用Altium Designer19,具体如图。在本科单片机设计中,设计电路使用的软件一般是Altium Designer或proteus,由于Altium Designer功能强大,可以设计硬件电路的原理图、PCB图,且界面简单,易操作,上手快。Altium Designer19是一款专业的整的端到端电子印刷电路板设计环境,用于电子印刷电路板设计。它结合了原理图设计、PCB设计、多种管理及仿真技术,能够很好的满足本次设计需求。
————————————————
仿真实现
本设计利用protues8.7软件实现仿真设计,具体如图。
Protues也是在单片机仿真设计中常用的设计软件之一,通过设计出硬件电路图,及写入驱动程序,就能在不实现硬件的情况进行电路调试。另外,protues还能实现PCB的设计,在仿真中也可以与KEIL实现联调,便于程序的调试,且支持多种平台,使用简单便捷。
————————————————
原理图 五、 程序 本设计利用KEIL5软件实现程序设计,具体如图。作为本科期间学习的第一门编程语言,C语言是我们最熟悉的编程语言之一。当然,由于其功能强大,C语言是当前世界上使用最广泛、最受欢迎的编程语言。在单片机设计中,C语言已经逐步完全取代汇编语言,因为相比于汇编语言,C语言编译与运行、调试十分方便,且可移植性高,可读性好,便于烧录与写入硬件系统,因此C语言被广泛应用在单片机设计中。keil软件由于其兼容单片机的设计,能够实现快速调试,并生成烧录文件,被广泛应用于C语言的编写和单片机的设计。
————————————————
六、 文章目录 目 录
摘 要 I
Abstract II
引 言 1
1 控制系统设计 2
1.1 主控系统方案设计 2
1.2 传感器方案设计 3
1.3 系统工作原理 5
计算机视觉算法——基于Transformer的目标检测(DN DETR / DINO) 计算机视觉算法——基于Transformer的目标检测(DN DETR / DINO)1. DN DETR1.1 Stablize Hungarian Matching1.2 Denoising1.3 Attention Mask 2. DINO2.1 Contrastive Denoising3.2 Mix Query3.3 Look Forward Twice 3. Sparse DETR3.1 Encoder Token Sparsification3.2 Scoring Network3.3 Encoder Auxiliary Loss and Top-K Decoder Queries 4. Lite DETR4.1 Motivation and Analysis4.2 Interleaved Update4.3 Key-aware Deformable Attention 计算机视觉算法——基于Transformer的目标检测(DN DETR / DINO) 自DETR年提出来之后,许多Paper针对DETR中收敛速度慢、检测效果差等问题进行了针对性优化,在
计算机视觉算法——基于Transformer的目标检测(DETR / Deformable DETR / Dynamic DETR / DETR 3D)
计算机视觉算法——基于Transformer的目标检测(Efficient DETR / Anchor DETR / Conditional DETR / DAB DETR)
目录
摘要
Abstract
文献阅读:深度学习递归神经网络预测水体浊度的鲁棒性研究
存在的问题
提出的方法
研究使用的方法
神经网络(NN)
递归神经网络(RNN1)
递归神经网络(RNN2)
研究分析的步骤
研究实验
数据集
评估指标
实验目的
实验内容
实验结果
研究结论
SVM-解决线性不可分问题
思路一:引入松弛变量和惩罚因子
思路二:低维映射到高维
如何划分非线性数据
核函数
摘要 本周阅读的文献是关于递归神经网络预测水体浊度的鲁棒性研究,该文献研究的重点是使用鲁棒深度学习模型来分析时间序列数据,以预测库区浊度的水质。本文的新颖之处在于使用了两个神经网络系统,一个人工神经网络系统用于常规无雨时间,RNN2系统用于子程序即当考虑下雨时间。利用光学波段构建回归函数监测水体浊度,然后利用递归神经网络(RNN2)模型对时间序列浊度数据进行分析。根据使用数据、预测水平和训练时间的准确性来比较所选模型的准确性。在上周学习了SVM解决线性可分问题,然而SVM也可以用来解决线性不可分问题,通过引入松弛变量和惩罚因子或者利用核函数将低维映射到高维两种思路,可以将线性不可分问题转化为线性可分问题,从而得出划分的超平面。
Abstract The literature read this week is about the robustness research of recursive neural networks for predicting water turbidity. The focus of this literature research is to use robust deep learning models to analyze time series data to predict the water quality of reservoir turbidity.
分析:
在主函数 main 中,程序首先定义一个字符变量 c,以及四个整型变量 letters、k、s 和 o,并初始化它们的值为 0。然后使用 printf 函数输出提示信息,让用户输入一行字符。
接下来,程序通过 while 循环结构和 getchar 函数,从标准输入中读取用户输入的字符,并根据其类型进行统计操作。具体来说,如果是英文字母,就将字母数 letters 加 1;如果是空格符,就将空格数 k 加 1;如果是数字,就将数字数 s 加 1;否则,就将其他字符数 o 加 1。
最后,程序使用 printf 函数输出统计结果,包括字母数、空格数、数字数和其他字符数。
代码:
#include<stdio.h> int main() { char c; int letters=0,k=0,s=0,o=0; printf("请输入一行字符:\n"); while((c=getchar())!='\n') { if(c>='a'&&c<='z'||c>='A'&&c<='Z') letters++; else if(c==' ') k++; else if(c>='0'&& c<='9') s++; else o++; } printf("字母数:%d\n空格数:%d\n数字数:%d\n其他字符数:%d\n",letters,k,s,o); return 0; } 运行结果:
介绍 Prometheus 支持 4 种 指标类型,分别是 Counter、Gauge、Histogram 和 Summary。
Counter 指标类型,指标值是只能递增,不能递减的数值。需要注意的是,当 Prometheus server 重启时,指标值会被重置为 0。该指标类型可用于统计接口的请求数、错误数等使用场景。
Gauge 指标类型,指标值是可增可减的数值。该指标类型可用于统计 CPU、内存和硬盘的使用情况,goroutine 的数量等使用场景。
Histogram 指标类型,指标值基于桶分布。开发者可以自定义桶的区间。该指标类型可用于统计接口的延时请求数等使用场景。
Summary 指标类型,与 Histogram 类似,区别是 Histogram 直接统计了不同区间中的指标数值,而 Summary 是基于客户端级别,因此不能统计多个实例的聚合数据。该指标类型可用于预先不知道指标桶划分区间的场景。
使用方式 一般在实际应用场景中,通常一个指标需要对应多条时序数据(Label Name 为维度),此时就需要使用支持标签的指标类型。
Prometheus 有 4 种支持标签的指标类型,分别是 ConterVec、GaugeVec、HistogramVec、SummaryVec。
CounterVec CounterVec 与 Counter 的区别是,它支持 Label,我们可以按照 Lable 维度,将同一个指标的数据按照 Lable 分组统计。例如,同一个 Api 接口的请求数,我们可以定义 Lable (Code、Method),按照状态码和 HTTP 请求方式,分组统计同一个 Api 接口的请求数。
示例代码:
var ( // 标签名 labelNames = []string{"host", "code", "path", "method"} // HttpReqs 实例化 CounterVec HttpReqs *prometheus.
缓存击穿 /** * 缓存击穿:高并发时,当一个key非常热点(热销品),在不停的扛着大并发,当这个key在失效的瞬间,持续的大并发就击穿缓存,直接请求数据库后再缓存数据,导致性能下降 * 解决方案:永不过期 或 加锁排队 或 两者都有 * * @param key 键 * @return {@link String} */ public String cacheBreakdown(String key) { String value = stringRedisTemplate.opsForValue().get(key); if (StringUtils.isNotBlank(value)) { return value; } synchronized (this) { value = stringRedisTemplate.opsForValue().get(key); if (StringUtils.isNotBlank(value)) { return value; } // 从数据库中获取数据 value = selectDb(key); stringRedisTemplate.opsForValue().set(key, value, Duration.ofHours(1L)); } return value; } 缓存雪崩 /** * 缓存雪崩:缓存集中过期,或者缓存服务器宕机,导致大量请求访问数据库,造成数据库瞬间压力过大,宕机 * 解决方案:加锁排队 和 随机失效时间 和 redis集群部署 * * @param key 钥匙 * @return {@link String} */ public String cacheAvalanche(String key) { String value = stringRedisTemplate.
文章目录 前言一、相机标定的基本原理1.1 相机模型与坐标系1.1.1 相机模型1.1.2 坐标系 1.2 相机内参与外参1.2.1 内部参数1.2.2 外部参数 1.3 镜头畸变1.4 透视变换1.5 标定的重要性和应用场景 二、单目视觉2.1 单目视觉的原理2.1.1 单目视觉的原理2.1.2 单目视觉的公式2.1.3 应用领域 2.2 实现单目视觉标定的步骤2.2.1 准备标定板2.2.2 捕获标定图像2.2.3 提取角点2.2.4 计算内参和畸变参数 2.3 单目视觉相机标定实战 三、双目视觉3.1 双目视觉的原理与应用3.1.1 双目视觉的原理3.1.2 双目视觉的应用 3.2 双目视觉与单目视觉的对比3.3 实现双目视觉标定的步骤3.4 OpenCV中的相关函数与方法 总结 前言 在当今科技日益发展的时代,计算机视觉作为人工智能的重要分支,已经深入到我们生活的各个领域。在这个广阔的领域中,相机标定是一个基础且关键的步骤,它直接影响到视觉系统的精度和效能。尤其是在单目视觉和双目视觉的应用中,准确的相机标定成为了实现高效和精确视觉感知的前提。
单目视觉(Monocular Vision)和双目视觉(Binocular Vision)是计算机视觉中两种最基本的视觉形式。单目视觉指的是只使用一个相机进行图像捕捉和处理,它是最常见的视觉形式,广泛应用于各种智能设备和监控系统中。单目视觉系统的主要挑战在于它无法直接从图像中获取深度信息,这就要求我们通过算法和模型来推断出场景的三维结构。而双目视觉则是模拟人类的双眼视觉机制,通过两个相机从略微不同的角度捕捉图像,从而能够直接计算出图像中对象的深度信息。这种方式使得双目视觉系统在处理三维空间信息时更加精确和高效,尤其在机器人导航、自动驾驶汽车等领域展现出巨大的潜力。
本文将简要介绍单目视觉和双目视觉相机标定的基本原理和实践方法。
一、相机标定的基本原理 相机标定是计算机视觉领域中一个极为重要的过程,它涉及到了理解和校正相机捕捉图像的方式。这个过程对于提高图像处理的精度和效果至关重要,尤其是在单目视觉和双目视觉的应用中。
1.1 相机模型与坐标系 在深入相机标定的实践之前,了解其背后的原理是必要的。相机模型和坐标系构成了相机标定的理论基础。
1.1.1 相机模型 相机模型用于描述三维世界中的点是如何映射到二维图像上的。其中,最常见的模型是针孔相机模型(Pinhole Camera Model)。
在针孔相机模型中,一个三维空间中的点 P ( x , y , z ) P(x, y, z) P(x,y,z) 通过一个投影过程被映射到二维图像平面上的点 p ( u , v ) p(u, v) p(u,v)。这个映射过程通常涉及到几何和线性代数中的一些基本概念。
一、引言 此文是之前贪心害人篇的续文,为啥写此文呢,因为最接近老做些奇怪的连续梦,乱糟糟的,后文中再说做了啥梦,哈哈。
当今时代的诱惑实在太多了,而因贪念所感召的祸事,越来越多。每天一看百度热搜,几乎全是各种因果报应实例,小到普通人小便小宜小报小应,大到几十亿,上千亿资本市场韭菜收割。这个时代究竟意味着什么?
经济社会巨大资本利益诱惑下,如何能洁身自好?
二、反思 真的,值得我们这代人反思。老实话,我是一个贪心很重的人,因为命里福报不大,庆幸命运没有给我安排大的名利考验,不然 … 哈哈。我只是经常辗转在,今天打豆浆时,大婶给我多加了点豆浆,结果暗自窃喜半天的级别。哈哈。
虽然贪不到啥大钱。但对生活中小便小宜的贪念还是不免的。面对各种商家的所谓让利促销优惠券。还有众多网络免费资源下载。还是不免要看看,点个收藏啥的。学了佛法,才明白,没有小贪,何来大贪?!哈哈。
年纪大了,吃亏多了,涨了点定力了,觉得自己不贪钱了吧,嘿,又开始贪知识。虽然看起来,此病在大多人看来算是优点,美其名曰"好学",但其实也还是贪!贪心在在个时代得到了最大的满足与挑战。
回看自己过去收集的大量教程,多年后才发现,根本没时间看。可能前世是个爱书人。贪书也成了自己的习气。上学时也偷过书,唉,虽然我不是孔乙己,惭愧。但知识多了也是灾祸,因为知事多时烦恼多,反而没了智慧,淹没在信息的海洋里,不知何为标准了。
这在佛家叫所知障。为啥自己的各种歪梦那么多,都是所知障的积累。如果不放下对知识的贪执,永远开不了智慧。
智慧原是每个人的本能,无需学习,本自具足。就像刚出生的婴儿,能快速接受各种新事物一样,能理解很多复杂的问题。正所谓无知才能无所不知。这个道理真的好深…
三、答案 所以,中国传统的学习方式是一门深入,开智慧后才广学多闻。接受事物的效率会几何指数级提升。
就像禅宗的开悟后起修。不开悟前尽量不接触过多事物。哈哈,这种学习方式,在西方教育体系的当下教育中,几乎很少见到了。现在的孩子都讲究广学多闻,学的越多越好。最后一团乱麻,脑子都学乱掉了。心浮气躁,看似很机灵,却没有智慧定力。很容易犯错误。更不懂得与人协作,如何相处。哈哈。
最近,还常做些连续梦,梦见自己前几次梦里借的书还没还。虽然在现实生活里,工作后就没借过书了。但梦却照做不误。真实神了!看来是梦在提醒我,不可以贪知识,哈哈,潜意识一直在梦里给我出考题,并提醒我潜在的毛病习气,提示我得改啊。十分感恩。
你经常梦到的东西就是你最在意最放不下的东西。如果,其中有不善的行为习惯,大家就要特别警惕了,那是在提醒你改正。阿弥陀佛。
佛家言,贪爱不重不堕娑婆。我们这个娑婆世界,就是因为各种爱贪所生的众业世界。一生的经历,所有的人事物。无量无边的爱缘,不管你贪爱什么,都像无数隐形链条一样,捆绑着自心,终不自在。最终在无尽轮回中打转转。
四、结论 在科技知识爆炸时代,对于从事科技行业的朋友来说,一定要保持绝对的人间清醒。对于知识的渴求,不可贪多嚼不烂。更要学会用“放下”的心态来面对职业变迁。因为世间本来无常。科技也如是,科技越发达,无常来的更猛烈,更快速,科技是第一生产力,生产力的加速也会加速无常的来临。对于无常我们要有正常的理解,无常即使正常,真常只在自心。
当人临终时,才明白,看似繁花似锦的五彩人生,也不过如我天天所做连续梦。记住《金刚经》对我们的忠告“凡所有相,皆是虚妄”,心能转境,则同如来,得大自在。南无阿弥陀佛。
如何不被物转? 口诀如下,与君共勉:
心不动,则转物,佛心不动,境随心转,心随物动,苦海无边。
不控制占有,则自在逍遥。
📌大前端入门到精通 专栏正在持续更新中,案例的原理图解析、各种模块分析💖这里都有哦,同时也欢迎大家订阅专栏,获取更多详细信息哦✊✊✊
✨个人主页:零小唬的博客主页
🥂欢迎大家 👍点赞 📨评论 🔔收藏
✨作者简介:20级计算机专业学生一枚,来自宁夏,可能会去做大前端,目前还在努力学习并记录博客中🧸
🎀本系列专栏: 大前端入门到精通
💕希望本文对你在学习前端的过程中有所帮助,如有不足请指正一起学习,一起进步🥇
⛪座右铭:只要你还愿意努力,世界一定会给你惊喜
首先,我们都应该知道在vue中可以自动执行的函数叫做钩子函数。
生命周期钩子函数
1、定义:vue实例从创建到销毁的过程中被自动执行的函数
2、书写位置:与 data methods watch computed directives 同级的位置
3、作用:给程序提供一个自动执行逻辑的场所
4、4大阶段8大钩子:
实例创建前后:
beforeCreate(数据的观测与事件的初始化 属性的创建还没有进行)created(此时vue实例已经创建完毕 所以数据的观测属性方法等内容都已经创建完毕(el属性还没有挂载)) 模板渲染前后:
beforeMount(页面挂载前调用,在此阶段页面还没有进行渲染与模板的编译,程序在此时会把数据绑定到页面上,但是页面并没有显示)mounted(页面已经渲染出来了,html的内容会在dom中进行加载展示) 数据更新前后:
beforeUpdate(在此时数据会不停的在dom中进行修改)updated(把修改之后的dom内容已经在页面成功的展示了) 实例销毁前后:
beforeDestory(此时vue实例还能用)destoryed(什么都没有了,vue实例等内容都没了) 5、生命周期第一次执行那些(页面第一次加载触发哪些)
实例创建之前-----beforeCreate实例创建之后-----created模板渲染之前-----beforeMount模板渲染之后-----mounted 6、dom在那个阶段渲染完毕
模板渲染之后-----mounted 自定义指令的钩子函数
1、常见的自定义指令的钩子函数:
bind 指令绑定到元素之上的时候执行 但是只执行一次unbind 指令被移除的时候执行 只执行一次update 所有组件节点更新的时候执行调用componentUpdate 指令所在节点以及所有的子节点都更新完成的时候调用inserted 绑定指令的元素在页面展示的时候调用(常用) 2、全局自定义指令–directive
Vue.directive("自定义指令名字",{ 自定义指令钩子函数(el你绑定自定义指令的dom){ 你的逻辑 } }) 3、局部自定义指令–directives
directives:{ 自定义指令的名字:{ 自定义指令的钩子函数(el代表的就是指定放在那个dom上形参就是谁){ 你的逻辑 inserted(el){ el.focus() } } }, 自定义指令的名字2:{ }, } 路由的钩子函数
1、路由钩子(路由守卫/导航守卫/路由卫士)
📌大前端入门到精通 专栏正在持续更新中,案例的原理图解析、各种模块分析💖这里都有哦,同时也欢迎大家订阅专栏,获取更多详细信息哦✊✊✊
✨个人主页:零小唬的博客主页
🥂欢迎大家 👍点赞 📨评论 🔔收藏
✨作者简介:20级计算机专业学生一枚,来自宁夏,可能会去做大前端,目前还在努力学习并记录博客中🧸
🎀本系列专栏: 大前端入门到精通
💕希望本文对你在学习前端的过程中有所帮助,如有不足请指正一起学习,一起进步🥇
⛪座右铭:只要你还愿意努力,世界一定会给你惊喜
在Vue Router中,声明式导航和编程式导航是两种不同的方式来进行路由导航。
声明式导航(标签的方式)
声明式导航是通过在模板中使用<router-link>标签来生成链接,实现页面之间的跳转(主要是通过to属性来完成的)。使用<router-link>标签可以根据指定的路由配置生成相应的链接,点击链接时,Vue Router会自动处理导航过程,并更新页面的内容。
示例代码:
<router-link to="/home">Home</router-link> 编程式导航(js的方式) 编程式导航是通过JavaScript代码来实现路由的跳转。使用$router.push()方法可以在代码中进行导航操作,可以是页面跳转、重定向等。
示例代码:
// 在某个事件触发时进行导航 methods: { goToHome() { this.$router.push('/home'); } } 总结:
声明式导航更适合在模板中使用,可以直观地定义链接和路由之间的关系
编程式导航更适合在JavaScript代码中使用,可以根据业务逻辑进行灵活的导航操作
拓展:
this.$router.replace(’/替换路径’) replace是替换 跳转之后不能回退
this.$router.go()正数前进 负数后退
🎉记录是为了不停的思考,创作更是为了更好的思考,有人说过:2023年以后的中国市场将永远属于长期主义者,如果你觉得对您有帮助,欢迎一起交流学习,本人也是一名很菜的20级学生,编程界的小白,一起加油变优秀啦!
文章目录 前言一、什么是任务通知二、任务通知和队列,信号量的区别三、任务通知的优点和缺点1.优点2.缺点 四、任务状态和通知值五、任务通知相关的函数发出通知取出通知 六、任务通知具体使用1.实现轻量级信号量二进制信号量计数型信号量 2.实现轻量级队列 总结 前言 本篇文章将带大家学习任务通知的概念和使用方法。
一、什么是任务通知 FreeRTOS中的任务通知(Task Notification)是一种轻量级的同步机制,允许一个任务通知另一个任务已发生的事件或条件。这对于多任务系统中的协作和同步非常有用。以下是有关FreeRTOS任务通知的详细讲解:
任务通知的作用:
任务通知的主要作用是允许一个任务通知其他任务已发生的事件,而无需使用更重的互斥锁或信号量。这可以用于线程间的通信和同步,以及处理任务之间的依赖关系。
通知值(Notification Value):
任务通知包括一个32位的通知值,用于传递信息。通知值可以是整数或位掩码,具体的含义由应用程序自行定义。任务可以等待特定的通知值或位掩码,以便在通知发生时采取相应的行动。
二、任务通知和队列,信号量的区别 任务通知、队列和信号量是FreeRTOS中用于任务间通信和同步的不同机制,它们有不同的特点和适用场景:
1.任务通知(Task Notification):
用途:任务通知主要用于任务之间的事件通知和同步,一个任务向其他任务发送通知,以表明某些事件已发生。
特点:轻量级、高效,通常用于一对一或一对多的任务通信。
通信方式:通知是无数据的,只包含一个32位的通知值,任务可以等待特定的通知值。
适用场景:适用于任务之间的事件通知、依赖关系、同步等情况,以及需要高效且快速的通信。
使用任务通知时发送方可以直接将发送信息给接收方,不需要通过中间的结构体对象(信号量,队列结构体)。
2.队列(Queue):
用途:队列用于任务之间的数据传递,允许一个任务发送数据给另一个任务。
特点:队列是有缓冲区的,可以传输多个数据元素,支持FIFO(先进先出)顺序。
通信方式:队列是带数据的通信机制,任务可以发送和接收数据。
适用场景:适用于需要任务之间传递数据的情况,如生产者-消费者问题、数据采集等。
3.信号量(Semaphore):
用途:信号量用于控制对共享资源的访问,允许任务对资源的使用进行同步和互斥。
特点:信号量通常用于资源保护和互斥访问,可以是二进制信号量(互斥锁)或计数信号量(资源计数)。
通信方式:信号量通常用于任务之间互斥,以确保只有一个任务可以访问共享资源。
适用场景:适用于共享资源的访问控制、互斥操作等情况,如保护共享内存、硬件设备等。
使用队列,信号量时都需要创建出通信对象结构体,通过这个结构体进行通信。
总的来说,任务通知适用于事件通知和轻量级的同步,队列适用于任务之间的数据传递,而信号量适用于资源访问的同步和互斥。在选择合适的通信和同步机制时,应根据具体需求和任务之间的关系来决定使用哪种机制。有时,这些机制也可以结合使用,以满足更复杂的任务间通信和同步需求。
三、任务通知的优点和缺点 1.优点 1.轻量级和高效: 任务通知是一种轻量级的通信机制,它不需要大量的内存和处理时间来维护,因此非常高效。
2.适用于一对多通信: 任务通知适用于一对多的任务通信,一个任务可以通知多个等待通知的任务,这在某些场景下非常有用。
3.实时性强: 任务通知可以提供较低的延迟,因为一旦通知被发送,接收通知的任务可以立即响应。
4.支持不同类型的通知: 任务通知可以发送不同类型的通知,任务可以等待特定的通知类型。
5.无需额外的资源: 与消息队列等机制不同,任务通知不需要为数据缓冲区分配额外的内存,因此它更节省资源。
2.缺点 1.无数据传递: 任务通知本身不支持数据传递,只能传递一个32位的通知值。如果需要传递数据,你可能需要结合其他机制来实现。
2.适用性有限: 任务通知更适用于简单的事件通知和同步需求,对于复杂的数据交换和同步需求,可能需要使用其他机制,如消息队列或信号量。
3.不适用于多生产者-多消费者问题: 任务通知通常不适合解决多生产者和多消费者问题,因为它不提供数据缓冲区来处理多个生产者和消费者之间的数据共享。
4.不适合长期阻塞: 任务通知通常用于短期同步,如果任务需要长期等待,其他机制如消息队列可能更合适。
总的来说,任务通知是一种非常高效的任务间通信机制,适用于简单的事件通知和同步需求,但对于复杂的数据传递和同步问题,可能需要结合其他FreeRTOS机制来实现。选择合适的通信机制应根据具体的应用需求来决定。
四、任务状态和通知值 每个任务都有一个结构体: TCB(Task Control Block),里面有2个成员。
一个是uint8 t类型,用来表示通知状态。
volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; ucNotifyState[] 数组:
如题 在使用repo 拉取瑞芯微提供的sdk 时,由于Ubuntu 版本不同,导致 执行repo sync 更新代码时报错:ModuleNotFoundError: No module named 'formatter'。
原因就是:formatter已经在python3.4标记成废弃接口,在python3.10已经正式删除,并且其依赖的cStringIO也已经删除。因此就算你按照网上教程添加这个模块也会出现各种各样的错误。
解决方法 其实Google已经提供了解决方法:
help: switch from formatter module to textwrap (303282) · Gerrit Code Review (googlesource.com) 按照提交修改
subcmds/help.py 就可以解决这个问题了。
注意:不要修改python版本
最后“祝你成功!”
文章目录 OAuth2.0 实现单点登录一、四种授权模式二、搭建验证服务器三、接口工具测试🍀3.1 客户端模式 (Client Credentials)🍀3.2 密码模式 (Resource Owner Password Credentials)🍀3.3 隐式授权模式 (Implicit Grant)🍀3.4 授权码模式 (Authrization Code)🍀3.5 令牌刷新 四、基于 @EnableOAuth2Sso 实现🍇4.1 微服务实现单点登录🍇4.2 SESSION 不同步问题 五、基于 @EnableResourceServer 实现 🚩🍬5.1 资源服务器🍬5.2 客户端访问🍬5.3 解决远程调用 六、使用 JWT 存储 Token🍒6.1 验证服务器🍒6.2 资源服务器🍒6.3 令牌中继 (远程调用) 总结 提示:以下是本篇文章正文内容,SpringCloud 系列学习将会持续更新 OAuth2.0 实现单点登录 注意: 第一次接触可能会比较难,不太好理解,需要多实践和观察。
前面我们虽然使用了统一存储来解决 Session 共享问题,但是我们发现就算实现了 Session 共享,依然存在一些问题,由于我们每个服务都有自己的验证模块,实际上整个系统是存在冗余功能的、同时还有我们上面出现的问题,那么能否实现只在一个服务进行登录,就可以访问其他的服务呢?
实际上之前的登录模式称为多点登录,而我们希望的是实现单点登陆,因此,我们得找一个更好的解决方案。
这里我们首先需要了解一种全新的登录方式:OAuth 2.0。我们经常看到一些网站支持第三方登录,比如淘宝、咸鱼我们就可以使用支付宝进行登录,腾讯游戏可以用QQ或是微信登陆,以及微信小程序都可以直接使用微信进行登录。我们知道它们并不是属于同一个系统,比如淘宝和咸鱼都不属于支付宝这个应用,但是由于需要获取支付宝的用户信息,这时我们就需要使用 OAuth2.0 来实现第三方授权,基于第三方应用访问用户信息的权限(本质上就是给别人调用自己服务接口的权限),那么它是如何实现的呢?
一、四种授权模式 我们还是从理论开始讲解,OAuth 2.0一共有四种授权模式:
客户端模式(Client Credentials)
这是最简单的一种模式,我们可以直接向验证服务器请求一个 Token(这里可能有些小伙伴对Token的概念不是很熟悉,Token 相当于是一个令牌,我们需要在验证服务器 (User Account And Authentication) 服务拿到令牌之后,才能去访问资源,比如用户信息、借阅信息等,这样资源服务器才能知道我们是谁以及是否成功登录了)
题目:根据 'buy_quantity' 列进行排名,相同值分配相同的最低排名。
import pandas as pd # 创建一个示例 DataFrame data = {'item_id': [1, 2, 3, 4, 5, 6, 7], 'buy_quantity': [1, 2, 2, 3, 3, 4, 5]} df = pd.DataFrame(data) # 使用 rank() 函数为 'buy_quantity' 列进行排名,相同值分配相同的最低排名 df['popular_逆序'] = df['buy_quantity'].rank(ascending=False, method='min').astype(int) df['popular_正序'] = df['buy_quantity'].rank(ascending=True, method='min').astype(int) # 打印结果 print(df) 输出:
详解重排重绘 前言页面渲染页面渲染 重排重绘重排重绘哪个更耗时间避免重排重绘发生重排重绘实例 前言 本文主要讲解在页面加载成功后可能因为页面中DOM元素样式或布局被修改从而引发的重排重绘进行一个讲解,那么好,本文正式开始.
页面渲染 因为重排重绘这两个概念其实是基于页面渲染这个层面进行一个拓展和延申,那么我们在讲解重排重绘前,先了解以下页面是如何渲染的,这里不对URL、DNS解析、三次握手四次挥手做深入展开,只针对渲染做讲解。
页面渲染 解析HTML,并把解析到的HTML渲染到DOM树,包括元素和布局都解析上去。解析CSS,就是将CSS解析到CSSOM(规则)树。将HTML树和CSS树构建成一个render(呈现)树。布局:根据render树上各个DOM元素上的位置,在页面上进行对应的布局。绘制:遍历render树进行页面元素的进一步的绘制。 那么了解这些,接下来讲解重排重绘的概念以及影响就方便很多了。
重排 概念:页面布局发生影响,比如某个在页面上已经呈现且在DOM树中的元素,被删除了,同时DOM树也没有这个节点了,那么就会进行重排操作。
重绘 概念:页面样式发生影响,比如某个元素的颜色发生变化了,这时候浏览器就会自动进行重绘的操作。
重排重绘哪个更耗时间 重排要比重绘更耗时间,因为在页面渲染模块我们发现,布局是要比绘制更耗时间,因为重排需要涉及到更多的关于遍历DOM树深度等的计算操作,而重绘省去了布局和分层阶段,所以重绘的效率更高
避免重排重绘 当我们频繁的去让页面处在一个动态的状态下,那么就会导致不断的去自动发生重排重绘的操作,那么就会对性能造成影响,所以在日常开发中,应该尽量避免重排重绘操作的出现。
发生重排重绘实例 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> div{ width:100px; height:100px; border:1px solid gray; } </style> </head> <body> <div id="chongpai"></div><br> <button onclick="btn1()">点击重排</button> <div id="chonghui"></div><br> <button onclick="btn2()">点击重绘</button> <script> let cp=document.getElementById('chongpai') let ch=document.getElementById('chonghui') function btn1(){ cp.style.display="none" } function btn2(){ ch.style.backgroundColor='red' } </script> </body> </html> 默认图:
点击重排按钮,调用重排:
在上述按钮中,我们创建了一个方法,这个方法控制div元素,让上面div元素的display为none,同时displaynone就是把渲染树上的这个div进行去除,那么就会导致重排效果出现。
点击重绘:
点击重绘后我们发现,颜色发生改变,那么如果样式发生变化时,就会引起重绘。
参考教程:[10-1] DS1302实时时钟_哔哩哔哩_bilibili
1、DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片,它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。
2、RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片
3、开发板上的DS1302时钟模块:
引脚名
作用
引脚名
作用
VCC2
主电源
CE
芯片使能
VCC1
备用电池
IO
数据输入/输出
GND
电源地
SLCK
串行时钟
X1、X2
32.768kHz晶振
(提供计数脉冲)
注:在单片机断电后,备用电池启动,时钟会继续计时,直到下次重启单片机时备用电池休息(单片机通电时备用电池充电,时钟由VCC2供电;开发板貌似没有提供备用电池,只是提供了这么一个引脚,备用电池需要自己安装)。
4、内部结构框图:X1、X2提供计数脉冲,实时时钟负责记录时间数据,当CE处于高电平时,实时时钟中的时间数据可以和移位寄存器的数据发生交互(读/写),这个过程和74HC595类似,这里不再赘述;命令控制逻辑用来解释命令字,然后执行相应操作,这个命令字在下面马上就有解释。
5、相关寄存器与命令字:
(1)下面九个寄存器是RTC相关的寄存器(实时时钟下的寄存器):WP置为1,前7个寄存器打开写保护,里面的数据只可读不可改;最后一个寄存器与充电相关,目前可以不予理会;前7个寄存器负责记录年月日时分秒以及星期几(采用的是BCD码,个位和十位分别记录),CH置为1的话,时钟会暂停计时。
(2)下图所示的是地址/命令字节,第7位固定为1,第6位置为0可操作时钟(操作RAM则置为1),第5位到第1位则是寄存器地址,第0位如果置为0则进行写操作(如果置为1则进行读操作)。这个命令字,其实就是上图中第一列和第二列,比如要对秒寄存器进行读操作,则命令字为0x81。
6、时序:
(1)CE为高电平时才能进行读/写操作。
(2)SCLK提供脉冲,每一个上升沿写入一位数据,每一个下降沿读出一位数据。
(3)CE置为高电平后,先将8位命令通过I/O写入单片机,单片机根据命令字的解释进行读or写操作,读/写的数据也是通过I/O进行传输,操作完成后CE置为低电平,SCLK也停止提供脉冲。
7、BCD码:BCD码(Binary Coded Decimal),用4位二进制数来表示1位十进制数。
(1)0001 0011表示13,1000 0101表示85,0001 1010不合法,对应在十六进制中的体现:0x13表示13,0x85表示85,0x1A不合法。
(2)BCD码转十进制:DEC=BCD/16*10+BCD%16; (2位BCD)
(3)十进制转BCD码:BCD=DEC/10*16+DEC%10; (2位BCD)
8、利用DS1302时钟显示当前时间:
(1)项目包含的文件:其中需要重写的都会在下面给出,未给出的沿用旧例出现过的即可(本例需要液晶屏模块的代码文件)。
(2)补充需要重写或新添加的代码文件,然后进行编译。
①DS1302.h文件:
#ifndef __DS1302_H__ #define __DS1302_H__ void DS1302_Init(void); void DS1302_WriteByte(unsigned char Command, Data); unsigned char DS1302_ReadByte(unsigned char Command); void DS1302_SetTime(void); void DS1302_ReadTime(void); extern unsigned char DS1302_Time[]; //外部可调用该数组 #endif ②DS1302.
循环神经网络的简洁实现 如何使用深度学习框架的高级API提供的函数更有效地实现相同的语言模型。 我们仍然从读取时光机器数据集开始。
import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2l batch_size, num_steps = 32, 35 train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps) 定义模型 高级API提供了循环神经网络的实现。 我们构造一个具有256个隐藏单元的单隐藏层的循环神经网络层rnn_layer。 事实上,我们还没有讨论多层循环神经网络的意义。 现在仅需要将多层理解为一层循环神经网络的输出被用作下一层循环神经网络的输入就足够了。
num_hiddens = 256 rnn_layer = nn.RNN(len(vocab), num_hiddens) 我们使用张量来初始化隐状态,它的形状是(隐藏层数,批量大小,隐藏单元数)。
state = torch.zeros((1, batch_size, num_hiddens)) state.shape torch.Size([1, 32, 256]) 通过一个隐状态和一个输入,我们就可以用更新后的隐状态计算输出。 需要强调的是,rnn_layer的“输出”(Y)不涉及输出层的计算: 它是指每个时间步的隐状态,这些隐状态可以用作后续输出层的输入。
X = torch.rand(size=(num_steps, batch_size, len(vocab))) Y, state_new = rnn_layer(X, state) Y.shape, state_new.shape (torch.Size([35, 32, 256]), torch.
前端路由hash和history的区别 前言谁的URL有#回车刷新时hash和history变化 谁支持低版本浏览器hash不会重新加载页面谁有历史记录谁需要后台配置hash缺点 前言 本文主要讲解hash和history路由的区别,那么好本文正式开始。
谁的URL有# 路由Hash的地址上有#,而history路由没有#,这也是它俩最直观的区别。
回车刷新时hash和history变化 当我们在url中用回车键进行刷新时,hash会加载对应的页面,而history就会报404的错误。报错404的原因是在history模式中,地址并不是真实存在的,所以会报错404.
谁支持低版本浏览器 Hash路由是支持低版本浏览器的,而history不支持低版本的浏览器。具体点说就是hash能兼容到IE8,而history只能兼容到IE10版本。因为history是HTML5新增的。
hash不会重新加载页面 hash (url中#后面的部分)出现在url中,但不会被包含在http请求中,对后端完全没有影响,因此改变hash不会重新加载页面。而history当改变时候会重新加载页面。
谁有历史记录 history有历史记录,并且可以修改历史记录,因为它在H5中新增了pushstate和replacestate两个方法用于修改历史记录。
谁需要后台配置 history因为不会立刻请求http,所以说它其实是需要后台对它的刷新进行一个配置。而hash不需要。
注:而 Vue / React 应用的是hash的原理。通过不同的路由去调用不同的 函数 / js去生成不同的页面代码。
hash缺点 不利于SEO(搜索引擎优化)由于浏览器需要先加载js再渲染页面,可能导致浏览器加载时间过慢导致白屏问题。
和传统网络安全不同,硬件安全、芯片安全、无线电安全属于网络底层安全的重要细分领域,是网络安全的真正基石,更是国家安全的重要组成部分,“夯实网络底层安全基础,筑牢网络强国安全底座”,是底网安全重要性的另一真实写照。
硬件黑客与硬件安全攻防人员的博弈未来会愈演愈烈,但因其底层敏感性、封闭性、不可见性等特征,相关攻防渗透技术、思路、工具、漏洞成果很少对外公布或透露,同理,类似深入硬件底层的攻防渗透技术、理念、方法在未来大国博弈、军工电子技术安全、硬件安全、芯片安全、工控安全、物联网安全、车联网安全等方面起着重要作用,关键时刻甚至可起“一两拨千斤”之效果,其“杀伤力”和“威胁力”不容忽视。
常言道,“知彼知己,百战不殆”,本次议题将揭开“硬件黑客”神秘面纱,分享硬件安全、芯片安全偏冷门但又极度重要的渗透技术–芯片安全故障注入技术,并将其与芯片内部结构、芯片类别、业务属性、固件安全、CPU指令运行机制强关联,深入“骨髓”洞察底层芯片安全的神秘世界,另外本议题还将分享无线电安全底层扫描渗透技术,通过重放攻击、协议逆向还原、无线电跟踪三种不同技术原理破解、干扰某渗透对象,从反面案例提醒大家:无线安全的重要性和必要性。
下面就让我们来回顾看雪·第七届安全开发者峰会(2023 SDC)上《芯片安全和无线电安全底层渗透技术》的精彩内容。
01
演讲嘉宾
【赵亚平–
湖南底网安全创始人&底网安全实验室负责人】
拥有通信技术中级职称,热爱并高度重视电子技术基础学科和网络底层安全,从电子技术最基础做起,拥有硬件测试/集成/开发、通信链路/协议设计、嵌入式开发、汇编设计等传统IT开发经历。依托传统基础学科的研发应用背景,无缝衔接传统网络安全、物联网安全、车联网安全、工控安全等领域。擅长从网络底层视野深度洞察信息安全本质,尤其是硬件安全、芯片安全、固件安全、通信安全、无线电安全等细分领域。曾在某安全机构、上市公司(2022中国民营企业50强)、国企分别担任车联网安全资深专家、工控物联安全资深专家、汽车&工控信息安全总工等重要岗位。
02
演讲内容
以下为速记全文:
大家好,我是来自湖南底网安全的赵亚平。
接下来咱们把网络安全的视野开始往下沉,因为不同行业的人对于网络的底层安全可能有不同的认知。比方说对于做上位机软件开发的人员来讲,最接近他们的底层可能是各类的 API或者SDK又或者是第三方组件的调用。
比方说对于做操作系统研发的人员而言,最接近他们的底层可能是各类驱动的调用。如果再往下沉,对于做驱动的开发人员来讲,最接近他们的底层可能是里面各类芯片的寄存器的配置以及相关的时序。
如果说再往下沉的话,就进入到我们今天要分享的议题,首先是关于芯片安全的底层的渗透技术——故障注入技术。这里说明一下,因为硬件/芯片底层的渗透技术有很多种,比较典型的像侧信道攻击DPA、无线SPA、电磁/激光注入等。我们今天讨论的重点是故障注入技术。
紧接着再往下讨论的是无线电领域,就是无线电安全底层扫描渗透技术。都是从最底层的视野来看这两个议题。首先我们了解一下相关的技术背景。最开始的就是安全基石,因为底层的安全它其实就是传统网络安全或者是数字安全、硬件安全、芯片安全的真正的基石。
如果说底层安全做得不好,你上层的应用或者你的机制搭建的再完美,你的数据的保密性、完整性、抗抵赖性的算法再先进,你的身份认证再强,一旦底层有缺失的话,你的安全依然得不到保障,依然很容易遭受来自底层的攻击,所以说它是真正的安全基石。
然后它的技术相对的比较封闭,可能平常跟客户沟通过程中做的更多的是关于常规的漏扫和安全检测,但是一旦接触到这种底层的故障注入的话,一般的客户可能不太关心,但是像那些大的企业客户,他们对这个安全则是非常重视。除了从自身的技术理念和它的渗透理念,包括它的渗透工具比较封闭之外,还有一个原因就是它的被测对象也比较封闭,因为我们注入的对象是芯片或硬件,一般其内部细节很难看到,厂商设置了重重阻拦。所以说它相对比较封闭。
同时它也是相对的“去”SaaS云服务化,不像传统的网络安全渗透。如果说有一台电脑连到互联网,在全球任何一个地方可能都会给对方发起攻击,但是像底层芯片安全的这种渗透测试,它是相对的“去”云端,可能跟云端的交集不是特别大(但某些场景还是会有交集),本地化的特征比较多,这也是软件黑客和硬件黑客的主要差异。
然后其测试工具、环境也是相对不太完善,平常我们看到、用到很多的漏扫以及相应的工具可能比较普遍,但是深入到底层的这种故障注入仪,包括后面分享的无线电的扫描渗透仪,可能大家接触的不太多。
再往后随着网络底层安全的这种意识加强,企业高校以及国家其实现在已经开始越来越重视这块了。跟很多客户对接的时候,接触最多的是可能是常规的漏扫、漏洞挖掘、安全渗透检测评估,除此之外,其实已经有不少客户对于这种故障注入类的安全检测渗透,他们已经在开始发力了,发力的方向是从攻防两个维度同时的,如果说渗透的方向为攻击方向的话,他们可能在类似这种攻击武器的渗透方向发力,也有可能是从抗故障注入的防御维度发力。
最后就是硬件黑客和硬件安全攻防人员的博弈,未来必定会愈演愈烈。其实类似的这种故障注入渗透技术以及理念,不仅仅在咱们民用行业的一些作用起得非常大,在未来这种大国博弈,尤其是在军工电子技术里面,它其实也是非常的重要,当然也包括咱们物联网、车联网、工控这一块。
接着开始讨论一下芯片安全的故障注入技术。这里抛砖引玉,借用了8个提问来贯穿我们议题分享的整个过程。
首先是芯片安全的故障注入定义,不同的人他可能有不同的定义,我们的定义是这样的,就是利用特定的装置或者工具向被测对象在合适的时间合适的位置,发出高度可调、可控、可配置的特定的故障注入信号。
因为我们主要描述的是芯片或者是硬件,如果是针对 SQL注入的话,他们的被测对象可能是SQL服务器,我们这里的被测对象包括但不限于芯片,硬件终端或者可能是某一个电路,硬件终端的话它就非常广了,像无人机、智能门锁、手机、机器人以及其他大家能想到的一些物联网的设备,包括什么物联网关、采集器之类的。
发出的故障信号必须是特定的,比方说是毛刺,你这个毛刺如果发出的时间不对的话,对方可能没有任何效果,你发出的参数比方说电压太高或者太低的话,也可能渗透不了什么成果,所以说是特定的故障注入型信号,进而影响其完整性、可用性、保密性的一些渗透测试行为。
然后关于故障注入工具的话,目前行业里边比较多的、最常见的就是专业的硬件故障注入仪,然后像之前风靡一时的特斯拉小线圈(小黑盒),其实也是类似的一种故障注入的工具。
然后再到传统行业EMC的一个测试,比如EFT瞬变、雷击浪涌测试仪,从某种程度上来讲的话,其实也是一种故障注入仪,只不过它跟我们今天要分享的一个维度不太一样,就是我们今天要分享的重点是精准的故障注入而非盲注。
然后再往下就激光电子注入,像最近诺贝尔奖有一个阿秒激光,在未来关于激光的这种注入,对于故障注入或者是侧信道攻击的话,会如虎添翼。
然后再往下关于后面6个问题,我们会逐一讨论,特点比较多,我们就重点挑蓝色的字来讨论一下,首先是0day的高危漏洞,因为我们被测的对象一般都是芯片或者硬件,如果说一旦测出有问题的话,基本上都是非常严重的,要么没测出,一旦测出,其问题非常严重。比如说某一个MCU芯片,如果说被恶意植入了某一段木马,那么一旦测出来的话,这个漏洞其实是非常严重的。
然后封闭性、敏感性、偏冷门,所谓的偏冷门,是说大家可能平常不太关心这一块,或者说他即便意识到这一块,也觉得没必要在这一块大做文章,但是故障注入渗透又是极度的重要,尤其是对于一些敏感基础设施的客户。然后它也是属于侧信道攻击的一个子集。大家可能经常听说过侧信道攻击,其实侧信道攻击严格来讲它是分很多的细分赛道,只不过我们今天讨论的是属于侧信道攻击的一个子集。
另外就是固件安全强关联,精准的故障注入渗透。抛开盲注的概念,因为我们今天重点讨论的是精准,之所以强调精准,是以CPU或者是MCU的固件运行为基准来参考,所以说真正有杀伤力的故障注入,它一定会和被测芯片的固件强关联,或者说和它的指令集运行机制强关联,然后它会严重依赖故障注入的工具,并且人为因素也很大。
比方说同一类被测对象用同样的工具,不同的人测出来的结果可能不太一样。另外它也是属于典型的网络底层的安全领域,对基础技术学科要求也比较高。当然其他网络安全各行各业对基础技术学科要求也都比较高。
另外一个就是它可能会颠覆某些认知,大家可能知道ROM值一般都是只读的,但是在我们渗透领域里面ROM值可能会被改写,这个下面会进一步分析到,接下来我们再讨论一下它的价值,或者说用在那些不怀好意的团队里面,它会给客户造成什么危害?
最开始的就是提供了一种新型的芯片安全0day的漏洞或者是后门的挖掘方式。
像我们刚才提到的,如果说某一个芯片它在某一个地址段里面放了1k的木马,正常的用户他是察觉不到的,但是通过硬件故障注入的渗透措施,如果你故障注入精准到位的话,可能会把它的PC的指针值,或者把它的堆栈值改写,又或者导致内存溢出,会让固件无意中跳转到不明确的地方,一旦那个地方是属于埋藏的木马区间内的话,那么随着它的芯片的外围的一些状态改变,比方说功耗特征或者是串口或者其他的一些接口状态会发生改变——因为他的木马运行肯定会执行一些动作,可能就会把木马给挖掘出来。
然后第二个就是从底层另一维度可以验证固件安全的可靠性,比方说正常情况下if(a == 1),执行开门的一个权限,如果说开发人员安全理念强的话,他在编程的时候会多加一层判断条件,if( a == 1 && b == 2) ,那么在这种固件编程情况下,可以更有效地抗故障注入攻击,所以说它也是从另一维度可以验证固件安全的可靠性。
另外它是让传统的暴力破解,可能不再受CPU的算力、加密算法的复杂性所局限。像我了解到的很多的高校,已经开始在做基于FPGA算法的芯片故障注入脆弱性验证。然后还提供了一种新的非常规的RAM敏感数据堆栈溢出、缓冲区溢出的底层渗透路径。
比方说执行一个内存的拷贝指令,你在拷贝的时候那个长度如果在这个瞬间通过故障注入把它那个值给刷写的话,那么可能就出现内存溢出,后果非常严重。再一个就是对身份认证权限绕过、加解密算法绕过,这个和暴力破解其实有点类同。
最后一个是将渗透的目标从数字信号安全向模拟信号安全蔓延了。大家可能经常讨论的都是一些网络的安全,它其实有一个共同的特征,就是数字安全,然后针对我们今天分享的芯片故障注入,它是真真切切的从数字安全渗透领域蔓延到模拟信号安全领域,也就是说很多的物联设备它会采集模拟信号、各种模拟传感器,然而这种模拟信号对毛刺最敏感,也是最害怕的。AD采集过程中,一旦有毛刺的话,如果无有效的算法、滤波机制规避,很容易对它产生一些不好的影响。
这个是针对故障注入分类定义。
主要有4种方式,首先是按照接触方式分类,这个应该好理解,有线和无线。如果是有线的话,需要把故障注入仪类似的各种探头探针或者测试夹,接到被测的设备里边。如果是无线的话,就类似于这种小黑盒,甚至是类似那种像太阳黑子那种电磁脉冲的武器,都是类同于这种无线的故障注入。
如果按照被测芯片的对象来分的话,它主要分为接口通信类的芯片、逻辑门的控制芯片和运算处理芯片。
蓝色的字体是我们今天重点要讨论的运算处理芯片,包括但不限于CPU、MCU、DSP、FPGA、GPU,然后就是通信接口类芯片,包括CAN总线、RS485、RS232,I2C、SPI这些外围设备接口芯片,按照故障注入信号的属性来区分的话,它分为毛刺、电压故障注入,时钟故障注入,这个时钟其实包含了这种毛刺掉电,所以说严格来讲的话,这之间的划分是有模糊的,也包括协议故障注入。
按照注入目的,它分为盲注和精准的故障注入,我们今天重点要讨论的就是精准,如何实施精准?能够发出可调可控可配置的特定的故障注入信号固然重要,当然这仅仅是盲注的特征,就是我随便将故障注入信号“打”进去,不知道会有什么效果,这也是很多的测试场景用到的,但是知道且何时能精准发出是关键,这个就进入到我们精准的故障注入特征。
这里我用词比较保守,要做到绝对的精准,可能世界上有些大牛的厂商能做到,但我还是不太放心,我们只是说是相对的精准。
要精准实施的话,通过硬件中断加信号联动的高速触发机制,是最适宜做到这种精准的,大家都知道触发中断,一旦是某种中断信号来的话,就让故障注入的条件可以实施。
然后这里面有三个段位,最厉害的段位是能达到这种指令周期级的,我也希望咱们国内有这种厂商能做到,然后一般情况下故障注入它能够精确到函数级,就是能够定位到你执行到某一个函数,把这个故障注入信号打进去,如果说你能在确保函数级别的前提下又能进入到指令集——因为所有的函数它是由指令组成的,但是每一个指令它是由指令周期级来组成的,比方说某一个指令它可能分为三个机器周期。所以说这里面有三个段位,我们的核心目的不是通过故障注入把对方的设备或者芯片打坏、打飞、打复位,最希望的是通过对其关键的业务精准的渗透——类似于篮球比赛,目的不是恶意犯规,而是要确保精准的盖帽。
我们现在正式进入到故障注入的原理,先了解一下 MCU内部的图片。
之所以了解这个图片,对于我们网络底层的从业者而言,有一种习惯,就是尽可能的知其然。通过内部的解剖图片,我们故障渗透人员至少可以得到一个信息,通过这个图片知道大概可能是在哪个位置,对其进行故障注入效果可能会最好,所以这个图片还是有一定的价值的。
这个是早期的ROM内部结构图。
这个图非常关键,下面讨论基准的核心都是围绕它,我们最终的目的——比方说要改变它的ROM值的话,其实它这边的字线和位线最终体现出它的指令机器码,也就是说我们最希望通过精准注入,把它的比特值刷写改变掉,也就是后面有一个专利会提到叫做比特故障。
咱们简单了解一下,这个是EEPROM。
同样它也是通过在芯片里面,通过直接或者间接方式和芯片的内核总线进行挂接,在一系列流水线的运行机制下,触发芯片最终会反应到这个字线或者位线里边。
一、GPU 利用率的定义 本文的 GPU 利用率主要指 GPU 在时间片上的利用率,即通过 nvidia-smi 显示的 GPU-util 这个指标。统计方式为:在采样周期内,GPU 上面有 kernel 执行的时间百分比。
二、GPU 利用率低的本质 常见 GPU 任务运行流程图如下:
如上图所示,GPU 任务会交替的使用 CPU 和 GPU 进行计算,当 CPU 计算成为瓶颈时,就会出现 GPU 等待的问题,GPU 空跑那利用率就低了。那么优化的方向就是缩短一切使用 CPU 计算环节的耗时,减少 CPU 计算对 GPU 的阻塞情况。常见的 CPU 计算操作如下:
数据加载数据预处理模型保存loss 计算评估指标计算日志打印指标上报进度上报 三、常见 GPU 利用率低原因分析 1、数据加载相关 1)存储和计算跨城了,跨城加载数据太慢导致 GPU 利用率低
说明:例如数据存储在“深圳 ceph”,但是 GPU 计算集群在“重庆”,那就涉及跨城使用了,影响很大。
优化:要么迁移数据,要么更换计算资源,确保存储及计算是同城的。
2)存储介质性能太差
说明:不同存储介质读写性能比较:本机 SSD > ceph > cfs-1.5 > hdfs > mdfs
优化:将数据先同步到本机 SSD,然后读本机 SSD 进行训练。本机 SSD 盘为“/dockerdata”,可先将其他介质下的数据同步到此盘下进行测试,排除存储介质的影响。
企业邮箱网页端 点击设置。
点击账户。
在“账户安全”一栏中,先开启安全登录(开启后,客户端登录的话只能用专用密码了)。
开启后就和我下面的截图一样,然后点击生成新密码,他会弹出一个页面。
复制这个页面的的客户端专用密码。(保存好,Outlook客户端里面要用到!)
密码用途可以改名成outlook,如果用的是foxmail就改成foxmail,这样好区分当前密码对应哪个客户端。
最后点击确定。
这样企业邮箱这里就设置完了,上面展示的核心的部分,登录企业邮箱啥的应该不用提示吧,哈哈哈。
Outlook客户端 打开Outlook客户端,点击添加账户。(我使用的是新版Outlook,旧版基本一样)
在弹出来的表单中,填入你要添加的企业邮箱账号。
然后它会提示出现问题,点击高级设置。(应该有直接进入高级设置的方法,不过无所谓了,进去就就行)
选择IMAP
在弹出的表单中,填写配置参数。
IMAP密码和SMTP密码都填写“企业邮箱设置”章节中,复制的“客户端专用密码”。
SMTP用户名就是企业邮箱账号。
IMAP接受服务器,SMTP发送服务器,端口,安全连接类型,按照我截图中的即可。我就是参考的企业微信的设置,如下图:
全部设置完毕后,连续点两次“继续”,就绪出现如下加载界面,加载结束后,就成功添加好账号啦!
在Outlook界面的左侧,可以看见添加成功的账户。
错误详情如下:
building for production...Error processing file: static/css/app.3d5caae7aaba719754d7d5c30b864551.css (node:33011) UnhandledPromiseRejectionWarning: CssSyntaxError: /Users/yt/Documents/BM/sims-plus/sims-website/static/css/app.3d5caae7aaba719754d7d5c30b864551.css:16:12: Unknown word at Input.error (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/input.js:128:16) at Parser.unknownWord (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/parser.js:561:22) at Parser.decl (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/parser.js:233:16) at Parser.other (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/parser.js:131:18) at Parser.parse (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/parser.js:75:16) at parse (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/parse.js:17:12) at new LazyResult (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/lazy-result.js:64:16) at Processor.<anonymous> (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/processor.js:142:12) at Processor.process (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/processor.js:121:23) at Function.creator.process (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/node_modules/postcss/lib/postcss.js:148:43) at OptimizeCssAssetsPlugin.processCss (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/index.js:63:19) at Object.processor (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/optimize-css-assets-webpack-plugin/index.js:29:23) at /Users/yt/Documents/BM/sims-plus/sims-website/node_modules/last-call-webpack-plugin/index.js:139:8 at arrayEach (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/lodash/_arrayEach.js:15:9) at forEach (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/lodash/forEach.js:38:10) at LastCallWebpackPlugin.process (/Users/yt/Documents/BM/sims-plus/sims-website/node_modules/last-call-webpack-plugin/index.js:136:3) (node:33011) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .
Python Flask 全流程全栈项目实战 download:百度网盘
Python Flask全流程全栈项目实战:构建一个在线书店 一、项目概述 我们将运用Python的Flask框架,构建一个功用齐全的在线书店。这个项目将掩盖全栈开发的各个方面,包括后端开发、前端开发、数据库设计和部署等。经过这个项目,你将深化理解如何运用Flask停止全栈开发,并控制相关技艺。
二、环境准备 首先,你需求装置Python和相关的库。倡议运用Python 3.7或更高版本,并装置以下库:
Flask:轻量级的Web框架Flask-SQLAlchemy:用于数据库操作Flask-WTF:用于表单处置Flask-Login:用于用户认证和会话管理 你能够运用pip停止装置:
bash复制代码
pip install flask flask_sqlalchemy flask_wtf flask_login 三、项目构造 在开端编码之前,我们需求规划好项目的构造。以下是一个倡议的项目构造:
lua复制代码
/online_bookstore|-- /static| |-- /css| |-- /js| |-- /images|-- /templates| |-- index.html| |-- login.html| |-- register.html| |-- books.html|-- /app.py|-- /models.py|-- /forms.py|-- /config.py 四、数据库设计 我们运用Flask-SQLAlchemy来操作数据库。首先,在models.py中定义数据模型:
python复制代码
from flask_sqlalchemy import SQLAlchemyfrom flask_login import UserMixinfrom werkzeug.security import generate_password_hash, check_password_hashdb = SQLAlchemy()class User(UserMixin, db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True, nullable=False)password_hash = db.
1、谈谈你对SpringIOC的理解 IOC,也叫控制反转,是Spring用来解耦的一种设计思想,它的做法就是将对象的控制权由程序员手中反转到Spring手中。具体来说呢就是,在没有IOC之前,对象都是程序员在类中主动去创建,需要哪个创建哪个;有了IOC之后,对象会交给Spring容器创建和管理,如果哪个对象中需要其它对象属性,Spring也会自动完成依赖注入。
总之一句话,IOC可以将对象的创建和对象之间依赖关系的维护交给Spring自动完成。
2、Spring中有哪些依赖注入方式 依赖注入指的是Spring给对象中属性进行赋值的过程,主要包括两种方式:
构造器依赖注入:构造器注入是指容器调用一个类的构造器创建对象时,直接传入给属性赋值
Setter方法注入:Setter方法注入是指容器在创建对象完成后,通过调用属性的Setter 方法,可以属性赋值
3、你用过哪些Spring注解 我们常用的Spring注解主要分类下面几大类:
1、创建对象:@Component、@Controller、@Service、@Repository
它们都可以标注在自己开发的类上,Spring会使用注解标注的类创建出对象,然后放入容器
2、依赖注入:@Autowired
标注在属性或者属性对应的set方法上,Spring会根据被标注属性的类型自动对属性进行赋值
3、依赖注入:@Qualifier
和@Autowired一块使用,在同一类型的bean有多个的情况下Spring会根据name进行选择注入
4、配置类:@Configuration、@Bean
主要标注在配置类中,用于声明配置类和向Spring容器中放入一些配置有关的对象
5、当然还有一些平时用的不是特别多的
比如:声明注解扫描的@ComponentScan,声明Bean的作用域的@Scope,用于切面编程的@Around,@Pointcut等等
4、SpringBean的作用域有几种 在Spring中作用域是用来对象的存活范围的,它支持5种作用域
第一种是单例,配置为单例的对象会跟随Spring容器创建而创建,跟随Spring容器销毁而销毁,在Spring容器中无论获取多少次单例对象,得到的都是同一个,这也是Spring中的对象的默认作用域
第二种是多例,配置为多例的对象在每次获取的时候才会创建,而且每次获取到的都不一样
还有三种分别是request、session和application,目前已经基本不再使用
其实,在我们平时的开发过程中,对象基本上都是配为单例的,这样可以有效的节省资源,只有单例对象存在线程安全问题时,才考虑调整为多例。
5、Spring中的bean线程安全吗 Spring中的Bean主要分为单例和多例
多例对象每次获取都会创建新实例,也就是说线程之间不存在Bean共享问题,也就不存在线程安全问题单例对象是所有线程共享一个实例,因此就可能会存在线程安全问题。但是单例对象又分为无状态和有状态。 无状态Bean是指只对对象的成员变量进行查询操作,不会修改成员变量的值,因此不存在线程安全问题有状态Bean需要对Bean中的成员变量进行数据更新操作,因此就可能存在线程安全问题 所以,最终我们得出结论,在Spring中,只有有状态的单例Bean才会存在线程安全问题
处理有状态单例Bean的线程安全问题有以下两种方法:
将Bean的作用域由单例改为多例将需要的可变成员变量保存在ThreadLocal中, ThreadLocal本身就具备线程隔离的特性,这就相当于为每个线程提供了一个独立的变量副本,每个线程只需要操作自己的线程副本变量,从而解决线程安全问题。 6、谈谈你对SpringAOP的理解 AOP,又叫面向切面编程,核心思想是将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理)封装起来,然后再动态插入到业务中的功能
使用AOP可以减少系统的重复代码,降低模块间的耦合度,并有利于扩展和维护,Spring AOP是基于动态代理的,它底层同时支持JDK和CGLIB的代理方式,并且会根据被代理类是否有接口自动选择最合适的代理方式
我们在开发中用到AOP的主要使用场景有:事务管理、日志、性能监视、安全检查
7、AOP的代理有几种方式 AOP思想的实现一般都是基于代理模式,在Java中一般采用JDK动态代理模式和CGLIB动态代理模式
JDK动态代理模式只能对有接口的类进行代理,而且效率较高CGLIB可以对任意的类进行动态代理,但是效率上不如JDK 因此在进行代理时,如果被代理类有接口,就用JDK;如果没有接口,就用CGLIB
使用Spring的AOP,底层会自动按照这个规则进行选择,开发者也无需关心
8、Spring的通知类型有哪些 通知是个在方法执行前或执行后要做的动作,实际上是程序执行时要通过SpringAOP框架触发的代码段。
Spring切面可以应用五种类型的通知:
前置通知:在某切点之前执行的通知返回后通知:在某切点正常完成后执行的通知抛出异常后通知:在某切点抛出异常退出时执行的通知后置通知:在某切点退出的时候执行的通知(不论是正常返回还是异常退出)环绕通知:包围一个切点的通知 9、了解Spring的事务管理吗 嗯,了解的,Spring支持编程式事务和声明式事务
第一种是编程式事务指的是在代码中使用try-catch捕获异常,然后配合事务的api来手动处理事务问题
这种方式的缺点是代码耦合,复用性低,优点是可以精确控制要增强的代码(不仅仅限于方法粒度)
第二种是声明式事务,声明式事务是AOP思想的一种应用,它的核心思想是将业务方法作为切点,
将事务处理方法作为增强,通过动态代理实现事务的管理,它的优点是降低代码耦合,提供复用
目前在企业中基本上都是采用声明式事务的。
10、Spring事务传播行为有几种 事务传播行为是为了解决业务层方法之间互相调用的事务问题。
当事务方法被另一事务方法调用时,必须指定事务应该如何传播。
1、项目中为什么选择SpringBoot SpringBoot简化了Spring,可以快速搭建企业级项目,而且开发起来效率也会更高,它的主要优点如下:
版本锁定:SpringBoot在父工程中进行了大量常见依赖的版本锁定,省去了我们查找依赖版本和解决版本冲突的麻烦起步依赖:SpringBoot以功能化的方式将需要的依赖进行组装,并且允许程序员以starter的方式进行引入默认配置:SpringBoot实现了大量依赖框架的默认配置项,程序员无须再进行自己配置内置Tomcat:SpringBoot内置了一个tomcat,使用它开发的程序无需再进行tomcat部署,可直接运行 2、SpringBoot的自动装配原理 Springboot自动装配主要是基于注解编程和约定优于配置的思想来进行设计的
自动装配就是自动地把其他组件中的Bean装载到IOC容器中,不需要开发人员再去配置文件中添加大量的配置
我们只需要在SpringBoot的启动类上添加一个@SpringBootApplication的注解,就可以开启自动装配
SpringBootApplication底层最重要的一部分是@EnableAutoConfiguration这个注解来实现的,它作用是:
读取所有jar包中两个指定配置文件中的所有自动配置类(xxxxAutoConfiguration)这些值必须声明为Spring的配置类,也就是在类中需要向Spring容器放入对象为了防止非当前所需的组件进入到容器,配置类中需要使用@Conditional注解来声明配置成立的必要条件 3、SpringBoot的核心注解是哪个 SpringBoot的核心注解在启动类上,叫@SpringBootApplication,主要组合包含了以下3个注解:
@SpringBootConfiguration:组合了@Configuration注解,实现配置文件的功能@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项@ComponentScan:Spring组件扫描,默认会扫描启动类所在的包 4、SpringBoot中的starter是干什么的 当项目足够复杂时,因为涉及的组件太多了,就需要引入很多的依赖,此时管理依赖就边的很麻烦
此时SpringBoot的starter就派上用场了,每个starter都可以为我们提供某个服务场景所需要的一系列依赖
在导入starter之后,SpringBoot主要帮我们完成了两件事情:
相关组件的自动导入相关组件的自动配置 5、SpringBoot可以有哪些方式加载配置 SpringBoot支持很多种方式加载配置,常见有
配置文件,直接在项目中提供SpringBoot支持的配置文件,比如properties、yaml 、yml
系统环境变量,SpringBoot是可以读取系统环境变量中的配置信息的,但不推荐这么做
命令行参数,SpringBoot在项目启动的时候运行通过命令行直接传递参数,一般用于临时修改配置的情况
6、bootstrap.yml和application.yml有何区别 这是SpringBoot支持的两个核心配置文件,区别点在于
boostrap比applicaton优先加载,在应用程序上下文的引导阶段生效,且里面的属性不能被覆盖
一般来说我们在SpringCloud Config或者Nacos中会用到它
application用于SpringBoot项目的自动化配置,一般来说我们会将自己项目的业务配置项写在这里面
7、SpringBoot读取配置的方式有几种 SpringBoot常见的读取配置信息的方式有两种:
使用@Value配合EL表达式(@Value(“${name}”))注解直接注入对应的值使用@ConfigurationProperties注解把对应的值绑定到一个配置对象,然后将配置对象注入到需要的地方 推荐使用使用第二种方式,在配置比较多的情况下,操作简单,可读性好
8、SpringBoot项目如何热部署 Spring Boot有一个开发工具(DevTools)模块,通过它可以实现SpringBoot项目的热部署
也就是开发人员将文件更改后,它会自动部署到服务器并自动重启服务器。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> 9、SpringBoot项目如何实现方法的异步调用 异步调用指的是a方法在调用b方法的时候,无需等待b方法执行完毕,就可以继续向下执行
一般用在a方法无需使用b方法返回结果的场景下,可以在一定程度上提高运行效率
在SpringBoot中使用异步调用是很简单的,只需要做两个操作就可以了
在启动类上添加@EnableAsync注解,开启异步调用支持在被调用的方法上添加@Async注解 controller-a(){ 代码1 service-a() 代码3 } @Async service-a(){} 10、SpringBoot中如何实现定时任务 在SpringBoot中使用定时任务主要有两种方式,一个就是使用SpringTask,另一个则是使用第三方框架Quartz
SpringTask主要是通过@Scheduled注解来实现定时任务触发的,格式如下
@Scheduled(fixedRate = 5000) public void printTime() { System.out.println(new Date().toLocaleString()); } 主要属性如下:
fixedRate:按一定的频率执行任务,参数类型为long,单位 msfixedDelay:上一次任务执行完后多久再执行,参数类型为long,单位 msinitialDelay:延迟多久再第一次执行任务,参数类型为 long,单位 mscron:使用cron表达式指定任务在特定时间执行 11、SpringBoot中如何解决跨域问题 跨域是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制
隐藏复选框图标
<style> .bs-checkbox{ display: none; } </style> 修改被选中的行颜色
在 bootstrap-table.min.css 中修改源码,或者backend.css
//选中行颜色 .fixed-table-container tbody .selected td { background-color: rgba(119, 211, 241, 0.5); } 在bootstrap.min.css中修改源码
//奇偶行颜色 .table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9} //滑过的颜色 .table-hover>tbody>tr:hover{background-color:#FAFAD2} 多选框禁止多选 在页面JS中设置 singleSelect:true,//单行选择单行,设置为true将禁止多选
什么叫缓存 将数据存放在程序内存中,用于减轻数据查询的压力,提升读取数据的速度,提高性能。
对于任何一个持久层框架,都有缓存机制;缓存在电脑中有一块真实的存储空间
Mybatis缓存 mybaits提供一级缓存,和二级缓存。
一级缓存(本地缓存)
sqlSession级别的缓存。(相当于一个方法内的缓存)二级缓存(全局缓存)
基于namespace名称空间级别的缓存.即一个mapper.xml对应一个缓存 一级缓存(本地缓存) 一级缓存基于sqlSession默认开启,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据。不同的SqlSession之间的缓存数据区域是互相不影响的。
一级缓存的作用域是SqlSession范围的,当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。
Mybatis的内部缓存使用一个HashMap,key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。
SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存。
需要注意的是,如果SqlSession执行了DML操作(增删改),并且提交到数据库,MyBatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存中存储的是最新的信息,避免出现脏读现象。
当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了。
关闭一级缓存后,再次访问,需要再次获取一级缓存,然后才能查找数据,否则会抛出异常。
案例: 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
二级缓存(全局缓存) Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。
Mybatis需要手动设置启动二级缓存。
二级缓存的作用域是mapper的同一个namespace。不同的sqlSession两次执行相同的namespace下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,则第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询会从缓存中获取数据,不再去底层数据库查询,从而提高效率。
案例: 基于namespace名称空间级别的缓存:一个namespace对应一个二级缓存即一个mapper.xml对应一个缓存: 1、工作机制: 一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;sqlSession=EmployeeMapper>Employee
DepartmentMapper===>Department
不同namespace查出的数据会放在自己对应的缓存中(map)
效果:数据会从二级缓存中获取
查出的数据都会被默认先放在一级缓存中。
只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中 2、 使用: 1)、开启全局二级缓存配置:
2)、去mapper.xml中配置使用二级缓存:
< cache>< /cache>
3)、我们的POJO需要实现序列化接口
1)在mybatis全局配置文件中开启全局二级缓存配置:< setting name=“cacheEnabled” value=“true”/>
2)在mapper.xml中配置使用二级缓存
直接加上: < cache>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper"> <cache><cache/> <!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName); --> <select id="
PDFormer: Propagation Delay-Aware Dynamic Long-Range Transformer for Traffic Flow Prediction Abstract As a core technology of Inteligent Transportation System, traffic flow prediction has a wide range of application. The fundamental challenge in traffic flow prediction is to effictely model the complex spatial-temporal dependencies in traffic data.
Spatial-temporal Graph Neural Network(GNN) models have emerged as one of the most promising methods to solve this problem.
However, GNN-based models have three major limitations for traffic predication:
配置方式 @Bean(name = "connectionFactory") @Primary public ConnectionFactory normalConnectionFactory( @Value("${spring.rabbitmq.username}") String username, @Value("${spring.rabbitmq.password}") String password, @Value("${spring.rabbitmq.addresses}") String address) { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setAddresses(address); connectionFactory.setUsername(username); connectionFactory.setPassword(password); // connectionFactory.setPublisherConfirms(true); connectionFactory.setPublisherReturns(true); connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED); connectionFactory.setExecutor(createThreadPool(10, 20, "mq-connection-", "mq-connection-group")); return connectionFactory; } 或者配置文件里配置
spring: # RabbitMQ 配置项,对应 RabbitProperties 配置类 rabbitmq: publisher-confirm-type: correlated publisher-confirm-type属性有三个可选值:
none(默认):关闭发布确认模式。correlated:消息从生产者发送到交换机后触发回调方法。simple:会触发回调方法,相当于单个确认(发一条确认一条)。在发布消息成功后使用rabbitTemplate调用waitForConfirms或waitForConfirmsOrDie方法等待broker节点返回发送结果,根据返回结果来判定下一步的逻辑,要注意的点是 waitForConfirmsOrDie方法如果返回false则会关闭channel,则接下来无法发送消息到broker。 使用方式 SIMPLE模式 开启simple模式需要在invoke方法中一起执行 rabbitTemplate.waitForConfirms
同时也会收到回调,回调后结束阻塞,同时可以获取到返回结果。
RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { if (ack){ System.
Vue项目起始时出现白屏问题需要刷新后才能显示解决方案 项目加\<div>为什么页面会出现加载过慢问题?如何让页面变得更快懒加载静态资源缓存 Webpack解决方案减少Js冗余操作 项目加<div> 在vue中,我们常常会因为在template模板中没有加div标签而使得页面出现白屏情况,这时我们加一个div标签就可以解决这个问题.
解决前
<template></template> 解决后:
<template><div></div></template> 为什么页面会出现加载过慢问题? 可能原因有以下两种:
js脚本加载时间过长资源过多加载延迟,在初次渲染时无法加载成功 如何让页面变得更快 懒加载 首先我们知道资源过多可能是导致页面白屏发生的情况之一,那么我们就可以通过懒加载的方式来进行页面加载,懒加载的含义就是:让可视区域的资源先被加载出来,而没有被可视区域看到的部分先不加载出来。比如我们常用的分页查询,假设一页有十条数据,那么我们在最初进入页面时,不论它有几千几万条数据,页面加载出来的数据只有十条,同时CSDN中我们的主页,也用到的类似懒加载的机制,在我们发布很多文章时候,超过可视区域,那么在主页中下拉,我们会发现下拉的过程中会出现一秒的卡顿,那是页面在进行新文章数据的加载,为了避免资源过多而引起的浪费。这样就可以有效的解决白屏问题。
静态资源缓存 浏览器是有自己的缓存机制:强缓存和协商缓存,当我们的静态资源长期不会发生变化时,那么我们就可以通过Cache-control来实现强制缓存,强缓存那些长期没有变化的资源也是能让页面更快的开启的一种方式,同时也可以解决白屏问题。
Webpack解决方案 如果我们使用的脚手架是webpack时,我们可以通过webpack的一个属性实现离线化预渲染: prerender-spa-plugin .从而解决白屏问题.
减少Js冗余操作 Js操作过多也可能导致页面加载速度过慢从而使得页面初次加载时出现白屏问题,可以通过常用的性能优化手段来解决这个问题:比如我们在使用百度联想词时候会不断的通过调用API在输入的时候,那么我们就可以利用防抖来实现一个性能优化,防抖就是指不是实时的进行调用联想词API,而是等待特定时间节点内用户没有继续输入时候再调用API,那么就可能实现一个性能优化,从而减少页面执行时间.
使用以太坊来创建去中心化应用程序(或称“dapp”),发挥加密货币和区块链技术的优势。 这些 dapp 可以是值得信赖的,也即一旦被部署到以太坊上,它们将总是按程序运行。 这些应用程序可以控制数字资产,以便创造新的金融应用; 它们可以是去中心化的,也即没有任何单一实体或个人能够控制它们,而且它们几乎是不可能被审查的。
智能合约和 SOLIDITY 语言入门 迈出第一步,将 Rust 与以太坊进行集成
需要更基础的入门知识? 请查看 ethereum.org/learn 或者 ethereum.org/developers。
区块链详解(opens in a new tab)理解智能合约(opens in a new tab)编写您的第一个智能合约(opens in a new tab)学习如何编写和部署 Solidity(opens in a new tab) 初学者文章 选择以太坊客户端(opens in a new tab)Rust 以太坊客户端(opens in a new tab) * 注意 OpenEthereum 已被废弃(opens in a new tab)并已停止维护。 请谨慎使用,最好切换至其他客户端实现。使用 Rust 向以太坊发送交易(opens in a new tab)Parity 以太坊客户端智能合约简介(opens in a new tab)如何用 Rust Wasm 为 Kovan 编写合约的分步教程(opens in a new tab) 面向中等程度用户的文章 面向高等程度用户的使用模式 pwasm_ethereum 外部库与类以太坊网络交互(opens in a new tab)
摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于高校教材征订系统当然也不能排除在外,随着网络技术的不断成熟,带动了高校教材征订系统,它彻底改变了过去传统的管理方式,不仅使服务管理难度变低了,还提升了管理的灵活性。高校教材征订系统,主要的模块包括管理员;系统首页、个人中心、学生管理、教师管理、教材类型管理、教材征订管理、教材信息管理、教材入库管理、样书申请管理、教材购买管理、通知公告管理,学生;系统首页、个人中心、教材信息管理、教材购买管理、通知公告管理,教师;系统首页、个人中心、教材征订管理、教材信息管理、样书申请管理、通知公告管理等功能。系统中管理员主要是为了安全有效地存储和管理各类信息,还可以对系统进行管理与更新维护等操作,并且对高校教材征订有相应的操作权限。这种个性化的平台特别注重交互协调与管理的相互配合,激发了管理人员的创造性与主动性,对高校教材征订系统而言非常有利。
本系统采用的数据库是Mysql,使用SpringBoot框架开发,运行环境使用Tomcat服务器,ECLIPSE 是本系统的开发平台。在设计过程中,充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。
关键字:高校教材征订系统 Mysql数据库 SpringBoot框架
Abstract
With the rapid development of science and technology, all walks of life are trying to integrate with modern advanced technology, through scientific and technological means to improve their own advantages; Of course, the recruitment system of university textbooks cannot be excluded. With the continuous maturity of network technology, the recruitment system of university textbooks has completely changed the traditional management mode in the past, which not only reduces the difficulty of service management, but also improves the flexibility of management.
一、mapper接口传参数的两大种方式 使用实体类、Map传参数,取值方式:#{实体类的属性名或键}使用@Param传参数,取值方式:#{指定value值} 二、spring boot项目的mapper接口方法中多个参数时,不使用@Param,却能使用属性名取值 Java8新增编译参数-parameters,使得反射可以获取方法的参数名,Java8之前只能获取到,arg0、arg1等
其原因是mybatis的setting参数useActualParamName 设置名描述有效值默认值useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)true 或者 falsetrue 所以说这个属性其实就是允许我们使用mapper接口方法的参数名称当作sql语句的参数名称,而且也不需要@Param注解,这个属性默认是开启的,使用这个特性还有以下几个要求: ①采用 Java 8 编译。
②编译时加上-parameters 选项。
③mybatis在3.4.1以上
注意: 不满足要求时,不添加@Param注解,依旧会报错如下:
org.apache.ibatis.binding.BindingException: Parameter 'XXX' not found. Available parameters arAvailable parameters are [arg1, arg0, param1, param2]] with root cause 三、Eclipse/IDEA编辑器设定调整 eclipse:项目右键->点击Properties->点击java Compiler->勾选图中选项
IDEA:
目录
一、准备文件
二、环境准备(安装CentOS7)
三、主机基本设置
关闭防火墙(两个都关)
修改主机名和从机名(改为Master和Slave1)
创建用户(Master和Slave1都创建)
创建目录
配置当前非root用户具有root的权限
ssh免密登录
将jdk和hadoop安装包传到虚拟机(主从机)(使用winSCP)
四、JDK的安装
卸载系统自带的JDK(主机从机都卸载)
五、安装 Hadoop 3.3.1
配置PATH变量
六、配置集群/分布式环境
(1)修改文件workers
(2)修改文件
(3)修改文件hdfs-site.xml
(4)修改文件mapred-site.xml
(5)修改文件 yarn-site.xml
七、将hadoop分发到slave1节点
一、准备文件 所用到 Hadoop3.3.1 、 JDK1.8_271 、CentOs7.x、xshell、winSCP
http://链接: https://pan.baidu.com/s/1nT0O3F0D65Y5QrrY9qHpxQ?pwd=2agi 提取码: 2agi 复制这段内容后打开百度网盘手机App,操作更方便哦
二、环境准备(安装CentOS7) 打开下载安装好的VMware Workstation
点击做左上角的文件->新建虚拟机->点击下一步
浏览选择下载好的CentOS7->下一步->
名称Master,位置自己选择一个喜欢的目录->下一步
选择自己需要的大小,和储存方式->下一步->完成
安装时出现的界面点enter就行
选择自己喜欢的语言,我这里选的是中文简体
选择好点击继续(下面配置网络比较重要)
安装位置选择
刚刚分配的20GB磁盘,点击完成
点击网络和主机(比较重要)
点击右边的打开,就会自动获取p地址(记住这个ip),并显示已连接,如果没链接成功,建议检查虚拟机设置,避免后面的麻烦。
然后点击完成->开始安装
点击设置一个root密码,等待安装完成(泡杯枸杞喝,别整电脑上)
安装完成后点重启
完整完成
这里搭建一主一从,一主多从(类似)
关闭虚拟机, 选择克隆-.下一步->下一步
选择自己喜欢的路径点击完成(如果选择了完全克隆时间可能长一点)
完成后启动master和slave1 查看master 和 slave1的ip ip add 使用xshell 链接虚拟机进行操作(为了方便操作),使用winSCP链接虚拟机(传文件用),
连接好下面在xshell里面进行操作。
三、主机基本设置 关闭防火墙(两个都关) # 在root用户下执行 systemctl stop firewalld systemctl disable firewalld.
大家好我是二狗
随着前天 OpenAI 官宣 Sam Altman 将回归,并继续担 CEO,OpenAI“宫斗事件”已经告一段落了。
然而,对于专业吃瓜的二狗来说,有一个核心问题还是没有搞明白:
Sam Altman究竟为何被董事会开除?
之前网络上有各种猜测,但似乎都没有得到石锤。
直到昨天,路透社最新爆料来了:
“在Sam Altman被OpenAI开除四天前,几名研究人员向董事会发出了一封信,警告一项强大的AI发现(Q*项目)可能威胁全人类。消息人士透露,这封此前未报道的信件和AI算法的突破是董事会罢免Sam Altman的原因之一。”
一些内部人士认为 Q* 项目可能是 OpenAI 在AGI上取得的关键突破。Q*项目背后的新模型能够解决某些数学问题(虽然仅达到小学生的水平),但研究人员认为数学是生成式AI发展的前沿。目前,生成式AI擅长通过统计预测下一个单词来进行写作和语言翻译,但同一问题的答案可能会有很大差异。
而征服只有一个正确答案的数学能力意味着AI可能拥有类似于人类智能的更强推理能力。
那为何这是董事会罢免Sam Altman的原因之一呢?
据合理猜测,OpenAI的几位董事会成员,如首席科学家Sutskever、曾担任多家科技公司的高管Tasha McCauley、乔治敦大学安全与新兴技术中心(CSET)战略和基础研究基金主任Helen Toner都是“有效理他主义”的信徒,你可以简单理解为是“AI保守派”,他们优先要确保创建对全人类都有益的AI、确保AI不能威胁到人类,这也正是OpenAI董事会的使命。
Helen Toner曾表示,即便发生了什么导致要因此解散OpenAI,那也无妨,董事会的使命更重要。
而Sam Altman则是AI加速派,Altman认为AI不会失控,他的第一优先级是让OpenAI拿到更多融资以及更好地商业化赚钱,毕竟GPT系列大模型太烧钱了,只有这样做才能保证后面慢慢做出AGI。
有可能这次 Q* 项目背后的取得的突破,被几位董事会成员认为可能威胁到人类,因此要放缓研发速度,优先考虑AI安全和对齐问题,这也正是最近几个月Sutskever所致力于做的事情。
Altman和几位董事会成员直接AI安全问题没有对齐,加上Altman长期以来的商业化路线和其他几位董事会成员有比较大的分歧。
这也许就导致了几位董事会成员想要不惜代价罢免Altman的原因。
ok,以上只是合理猜测,Altman被罢免的真正原因还需要进一步被官方揭露,我们继续看一下这个 Q* 项目到底是何物?
Q*项目背景和更多信息曝光 据 The Information 报道及知情人士透露,多年来,OpenAI 首席科学家Sutskever 一直致力于研究如何让像GPT-4这样的语言模型解决如数学或科学等涉及推理的任务。2021 年,他启动了一个名为 GPT-Zero 的项目,这个起名是向DeepMind 的 下棋大师AlphaZero致敬。
在今年早些时候,Sutskever领导的这一项目取得了技术突破,能自己“生产”数据——理论上能够像AlphaZero自我对弈一样,使用计算机生成无限高质量数据,这一举克服了如何获取足够高质量数据来训练新模型方面的限制,因为据了解,OpenAI 已经几乎把从互联网上公开获取的数据训练了一遍,已经无法再获得更多的数据来进行下一阶段训练。
Abacusai 的CEO Bindu Reddy在推特上引用了这一消息:
正如所怀疑的那样,OpenAI发明了一种利用合成数据克服训练数据限制的方法,当用足够的例子进行训练时,模型开始很好地总结!
对于开源和去中心化AI来说是个好消息——我们不再受制于数据丰富的公司 。
两位研究人员 Jakub Pachocki 和 Szymon Sidor 运用Sutskever 的研究成果,开发出了一个名为 Q*的模型,构建了能解决基础数学问题的系统,而这一直是现有AI模型的难题。
文章目录 前言一、角点检测1.1 角点特征1.1.1 角点特征概念1.1.2 角点的特点1.1.3 关键点绘制代码实现1.1.4 函数解析 1.2 Harris角点检测1.2.1 Harris角点检测原理1.2.2 Harris角点检测公式1.2.3 代码实现1.2.4 函数解析 1.3 Shi-Tomasi角点检测1.3.1 Shi-Tomasi角点检测原理1.3.2 Shi-Tomasi角点检测公式1.3.3 代码实现1.3.4 函数解析 1.4 FAST角点检测1.4.1 FAST角点检测原理1.4.2 FAST角点检测特点和应用1.4.3 代码实现1.4.4 函数解析 1.5 亚像素角点检测1.5.1 亚像素角点检测原理1.5.2 亚像素角点检测公式1.5.3 代码实现1.5.4 函数解析 二、特征点检测2.1 SIFT(尺度不变特征变换)2.1.1 SIFT原理2.1.2 代码实现2.1.3 函数解析 2.2 SURF(加速稳健特征)2.2.1 SURF原理2.2.2 代码实现2.2.3 函数解析 2.3 ORB(方向快速和旋转二进制)2.3.1 ORB原理2.3.2 代码实现2.3.3 函数解析 三、特征点匹配3.1 BF匹配器3.1.1 BF匹配器原理3.1.2 代码实现3.1.3 函数解析 3.2 FLANN匹配器3.2.1 FLANN匹配器原理3.2.2 代码实现3.2.3 函数解析 3.3 RANSAC特征点匹配3.3.1 RANSAC原理3.3.2 代码实现3.3.3 函数解析 总结 前言 在计算机视觉领域,特征点检测与匹配是解决多种问题的核心,包括图像识别、跟踪、三维重建和运动分析。OpenCV作为一个功能强大的视觉处理库,提供了丰富的功能来处理这些任务。本博客旨在提供一个关于OpenCV中特征点检测与匹配方法的快速入门指南。
我们将从角点检测开始,探讨如Harris、Shi-Tomasi和FAST等经典算法,介绍它们的原理、公式和代码实现。接着,我们将深入到特征点检测的高级话题,覆盖如SIFT、SURF和ORB等算法。每种方法都会有详细的函数解析,帮助理解其背后的工作原理。最后,我们将讨论特征点匹配技术,包括BF匹配器、FLANN匹配器和RANSAC匹配方法,它们在处理不同图像间的特征点对应关系时至关重要。
一、角点检测 角点检测(Corner Detection)是计算机视觉和图像处理中的一个基本概念,指的是在图像中识别出具有明显角点特征的点。在OpenCV中,我们通常使用Harris 角点检测或Shi-Tomasi角点检测来实现这一功能。
背景
Streamlit是一个Python库,可帮助我们为没有HTML / CSS / JS的模型开发UI。 大多数模型都停留在Jupyter Notebook且没有吸引力。 然而,使用Streamlit,您可以为模型创建一个干净的界面并将其展示给其他人。 构建界面可使用户以更加用户友好的格式使用您的模型。
您无需处理HTML / CSS / JSS支持markdown它具有许多可用的预构建窗口小部件,从而进一步减少了您花费在构建UI上的时间建立一个响应式用户界面使用Streamlit共享易于部署Streamlit应用程序它是开源的,您可以根据需要创建窗口小部件 本文将建立一个逻辑回归模型,以预测一个人是否能度过泰坦尼克号灾难。 构建模型后,我们将使用Streamlit为模型构建一个Web应用程序和一个UI。 该网络应用将允许用户输入值并获得预测结果。
准备
本文的重点是Streamlit,因此需要熟悉使用scikit-learn构建机器学习模型。
对Python有很好的了解
基本了解数据清理和标准技术,例如数值编码,单次热编码熟悉scikit-learn库熟悉Logistic回归会有所帮助,但不是必需的熟悉Pandas库对Matplotlib库的基本了解 库安装
导入库
逻辑回归模型
首先,我们将加载Titanic数据集并处理我们的数据集以满足我们的要求。您可以从此链接下载数据集。
我们导入数据集并创建一个数据框。
您可以打印数据框以检查其中的列。
在我们的逻辑回归模型可以使用它之前,我们需要对我们的数据执行以下操作。
为“性别”特征分配一个数值。
在“ Pclass”特征上使用一键编码。
在“年龄”列中填写缺失的值。
仅选择所需的功能。
我们将定义一个函数来转换我们的数据,以使其可用于我们的Logistic回归模型。
处理数据
对于性别列,如果乘客是男性,我们将值设置为0,如果乘客是女性,则将值设置为1。
Streamlit分列嵌套 Python 数据可视化 详情参阅 - 亚图跨际
123apps:
Online MP3 Cutter - Cut Songs, Make Ringtones
一、语音合成概述 语音信号的产生分为两个阶段,信息编码和生理控制。首先在大脑中出现某种想要表达的想法,然后由大脑将其编码为具体的语言文字序列,及语音中可能存在的强调、重读等韵律信息。经过语言的组织,大脑通过控制发音器官肌肉的运动,产生出相应的语音信号。其中第一阶段主要涉及人脑语言处理方面,第二阶段涉及语音信号产生的生理机制。
从滤波的角度,人体涉及发音的器官可以分为两部分:激励系统和声道系统。激励系统中,储存于肺部的空气源,经过胸腔的压缩排出,经过气管进入声带,根据发音单元决定是否产生振动,形成准周期的脉冲空气激励流或噪声空气激励流。这些空气流作为激励,进入声道系统,被频率整形,形成不同的声音。声道系统包括咽喉、口腔(舌、唇、颌和口)组成,可能还包括鼻道。不同周期的脉冲空气流或者噪声空气流,以及不同声道器官的位置决定了产生的声音。因此,语音合成中通常将语音的建模分解为激励建模和声道建模。
1. 语音合成的历史和研究方法 语音合成系统分为两部分,分别称为文本前端和后端。文本前端主要负责在语言层、语法层、语义层对输入文本进行文本分析;后端主要是从信号处理、模式识别、机器学习等角度,在语音层面上进行韵律特征建模,声学特征建模,然后进行声学预测或者在音库中进行单元挑选,最终经过合成器或者波形拼接等方法合成语音。
根据语音合成研究的历史,语音合成研究方法可以分为:机械式语音合成器、电子式语音合成器、共振峰参数合成器、基于波形拼接的语音合成(Concatenative Speech Synthesis)、统计参数语音合成(Statistical Parametric Speech Synthesis,SPSS)、以及神经网络语音合成。
早期的语音合成方法由于模型简单,系统复杂等原因,难以在实际场景应用。随着计算机技术的发展,基于波形拼接的语音合成被提出。基于波形拼接的语音合成 Concatenative Speech Synthesis的基本原理是首先构建一个音库,在合成阶段,通过对合成文本的分析,按照一定的准则,从音库中挑选出与待合成语音相似的声学单元,对这些声学单元进行少量调整,拼接得到合成的语音。早期的波形拼接系统受限于音库大小、挑选算法、拼接调整的限制,合成语音质量较低。1990年,基于同步叠加的时域波形修改算法被提出,解决了声学单元拼接处的局部不连续问题。更进一步,基于大语料库的波形拼接语音合成方法被提出,采用更精细的挑选策略,将语音音库极大地拓展,大幅提升了合成语音的自然度。由于直接使用发音人的原始语音,基于波形拼接的语音合成方法合成语音的音质接近自然语音,被广泛应用。但其缺点也较为明显,包括音库制作时间长、需要保存整个音库、拓展性差、合成语音自然度受音库和挑选算法影响,鲁棒性不高等。
随着统计建模理论的完善,以及对语音信号理解的深入,基于统计参数的语音合成方法(Statistical Parametric Speech Synthesis,SPSS)被提出。其基本原理是使用统计模型,对语音的参数化表征进行建模。在合成阶段,给定待合成文本,使用统计模型预测出对应的声学参数,经过声码器vocoder合成语音波形。统计参数语音合成方法是目前的主流语音合成方法之一。统计参数音合成方法的优点很多,包括只需要较少的人工干预,能够快速地自动构建系统,同时具有较强的灵活性,能够适应不同发音人,不同发音风格,多语种的语音合成,具有较强的鲁棒性等。由于语音参数化表示以及统计建模的平均效应,统计参数语音合成方法生成的语音自然度相比自然语音通常会有一定的差距。基于隐马尔科夫HMM的统计参数语音合成方法是发展最为完善的一种。基于HMM的统计参数语音合成系统能够同时对语音的基频、频谱和时长进行建模,生成出连续流畅且可懂度高的语音,被广泛应用,但其合成音质较差。
和统计参数语音合成系统类似,深度学习语音合成系统也可大致分为两个部分:文本前端和声学后端。文本前端的主要作用是文本预处理,如:为文本添加韵律信息,并将文本词面转化为语言学特征序列(Linguistic Feature Sequence);声学后端又可以分为声学特征生成网络和声码器,其中声学特征生成网络根据文本前端输出的信息产生声学特征,如:将语言学特征序列映射到梅尔频谱Mel 或线性谱;声码器利用频谱等声学特征,生成语音样本点并重建时域波形,如:将梅尔频谱恢复为对应的语音。近年来,也出现了完全端到端的语音合成系统,将声学特征生成网络和声码器和合并起来,声学后端成为一个整体,直接将语言学特征序列,甚至文本词面端到端转换为语音波形。
2. 语音合成各部分 2.1. 文本前端 文本前端的作用是从文本中提取发音和语言学信息,其任务至少包括以下四点。
(a). 文本正则化
在语音合成中,用于合成的文本存在特殊符号、阿拉伯数字等,需要把符号转换为文本。如“1.5 元” 需要转换成“一点五元”,方便后续的语言学分析。
(b). 韵律预测
该模块的主要作用是添加句子中韵律停顿或起伏。如“在抗击新型冠状病毒的战役中,党和人民群众经受了一次次的考验”,如果停顿信息不准确就会出现:“在/抗击/新型冠状病毒/的/战役中,党/和/人民群众/经受了/一次/次/的/考验”。“一次次”的地方存在一个错误停顿,这将会导致合成语音不自然,如果严重些甚至会影响语义信息的传达。
(c). 字形转音素
文字转化为发音信息。比如“中国”是汉字表示,需要先将其转化为拼音“zhong1 guo2”,以帮助后续的声学模型更加准确地获知每个汉字的发音情况。
(d). 多音字和变调
许多语言中都有多音字的现象,比如“模型”和“模样”,这里“模”字的发音就存在差异。另外,汉字中又存在变调现象,如“一个”和“看一看”中的“一”发音音调不同。所以在输入一个句子的时候,文本前端就需要准确判断出文字中的特殊发音情况,否则可能会导致后续的声学模型合成错误的声学特征,进而生成不正确的语音。
2.2. 声学特征生成网络 Acoustic model 声学特征生成网络根据文本前端的发音信息,产生声学特征,如梅尔频谱或线性谱。近年来,基于深度学习的生成网络甚至可以去除文本前端,直接由英文等文本生成对应的频谱。但是一般来说,因为中文字形和读音关联寥寥,因此中文语音合成系统大多无法抛弃文本前端,换言之,直接将中文文本输入到声学特征生成网络中是不可行的。基于深度学习的声学特征生成网络发展迅速,比较有代表性的模型有Tacotron系列,FastSpeech系列等。近年来,也涌现出类似于VITS的语音合成模型,将声学特征生成网络和声码器融合在一起,直接将文本映射为语音波形。
2.3. 声码器 Vocoder 通过声学特征产生语音波形的系统被称作声码器,声码器是决定语音质量的一个重要因素。一般而言,声码器可以分为以下4类:纯信号处理,如Griffin-Lim、STRAIGHT和WORLD;自回归深度网络模型,如WaveNet和WaveRNN;非自回归模型,如Parallel WaveNet、ClariNet和WaveGlow;基于生成对抗网络(Generative Adversarial Network,GAN)的模型,如MelGAN、Parallel WaveGAN和HiFiGAN。
3. 语音合成评价指标 对合成语音的质量评价,主要可以分为主观和客观评价。主观评价是通过人类对语音进行打分,比如平均意见得分(Mean Opinion Score,MOS)、众包平均意见得分(CrowdMOS,CMOS)和ABX测试。客观评价是通过计算机自动给出语音音质的评估,在语音合成领域研究的比较少,论文中常常通过展示频谱细节,计算梅尔倒谱失真(Mel Cepstral Distortion,MCD)等方法作为客观评价。客观评价还可以分为有参考和无参考质量评估,这两者的主要判别依据在于该方法是否需要标准信号。有参考评估方法除了待评测信号,还需要一个音质优异的,可以认为没有损伤的参考信号。常见的有参考质量评估主要有ITU-T P.861 (MNB)、ITU-T P.862 (PESQ)、ITU-T P.863 (POLQA)、STOI和BSSEval。无参考评估方法则不需要参考信号,直接根据待评估信号,给出质量评分,无参考评估方法还可以分为基于信号、基于参数以及基于深度学习的质量评估方法。常见的基于信号的无参考质量评估包括ITU-T P.
区别 好的,我可以为你整理一个关于网卡绑定模式的表格,包括7种不同模式的区别。请注意,网卡绑定模式可能因操作系统和网络硬件的不同而有所变化。以下是一个一般性的参考表格:
模式描述优点缺点负载平衡平均分配流量到所有绑定的网卡增加网络吞吐量需要支持负载平衡的硬件和网络设备负载平衡+故障转移结合负载平衡和故障转移,当某个网卡出现问题时切换到其他网卡提高系统的稳定性需要额外的故障转移和监控机制透明故障转移当主网卡故障时,自动切换到备用网卡提高系统的可用性需要支持透明故障转移的硬件和网络设备负载平衡+透明故障转移结合负载平衡和透明故障转移,提高网络性能和可用性综合利用多个网卡资源需要支持的硬件和网络设备较为昂贵源地址哈希根据源地址对流量进行哈希,分配到不同的网卡提高对特定源地址的负载平衡效果不适用于所有类型的流量,可能导致不均匀的负载分布IP散列根据IP地址对流量进行哈希,分配到不同的网卡提高对特定IP地址的负载平衡效果可能导致某些IP地址的流量过载,不适用于所有场景混合模式结合多种模式,根据需求动态选择合适的模式灵活适应不同网络环境需要更复杂的配置和管理 请注意,具体的实现方式和性能表现可能会因厂商和具体设备而有所不同。在配置网卡绑定时,建议参考相应硬件和操作系统的文档以获取最佳实践。
明白了,你的要求是针对不同的网卡绑定模式,以及与交换机相关的特定情况,整理一个表格。以下是一个简单的表格,描述了七种网卡绑定模式及其与交换机的关系:
模式描述交换机模式交换机看IP对应MAC数交换机看MAC备注负载平衡平均分配流量到所有绑定的网卡普通交换机较平均忽略IP,只关注MAC需要支持负载平衡的硬件和网络设备负载平衡+故障转移结合负载平衡和故障转移,提高系统的稳定性普通交换机较平均忽略IP,只关注MAC需要额外的故障转移和监控机制透明故障转移当主网卡故障时,自动切换到备用网卡普通交换机单一(备用)忽略IP,只关注MAC需要支持透明故障转移的硬件和网络设备负载平衡+透明故障转移结合负载平衡和透明故障转移,提高网络性能和可用性普通交换机较平均忽略IP,只关注MAC需要支持的硬件和网络设备较为昂贵源地址哈希根据源地址对流量进行哈希,分配到不同的网卡支持IP和MAC的交换机较平均关注IP和MAC需要支持哈希分配的交换机IP散列根据IP地址对流量进行哈希,分配到不同的网卡支持IP的交换机较平均关注IP需要支持哈希分配的交换机混合模式结合多种模式,根据需求动态选择合适的模式可以根据模式需要的交换机根据选择的模式变化根据选择的模式变化需要更复杂的配置和管理 这个表格提供了一些一般性的信息,但具体情况可能会因厂商和设备型号而有所不同。在实际配置中,请参考相应硬件和操作系统的文档以获取最佳实践。
网卡配置 网卡聚合(bond)模式简介及交换机侧配置
在网络中,Bond(也称为网络绑定或链路聚合)是一种将多个网络接口绑定在一起形成逻辑上的单个接口的技术。这种绑定可以提供高可用性、负载均衡和冗余性。
以下是常见的七种Bond模式及其解释:
Mode 0(balance-rr):又称为“round-robin”模式。数据包按照轮询的方式依次发送到每个接口,实现负载均衡。这种模式不提供冗余性。
Mode 1(active-backup):又称为“active-passive”模式。只有一个接口处于活动状态,用于传输数据。其他接口处于备用状态,仅在活动接口故障时接管。提供故障切换和冗余性。
Mode 2(balance-xor):使用源和目的MAC地址以及传输层协议和端口号来选择要发送的接口。提供负载均衡和冗余性。
Mode 3(broadcast):将所有数据包发送到所有接口。实现广播传输,但不提供负载均衡或冗余性。
Mode 4(802.3ad):也称为“LACP”(Link Aggregation Control Protocol)模式。使用LACP协议动态协商绑定接口的工作方式。提供负载均衡和冗余性。
Mode 5(balance-tlb):使用负载传输平衡(TLB)算法在传输和接收时进行负载均衡。这种模式仅在传输方向上实现负载均衡,接收方向上只使用一个接口。
Mode 6(balance-alb):使用自适应负载平衡(ALB)算法在传输和接收时进行负载均衡。这种模式在传输和接收方向上都实现负载均衡,不需要特殊的交换机支持。
以下是一个配置Bond模式的例子,假设我们有两个网络接口:eth0和eth1。
Mode 0(balance-rr)的配置示例: sudo vi /etc/network/interfaces auto bond0 iface bond0 inet static address 192.168.1.10 netmask 255.255.255.0 bond-mode balance-rr bond-slaves eth0 eth1 Mode 1(active-backup)的配置示例: sudo vi /etc/network/interfaces auto bond0 iface bond0 inet static address 192.168.1.10 netmask 255.255.255.0 bond-mode active-backup bond-primary eth0 bond-slaves none bond-primary eth0 bond-slaves eth1 Mode 4(802.
wxml
<view class="cv" bindtap="copyText" data-title="{{item.code}}">复制</view> js
copyText(e) { console.log(e); let that = this; wx.setClipboardData({ //复制文本 data:e.currentTarget.dataset.title,//要复制的文本内容 success: function (res) { wx.showToast({ title: '复制成功', icon: "none", mask: "true" //是否设置点击蒙版,防止点击穿透 }) } }) },