css常见的单位汇总分类

在CSS中,采用范围广泛的单位表示长度、角度、时间、频率等变量。以下是一些常见的CSS单位,它们根据其采用领域或类型,被划分为不同的类别: 绝对长度单位 (这类单位在所有媒体中都有固定的物理尺寸) px: 像素 cm: 厘米 mm: 毫米 in: 英寸 pc: 派克(1pc等于12pt) pt: 点(1in等于72pt) 相对长度单位 em: 相对于元素字体大小的计量单位 ex: 相对于元素字体x高度的计量单位 ch: 相对于元素字体’0’字符宽度的计量单位 rem: 相对于根元素字体大小的计量单位 vh: 相对于视口高度的计量单位(1vh = 1% 的视口高度) vw: 相对于视口宽度的计量单位(1vw = 1% 的视口宽度) vmin: 相对于视口较小尺寸的计量单位(1vmin = 1% 的视口较小尺寸) vmax: 相对于视口较大尺寸的计量单位(1vmax = 1% 的视口较大尺寸) %: 相对于父元素大小的计量单位 时间单位 s: 秒 ms: 毫秒 角度单位 deg: 度 rad: 弧度 grad: 百分度 turn: 圈 频率单位 hz: 赫兹 khz: 千赫兹解析度单位 dpi: 每英寸点数 dpcm: 每厘米点数

cv_bridge报错

_,contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

Jetson Nano (aarch64)安装conda环境(极速版)

在Jetson Nano中我们可以用conda系列中的archiconda来安装conda环境 一、首先下载Anaconda3-2021.05-Linux-aarch64(1).sh脚本 百度网盘链接:https://pan.baidu.com/s/19D8mBL0CmV92F-9vKH1UjQ?pwd=3kta 提取码:3kta 二、然后打开终端运行该脚本 ./Anaconda3-2021.05-Linux-aarch64 (1).sh 一直回车,然后其中init选择no 其余确认全部选择yes 三、编辑环境变量: sudo gedit ~/.bashrc 在最后一行添加下面一句 #conda env export PATH="/home/你的用户名/archiconda3/bin:"$PATH 刷新bash文件:source ~/.bashrc 四、测试: conda -V 显示版本号,就说明安装conda成功 然后就可以创建虚拟环境了 conda create -n yolov5 python=3.8

我的命令笔记

要在conda环境下设置清华源,可以按照以下步骤进行: 1. 打开终端或命令行窗口,进入conda环境。 2. 使用以下命令添加清华源: conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --set show_channel_urls yes 3. 使用以下命令检查清华源是否已成功添加: conda config --show channels 如果清华源已经添加成功,输出的结果应该包括 `https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/` 和 `https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/` 两个链接。 4. 如果想要删除之前添加的清华源,可以使用以下命令: conda config --remove-key channels 这会将所有已添加的渠道删除。如果只想删除清华源,可以使用以下命令: conda config --remove channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --remove channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ 这会将清华源从渠道列表中删除。 注意:以上命令中的链接是清华大学开源软件镜像站提供的链接,如果出现链接失效或不可访问的情况,可以到清华大学开源软件镜像站的网站上查看最新的链接。 ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— pip install 包名 -i 源url地址 --trusted-host 源域名 e.g.: pip install keras -i http://pypi.douban.com/simple --trusted-host pypi.douban.com tar zxvf 查找功能包路径

用python实现自定义语音播报

在ubuntu18.04系统中使用时: 步骤 1:安装pydub库 如果尚未安装pydub库,可以通过以下命令来安装: pip install pydub 步骤 2:准备M4A音频文件 将你想要播放的M4A音频文件准备好,并记下其文件路径。 步骤 3:导入pydub库 在Python脚本中,导入pydub库以及AudioSegment和play模块: from pydub import AudioSegment from pydub.playback import play 步骤 4:定义播放函数 在脚本中,定义一个函数用于播放M4A音频文件: def play_m4a(file_path): sound = AudioSegment.from_file(file_path, format="m4a") play(sound) 步骤 5:播放音频 在__main__部分,指定要播放的M4A文件路径,并调用play_m4a函数来播放音频: if __name__ == "__main__": m4a_file = "/path/to/your/M4A/file.m4a" # 替换为你的M4A文件路径 play_m4a(m4a_file) 整体代码: from pydub import AudioSegment from pydub.playback import play def play_m4a(file_path): sound = AudioSegment.from_file(file_path, format="m4a") play(sound) if __name__ == "__main__": m4a_file = "/home/k/tools/语音播报/可回收垃圾.m4a" # 替换为你的M4A文件路径 play_m4a(m4a_file) 在Windows系统中: 装pyglet库:如果你还没有安装pyglet库,可以使用以下命令通过pip进行安装。 pip install pyglet 2.

总结一下常用的算法

Other 初始化二维vector vector< vector<int> >g(n+1, vector<int>(n+1, 0)); 初始化: memset(a, 0/-1/INF,sizeof(a)); //初始化数组a,使其中值为0/-1/INF。 memcpy(b,a,sizeof(a)); // 将数组a中的值复制到新数组b中。 字符串: string s; s.substr(pos,len); // 获得字符串s从位置pos开始长度为len的子串。 s.push_back('c'); //在字符串s的尾部添加字符c s.pop_back(); //弹出字符串s的最后一个元素 C语言的排序: //对数组a[1]-a[100]排序 int cmp(const void *a, const void *b){ return *(int *)a - *(int *)b; } qsort(a+1, 100, sizeof(int), cmp); //对结构体a[1]-a[100]排序 struct Node{ char s; int cnt; }a[105]; int cmp(const void *a, const void *b){ return (*(Node *)a).cnt - (*(Node *)b).cnt; } qsort(a+1, 100, sizeof(Node), cmp); C语言的文件操作:

Day10-作业(SpringBootWeb案例)

作业1:完成课上预留给大家自己完成的功能 【部门管理的修改功能】 注意: 部门管理的修改功能,需要开发两个接口: 先开发根据ID查询部门信息的接口,该接口用户查询数据并展示 。(一定一定先做这个功能) 再开发根据ID修改部门数据的接口,记得在修改的时候,需要修改updateTime为当前系统时间 作业2:根据如下提供的接口文档 及 页面原型(需求)完成接口文档中的接口开发,并通过postman测试接口 备注:根据接口文档开发接口,并给予postman进行测试即可,前端工程前端人员还未开发,所以无需联调测试。 页面原型: 页面原型,提取码:5555https://pan.baidu.com/s/1sSVPV1Nhu8hKDJPoMjDSNA 接口文档: 接口文档,提取码:5555https://pan.baidu.com/s/1f5IQVSXKlEZEcgX7xLN0Xw 基础代码: 基础代码,提取码:5555https://pan.baidu.com/s/1X30Q7sWKKXd1ZHt8sLqnwg 直接将提供的基础工程,导入到idea,基础工程结构如下: 温馨提示:上述的基础工程代码中,controller、service、mapper中都没有加注解,需要自己添加。 建表语句: -- 学员表 create table student( id int unsigned primary key auto_increment comment 'ID,主键', name varchar(10) not null comment '姓名', no char(10) not null unique comment '学号', gender tinyint unsigned not null comment '性别, 1: 男, 2: 女', phone varchar(11) not null unique comment '手机号', degree tinyint unsigned comment '最高学历, 1:初中, 2:高中, 3:大专, 4:本科, 5:硕士, 6:博士', violation_count tinyint unsigned not null default 0 comment '违纪次数', violation_score tinyint unsigned not null default 0 comment '违纪扣分', class_id int unsigned not null comment '班级ID, 关联班级表ID', create_time datetime not null comment '创建时间', update_time datetime not null comment '修改时间' ) comment '学员表'; insert into student(name, no, gender, phone, degree, class_id, create_time, update_time)VALUES ('段誉','2022000001',1,'18800000001',1,1,now(),now()), ('萧峰','2022000002',1,'18800210003',2,1,now(),now()), ('虚竹','2022000003',1,'18800013001',2,1,now(),now()), ('萧远山','2022000004',1,'18800003211',3,1,now(),now()), ('阿朱','2022000005',2,'18800160002',4,1,now(),now()), ('阿紫','2022000006',2,'18800000034',4,2,now(),now()), ('游坦之','2022000007',1,'18800000067',4,2,now(),now()), ('康敏','2022000008',2,'18800000077',5,2,now(),now()), ('徐长老','2022000009',1,'18800000341',3,2,now(),now()), ('云中鹤','2022000010',1,'18800006571',2,2,now(),now()), ('钟万仇','2022000011',1,'18800000391',4,3,now(),now()), ('崔百泉','2022000012',1,'18800000781',4,3,now(),now()), ('耶律洪基','2022000013',1,'18800008901',4,3,now(),now()), ('天山童姥','2022000014',2,'18800009201',4,3,now(),now()), ('刘竹庄','2022000015',1,'18800009401',3,4,now(),now()), ('李春来','2022000016',1,'18800008501',4,4,now(),now()), ('王语嫣','2022000017',2,'18800007601',2,4,now(),now()); 需求:

Day15-作业(Maven高级)

作业1:完成苍穹外卖项目目录结构创建 说明: 1.sky-take-out 是父工程 2.sky-common/sky-pojo/sky-server 是子工程 3.sky-server模块引用了sky-common/sky-pojo模块 作业2:完成汇客CRM项目目录结构创建 说明: huike-parent 是父工程其他模块都是子工程模块之间的引用关系 模块名称依赖的模块huike-adminhuike-framework huike-task huike-clues huike-business huike-contract huike-reporthuike-businesshuike-system huike-common huike-clueshuike-clueshuike-common huike-systemhuike-common无huike-contracthuike-common huike-businesshuike-frameworkhuike-systemhuike-reporthuike-contracthuike-systemhuike-commonhuike-taskhuike-common

pyinstaller打包报错以及解决

#使用方法 -h,--help 查看该模块的帮助信息 -F,-onefile 产生单个的可执行文件 -D,--onedir 产生一个目录(包含多个文件)作为可执行程序 -a,--ascii 不包含 Unicode 字符集支持 -d,--debug 产生 debug 版本的可执行文件 -w,--windowed,--noconsolc 指定程序运行时不显示命令行窗口(仅对 Windows 有效) -c,--nowindowed,--console 指定使用命令行窗口运行程序(仅对 Windows 有效) -o DIR,--out=DIR 指定 spec 文件的生成目录。如果没有指定,则默认使用当前目录来生成 spec 文件 -p DIR,--path=DIR 设置 Python 导入模块的路径(和设置 PYTHONPATH 环境变量的作用相似)。也可使用路径分隔符(Windows 使用分号,Linux 使用冒号)来分隔多个路径 -n NAME,--name=NAME 指定项目(产生的 spec)名字。如果省略该选项,那么第一个脚本的主文件名将作为 spec 的名字 打包命令 pyinstaller -F thired.py pyinstaller -F -i ajai4-i7gr6-001.ico db.py pyinstaller -F -i jykj.ico -w acx-14.spec 没有命令行 pyinstaller -F -w -i "res/jykj.ico" --key "chenziqing-data" text.py --add-data="

Java后端WebSocket的实现

WebSocket 1.什么是WebSocket? webSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。 webSocket使得客户端和服务器之间的数据交换变得更加简单,(在线聊天基础)允许服务端主动向客户端推送数据(服务器可以主动发消息给客户端)。在webSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 其他特点: 较少的控制开销更强的实时性保持连接状态更好的二进制支持可以支持扩展更好的压缩效果 2.为什么需要WebSocket? 举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP协议做不到服务器主动向客户端推送信息。 现在,很多网站为了实现推送技术,所用的技术都是Ajax轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。 而比较新的技术去做轮询的效果是comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。 HTML5定义的WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。 3.WebSocket实现聊天功能(后端) Note:WebSocket在前端实现较为复杂,在后端只是起一个中转消息的功能! 引入依赖: <!-- WebSocket实现聊天功能--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> 编写WebSocket配置类: /** * WebSocket配置类 * * @author liu xiang zheng * @data 4.18 20:57 **/ @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Value("${jwt.tokenHead}") private String tokenHead; @Autowired private JwtTokenUtil jwtTokenUtil; @Autowired private UserDetailsService userDetailsService; /** * 让前端连接后端的websocket服务 * 添加这个Endpoint,这样在网页可以通过websocket连接上服务 * 也就是我们配置websocket的服务地址,并且可以指定是否使用socketJS * 前端使用socketJS去连接后端的服务 * @param registry */ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { /** * 1.

C++string类replace()函数(替换字符串中的子串)

C++中的string类提供了replace()函数,用于替换字符串中的子串。其函数原型如下: string replace (size_t pos, size_t len, const string& str); 其中,pos表示要替换的子串在原字符串中的起始位置,len表示要替换的子串的长度,str表示用来替换的字符串。 replace()函数的使用方法非常简单,只需要传入要替换的子串的位置、长度和替换字符串即可。下面是一个示例: #include <iostream> #include <string> using namespace std; int main() { string str = "hello world"; str.replace(0, 5, "hi"); cout << str << endl; // 输出:hi world return 0; } 在上面的示例中,将字符串中的"hello"替换为"hi",得到了"hi world"这个新的字符串。 20230816 文章目录 C++ string类replace()函数详解目录1. replace()函数基本介绍2. replace()函数的重载版本2.1 replace() 的第一种重载形式2.2 replace() 的第二种重载形式2.3 replace() 的第三种重载形式2.4 replace() 的第四种重载形式 3. 实际应用示例3.1 基本使用3.2 使用迭代器进行替换3.3 使用C风格字符串替换 4. 总结5. 参考链接 C++ string类replace()函数详解 在C++中,string类有一个非常有用的函数:replace()。这个函数被用于替换字符串中的特定子串。这篇文章将深入探讨这个函数的使用方法、重载版本和一些实际应用示例。 目录 replace()函数基本介绍replace()函数的重载版本实际应用示例总结参考链接 1.

SQL存储过程

目录 引言 1、什么是SQL存储过程? 2、SQL存储过程的优点 2.1、提高数据库操作效率 2.2、减少网络流量 2.3、提高安全性 2.4、增强可维护性 2.5、优点 2.6、存储过程和触发器的区别 3、SQL存储过程的实际应用 3.1、添加新订单 3.2、更新订单状态 3.3、调用SQL存储过程 4、总结 引言 在现代软件开发领域,数据库操作是任何应用的核心部分。为了高效地处理数据库查询、更新和管理,开发人员需要采取一些策略来提升性能、可维护性和安全性。其中,SQL存储过程是一个强大的工具,它可以提高数据库操作的效率、可维护性和安全性。 1、什么是SQL存储过程? SQL存储过程是一组预定义的SQL语句,它们以一种事务性的方式封装在一个单元中,可以通过单一的调用来执行。存储过程通常在数据库服务器上创建、编译和存储,然后可以由应用程序通过命名调用。可以提高数据库操作的效率、可维护性和安全性。 2、SQL存储过程的优点 2.1、提高数据库操作效率 存储过程在数据库服务器上进行编译,因此执行速度相对更快。每次调用存储过程时,数据库不需要重新解析SQL语句,这大大减少了执行时间,尤其在需要处理大量数据时更为明显。 例如,假设我们有一个需求是计算某个产品的库存总量。如果每次都在应用程序中拼接SQL语句来执行,会导致每次查询都需要重新解析和执行SQL,从而降低了性能。而通过将计算逻辑封装在存储过程中,我们可以在数据库服务器上预编译并重复使用,大幅提升效率。 2.2、减少网络流量 在传统的数据库操作中,应用程序通常需要多次往返于客户端和数据库之间,以执行多个SQL语句。通过存储过程,可以将多个操作合并为一个,从而减少了网络传输的数据量,提高了性能。 以查询订单信息为例,如果需要获取一张订单的详细信息以及相关的顾客信息和产品信息,传统方式可能需要多次查询,造成了不必要的网络开销。而通过存储过程,我们可以将这些查询整合到一个存储过程中,一次性获取所需信息,从而减少了网络通信的次数。 2.3、提高安全性 存储过程可以被授权的用户直接调用,从而限制了对数据库的直接访问。这有助于减少恶意用户的风险,并为数据库操作提供更多的安全性。此外,存储过程还可以通过参数来执行权限检查,确保只有授权用户可以执行特定的操作。 例如,某个在线商店的数据库中包含了用户的敏感信息,如信用卡号等。通过存储过程,可以只允许特定角色的用户执行更新信用卡信息的操作,从而限制了不必要的访问。 在这些存储过程的优点中,有一个共同点,那就是为了完成某一功能要使用大量的SQL语句,如果只有一条SQL语句的话,就不推荐使用存储过程了,因为只有一条SQL语句的话,单条SQL语句的执行要比存储过程快,因为存储过程再执行的时候有一个预编辑的环节。 2.4、增强可维护性 通过将一系列操作封装在存储过程中,可以实现代码的模块化和可维护性。当需要更改某个功能时,只需修改存储过程,而不必在应用程序中的多处进行修改。这有助于减少代码重复,提高代码的可维护性和可重用性。 假设一个电子商务平台需要对订单进行确认操作,并发送确认邮件。如果这个确认逻辑在多个地方都有实现,当需要修改确认逻辑时,就需要在多个地方进行修改,容易出错。而通过存储过程,可以将确认逻辑封装在一个地方,减少了重复代码,降低了维护成本。 2.5、优点 1、方便修改。为什么这么说呢,是因为存储过程是存储在数据库中的,如果需要涉及到修改SQL语句,那么数据库专业人员只需要去修改数据库中的存储过程就可以,对程序毫无影响,如果用SQL语句的话,SQL语句是写在程序中的,如果涉及到修改SQL语句,那么就需要去修改源程序。 2、存储过程比SQL语句执行要快; 噢?这是为什么呢? 首先存储过程是为了完成特定功能的SQL语句的集合,如果为了完成某一功能,使用了大量的SQL语句,那么执行存储过程只执行一次就可以,而SQL语句呢,则是需要执行多个。 3、存储过程比SQL语句节省资源。 每执行一次SQL语句就要打开一次数据库连接,为了完成某一功能而使用了大量SQL语句,所以数据库连接开关进行了多次,存储过程执行一次就可,数据库连接也是开关一次即可。 2.6、存储过程和触发器的区别 1、存储过程可以直接使用exec或execute来直接调用或执行存储过程,而触发器只能是设定好的触发相关事件时,会自动执行触发器。 2、存储过程有参数,而触发器没有 3、存储过程可以有返回值,而触发器无法返回值 4、存储过程就好比我们编程中的函数或者方法,触发器就好比是事件,单击事件、加载事件等等。 3、SQL存储过程的实际应用 3.1、添加新订单 CREATE PROCEDURE AddOrder @CustomerID INT, @ProductID INT, @Quantity INT AS BEGIN INSERT INTO Orders (CustomerID, ProductID, Quantity, OrderDate, Status) VALUES (@CustomerID, @ProductID, @Quantity, GETDATE(), 'Pending') END 在这个存储过程中,我们接受客户ID、产品ID和数量作为参数,并在Orders表中插入新的订单记录。这样,无论在哪个应用程序中调用这个存储过程,都可以使用相同的逻辑添加新订单,提高了代码的重用性。

Linux磁盘三种扩容方式和分区表重做;LVM移除恢复;取消挂载

一、Linux磁盘扩容 1、直接给 / 分区(或者某一分区)扩容,直接在原有磁盘上增大空间 2、给虚拟机新增一块磁盘,为这块磁盘新建一个分区,把这个新分区扩容到原有分区卷组 3、给虚拟机新增一块磁盘,并把整个磁盘空间扩容到原有分区卷组 注释:一般实际情况都是采用第二种方式,后期空间不够还可以继续创建分区去扩容,而不是把整个磁盘空间都扩容到原有分区,第2、3方式其实逻辑上是一样的道理,一个是把整个磁盘分成一个个的分区去扩容,一个是把整个磁盘去扩容 第一步,拥有基本分区 做成物理卷: pv ------- sdb1、sdb2 打pv的标记。 加入卷组: vg-------- 卷组里面包含:sdb1 sdb2,建立在PV之上。 逻辑卷 lv ------- 逻辑卷是从卷组里面拿空间出来做成的逻辑卷,在起个名,建立在VG之上 制作文件系统------mkfs.xfs lvm路径 挂载 ------mount 使用lvm #制作lvm的时候可以是一整块硬盘也可以是硬盘分好的区并且是还没有用的。必须是没有做文件系统的 1、直接给 / 分区(或者某一分区)扩容,直接在原有磁盘上增大空间 注释:实际生产一般都不会把整块磁盘释放出来,就在原有磁盘创建新的分区去扩容 ######创建LVM挂载##### 1、创建分区并刷新 fdisk /dev/sda && partprobe /dev/sda 2、创建物理卷并加入加入vg pvcreate /dev/sda4 && vgextend vg_os /dev/sda4 3、创建逻辑卷(注意逻辑卷的名字不要搞错,建议用lvs查看一下) lvcreate -L 50G -n lv_data vg_os 4、制作文件系统并挂载 mkfs.xfs /dev/mapper/vg_os-lv_data && mount /dev/mapper/vg_os-lv_data /data && vim /etc/fstab ####LVM扩容#### 如果vg有空间的话之间执行第四步跟第五步就好了 1、创建分区并刷新 fdisk /dev/sda && partprobe /dev/sda 2、创建pv pvcreate /dev/sda5 3、vgextent对卷组vg_os扩容 vgextend vg_os /dev/sda5 4、在原有基础上扩容+20G lvextend -L +20G /dev/mapper/vg_os-lv_var 5、文件系统扩容 xfs_growfs /dev/mapper/vg_os-lv_var ####LVM新盘单独挂载数据#### 1、创建分区并刷新 fdisk /dev/sdb && partprobe /dev/sdb (+500G) 2、创建pv pvcreate /dev/sdb1 3、创建卷组 vgcreate vg1 /dev/sdb1 4、创建逻辑卷(注意逻辑卷的名字不要搞错,建议用lvs查看一下) lvcreate -L 50G -n lv_data vg1 5、制作文件系统并挂载 mkfs.

CDH集群之YARN性能调优

CDH集群之YARN性能调优 本文主要讨论CDH集群的YARN调优配置,关于YARN的调优配置,主要关注CPU和内存的调优,其中CPU是指物理CPU个数乘以CPU核数,即Vcores = CPU数量*CPU核数。YARN是以container容器的形式封装资源的,task在container内部执行。 集群配置 集群的配置主要包括三步,第一是先规划集群的工作主机以及每台主机的配置,第二是规划每台主机的安装的组件及其资源分配,第三是规划集群的规模大小。 工作主机的配置 如下表所示:主机的内存为256G,4个6核CPU,CPU支持超线程,网络带宽为2G 工作主机安装组件配置 第一步已经明确每台主机的内存和CPU配置,下面为每台节点的服务分配资源,主要分配CPU和内存 container资源分配 Physical Cores to Vcores Multiplier:每个container的cpu core的并发线程数,本文设置为1 YARN Available Vcores:YARN可用的CPU核数=Available Container Resources * Physical Cores to Vcores Multiplier,即为44 YARN Available Memory:250880 集群大小 集群的工作节点个数:10 YARN配置 YARN NodeManager配置属性 验证YARN的配置 登录YARN的resourcemanager的WEBUI:http://:8088/,验证’Memory Total’与’Vcores Total’,如果节点都正常,那么Vcores Total应该为440,Memory应该为2450G,即250800/1024*10 YARN的container配置 YARN的container的Vcore配置 YARN的container内存配置 集群资源分配估计 container合理配置检查 MapReduce配置 ApplicationMaster配置 堆与容器大小之比 map task配置 reduce task配置 MapReduce配置合理性检查 Application Master配置的合理性检查 yarn.scheduler.minimum-allocation-vcores <= yarn.app.mapreduce.am.resource.cpu-vcores<= yarn-scheduler.maximum-allocation-vcores yarn.scheduler.minimum-allocation-mb <= yarn.app.mapreduce.am.resource.cpu-vcores <= yarn.scheduler.maximum-allocation-mb Java Heap大小是container大小的75%~90%: 太低会造成资源浪费, 太高会造成OOMMap Task配置的合理性检查

SpringBoot集成EasyExcel实现Excel文件导入导出详解

一 导入EasyExcel依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency> 二 创建实体类 @AllArgsConstructor @NoArgsConstructor @Data public class Student { private Integer id; private String name; private Integer age; private String sex; private String uno; } 三 工具类 //Bean拷贝工具类封装(对象复制,复制共有的字段) public class BeanCopyUtils { ​ private BeanCopyUtils() { } ​ //单个对象的拷贝 public static <V> V copyBean(Object source,Class<V> clazz) { //利用反射来创建接收对象 ​ //创建目标对象 V result = null; try { result = clazz.newInstance(); //实现属性copy BeanUtils.copyProperties(source, result); } catch (Exception e) { e.

Java请求Http接口-OkHttp(超详细-附带工具类)

简介:OkHttp是一个默认有效的HTTP客户端,有效地执行HTTP可以加快您的负载并节省带宽,如果您的服务有多个IP地址,如果第一次连接失败,OkHttp将尝试备用地址。这对于IPv4 + IPv6和冗余数据中心中托管的服务是必需的。OkHttp启动具有现代TLS功能(SNI,ALPN)的新连接,并在握手失败时回退到TLS 1.0,OkHttp支持Android 2.3及更高版本。对于Java,最低要求是1.7。 操作步骤: 1、创建OkhttpClient。 2、mClient执行newCall将Request转化成一个Call。 3、最后call执行excute同步执行,enqueue异步执行。 4、Request主要通过Request.Builder来构建。 5、缓存。 6、取消请求。 导包 <!--okhttp3--> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.9.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> GET请求 get无参 /** * 以get方式调用第三方接口 * @param url */ public static void doGet1(String url) throws IOException { OkHttpClient okHttpClient = new OkHttpClient(); final Request request = new Request.Builder() .url(url) .get()//默认就是GET请求,可以不写 .build(); Response response = okHttpClient.newCall(request).execute(); String string = response.body().string(); System.out.println(string); } get有参 public static void doGet2(String url, Map<String, Object> paramMap) throws IOException { OkHttpClient okHttpClient = new OkHttpClient(); Request.

vue启动配置npm run serve,动态环境变量,根据不同环境访问不同域名

首先创建不同环境的配置文件,比如域名和一些常量,创建一个env文件,先看看文件目录 env.dev就是dev环境的域名,.test就是test环境域名,其他同理,然后配置package.json文件 { "name": "require-admin", "version": "0.0.0", "private": true, "scripts": { "dev": "vite --mode dev", "test": "vite build --mode test", "prod": "vite build --mode prod", "preview": "vite preview" }, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.14", "axios": "^1.3.4", "element-plus": "^2.3.1", "html2canvas": "^1.4.1", "pinia": "^2.0.32", "vue": "^3.2.47", "vue-router": "^4.1.6", "vue3-video-play": "^1.3.1-beta.6", "vuex": "^4.1.0" }, "devDependencies": { "@vitejs/plugin-vue": "^4.0.0", "@vitejs/plugin-vue-jsx": "^3.0.0", "sass": "^1.60.0", "sass-loader": "^13.2.2", "vite": "^4.1.4" } } scripts里面就是我们的运行配置,当我们执行npm run dev的时候就会读取env.dev文件里面的配置,其他同理,需要运行test环境就用test,最后是我们的接口请求配置文件, request.js,import.meta.env.VITE_APP_BASE_UR这个就是引用env文件里面的域名了 import axios from "

WSL2 Ubuntu子系统安装cuda+cudnn+torch

文章目录 前言一、安装cudn二、安装cudnn三、安装pytorch 前言 确保Windows系统版本高于windows10 21H2或Windows11,然后在Windows中将显卡驱动升级到最新即可,WSL2已支持对显卡的直接调用。 一、安装cudn 进入英伟达官网中的cuda下载地址:CUDA Toolkit 11.7 Update 1 Downloads | NVIDIA Developer 由于作者使用的是WSL-Ubuntu20.04长期支持版,所以按照以下配置来进行安装。 作者采用的是runfile(local)下载方式,因为此方式简单,原理为通过wget命令下载cuda安装包,通过sh命令解压安装cuda wget https://developer.download.nvidia.com/compute/cuda/11.7.1/local_installers/cuda_11.7.1_515.65.01_linux.run sudo sh cuda_11.7.1_515.65.01_linux.run 程序会进行解压和安装,速度会比较慢,最后会出现如下界面:输入accept+回车确认 之后便会出现如下界面,前面带有[X]的表示你要安装的工具,最后选择Install+回车确认 安装完成后通过修改bashrc文件配置,来让cuda更好的运行: 使用vim打开配置文件 sudo vi ~/.bashrc 将如下代码加入到文件的最后几行: export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH 使配置文件生效 source ~/.bashrc 使用nvcc -V查看cuda是否安装成功:成功会如下显示 二、安装cudnn 因为作者使用的是WSL2-Ubuntu20.04,所以进入cuDNN下载地址:cuDNN Archive | NVIDIA Developer中选择如下安装包(注意,cudnn的版本必须与安装的cuda百分百对应!!!!),并将此安装包复制到Ubuntu下的/home/文件夹下 通过如下命令解压cudnn包:(使用tar xvf命令) tar xvf cudnn-linux-x86_64-8.9.2.26_cuda11-archive.tar.xz 然后通过cp复制命令,将解压好的cuDNN文件复制到cuda配置文件中: 即配置cuda/include下所有文件和cuda/lib64下所有文件; 运行如下代码即可: sudo cp cudnn-linux-x86_64-8.9.2.26_cuda11-archive/include/* /usr/local/cuda/include/ sudo cp cudnn-linux-x86_64-8.9.2.26_cuda11-archive/lib/* /usr/local/cuda/lib64/ 至此,cudnn已经安装完成。 三、安装pytorch 安装地址:https://pytorch.org/get-started/previous-versions/,找到1.13.1版本,选择对应cuda版本安装 输入以下命令即可 pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 torchaudio==0.

latex 使用 (更新)

2个在线网址 https://cn.overleaf.com/ https://www.texpage.com/ 第二个网址编辑快 不太会卡设置里面选择PDF latex 插入图片 在LaTeX中,\begin{figure}[!t] 、\begin{figure*}[!t] 、\begin{figure}[htbp] 和 \begin{figure*}[htbp] 是用于插入图片的环境。它们之间的区别在于所使用的命令和排版布局。 下面对这些命令进行解释: \begin{figure}[!t]:此命令用于在单栏文档中插入图片。选项 [!t] 表示强制将图片放在当前位置,即尽可能在当前位置插入图片。\begin{figure*}[!t]:此命令用于在双栏文档中插入宽图片,图片将跨越两栏。选项 [!t] 表示尽可能将图片放在当前位置,并占据两栏的宽度。\begin{figure}[htbp]:此命令同样用于在单栏文档中插入图片,选项 [htbp] 是用来指定图片的排版位置,具体含义如下: h:尽可能将图片放在当前位置(here)t:将图片放在页面的顶部(top)b:将图片放在页面的底部(bottom)p:单独放置在一个页面(page) \begin{figure*}[htbp]:此命令用于在双栏文档中插入宽图片,图片将跨越两栏,并且可以使用选项 [htbp] 来指定图片的排版位置。 总结来说,\begin{figure}[!t] 和 \begin{figure*}[!t] 都是尽可能在当前位置插入图片,但\begin{figure*}[!t] 用于双栏文档中的宽图片插入。而 \begin{figure}[htbp] 和 \begin{figure*}[htbp] 都可以指定图片的排版位置,且前者用于单栏文档,后者用于双栏文档的宽图片插入。 \begin{figure}[htbp] \centering \subfloat[The retrieval results on Market-1501]{\includegraphics[width=0.48\textwidth]{rank_market.pdf}}\hfill %\subfloat[Market-\textit{mAP}]{\includegraphics[width=0.25\textwidth]{market_map.eps}} \subfloat[The retrieval results on MSMT17]{\includegraphics[width=0.48\textwidth]{rank_msmt17.pdf}} %\subfloat[MSMT17-\textit{mAP}]{\includegraphics[width=0.25\textwidth]{msmt_map.eps}} \caption{Retrieval results of original queries and adversarial queries generated by the proposed GSVM method.} \label{fig:r_result} \end{figure} \begin{figure}[H] \centering \includegraphics[width=1.0\textwidth]{visual iamge.pdf} \caption{Visual comparisons among different attacks.

IDEAdebug调试时查看时间戳和Date类型的对象,格式化为yyyy-mm-hh

平时debug时遇到Date或者时间戳时看时间不好判断到底是几月几号,希望直接格式化为想要的格式 比如 下面,Date直接显示为 yyyy-mm-hh的格式 解决方案: 无需下载插件,如图 //Date格式化 return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this); //Long格式化 Long time = this; if (time.toString().length() == 10) { //Long为秒时 return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time * 1000)); } if (time.toString().length() == 13) { //时间戳 return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time)); }

日期相互转换的写法记载

LocalDate 使用 //解析日期 String dateStr= "2023年08月17日"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); //LocalDate转换 LocalDate date= LocalDate.parse(dateStr, formatter); System.out.println(date); String format1 = date.format(formatter); System.out.println(format1); 2023-08-17 2023年08月17日

2023全国大学生数学建模竞赛A题B题C题D题E题思路+模型+代码+论文

目录 一. 2023国赛数学建模思路: 赛题发布后会第一时间发布选题建议,思路,模型代码等 详细思路获取见文末名片,9.7号第一时间更新 二.国赛常用的模型算法: 三、算法简介 四.超重要!!!国赛ABCDE题思路模型代码获取见此 一. 2023国赛数学建模思路: 赛题发布后会第一时间发布选题建议,思路,模型代码等 详细思路获取见文末名片,9.7号第一时间更新 二.国赛常用的模型算法: 1、蒙特卡罗算法 该算法又称随机性模拟算法,是通过计算机仿真来解决问题的算法,同时可以通过模拟可以来检验自己模型的正确性,比较好用的算法。 2、数据拟合、参数估计、插值等数据处理算法 比赛中通常会遇到大量的数据需要处理,而处理数据的关键就在于这些算法,通常使用 Matlab 作为工具。 3、线性规划、整数规划、多元规划、二次规划等规划类问题 建模竞赛大多数问题属于最优化问题,很多时候这些问题可以用数学规划算法来描述,通常使用 Lindo、Lingo 软件实现 4、图论算法 这类算法可以分为很多种,包括最短路、网络流、二分图等算法,涉及到图论的问题可以用这些方法解决。 5、动态规划、回溯搜索、分治算法、分支定界等计算机算法 这些算法是算法设计中比较常用的方法,很多场合可以用到竞赛中。 6 、最优化理论的三大非经典算法:模拟退火法、神经网络、遗传算法 这些问题是用来解决一些较困难的最优化问题的算法,对于有些问题非常有帮助,算法的实现有一定困难。 7 、网格算法和穷举法 当重点讨论模型本身而轻视算法的时候,可以使用这种暴力方案,最好使用一些高级语言作为编程工具。 8 、一些连续离散化方法 很多问题都是从实际来的,数据可以是连续的,而经典计算机架构只认的是离散的数据,因此将其离散化后进行差分代替微分、求和代替积分等思想是非常重要的。 9 、数值分析算法 如果在比赛中采用高级语言进行编程的话,那一些数值分析中常用的算法。比如方程组求解、矩阵运算、函数积分等算法就需要额外编写库函数进行调用 10 、图象处理算法 赛题中有一类问题与图形有关,即使与图形无关,论文中也应该要不乏图片的。这些图形如何展示,以及如何处理就是需要解决的问题,通常使用 Matlab 进行处理 三、算法简介 1 、灰色预测模型 ( 一般 ) 解决预测类型题目。由于属于灰箱模型,一般比赛期间不优先使用。满足两个条件可用: ①数据样本点个数 6 个以上 ②数据呈现指数或曲线的形式,数据波动不大 2 、微分方程模型 ( 一般 ) 微分方程模型是方程类模型中最常见的一种算法。近几年比赛都有体现,但其中的要求,不言而喻,学习过程中无法直接找到原始数据之间的关系,但可以找到原始数据变化速度之间的关系,通过公式推导转化为原始数据的关系。 3 、回归分析预测 ( 一般 ) 求一个因变量与若干自变量之间的关系,若自变量变化后,求因变量如何变化; 样本点的个数有要求: ①自变量之间协方差比较小,最好趋近于 0,自变量间的相关性小;

电脑无法识别硬盘问题解决指南

随着电脑成为我们日常工作和娱乐不可或缺的工具,硬盘也扮演着重要的角色。然而,在平时使用硬盘的过程中,我们有时会遇到电脑无法识别硬盘的问题,让人困扰不已。虽然这看似可能是硬盘或电脑本身出了问题,但实际上,许多情况下这个问题可以通过一些简单的方法来解决。本文将为您介绍一些常见的解决方法,希望能帮助您彻底解决电脑无法识别硬盘的困扰。 1.更新驱动:保持设备通畅 电脑出现问题很多时候是因为各种链接处的不顺畅,所以我们可以试试先查看是否因为引荐方面的问题出错。 点击【此电脑】—【计算机】—【管理】—【设备管理器】—【通用串行总线控制器】,检查硬盘的USB驱动是否有问题。如果出现黄色感叹号,说明需要更新驱动。及时更新驱动可以确保设备的正常运作。 2.卸载USB设备:排除驱动冲突 在磁盘管理中,如果发现硬盘未显示或不正常显示,可以尝试卸载USB设备,特别是USB大容量存储设备。右键点击通用串行中的USB大容量存储设备,进行卸载后,尝试重新扫描。这有助于解决因驱动冲突引起的无法识别问题。 3.对硬盘进行格式化:兼容性的关键 有时在连接MAC电脑后,硬盘可能会出现分区格式问题,导致电脑无法识别。您可以通过重新格式化来解决这个问题,但在格式化之前务必备份硬盘中的数据。您可以通过磁盘管理中的操作,删除不正常的分区,重新分配合适的分区格式,以确保硬盘的兼容性和正常使用。 电脑无法识别硬盘的问题在日常使用中可能会让人感到烦恼,但大多数情况下,这个问题并不是无解的。通过更新驱动、卸载USB设备以及适当的格式化,您可以解决这一问题,让硬盘恢复正常的工作状态。然而,为了避免类似问题的发生,建议您在使用硬盘时注意连接的稳定性,不要频繁更换不同系统的电脑,以保证硬盘的稳定性和兼容性。通过了解和掌握这些解决方法,相信您可以轻松排除电脑无法识别硬盘的隐患,让您的工作和娱乐更加畅快。以上就是我今天的分享啦,希望对你有帮助哦。如果你也喜欢我今天的分享的话,那不如就把这篇文章分享给你的朋友们吧!

Hbase的列式存储到底是什么意思?一篇文章让你彻底明白

一、 HBase 定义 Apache HBase™ 是以 hdfs 为数据存储的,一种分布式、可扩展的 NoSQL 数据库。 二、 HBase 数据模型 HBase 的设计理念依据 Google 的 BigTable 论文,论文中对于数据模型的首句介绍。 Bigtable 是一个稀疏的、分布式的、持久的多维排序 map。 之后对于映射的解释如下: 该映射由行键、列键和时间戳索引;映射中的每个值都是一个未解释的字节数组。 最终 HBase 关于数据模型和 BigTable 的对应关系如下: HBase 使用与 Bigtable 非常相似的数据模型。用户将数据行存储在带标签的表中。数 据行具有可排序的键和任意数量的列。该表存储稀疏,因此如果用户喜欢,同一表中的行可 以具有疯狂变化的列。 最终理解 HBase 数据模型的关键在于稀疏、分布式、多维、排序的映射。其中映射 map 指代非关系型数据库的 key-Value 结构。 1)Name Space 命名空间,类似于MSYQL的数据库,每个命名空间下有多个表。HBase 两 个自带的命名空间,分别是 hbase 和 default,hbase 中存放的是 HBase 内置的表,default 2)Table 类似于MYSQL的表。不同的是,HBase 定义表时只需要声明列族即可,不需 要声明具体的列。因为数据存储时稀疏的,所有往 HBase 写入数据时,字段可以动态、按需指定。因此,和关系型数据库相比,HBase 能够轻松应对字段变更的场景。 3)Row 类似于MYSQL中的每一行。HBase 表中的每行数据都由一个 RowKey 和多个 Column(列)组成,数据是按照 RowKey 的字典顺序存储的,并且查询数据时只能根据 RowKey 进行检索,所以 RowKey 的设计十分重

MyBatis-缓存

1.了解一级缓存 MyBatis 一级缓存是指在同一个 SqlSession 中,对于相同的查询语句和参数,MyBatis会将查询的结果缓存起来,下次再执行相同的查询时,直接从缓存中获取结果,避免了重复查询数据库的开销。 一级缓存是默认开启的,可以通过配置来关闭或手动清除。一级缓存的作用范围是在一个SqlSession 内部有效,不同的SqlSession 之间的缓存互相独立。 一级缓存的工作原理如下: 当执行一个查询语句时,MyBatis会先检查缓存中是否已经有该查询的结果,如果有,则直接返回缓存中的结果。 如果缓存中没有该查询的结果,则继续执行查询操作,并将查询结果放入缓存中。 下次执行相同的查询时,MyBatis会先检查缓存中是否已经有该查询的结果,如果有,则直接返回缓存中的结果。 可以通过配置文件中的<setting>元素来控制一级缓存的开启和关闭,例如: <setting name="localCacheScope" value="STATEMENT"/> 将localCacheScope设置为STATEMENT表示关闭一级缓存,设置为SESSION表示开启一级缓存。另外,在需要手动清除一级缓存时,可以调用SqlSession的clearCache()方法来清空缓存。 2.MyBatis 一级缓存的简单示例 首先,假设我们有一个 StudentMapper 接口来操作用户信息,其中包含了查询用户列表的方法 getStudentClssAll()。 然后,在配置文件中设置开启一级缓存 接着,创建 StudentMapper.xml 文件,配置查询语句和映射规则 大家可以写单表的简单查询 在测试类代码中,我们可以通过 SqlSessionFactory 获取一个 SqlSession 实例,并调用 StudentMapper的方法进行查询 运行结果 在上述示例中,第一次调用 studentList1() 方法时,会从数据库中查询用户列表,并将结果放入一级缓存。然后,第二次调用 studentList2() 方法时,会直接从一级缓存中获取结果,而不再访问数据库。 2.了解二级缓存的配置 二级缓存是MyBatis中的一种缓存机制,用于缓存查询结果。它位于SqlSessionFactory的作用域内,可以在多个会话之间共享。 当使用二级缓存时,首先需要在配置文件中进行相应的设置。在 <settings> 标签下,添加 <setting name="cacheEnabled" value="true"/> ,这样即可启用二级缓存。 MyBatis的二级缓存可以提高查询性能,减少数据库访问次数,但需要注意处理对象修改和缓存命中率等问题。 <setting name="cacheEnabled" value="true"/> MyBaits二级缓存的示例 1.首先,在MyBatis配置文件中启用二级缓存。在 <configuration> 标签下添加如下配置 <settings> <setting name="cacheEnabled" value="true"/> </settings> 2.在Mapper接口对应的映射文件中开启二级缓存。在需要缓存结果的查询语句上添加 cache="true" 属性。 <!-- UserMapper.xml --> <mapper namespace="

【Python】Python 去除图片水印

在Python中,你可以使用一些图像处理库来去除图片中的水印。其中一个常用的库是OpenCV,它提供了一些强大的图像处理功能。 首先 你需要安装OpenCV库。你可以使用以下命令在终端中安装它: pip install opencv-python 安装完成后,你可以使用以下代码加载图像并去除水印: import cv2 def remove_watermark(image_path): # 加载图像 image = cv2.imread(image_path) # 定义水印区域的位置和大小 watermark_x = 10 watermark_y = 10 watermark_width = 100 watermark_height = 50 # 创建一个掩膜,将水印区域置为白色(255) mask = 255 * np.ones((watermark_height, watermark_width), dtype=np.uint8) # 将掩膜应用到图像上 image[watermark_y:watermark_y+watermark_height, watermark_x:watermark_x+watermark_width] = cv2.bitwise_and( image[watermark_y:watermark_y+watermark_height, watermark_x:watermark_x+watermark_width], mask) # 显示处理后的图像 cv2.imshow("Image", image) cv2.waitKey(0) cv2.destroyAllWindows() 图片路径 image_path = “path/to/your/image.jpg” 去除水印 remove_watermark(image_path) 在代码中,你需要指定图片的路径,并根据实际情况调整水印区域的位置和大小。然后,通过创建一个掩膜,并将其应用到图像上,即可实现去除水印的效果。最后,使用cv2.imshow()函数显示处理后的图像。

解决@MapKey is required

问题复现: 出现原因: 因为使用了mybatisX插件,导致检查报错mapkey is required 当我们在mapper接口中产生错误,提示@MapKey is required 时 解决方案: 1、关闭mybatis的检查,ctrl+alt+s打开setting,Editor→inspections→mybatis 2、方法上加 @MapKey("id"),指定一下key @MapKey("xx") 指定一个字段xx作为返回Map中的key 输出时id即作为Map中的key

将微信小程序页面转为图片

最近做项目遇到一个需求,那就是要将某个页面转为图片然后传给后端,我仔细找了一圈,发现官方那个Api也就是wx.canvasToTempFilePath生成的图片很有可能为空,太坑了,于是我放弃用它了,选择了用wxml2canvas。 安装wxml2canvas npm init npm install wxml2canvas --save --production npm init 是npm初始化,这个时候根据编译器终端一路回车最终会生成一个package.json文件 –production 是减少安装与业务无关的包,减少项目的体积。如果没有构建npm,需要我们工具-构建npm,或者勾选中 如果你没看到这一项也别急,我们高级版本的微信开发者工具默认支持npm,默认就构建了。然后我们要在utils文件夹下新建index.js,这个文件作用就是为了将页面转为图片的,其代码如下: //此js文件主要用于将页面转图片 import Util from './util' const imageMode = [ 'scaleToFill', 'aspectFit', 'aspectFill', 'widthFix', 'top', 'bottom', 'center', 'left', 'right', 'top left', 'top right', 'bottom left', 'bottom right', ] class Wxml2Canvas { constructor(options = {}) { this.device = (wx.getSystemInfoSync && wx.getSystemInfoSync()) || {} if (!options.zoom) { this.zoom = this.device.windowWidth / 375 } else { this.zoom = options.

CS使用+后渗透

首先,让我们了解CS是什么, 又称“Cobalt Strike” 一款以由美国redteam团队,研 发出来的一款以Metasploit为基础的GUI框架 式渗透测试工具。 它是一款基于java的渗透测试神器,常被业界人称为CS,也被戏称为“线上多人运动平台” 为什么又叫“多人运动平台”? CS使用了C/S架构,它分为客户端和服务端,服务端只要一个,客户端可有多个,多人 连接服务端后可协同测试,与其他人分享shell。 首先官网下载,在kali中解压压缩包并且将压缩包单独放入一个文件 或者在本机中压缩拉入kali。 环境 攻击机:Kali-linux ip:192.168.1.47 靶机 :windows7 ip:192.168.1.45 工具 Cobaltstrike 搭建服务器 首先进入kali,切换root权限,密码kali 进入CS目录,并且给予相关权限 Ls 查看名下10个目录 cd cobalt­­­­_strike_4.5 进入cs目录 chmod 777 * 最高指令,给所有的文件可读,可写可执行权限(777表示可读可写可执行) .运行CS文件,设置服务器IP,密码 ./teamserver +kali的IP + 连接密码 ./teamserver.sh 192.168.1.47 admin 可以看到上图端口是50050,记得后面需要确认端口号 接下来再重新打开一个终端,也就是所谓的客户端,命令按照上面再输一遍 会弹出一个窗口,名字随便写,密码admin 登陆成功的界面 点击左上方CobaltStrike选项——>在下拉框中选择 监听器 接着选择 添加 1. 2. 下面会弹出一个窗口, 名字是监听器名字可随便写, 点击加号,shell反弹的主机,也就是我们kali的ip 此时监听器已经启动可以开始克隆下一步 点击(攻击)选项,选择clone site(网站克隆) 攻击---钓鱼攻击---克隆网站 Clone Url(克隆url): 选择要复制的网站,我这里选择心理登录网站 Local URL(本地url): 如果你自己有网站域名那就填写 勾选一下 下面的选项,这个是监听键盘选项 点击确认之后,会生成一个url,点击url去访问就可以了 为什么上面和下面端口不一样 同一个端口应该是被占用了,这里换了一个8080就可以进去了 通过访问view(视图)的web

C++调用matlab编译的动态链接库dll

Matlab在语法上具有诸多的便利性,可以把matlab的代码(.m文件)为动态链接库dll,之后在c++中调用。本文讲解如何操作以及一些细节。 测试环境: 操作系统:windows10C++:visual studio 2017Matlab版本:Matlab R2020b Matlab代码编译dll 第一步:编写matlab代码。这里以计算标量与向量的乘积为例。选用该实例的原因是为了演示C++调用matlab的函数时如何返回数组。 function [c]=example(a,v) %v为一个向量 %a为double %函数返回标量与向量的乘积 num=length(v); c=zeros(1,num); for i=1:num c(i)=a*v(i); end end 第二步:配置编译环境。在matlab的命令行窗口中输入mbuild -setup,matlab会自动搜索系统安装的vs编译环境。点击其中的Microsoft Visual C++ 2017 (C) 和mex -setup C++ -client MBUILD 配置好环境。 >> mbuild -setup MBUILD 配置为使用 'Microsoft Visual C++ 2017 (C)' 以进行 C 语言编译。 要选择不同的 C 编译器,请从以下选项中选择一种命令: Microsoft Visual C++ 2017 (C) mex -setup:C:\Users\wanyz\AppData\Roaming\MathWorks\MATLAB\R2020b\MBUILD_C_win64.xml C -client MBUILD Microsoft Visual C++ 2019 (C) mex -setup:'C:\Program Files\Polyspace\R2020b\bin\win64\mexopts\msvc2019.xml' C -client MBUILD 要选择不同的语言,请从以下选项中选择一种命令: mex -setup C++ -client MBUILD mex -setup FORTRAN -client MBUILD 第三步: 编译matlab的代码为动态链接库。在matlab的命令行窗口中输入deploytool命令,打开matlab compiler,选择Library Compiler。

Java内存区域(运行时数据区域)和内存模型(JMM)

Java 内存区域和内存模型是不一样的东西,内存区域是指 Jvm 运行时将数据分区域存储,强调对内存空间的划分。 而内存模型(Java Memory Model,简称 JMM )是定义了线程和主内存之间的抽象关系,即 JMM 定义了 JVM 在计算机内存(RAM)中的工作方式,如果我们要想深入了解Java并发编程,就要先理解好Java内存模型。 Java运行时数据区域 众所周知,Java 虚拟机有自动内存管理机制,如果出现内存泄漏和溢出方面的问题,排查错误就必须要了解虚拟机是怎样使用内存的。 下图是 JDK8 之后的 JVM 内存布局。 JDK8 之前的内存区域图如下: 在 HotSpot JVM 中,永久代中用于存放类和方法的元数据以及常量池,比如Class和Method。每当一个类初次被加载的时候,它的元数据都会放到永久代中。 永久代是有大小限制的,因此如果加载的类太多,很有可能导致永久代内存溢出,即万恶的 java.lang.OutOfMemoryError: PermGen ,为此我们不得不对虚拟机做调优。 那么,Java 8 中 PermGen 为什么被移出 HotSpot JVM 了?我总结了两个主要原因: 由于 PermGen 内存经常会溢出,引发恼人的 java.lang.OutOfMemoryError: PermGen,因此 JVM 的开发者希望这一块内存可以更灵活地被管理,不要再经常出现这样的 OOM移除 PermGen 可以促进 HotSpot JVM 与 JRockit VM 的融合,因为 JRockit 没有永久代。 根据上面的各种原因,PermGen 最终被移除,方法区移至 Metaspace,字符串常量移至 Java Heap。 程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。 由于 Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器内核都只会执行一条线程中的指令。

垃圾回收算法

1.引用计数法 ​ 描述:每一个对象都有一个引用计数器,当有引用连接到对象的时候,引用计数加一,当引用离开作用域或者被置为null的时候,引用计数减一。 虽然管理引用计数的开销并不大,但是这项开销在整一个程序的生命周期中持续发生。垃圾回收器会在含有全部对象的列表上面遍历,当发现某个对象的引用计数为0的时候,就释放这个对象的空间。但是这种方法有一个缺陷:如果某个对象在循环中被引用,可能会出现“对象应该被回收,但是引用计数不为0的情况”。引用计数法通常用来说明垃圾回收的工作方式,但是好像没有哪一个java虚拟机是采用这种方式实现垃圾回收的 2.自适应的垃圾回收技术: 一种更快的模型:对于任何“活”的对象,一定能够最终追溯到其存活在堆栈或静态存储空间的引用。由此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有“活”的对象。对于每发现一个引用,必须追踪到它引用的对象,然后是此对象的所有引用,如此反复进行,直到“根源于堆栈和静态存储区中所有的引用”所形成的网络全被访问为止。 在这种方式下,java虚拟机将采用一种自适应的垃圾回收技术。 自适应主要有两种方式: 1)停止—复制法:先暂停程序的运行,然后将所有存活的对象从当前的堆复制到另一个堆,没有被复制的全部都是垃圾,当对象被复制到新的堆的时候,它们是一个挨着一个的,所以新堆保证紧凑排列,然后就可以按照上面的方法简单的分配新的空间了。 当一个对象从一处搬到另一处的时候,所有指向它的那些引用必须全部修正。 对于这种所谓的“复制式回收器”而言,效率会降低,因为,第一,你要有两个堆,然后要在这两个分离的堆中操作,从而,你要维护的是比实际操作多一倍的空间。某些java虚拟机对这个问题的处理方式是这样的,按需从内存中分配几块较大的内存,复制动作发生在这些大块的内存之间。第二,如果程序处于稳定状态,那么可能只会产生少量的垃圾,甚至没有垃圾。这时候,垃圾复制式的回收器还会尽心复制操作,这显然没有必要,而且很浪费。为了避免这种情形,一些java虚拟机会进行检查,要是没有垃圾产生,那么就会切换到另一种工作模式——标记—清理模式,标记—清理的速度非常慢,但是只有少量垃圾的时候,就会很快了。 2)标记—清理法:从堆栈和静态存储区出发,遍历所有的引用,进而找到所有的存活的对象,每当找到一个存活的对象的时候,就会给这个对象设一个标记,在这个过程不会做任何的回收对象操作。只有全部标记完成之后,清理动作才开始,在清理的过程中,没有被标记的对象被释放,不会发生任何复制的动作,所以剩下的堆空间是不连续的。垃圾回收器要是希望得到连续的空间的话,就必须重新整理剩下的对象。 在这里所讨论的java虚拟机中,内存分配以较大的“块”为单位。如果对象较大,那么它会占用单独的块。严格来说,停止—复制法要求在释放旧对象之前,必须把所有存活的对象从旧堆复制到新堆,这导致大量的内存复制行为。有了块之后,垃圾回收器在回收的时候就可以往废弃的块中拷贝对象了。每一个块都有相应的代数来记录它是否存活。通常,如果块在某处被引用,其代数会增加,垃圾回收器会定期对上次回收动作完成之后新分配的块进行整理。垃圾回收器会定期进行完整的清理动作——大型对象仍然不会被复制,其代数会增加,内含小型的那一块则被复制并整理。java虚拟机会进行监视,如果对像都稳定,那么就会切换到标记—清理模式。同样,如果标记—清理的效果变差,那么会切换会停止—复制的方式。 3.标记—整理法 和标记—清理法差不多,但是标记之后不是直接清理消亡的对象,而是让存活的对象往一边移动,然后清理掉边界之后的空间,这样操作之后,就会产生连续的堆空间。 4.分代算法: 分代的垃圾回收策略,是基于这样的事实:不同的对象生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。 年轻代(大部分存活的时间很短): 所有的新生成的对象首先都是放在年轻代的,年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。 由于对象的存活率不高 新生代内存按照8:1:1的比例分为eden区和两个survivor(survivor0,survivor1)区。 但是如果存活的对象超过10%怎么办?为了解决这个问题,我们会把java的堆分为两部分,一部分就是存放新生代的,另一部分就是存放年老代(对象存活的时间很长)的。 以前是没有永久代的,之前永久代是和年老代存放在一起的,但是一些类的信息很少发生变化,于是就将年老代和永久代分开,这有助于性能的提高。 以下两种情况会将对象从新生代转到年老代。 一、新生代里的每一个对象,都有一个年龄,这些对象达到一定的程度的时候(年龄就是熬过GC的次数,每一次GC,如果这个对象存活下来,年龄加一),则会被转移到年老代,这个转入的年龄值在JVM中是可以设置的。 二、在新生代存活的对象占用的内存空间超过10%的时候,多余的对象会被放入年老代。 下面来这种算法谈谈java GC机制: 这种算法分两种GC,一种是minor GC针对年轻代的GC,一种是Full GC。 当Eden满的时候,执行minor GC(采用停止—复制法),将消亡的对象清理,将剩余的对象复制到一个存活区Survivor0(两个存活区总有一个是空白的),此后每次eden区满的时候,就执行mimor GC,并将剩余的对象都添加到survivor0,当survivor0也满的时候,将其中仍然存活的对象直接复制到Survivor1,以后没执行minor GC后,就将剩余的对象添加到Survivor1,这个时候survivor0是空白的。 老年代: 由于存活的对象比较多,而且还存活一些大对象,那么在对老年代GC(Full GC)的时候,如果采用停止—复制法,那会非常的低效,老年代一般采用标记—整理法。发生minor GC之后,虚拟机会检测每一次进入老年代的大小是不是大于老年代剩余空间的大小,如果大于,就触发一次FullGC。 方法区(永久代): 永久代的回收有两种:常量池中的常量,无用的类信息,常量的回收很简单,没有引用了就可以被回收。对于无用的类进行回收,必须保证3点: 类的所有实例都已经被回收 加载类的ClassLoader已经被回收 类对象的Class对象没有被引用(即没有通过反射引用该类的地方) 永久代的回收并不是必须的,可以通过参数来设置是否对类进行回收。 补充知识点: 内存分配与回收策略 1.对象优先在Eden分配 在大多数情况下,对象在新生代的Eden区分配。当Eden区没有足够的空间进行分配的时候,虚拟机将触发一次Minor GC。 2.大对象直接进入老年代 所谓大对象是指,需要大量连续内存空间的java对象。一般来说大对象都直接进入老年区。 3.长期存活的对象进入老年代 虚拟机给每一个对象定义了一个对象年龄计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存在,并且能被Survior容纳的话,将被移动到Survivor空间中,并且对象年龄设置为1,对象在survivor中,没经历一次minor GC,年龄就增加1,当年龄到一定程度的时候,就会被晋升到老年代中。 4.动态对象年龄判定 如果Survivor空间中相同的年龄所有的对象大小的总和大于Survivor空间的一半,年龄大于或者等于该年龄对象就可以直接进入老年代。 空间分配担保 在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者HandlePromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC。 前面提到过,新生代使用复制收集算法,但为了内存利用率,只使用其中一个Survivor空间来作为轮换备份,因此当出现大量对象在Minor GC后仍然存活的情况(最极端的情况就是内存回收后新生代中所有对象都存活),就需要老年代进行分配担保,把Survivor无法容纳的对象直接进入老年代。与生活中的贷款担保类似,老年代要进行这样的担保,前提是老年代本身还有容纳这些对象的剩余空间,一共有多少对象会活下来在实际完成内存回收之前是无法明确知道的,所以只好取之前每一次回收晋升到老年代对象容量的平均大小值作为经验值,与老年代的剩余空间进行比较,决定是否进行Full GC来让老年代腾出更多空间。 取平均值进行比较其实仍然是一种动态概率的手段,也就是说,如果某次Minor GC存活后的对象突增,远远高于平均值的话,依然会导致担保失败(Handle Promotion Failure)。如果出现了HandlePromotionFailure失败,那就只好在失败后重新发起一次Full GC。虽然担保失败时绕的圈子是最大的,但大部分情况下都还是会将HandlePromotionFailure开关打开,避免Full GC过于频繁。

jvm 运行时数据区

Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁 1.1程序计数器 程序计数器也叫pc寄存器 可以看作是当前线程所执行字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条要执行的字节码指令。需要注意的是,每条线程都需要有一个独立的程序计数器,这样在程序多线程执行时才不会出错。 每个JVM只有一个Runtime实例。即为运行时环境,相当于内存结构的中间的那个框框:运行时环境。 1.2虚拟机栈 与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。 经常有人把Java内存区分成堆内存和栈内存,这是一种很粗糙的分法,其中栈内存就是现在讲的虚拟机栈,或者说是虚拟机栈中局部变量表部分。局部变量表存放了编译器克制的各种基本数据类型(如boolean、char等)、对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。 局部变量表所需的内存空间在编译器间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。 1.3本地方法栈 它的作用和虚拟机栈十分相似,不同在于,虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。有的虚拟机直接把本地方法栈和虚拟机栈合二为一。 1.4堆 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存(所有的对象实例以及数组都要在堆上分配内存)。 堆是垃圾收集器管理的主要区域,很多时候也被称为GC堆。Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。 1.5方法区 方法区也是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。运行时常量池也是方法区的一部分。 2.线程 线程是一个程序里的运行单元。JVM允许一个应用有多个执行。线程并行的在Hotspot JVM里,每个线程都与操作系统的本地线程直接映射。当一个Java线程准备好执行以后,此时一个操作系统的本地线程也同时创建。Java线程执行终止后,本地线程也会回收。操作系统负责所有线程的安排调度到任何一个可用的CPU上。一旦本地线程初始化成功,它就会调用Java线程中的run()方法。

git-解决.gitignore文件不生效问题

目录 前言 1、什么是.gitgnore文件 2. 常见问题及解决方案 2.1 文件已经被追踪 2.2缓存问题 2.3 子模块问题 2.4 全局 .gitignore 文件 4.总结 前言 当处理代码版本控制时,.gitignore 文件是一个非常有用的工具,它可以用来指示 Git 忽略某些文件或文件夹,以便它们不会被添加到版本控制中。然而,有时候你可能会遇到 .gitignore 文件不生效的情况。在本篇博客中,我们将探讨一些常见的情况和解决方案,以解决 .gitignore 文件不生效的问题。 1、什么是.gitgnore文件 .gitignore 文件是一个文本文件,用来告诉 Git 忽略哪些文件和文件夹,不将它们包括在版本控制中。这对于保持代码库整洁、避免不必要的文件和敏感信息泄漏非常重要。 2. 常见问题及解决方案 2.1 文件已经被追踪 如果某个文件在你添加 .gitignore 文件之前已经被 Git 跟踪(被添加到版本控制中),那么 .gitignore 文件对这个文件将不起作用。解决方法是需要先从版本控制中移除该文件,然后再将其加入 .gitignore。 # 停止跟踪文件 git rm --cached <文件名> 2.2缓存问题 有时候 Git 可能会缓存一些文件的状态,导致 .gitignore 文件不生效。解决这个问题,你可以尝试清除缓存并重新添加文件。 # 清除缓存 git rm -r --cached . # 重新添加所有文件 git add . 2.3 子模块问题 如果你的项目包含子模块,子模块内部的 .gitignore 文件可能会影响外部项目的 .

docker快速部署wordpress(两台服务器)

第一台机器准备工作 安装部署数据库(yum源安装) # 启动数据库服务 #输入mysql 就可以进入数据库 进入数据库安全加固模式设置密码 进入数据库创建我们需要的用户,数据库(一定要给用户权限!不然导致后面无法初始化) #到这里第一台机器部署就已经完成了 第二台机器部署 #通过yum -y install docker 安装docker #启动服务systemctl start docker #上传我们所需要的wordpress和php包(如有需要私信博主!) #使用docker pull获取镜像源 #docker pull wordpress:5.8.0-php8.0-apache 创建一个文件存放我们连接的另外一台数据库的信息 运行docker容器 并查看端口(如下图便成功) 进入浏览器访问我们的IP地址 http://10.0.0.8 #到这就完成了我们的全部部署(初始化就可以正常使用)

【JVM】垃圾回收算法

目录 一、判断对象已“死” 1.1、引用计数算法 1.2、可达性分析算法 1.3、引用的概念 二、垃圾收集算法理论 2.1、分代收集理论 三、垃圾收集算法 3.1、标记--清除算法 3.2、标记--复制算法 3.3、标记--整理算法 一、判断对象已“死” 在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”(“死去”即不可能再被任何途径使用的对象)了。 1.1、引用计数算法 在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。但是主流的Java虚拟机里面都没有选用引用计数算法来管理内存。 优点:实现简单,效率高。 缺点:很难解决对象之间循环引用的问题。 1.2、可达性分析算法 当前主流的商用程序语言(Java、C#,上溯至前面提到的古老的Lisp)的内存管理子系统,都是通过可达性分析算法来判定对象是否存活的。这个算法的基本思路就是通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。 如下图3-1: 固定可作为GC Roots的对象包括以下几种: 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量。在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。在本地方法栈中JNI(即通常所说的Native方法)引用的对象。Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。所有被同步锁(synchronized关键字)持有的对象。反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。 1.3、引用的概念 无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象是否引用链可达,判定对象是否存活都和“引用”离不开关系。 在JDK 1.2版之后,Java对引用的概念进行了扩充,将引用分为强引用(Strongly Re-ference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)4种,这4种引用强度依次逐渐减弱。 四种引用概念: 强引用:是最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,即类似“Objectobj=new Object()”这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。软引用:用来描述一些还有用,但非必须的对象。在系统要发生oom,会回收所有的软引用对象,如果回收完,还是放不上这个对象,才溢出。,每次垃圾回收的时候,如果对象还没死,就不回收,但是在oom之前,不管有没有死,都会被回收。弱引用:在每次垃圾回收的时候,不管有没有引用,都会被回收。虚引用:相当于什么时候回收都没问题,也无法通过虚引用来取得一个对象实例。 为一个对象设置虚 引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知 二、垃圾收集算法理论 2.1、分代收集理论 当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集” 的理论进行设计的。 分代收集假说: 弱分代假说:绝大多数对象都是朝生夕灭的。强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。跨代引用假说:跨代引用相对于同代引用来说仅占极少数。 这两个分代假说共同奠定了多款常用的垃圾收集器的一致的设计原则:收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。 把分代收集理论具体放到现在的商用Java虚拟机里,设计者一般至少会把Java堆划分为新生代和老年代两个区域 。顾名思义,在新生代中,每次垃圾收集时都发现有大批对象死去,而每次回收后存活的少量对象,将会逐步晋升到老年代中存放。 1、部分收集: 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。另外请注意“Major GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老年代的收集还是整堆收集。混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。 2、整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。 三、垃圾收集算法 3.1、标记--清除算法 1、概念:算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来,标记存活的对象,统一回收所有未被标记的对象。 2、缺点: 执行效率不稳定:如果Java堆中包含大量对象,而且其中大部分是需要被回收的,这时必须进行大量标记和清除的动作,导致标记和清除两个过程的执行效率都随对象数量增长而降低;内存空间的碎片化问题:标记、清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。 3.2、标记--复制算法 1、半区复制:将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。 优点:实现简单,运行高效。 缺点:这种复制回收算法的代价是将可用内存缩小为了原来的一半,空间浪费太多。

C语言小游戏的实现——扫雷(使用C语言基础语法)

前言 结合前边我们所学的C语言知识,本期我们将使用C语言实现一个简单的小游戏——扫雷 目录 前言 总体框架设计 多文件分装程序 各功能模块化实现 初始化棋盘 棋盘打印 埋雷 判赢与排雷 游戏逻辑安排 总结 1. 总体框架设计 和三子棋相同,游戏开始时不需要任何判断与操作直接进入游戏(符合我们所学的do…while结构),然后再根据菜单选择,开始游戏和退出游戏,这部分的操作与三子棋较为类似,这里不再详细讲解(详请看三子棋那期博客)。 int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择>:\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏!\n"); break; default: printf("输入错误请重新输入>:\n"); break; } } while (input); return 0; } 菜单打印部分也是相同 void menu() { printf("******************************\n"); printf("********* 1.play *********\n"); printf("********* 0.exit *********\n"); printf("******************************\n"); } 2. 多文件分装程序 当然根据之前的方法,我将程序分装到多文件,.h文件用于声明函数,test.c文件用于程序设计,game.c文件用于函数定义。 注意:函数的定义和声明是不同的(详细请看函数那期内容)

解构助贷:信贷机构和资金方的后台系统设计

助贷是金融行业中常见的一种业务模式,通过撮合资产方和资金方,达成流量、技术、资金的多方合作,从而实现大体量放贷和低违约率。同时,助贷也是一种更加合规、更加专业化的模式,实现流量归流量,技术归技术,资金归资金。 一、助贷业务介绍 1. 助贷模式的价值 对于助贷方来说,助贷业务一方面可以利用自身技术/资金优势,获得收入;另一方面可以通过合作达成能力互补,提升放贷体量。 2. 助贷模式的角色 在助贷业务模式中,通常有借款人、征信机构、资金方3方角色。征信机构通过风控技术筛选低违约率资产,从而降低资金风险;资金方通过提供资金,达成与资产的匹配,资金规模决定放贷体量。 3. 2种常见业务模式 从业务视角来看,助贷业务有2种常见的业务模式: 模式一:征信机构作为助贷方模式二:牵头资方作为助贷方 两种模式的主要区别: 模式一中,征信机构通常是一些信贷服务提供商,债权关系主要在借款人和征信机构之间; 模式二中,往往是牵头资金方作为强势方,且放贷体量整体较大,债权关系主要在借款人和资金方之间(例如蚂蚁消金的花呗借呗); 通常情况下,作为助贷方的角色系统需要承担还款收款、分润、返回借款结果的职责。 下面对这两种模式进行详细介绍,适合助贷项目owner、金融产品经理、助贷后台系统产品经理作为业务视角补充。 二、模式一:征信机构作为助贷方 1. 业务模式 在业务流程中,作为助贷方的征信机构主要承担风控审核、资产推送、还款计划生成、贷后催收、利息分润计算的功能。简单来说,金融机构是助贷模式中的“裁判”角色,判定这笔资产是否可信,也需要对上下游间制定规则(还款计划和分润)。 2. 系统架构 模式一情况下,征信机构的后台系统本质上是信贷后台系统,后台的系统架构需要包含哪些板块,可以从以下3个维度来考虑:信贷流程、业务粒度、系统基础。 信贷流程维度:贷前、贷中、贷后,对应的就是贷前管理、贷中管理、贷后管理;业务维度:用户、产品、订单,对应的就是用户管理、产品管理、订单管理;系统基础维度:账号、权限、数据,对应的就是账号管理、权限管理、数据管理。 这9个管理模块,可以按照实际业务需要进行调整。 3. 系统主要功能 1)贷前管理 对上游同步的用户/资产进行风控审核,一般包括授信管理、额度管理、进件管理: 授信管理:根据收集到的用户信息,对用户信用进行审核,排除欺诈风险用户;额度管理:通过授信审批的用户,系统会根据用户能力(还款能力、支付能力等)审批额度;进件管理:对用户的借款订单进行审核,包括借款用途、可借额度范围等。 2)贷中管理 对已放款订单进行监控,并根据用户行为评估是否需要展期缩期、提额降额、调整利率(贷中管理非必要能力)。 3)贷后管理 催收管理:催收可分为自动化催收和人工催收,自动化催收需支持催收策略配置,人工催收需支持催收单分配、短信催收、电话催收等功能。 4)用户管理 用户管理提供用户信息追溯和用户审核的能力,包括用户信息、用户审核等功能。 5)产品管理 产品管理也叫资产管理,提供产品包装、资产配置等能力,包括产品配置(新增/审核/上架)、资产信息等功能。 6)订单管理 订单管理提供放款管理和还款管理的能力,提供订单信息状态展示、还款计划、打款状态等功能。 7)账号管理 提供给系统账号赋予角色的能力,包括账号的增删改查功能。 8)权限管理 提供给角色赋予权限的能力,包括角色的增删改查功能。 9)数据管理 提供数据追溯、数据复核、数据报表导出的能力。 4. 场景:消费分期平台的助贷模式 对于大多数信贷机构来说,流量来源是一个重要的问题,需要结合有借贷需求场景的渠道来获客。常见的引流平台有以下几大类:电商平台、本地生活、短视频平台、社区平台...… 越是大额、高频、刚需的需求入口,越有可能转化信贷用户。 以电商平台消费分期业务为例,业务模式如下图: 1)相比于模式一,引入了引流平台的角色,提供场景和流量,收取流量费用(关于流量费结算,可以在还款时由征信机构向引流平台分润结算,也可以在放款时由资金方先与引流平台结算,还款后征信机构与资金方结算)。 2)借款人在电商平台完成交易,电商平台通常会先垫资完成交易;借款人与信贷机构之间是债权关系,用户直接还款给信贷机构。 三、模式二:牵头资方作为助贷方 1. 业务模式 【从模式一到模式二】 在实际业务需要中,上述模式一的资金方可能面临自身资金限制的问题,因此考虑将部分资产导流给外部资金方,提升放贷体量的同时赚取中间收入。此时,该资金方作为牵头资金方承担助贷角色,匹配上游推送过来的风控资产和下游的资金(自有资金+外部资金)。 国内比较典型的案例就是蚂蚁消金公司。征信断直连后的蚂蚁消金,可以看成牵头资金方的角色。淘宝、支付宝作为引流平台创造场景;成立独立的征信机构提供风控技术;蚂蚁消金作为资金方,利用自有资金放贷、或通过助贷/联合贷模式将部分资产导流给外部资方。 【模式二的简化】 模式二的角色更多,系统间交互更复杂,但如果我们作为助贷方视角,可以将其它角色进行合并和抽象,将业务模式化简为如下图: 在助贷业务流程中,作为助贷方的牵头资方主要承担资产承接、匹配撮合、还款计划生成、利息分润计算等功能。我们可以把牵头资金方看成“中介”,将资产匹配给合适的资金方,赚取中间费用。 另外,根据出资比例不同,牵头资金方可开展的贷款业务有3种类型: 自有资金放贷:100%牵头资金方出资,无需与其它资金方分润;助贷:将资产匹配给外部资金方,100%外部资方出资,牵头资方赚取中间费用;联合贷:牵头资方和外部资方联合出资(出资比例自行协商),按出资比例或协商分润比例进行分润。 2. 后台系统架构 牵头资金方的助贷后台系统,更侧重于对资产侧和资金侧的对接,以及资产资金的匹配。我们根据以下3个维度来设计系统模块:业务生态、业务粒度、系统基础。 业务生态:资产侧、资金侧,对应的是资产管理、资金管理;业务粒度:用户、产品、订单,对应用户管理、产品管理、订单管理;系统基础:账号、权限、数据,对应账号管理、权限管理、数据管理。 也就是包括以下模块:资产管理、资金管理、用户管理、产品管理、订单管理、账号管理、权限管理、数据管理。

【Lua】 Lua学习笔记(六)

文章目录 零、相关文章一、前言二、 Lua table(表)(2.1) table 的构造(2.2) Table的操作(2.2.1)table.concat()(2.2.2)table.insert()(2.2.3)table.remove()(2.2.4)table.sort()(2.2.5)table.maxn()(2.2.6)获取 table 长度 三、Lua 模块与包(3.1)require 函数(3.2)加载机制(3.3)C 包 零、相关文章 【Lua】 Lua学习笔记(一) 【Lua】 Lua学习笔记(二) 【Lua】 Lua学习笔记(三) 【Lua】 Lua学习笔记(四) 【Lua】 Lua学习笔记(五) 一、前言 哈喽大家好,我是 FEZ98 ,今天继续系统学习Lua。这个系列是我系统学习Lua语言的学习笔记,我会把遇到的一些比较值得记录与关注的知识写在里面,供自己以后进行回顾。 二、 Lua table(表) table 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型,如数组,字典等。其使用关联型数组,可以用任意类型的值来作为数组的索引,但这个值不能是 nil。table 的大小不是固定的,可以根据需要添加长度。 Lua 也是通过 table 来解决模块(module)、包(package)和对象(Object)的。例如 string.foormat 表示使用 “format” 来索引table string。 (2.1) table 的构造 构造器是创建和初始化表的表达式。表是 Lua 特有的数据结构。 最简单的构造函数是{},可以用来创建一个空表,也可用来初始化数组。 实例: 如上图所示,我们创建一个表 myTable 并初始化后,当我们将 myTable 赋值给 otherTable 时,两个表的都指向同一个内存,如果 myTable设置为 nil , otherTable 仍能访问 table 中的元素,如果没有指定的变量指向 myTable,Lua 的垃圾回收机制会清理对应的内存。

Mac安装opencv后无法导入cv2的解决方法

前提条件:以下两个插件安装成功 pip install opencv-python pip install --user opencv-contrib-python 注:直接用pip install opencv-contrib-python如果报错,就加上“–user" 第一步: 设置–添加python解释器 第二步: 安装了Anaconda3,就去该目录中找到python的解释器,点击右上角,Add 为了区分其他解释器,可以更改下名称: 点击OK保存之后,依然导入报错,提示没有cv2这个模块。原因找到了:在运行界面,需要在右下方切换解释器。如果【Run】不成功,需要等待几分钟,直到下方状态栏切换完毕。

【Git学习】本地文件夹不显示状态图标的解决办法

第一步 win+r,输入regedit.exe,打开注册表 第二步 找到以下路径 “ HKEY_LOCAL_MACHINE–>SOFTWARE–>Microsoft–>Windows–>CurrentVersion–>Explorer–>ShellIconOverlayIdentifiers ” 第三步 将Tortoise开头的几个文件夹重命名,在前面敲几个空格,使得这几个文件夹名称的前面空格最多 第四步 重启资源管理器 打开任务管理器,找到Windows资源管理器,重新启动。查看图标,已经可以正常显示了

MyBatis多表查询

了解resultMap resultMap 是 MyBatis 中用于将查询结果映射到对象的配置项。 在 MyBatis 中,我们可以使用 resultMap 来定义查询结果与 Java 对象之间的映射关系。通过 resultMap,我们可以将查询结果中的列映射到 Java 对象的属性上,以便于进行数据的读取和处理。 一个 resultMap 配置通常包含以下几个部分: id:指定 resultMap 的唯一标识符。 type:指定对应的 Java 对象类型。 result:指定每个列与 Java 对象属性之间的映射关系。 property:Java 对象属性名。 column:查询结果集中的列名。 association:用于处理一对一关联关系的配置项。 collection:用于处理一对多关联关系的配置项。 实现resultMap多表查询 一.先创建好2个实体类 二.在主表实体类中引用第二张表的实体类 三.在 MyBatis 的映射文件中,使用 collection配置将 User 类与 sysRole类关联起来 四.在SysUserMaper接口中添加多表查询方法 五.测试方法 MyBatis自动映射 自动映射的前提:属性名与字段名一致 自动映射级别:autoMappingBehavior <settings> <setting name="autoMappingBehavior" value="[ NONE | PARTIAL | FULL ]" /> </settings>

elementui Cascader 级联选择使用心得

相信大家对于elementui并不陌生,作为适配Vue的优秀UI框架之一,一直被所有的开发者痛并快乐着。今天要记录的就是里边的主角之一Cascader。 首先先介绍一下Cascader ---> 当一个数据集合有清晰的层级结构时,可通过级联选择器逐级查看并选择。 <el-cascader :options="options" clearable></el-cascader> 1、级联选择器经常会用来做地区的选择,在使用过程中发现了第一个有意思的地方----清空,比如我们经常会给元素添加clearable属性 <el-cascader :options="options" clearable></el-cascader> 正常选中没问题 当点击了清空按钮之后 下拉的面板应该回到之前没选中的状态,但没有回到之前的状态 解决办法: <el-cascader ref="addressCascader" :props="addressOptions" filterable clearable v-model="selectOptions" @change="addressChange" @visible-change="visibleChange"></el-cascader> addressChange(data){ if(data && data.length == 0){ this.$refs['addressCascader'][0].$refs.panel.checkedValue = [] // 清空选中值 this.$refs['addressCascader'][0].$refs.panel.clearCheckedNodes() // 清空级联选择器选中状态 this.$refs['addressCascader'][0].$refs.panel.activePath = [] // 清除高亮 this.$refs['addressCascader'][0].$refs.panel.syncActivePath() // 初始化(只展示一级节点) } } 2、面板展开可直接看到选中的数据 visibleChange(val) { if(val) { if (this.$refs['addressCascader']) { if(this.$refs['addressCascader'][0].getCheckedNodes()[0]){ this.$refs['addressCascader'][0].$refs.panel.activePath = this.$refs['addressCascader'][0].getCheckedNodes() } } } } 3、动态加载数据 addressOptions: { lazy: true, lazyLoad: (node, resolve) => { const { level } = node const nodes = [] let type = level ?

Android设备通过蓝牙HID技术模拟键盘实现

目录 一,背景介绍 二,技术方案 2.1 获取BluetoothHidDevice实例 2.2 注册/解除注册HID实例 2.3 Hid report description描述符生成工具 2.4 键盘映射表 2.5 通过HID发送键盘事件 三,实例 一,背景介绍 日常生活中,各种物理遥控器和鼠标等设备,需要摆放和携带,便捷性有待考验。根据蓝牙HID特性,可以用蓝牙协议模仿键盘,来实现空中键盘等功能。 二,技术方案 自Android 9开放BluetoothHidDevice功能后,Android平台可以很简单的通过BluetoothHidDevice模拟键盘鼠标等蓝牙hid device角色。 2.1 获取BluetoothHidDevice实例 BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); bluetoothAdapter.setName("KEYBOARD BT"); bluetoothAdapter.getProfileProxy(context,mProfileServiceListener,BluetoothProfile.HID_DEVICE); 2.2 注册/解除注册HID实例 public static BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() { @Override public void onServiceDisconnected(int profile) { Log.e(TAG, "hid onServiceDisconnected"); if (profile == BluetoothProfile.HID_DEVICE) { mHidDevice.unregisterApp(); } } @SuppressLint("NewApi") @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { Log.e(TAG, "hid onServiceConnected"

python 控制SecureCRT运行脚本

测试工作,经常用到SecureCRT,做了一个最笨的python 脚本来控制CRT ,在运行脚本。 实现原理就是用pyautogui 来模拟快捷键。 #coding=utf-8 import pyautogui as pg import os import time scriptpath= 'D:\script' #开启CRT软件 def openoltcrt(): os.system(r" start D:\SecureCRT\SecureCRT.exe")#CRT 软件放在D盘的 ,用这句来打开CRT pg.press('enter') #打开 CRT 后要选择你的连接。 time.sleep(2) #关闭CRT软件 def closecrt(): pg.hotkey("alt","f4") #用快捷键来关闭 CRT 软件 pg.press('y') #关闭 CRT 软件,按Y 来确认你要关闭。 #在CRT软件里面运行脚本 def runscript(scriptpath,script): pg.keyDown('alt') pg.press('s') #按快捷键ALT+S 来 选择script 菜单 time.sleep(1) pg.press('r') #script 菜单出来了按r 来运行脚本 pg.keyUp('alt') #ALT 键要释放出来,不然要出问题。 time.sleep(1) crt_script_path = str(scriptpath) # 调用脚本打开连接 script1 = os.path.join(crt_script_path, str(script)) # 脚本存放路径,和脚本的名字

知识扫盲:安可、信创、国产化是什么意思?

现在,做 ToB 软件,不管是跟客户沟通、内部会议、还是网上的资讯,经常会看到安可、信创、国产化这样的字眼。下面通过模拟一些问题,来梳理国产化相关的知识。 一、什么是安可? 安可是「安全可靠」的简称。2019 年,我国启动了「安全可靠工程」,旨在加强信息和网络安全领域的能力。通过安全可靠工程,我国证明了具有安全可靠的关键系统、关键应用和关键软硬件产品的研发和集成能力,初步实现了对国外信息技术产品的全方位替代。 二、什么是信创? 信创是「信息技术应用创新产业」的简称,主要包括基础设施、基础软件、应用软件和信息安全等四大领域。可以把信创理解为安可的升级版本。2020 年央行成立金融信创生态实验室,第一批「金融信创解决方案」出现,被公认为信创产业的应用实践元年。 三、什么是 2+8+N 体系? 2020 年,我国提出了「2+8+N」的安全可控体系,其中: 2:党、政府 8:金融、交通、电信、教育、电力、航空航天、石油和医疗八个行业 N:其他行业,例如:汽车、地产、物流等 党和政府部门先行,随后逐步在涉及国计民生的 8 大行业实现安全可靠、自主可控,保障国家信息安全的工作全面展开,最后是其他行业。 四、为什么要发展信创产业? 通过自主研发和推广自主化、国产化的技术标准,从信息安全角度出发,达到自主可控,解决核心技术「卡脖子」的问题,不受制于外国技术的制约。俄乌战争后,微软、西门子、甲骨文、SAP、Autodesk、ABB、GENESYS、 Red Hat、GitHub、Docker 等基础软件、开源社区、核心工业软件厂商相继停止俄罗斯境内服务,值得我们警醒。 所以,安可和信创对于提升我国IT产业核心竞争力、促进数字经济发展以及构建新基建都有着重要的价值。 五、信创产品有哪些发展阶段? 新创产业现在已经进入到了「规模化推广期」,从发展到现在可以分为四个阶段: 萌芽期(1999-2005):1999 年时任科技部部长徐冠华指出中国信息产业缺芯少魂(指的是芯片和操作系统),Xteam、蓝点、中科红旗、银河麒麟、中软 Linux 等公司陆续成立,产业进入萌芽期。 起步期(2006-2013):2006 年,「核高基」政策推出,明确核心电子器件、高端通用芯片及基础软件产品方向,标志着信创产业的起步。 试点期(2014-2017):2014 年中央网络安全与信息化领导小组成立,研究制定网络安全和信息化发展战略、宏观规划和重大政策,推动国家网络安全和信息化法治建设,不断增强安全保障能力。2016年《十三五国家信息化规划》出台,各地开始部署现代信息技术产业生态体系,信 创试点工作进入实质性阶段。 推广期(2018- 至今):2018年-2019年,中兴/华为被美国制裁,美国开始加大对中国进出口限制,我国加速推进自主研发应用试点并扩大范围,信创产业招投标大幅增加,信创产业从「试点实践」进入「规模化推广阶段」。 六、信创产业的范畴有哪些? 信创产业主要涉及基础硬件、基础软件、应用软件、信息安全四大板块。从软件关注的纬度来看,涉及: 芯片:鲲鹏(ARM)、海光(x86)、龙芯(MIPS)、兆芯(x86)、飞腾(ARM)、申威(Alpha)等 操作系统:中标麒麟、银河麒麟、统信UOS、华为欧拉、中兴新支点、中科红旗等 数据库:达梦、易鲸捷、腾讯 TDSQL、华为 GaussDB、中兴通讯 GoldenDB、人大金仓KingBase 等 中间件:东方通、普元中间件、金蝶天燕、宝兰德中间件等 云服务:阿里云、华为云、QingCloud、DaoCloud 等 七、.NET 符合信创要求吗? 很多人一听到 .NET 就会想到微软,一想到微软就会说能跨平台吗?能部署到 Liunx 吗?这种思想还停留在 10 几年前。下面简单说下 .NET 的历程就可以清晰地知道现在的 .NET 并不是以前的 .NET Framework 。 2002 年 2 月 23 日最早的 .

JDK1.6 linux下载安装

一、下载jdk 1、oracle官网:Oracle官网https://www.oracle.com/java/ 2、JDK1.6下载地址 jdk1.6下载地址https://www.oracle.com/java/technologies/javase-java-archive-javase6-downloads.html#jdk-6u45-oth-JPR 3、查看系统版本 用uname -a命令查看 如图所示系统是64位,所以需要安装X64位的版本,而不是X86(X86的jdk是32位的),下载下图的版本。 如果下载时候需要登录oracle账户,有账户就登录,没有就注册一个就可以下载了。 二、 Linux系统安装jdk 1、检查是否安装过了jdk 用 rpm -qa | grep jdk 或者 rpm -q jdk 或者 java -version 三个命令都可以验证是否安装了jdk 以上三种都是没有安装jdk 2、安装jdk 1,先建好文件夹,在usr下新建java文件夹: 用 mkdir /usr/java命令 或者 直接在xftp中直接新建 2,将已经下载好的jdk拷贝到java目录下 3,执行命令赋予安装文件777权限(用自己的用户执行,我用的root) 4、执行./jdk-6u45-linux-x64.bin安装jdk 这样jdk就安装完毕了。 三、配置环境变量 1、进入etc编辑profile文件 2、按键盘的“i”建进入编辑模式,并按键盘的“↓”到文档最后。 3、在文档最后添加下面的配置(具体的jdk版本和路径名需要根据实际情况修改) export JAVA_HOME=/usr/java/jdk1.6.0_45 export JAVA_BIN=/usr/java/jdk1.6.0_45/bin export PATH=$PATH:$JAVA_HOME/bin export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export JAVA_HOME JAVA_BIN PATH CLASSPATH 4、保存退出。 按键盘的“esc”建,左下角的“inster”消失后,输入“:wq” 再回车,就保存推出了。 5、执行生效(点和/之间有空格) . /etc/profile 如果在etc目录下就直接 . profile 6、验证jdk是否安装成功 java -version 如图出现了jdk版本说明jdk安装成功了。

Flask框架-配置日志(1):flask使用日志

一、项目结构 study_flask --| apps/ --| __init__.py --| base/ --| logger.py --| __init__.py --| app.py 二、配置日志功能 1、base/logger.py import os import logging from datetime import datetime,date,timedelta from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler #项目根目录 BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) #日志文件存放的目录 LOGS_DIR = os.path.join(BASE_DIR,'logs') #使用RotatingFileHandler日志处理器,生成的日志文件存放的位置 FILE_LOGS_DIR = os.path.join(LOGS_DIR,'file_handler') #使用TimedRotatingFileHandler日志处理器,生成的日志文件存放的位置 TIME_LOGS_DIR = os.path.join(LOGS_DIR,'time_handler') #创建logs目录 if not os.path.exists(LOGS_DIR): os.makedirs(LOGS_DIR) #创建logs/file_handler目录 if not os.path.exists(FILE_LOGS_DIR): os.makedirs(FILE_LOGS_DIR) #创建logs/time_handler目录 if not os.path.exists(TIME_LOGS_DIR): os.makedirs(TIME_LOGS_DIR) #1、基于文件大小切割的日志处理器 def getLogHandlerFile(): # 文件名,以日期作为文件名 log_file_name = date.today().strftime('%Y-%m-%d.log') # 构建日志文件的路径 log_file_str = os.

STM32CubeMX+FreeRTOS-多任务(线程)点灯

1、SYS配置 2、RCC配置 3、时钟树配置 4、FREERTOS配置 5、定时器提供时钟 6、LED配置 7、工程建立 8、LED宏定义 在main.h下方插入如下代码: /* USER CODE BEGIN Private defines */ #define LED1_ON HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET) #define LED1_OFF HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET) #define LED2_ON HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET) #define LED2_OFF HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET) #define LED3_ON HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET) #define LED3_OFF HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET) /* USER CODE END Private defines */ 9、代码书写 void StartDefaultTask(void const * argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ for(;;) { osDelay(1); } /* USER CODE END StartDefaultTask */ } /* USER CODE BEGIN Header_StartTaskLED1 */ /** * @brief Function implementing the myTaskLED1 thread.

swiper组件点击事件失效的问题

**问题:**当我直接在swiper组件里的div上放@click事件时,点击事件偶尔会失效; 原因: 当swiper设置loop=true时,会生成虚拟slide进行填充,对这些虚拟slide元素进行操作无效; 解决方法: 将点击事件以下代码放进swiperOption里 on: { click(e) { self.slideChange(e, this.realIndex); }, touchStart() { self.touchstart(); }, touchMove() { self.touchmove(); }, touchEnd() { self.touchend(); }, }, 整体展示: swiperOption: { direction: 'horizontal', // 平行方向移动 slidesPerView: 1, // 每次滑动图片一张 // 设定初始化时slide的索引 initialSlide: 0, // 循环 loop: true, // 自动播放 autoplay: { // 隔×秒自动滑动一次 delay: 1500, // 设置为false,用户操作swiper之后自动切换不会停止,每次都会重新启动autoplay。默认为true disableOnInteraction: false, }, // 设置轮播切换效果 effect: 'slide', // 轮播切换动速度 speed: 800, // 小手掌抓取滑动 grabCursor: true, preventLinksPropagation: false, on: { click(e) { self.

vscode Palenight Theme 主题选中颜色优化

如果你有和我一样的困惑,喜欢Palenight Theme主题,但是它的文本选中状态等颜色实在看不清楚,你可以这样做👇 打开settings.json 添加如下配置即可,覆盖它的默认颜色 "workbench.colorCustomizations": { "[Palenight Operator]": { // 选中某个单词时,该单词高亮 "editor.selectionHighlightBackground": "#595e7d", // 搜索结果高亮 "editor.findMatchHighlightBackground": "#7e57c2e8", // 鼠标点击某个单词时,该单词高亮 "editor.wordHighlightBackground": "#595e7d", // 变量定义时,所有该变量的引用都会高亮 "editor.wordHighlightStrongBackground": "#595e7d", } } 其中 [Palenight Operator] 是你当前设置的Palenight Theme 的主题,它包含了如下几个主题,请对应设置 选中效果: 搜索效果:

超详细解决pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it‘s not in yo...

1、在使用pytesseract打开图片是遇到错误,没有找到文件 pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your PATH 2、排查解决: 在我们下载了PIL(命令pip install pillow)后,找到pytesseract.py文件,里面的tesseract_cmd ='tesseract',这里并没有指定文件路径 3、直接在pycharm中安装tesseract-cor失败 4、从网上找到相应的‘Tesseract-OCR’下载安装(寻找对应版本): 地址:https://github.com/tesseract-ocr/tesseract/wiki Windows为例: 点击Tesseract at UB Mannheim 找到符合自己电脑的下载 5、下载完后安装Tesseract-OCR 选择自己安装的目录(要添加到环境变量里面去),一直下一步就完成了 6、添加到环境变量的系统变量(PATH)去 7、增加一个TESSDATA_PREFIX变量名,变量值还是我的安装路径C:\Program Files\Tesseract-OCR\tessdata这是将语言字库文件夹添加到变量中; 8、打开终端,输入:tesseract -v,可以看到版本信息 9、在pytesseract库下的pytesseract.py文件中找到tesseract_cmd = 'tesseract',修改成 tesseract_cmd =r'C:\Program Files\Tesseract-OCR\tesseract.exe' (刚才安装的路径下) 10、再去运行程序 可以简单识别验证码,没有报错了 作者:小邝小邝 链接:https://www.jianshu.com/p/93ab58dea50f 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

从0到1实现GCN——最详细的代码实现

最近论文中需要使用图卷积神经网络(GNN),看了一些关于GCN的代码,还有基于PyTorch Geometric Temporal的代码实现,在这里做一下记录。 GCN原始代码 关于GCN的原理在这里不进行过多阐述,其他文章里面解释的已经很详细了,这里就直接进入到代码的部分。GCN的公式如下: 其中为邻接矩阵;为t时刻输入的节点的特征矩阵;是近似的图卷积滤波器,其中=+(是N维的单位矩阵);是度矩阵;代表需要神经网络训练的权重矩阵;是激活函数Relu。 根据公式逐步实现GCN的代码如下: def get_gcn_fact(adj): ''' Function to calculate the GCN factor of a certain network snapshot 计算GCN因子(图卷积因子D^-1/2AD^-1/2)的函数 :param adj: the adjacency matrix of a specific network snapshot 特定网络快照的邻接矩阵 :return: the corresponding GCN factor 对应的GCN因子 DAD ''' adj_ = adj + np.eye(node_num, node_num) # A+IN row_sum = np.array(adj_.sum(1)) # 求度矩阵D d_inv_sqrt = np.power(row_sum, -0.5).flatten() # D^-1/2 d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0. # 将一些计算得到的NAN值赋0值 d_mat_inv_sqrt = np.mat(np.diag(d_inv_sqrt)) # 将D^-1/2对角化 gcn_fact = d_mat_inv_sqrt*adj_*d_mat_inv_sqrt # 计算D^-1/2AD^-1/2 return gcn_fact 这里根据输入数据代表的邻接矩阵,如果图的拓扑结构不会发生变化,那么GCN因子的值就是固定的,否则要根据时序变化分别计算其对应的GCN因子。

Js读取本地json文件做修改后再保存为json文件

先使用XMLHttpRequest读取json var url = "heliuline.json" var request = new XMLHttpRequest(); request.open("get", url); request.send(null); request.onload = function () { if (request.status == 200) { var json = JSON.parse(request.responseText); console.log(json); } } 编辑json中的数据,比如我想对geojson数据中的数组进行编辑,在坐标数据后面追加高度数据。 for (let i = 0; i < json.features[0].geometry.coordinates.length; i++) { for (let j = 0; j < json.features[0].geometry.coordinates[i].length; j++) { json.features[0].geometry.coordinates[i][j].push(1857) } } 在JavaScript中,浏览器环境中无法直接将数据保存为JSON文件。但是你可以通过将数据转换为JSON字符串,然后让用户下载这个字符串作为一个JSON文件。 const jsonData = JSON.stringify(json); const blob = new Blob([jsonData], { type:"application/json" }); const url = URL.

vector实现二维数组笔记

定义一个二维数组: vector<vector<int> > v; 访问二维vector的元素: 如果指定外层和内层向量的大小,就可用operator[]进行读和写;如果只指定外层向量大小,就能用push_back()函数进行写,不能用operator[]进行读和写。 (1)创建m*n的二维vector: vector<vector <int>> nums(m ,vector<int>(n)); //m*n的二维vector 定义了一个vector容器,元素类型为vector,初始化为包含m个vector对象,每个对象都是一个新创立的vector对象的拷贝,而这个新创立的vector对象被初始化为包含n个0。 vector(n)表示构造一个无名且含n个0的vector对象。 (2)动态创建m*n的二维vector 方法一: vector<vector <int> > nums; nums.resize(m); for(int i=0;i<m;i++) nums[i].resize(n); 方法二: vector<vector <int> > nums; nums.resize(m,vector<int>(n)); (3)初始化二维数组 vector<vector <int>> nums(m , vector<int>(n,0)); //m*n的二维vector,所有元素为0 获得二维数组的行数:nums.size() 获得二维数组的列数:nums[0].size()

MATLAB-repmat函数

函数介绍: 在MATLAB中,repmat函数用于将一个矩阵或向量复制成指定大小的矩阵。 函数语法: 语法如下: B = repmat(A, m, n) 其中,A是要复制的矩阵或向量,m是复制的行数,n是复制的列数。函数将会生成一个大小为m * size(A, 1)行和n * size(A, 2)列的矩阵B。 实例: 以下是一个示例: r = [1 2 3]; % 假设 r 是一个向量 a = repmat(r, 7, 1); disp(a); 输出: 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 在上面的示例中,向量r被复制成了7行,每一行的元素与原始向量r保持一致。 如果r是一个矩阵,a函数同样可以将其复制成指定大小的矩阵。复制的方式是按行复制和按列复制。

Pod控制器

目录 一、Pod控制器概述 1.Pod控制器简介 2.Pod控制器的类型 2.1ReplicaSet 2.2Deployment 2.3DaemonSet 2.4StatefulSet 2.5Job 2.6Cronjob 3.Pod与控制器之间的关系 二、Deployment控制器 三、 StatefulSet控制器 1.StatefulSet组成 2. 为什么要有volumeClaimTemplate? 3.应用场景 4.如何实现服务发现? 5.更新策略 6.部署statefulset 四、 DaemonSet控制器 五、Job控制器 六、CronJob控制器 一、Pod控制器概述 1.Pod控制器简介 Pod控制器,又称之为工作负载(workload),是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资源。 2.Pod控制器的类型 2.1ReplicaSet ReplicaSet:代用户创建指定数量的pod副本,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。 ReplicaSet主要三个组件组成: 用户期望的pod副本数量标签选择器,判断哪个pod归自己管理当现存的pod数量不足,会根据pod资源模板进行新建 帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。 2.2Deployment 工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。 ReplicaSet 与Deployment 这两个资源对象逐步替换之前RC的作用。 2.3DaemonSet 用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务 特性:服务是无状态的 服务必须是守护进程 2.4StatefulSet 管理有状态应用 2.5Job 只要完成就立即退出,不需要重启或重建 2.6Cronjob 周期性任务控制,不需要持续后台运行 3.Pod与控制器之间的关系 controllers:在集群上管理和运行容器的 pod 对象, pod 通过 label-selector 相关联。 Pod 通过控制器实现应用的运维,如伸缩,升级等。 二、Deployment控制器 部署无状态应用管理Pod和ReplicaSet具有上线部署、副本设定、滚动升级、回滚等功能提供声明式更新,例如只更新一个新的image应用场景:web服务 vim nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.

Android 广播发送流程分析

在上一篇文章中Android 广播阻塞、延迟问题分析方法讲了广播阻塞的分析方法,但是分析完这个问题,自己还是有一些疑问: 广播为啥会阻塞呢?发送给接收器就行了,为啥还要等着接收器处理完才处理下一个?由普通的后台广播改为前台广播后,为啥处理的会更快? 这篇参考文章Android 9.0系统源码_广播(三)广播的发送来学习下广播的分发过程,这样对广播阻塞这个问题会理解更深刻。 首先,复习下广播相关的概念。 一、广播相关概念 广播分类 1、标准广播:异步广播,广播发出后,所有注册了的广播接收器都会同时接收到该广播。打个比方:做地铁过程中的语音播报,当列车员(广播发出者)进行语音播报(发送广播)时,所有乘客(注册接收该广播的程序)都可以同时听到语音,不分先后顺序。 sendBroadcast(); 2、有序广播:同步发送,广播发出后,按照注册了的广播接收器的优先级顺序广播,优先级的范围是-1000~1000,数字越大,优先级越高,最先接收到该广播,接收器的优先级通过android:priority设置,并且先收到广播的可以修改或者抛弃该广播,后面优先级小的接收器就无法收到了。同级别的广播,动态优先于静态;同级别同类型的广播,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。 sendOrderedBroadcast(); 3、粘性广播:粘性广播的机制就是发送广播的时候如果没有找到接收器,就会先保存下来,等有广播接收器注册的时候,再把之前保存的广播发出去。因为从Android 5.0(API 21)开始,因为安全性的问题,官方已经正式废弃了粘性广播。 sendStickyBroadcast(); 广播注册方式 1、动态注册:在Context(即Service或Activity)组件中注册,通过registerReceiver()方法注册,在不使用时取消注册unregisterReceiver()。如果广播发送的时候注册Broadcast的组件没有启动的话,是收不到广播的。 2、 静态注册:在AndroidManifest.xml中注册,并在intent-filter中添加响应的action,并新建一个Broadcast组件类来处理注册广播。如果广播发送的时候Broadcast的组件类进程没有启动的话,会收到广播并启动进程。 具体实现可参考Android的有序广播和无序广播(解决安卓8.0版本之后有序广播的接收问题) 区分了Android8.0前后的实现方式。 前台广播及后台广播 前台广播:在广播发送的时候添加Intent.FLAG_RECEIVER_FOREGROUND flag。 后台广播:在广播发送的时候没有Intent.FLAG_RECEIVER_FOREGROUND flag。 默认情况下,Intent是不带Intent.FLAG_RECEIVER_FOREGROUND 的flag的,所以我们默认使用的都是后台广播。 二、广播发送流程 参考文章写得非常详细,建议大家好好看看,我是看完又按照自己的思路整理了一遍写个笔记,只是大体的逻辑思路,重点是帮助我搞清楚上面对广播的一些疑问。 1、调用ContextImpl的sendBroadcast发送广播 frameworks/base/core/java/android/app/ContextImpl.java @Override public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); //直接调用AMS的broadcastIntent方法 ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } 2、调用AMS的broadcastIntent方法 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.

搭建nacos集群

下载Nacos服务器:你可以从Nacos的官方网站(https://github.com/alibaba/nacos/releases)下载最新版本的Nacos服务器。 解压缩文件:将下载的Nacos服务器压缩包解压到你选择的目录中。 配置集群节点:进入解压后的Nacos目录,编辑conf/cluster.conf文件,指定集群中的节点信息。每个节点占据一行,格式为hostname:port。例如: 192.168.0.1:8848 192.168.0.2:8848 192.168.0.3:8848 确保集群节点之间可以相互通信,确保节点的主机名和端口正确设置。 启动集群节点:打开命令行终端,进入解压后的Nacos目录,执行以下命令启动每个节点: ./startup.sh -m standalone 每个节点都应该使用不同的端口号。 验证集群:访问任意一个节点的管理界面,例如:http://hostname:port/nacos。如果一切正常,你应该能够看到Nacos的管理页面。 配置负载均衡:在你的应用程序中使用Nacos作为服务注册和发现的组件时,确保在客户端上配置正确的负载均衡策略,以便在集群中的节点之间进行负载均衡。

C语言学习笔记:C语言中占位符汇总

在C语言学习的时候,我跟随的是中国大学慕课平台中浙江大学翁凯教授的“C语言程序设计”课程,在跟随视频学习的时候我发现老师时常在在课程中提到占位符。却没有系统具体地介绍过。于是特地搜集汇总如下: 定义: 定义:占位符是在C语言开发中负责格式化输出的特殊字符。 下面来看一种常用的格式化例子。 #include <stdio.h> int main(){ int amount = 0; int price = 0; printf("请输入金额(元):"); scanf("%d",&price); printf("请输入票面(元):"); scanf("%d",&amount); int change = amount - price; printf("找您%d元",change); return 0; } 在这个处理找零的程序中,“%d”就是一个占位符,用于在printf函数输出时先占一个位置,在等待变量的具体的值的输入。 但是占位符有具体的格式限定,比如刚才的代码中之所以用“%d”是因为变量amount,price都是int类型的。 那么,不同的变量类型都对应什么占位符呢? C语言占位符汇总: C语言占位符汇总 占位符占位符的具体格式%d,%i整数%f浮点数%p指针%fL长log%e科学计数%g小数或科学计数%a,%A读入一个浮点值(仅C99有效)%c读入一个字符%d读入十进制整数%i读入十进制,八进制,十六进制整数%o读入八进制整数%x,%X读入十六进制整数%s读入一个字符串,遇到空格、制表符或换行符结束。%f,%F,%e,%E,%g,%G用来输入实数,可以用小数或者指数形式输入%u读入一个无符号十进制整数%n至此已读入值的等价字符串%[]扫描字符合集%%读%符号 但是总结了那么多占位符的用法,我却不能很好地理解其中一些占位符的意思,我将其中的一些用红色标记了出来,准备探索具体的用法。 部分占位符具体用法: 1."%c","%s"和"%n"的区别辨析: %c在C语言中代表字符型格式符。 %s在C语言中代表字符串型格式符。 说了等于没说,我们放到代码中具体看一下: #include <stdio.h> int main() { char c = 'A'; printf("用占位符输出一个字符:%c\n",c); char s[] = "字符串"; printf("用占位符输出一个字符串:%s\n",s); return 0; } 看一下输出: 基本懂了,在附上一些字符和字符串的区别作为参考资料。 1.C语言中字符定义为一种基本数据类型(char),表示单个字符;字符串不是基本数据类型,但可以通过char的数组代替,末尾用’\0’结束。 2.字符串一定是一个char型数组,但是char型数组不一定是字符串;char型数组和字符串的 区别就是是否在末尾处有‘\0’。 3.char是一个单独的字符,在32位系统中占用1个字节的存储空间;字符串是固定长度的连续空间(实际上就是数组的定义)。 下面来看更加复杂的"%n": 1.%n与其他格式说明符号不同。%n不向printf传递格式化信息,而是令printf把自己到该点已 打出的字符总数放到相应变元指向的整形变量中。因此%n对于的变元必须是整形指针。

Bug日记-webstorm运行yarn 命令报错

在windows中输入yarn -v正确输出,在webstrom终端中运行yarn命令输出错误 问题:可能是由于 WebStorm 配置问题导致的。 解决方案: 检查 WebStorm 的终端配置:在 WebStorm 中,点击菜单栏的 “File”(文件)选项,然后选择 “Settings”(设置)。在打开的窗口中,找到 “Tools”(工具)下的 “Terminal”(终端)选项。检查 “Shell path”(Shell 路径)字段,确保指向正确的命令行解释器(例如,对于 Windows,应为 cmd.exe 或 PowerShell.exe)。重新启动 WebStorm:有时候,重新启动 WebStorm 可以解决终端相关的问题。尝试关闭 WebStorm 并重新打开它,然后再次在终端中运行 yarn -v 命令。

数据结构:顺序表,链表,双向链表

顺序表,链表以及双向链表都属于线性表,线性顾名思义,就像一根绳子一样按照一定的顺序将数据连接起来,线性表是我们日常存储数据常用的结构,在不同的场景下有着不同的应用。事实上,线性表还包括栈和队列,不过篇幅原因,这篇文章将只详细讲述顺序表,单向链表,双向链表这三种线性表,主要有存储形式,实现步骤,及它们之间的区别。 目录 顺序表 顺序表的存储形式 顺序表的动态实现 顺序表的数据插入 顺序表数据的删除 顺序表的查改 单向链表 单向链表的存储形式 单向链表数据的插入 单向链表数据的删除 双向链表 双向链表的存储形式 带头双向循环链表数据的插入和删除 顺序表与链表的区别 顺序表与链表的优缺点 何为cpu高速缓存命中率 顺序表 顺序表的存储形式 顺序表是在内存中按照顺序存放的数据形式,要求内存地址的连续,因此顺序表要靠数组来实现,但实现方法又分为静态实现和动态实现。静态实现是给定了数组的大小,数据的增删查改只能在这么大的空间里进行,多应用在明确给定了空间的大小对数据进行维护。而动态实现则可以根据需要扩大数据的容量,实现对数据的维护,静态的实现是比较容易的,设立指定大小的数据类型的数组即可,我们重点探讨动态实现。 顺序表的动态实现 实现数据容量的动态扩增,要了解动态内存开辟函数,在C语言中分别是malloc,calloc,realloc具体的功能大家自行查询,这里我们要用到realloc。要实现对已开辟空间的管理,以及当空间满了自动开辟更大的空间的功能,我们需要至少三个变量。第一个是数据类型的指针变量,设为DataType * p,用来维护已经开辟好的空间,第二个变量用来指明当前已存放了多少个数据,设为int size,第三个变量用来指明总共能存放多少个数据,将其设立为 int capacity,当size == capacity时,说明容量满了,需要扩大容量,然后利用realloc函数开辟一块更大的空间再把指针交给DataType * p来维护,为了方便传值使用,我们将这三个变量全部封装到一个结构体里。 代码实现 typedef int DateType; typedef struct SeqList { SLDateType * a; //用来维护已开辟的空间 int size; //表中存放了多少个数据 int capacity; //表中实际能存放的数据 }SL; void SeqListInit(SL* ps) //将封装后的结构体的值进行初始化 { ps->a = NULL; ps->size = 0; ps->capacity = 0; } void SeqListAddCapacity(SL* ps) //实现顺序表的容量的动态开辟 { if (ps->capacity == ps->size) { int newcapacity = ps->capacity == 0 ?

day9 STM32 I2C总线通信

I2C总线简介 I2C总线介绍 I2C(Inter-Integrated Circuit)总线(也称IIC或I2C)是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备,是微电子通信控制领域广泛采用的一种总线标准。 它是同步通信的一种特殊形式,具有接口线少,控制方式简单,期间封装形式少,通信速率高等优点。 I2C总线特征 两条总线线路:一条串行数据线SDA,一条串行时钟线SCL来完成数据的传输及外围器件的扩展;I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址;I2C总线数据传输速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。一般通过I2C总线接口可编程时钟来实现传输速率的调整,同时也跟所接的上拉电阻的阻值有关。I2C总线上的主设备与从设备之间以字节(8位)为单位进行单双工的数据传输。 I2C总线物理拓扑结构 I2C总线在物理连接上分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。 I2C总线协议 I2C协议规定 总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。起始和结束信号总是由主设备产生。总线在空闲状态时,SCL和SDA都保持高电平。 起始信号:当SCL为高电平时,SDA产生由高到低的跳变(下降沿时),表示产生一个起始条件。 结束信号:当SCL为高电平时,SDA产生由低到高的跳变(上升沿时),表示产生一个结束条件。 数据传输 数据传输以字节为单位,主设备在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,数据在时钟线的高电平时被采样,一个字节按数据位从高位到低位的顺序进行传输。主设备在传输有效数据之前,要先指定从设备的地址,一般为7位,然后在发送数据传输的方向位,0表示主设备向从设备写数据,1表示主设备向从设备读数据。 应答信号 接受数据的器件在接收到8bit数据后,向发送数据的器件发出低电平的应答信号,表示已收到数据。这个信号可以是主控器件发出的,也可以是从动器件发出的。总之,是由接收数据的器件发出的。 I2C总线读写操作 主设备往从设备写数据 主设备读从设备数据 主设备读从设备的某个寄存器 STM32F0-I2C控制器特性 软件模拟I2C时序 由于直接控制GPIO引脚电平产生通讯时序时,需要有CPU控制每个时刻的引脚状态,所以称之为“软件模拟协议”方式。 硬件控制产生I2C时序 STM32 的 I2C 片上外设专门负责实现 I2C 通讯协议,只要配置好该外设,它就会自动根据协议要求产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器,就能完成数据收发。这种由硬件外设处理 I2C协议的方式减轻了 CPU 的工作,且使软件设计更加简单。 STM32F0-I2C控制 I2C的主要特点: 64KB片上闪存的F0带2个I2C:I2C1和I2C2 32KB片上闪存的F0只带1个I2C:I2C1 I2C2比I2C1所支持的功能少些,不具备 对SMBus的硬件支持 20mA的驱动能力 模块双时钟域以及从停止模式唤醒

Postman 的 Pre-request Script 使用RSA加解密

文章目录 一、概述 一、概述 Postman内置的Js不支持进行RSA加解密,所以需要引入forgeJS来实现。在 Pre-request Script使用以下脚本: // ------ 导入RSA ------ if (!pm.globals.has("forgeJS")) { pm.sendRequest("https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js", (err, res) => { if (!err) { pm.globals.set("forgeJS", res.text()); executeRSAOperations(); } }); } else { executeRSAOperations(); } function executeRSAOperations() { // 引入 forge 库 eval(pm.globals.get("forgeJS")); // 原始 JSON 数据 const jsonData = { "key1": "value1", "key2": "value2" }; // 将 JSON 数据转换为字符串 const jsonString = JSON.stringify(jsonData); // RSA 公钥 const publicKeyPem = `-----BEGIN PUBLIC KEY----- 公钥内容 -----END PUBLIC KEY-----`; // RSA 私钥 const privateKeyPem = `-----BEGIN PRIVATE KEY----- 私钥内容 -----END PRIVATE KEY-----`; // 使用公钥进行 RSA 加密 const publicKey = forge.

vue3之后台管理系统权限

权限概括 后台管理系统中权限是不可少的一部分,例如:页面权限,菜单权限,按钮权限,路由权限等 文章目录 权限概括定义权限一、用户登录和认证二、前端路由控制三、菜单权限四、数据级别的权限控制五、前端界面的反馈六、按钮权限实现思路总结 定义权限 首先,你需要明确系统中的角色和权限。将权限划分为不同的角色,例如管理员、普通用户、编辑者等。每个角色可以拥有不同的权限,例如访问某个页面、进行某个操作等。定义权限的粒度取决于你的系统需求。 提示:以下是本篇文章正文内容,下面案例可供参考 一、用户登录和认证 实现用户登录功能,并且在用户登录成功后获取用户的角色信息和权限。通常会使用后端 API 来进行用户认证,并获取用户的角色和权限信息。 二、前端路由控制 使用前端路由来控制页面的访问权限。你可以通过在路由配置中添加 meta 信息,标识页面需要的权限,然后在导航守卫中根据用户的角色和权限信息来判断是否允许访问该页面。 三、菜单权限 这里的菜单权限是指登录的时候输入用户名和密码后端会返回的token,然后拿着这个token是访问菜单,有的用户是只有查看功能不具备编辑的,有的是可查看可编辑等等。 四、数据级别的权限控制 在某些情况下,可能需要对数据进行权限控制。例如,某个用户只能查看、编辑自己创建的数据。这时,你需要在后端 API 中实现数据权限过滤,确保用户只能访问其拥有权限的数据。 五、前端界面的反馈 用户无权限访问某个页面或操作时,需要给用户一个友好的提示,告诉用户没有权限进行该操作。可以显示一个错误提示或者跳转到特定的无权限页面。 六、按钮权限 按钮权限是指用户登录页面后,可以去对页面数据做指定的处理,比如说有的页面他只能做添加不能做删除的功能,类似这种就属于按钮权限。 实现思路 RBAC实现思路:用户可以在管理员账号下添加新用户信息并配置相应的页面权限,在用户实现登录的时候点击登录按钮可跳转到指定的菜单和页面。 ABAC实现思路:据业务需求,定义访问策略规则。策略规则是一组规则,用于决定用户是否有权访问某个对象或执行某个操作。例如,可以定义一个策略规则,只有拥有特定角色且数据所有者为当前用户的才能访问数据。 总结 后台管理系统的权限管理是确保系统安全性、合规性和用户体验的关键组成部分。适当的权限控制可以防止未授权的访问,保护敏感数据,并确保系统正常运行

2023牛客暑期多校训练营9 B.Semi-Puzzle: Brain Storm

文章目录 题目大意题解求解回溯 参考代码 题目大意 给定两个数 a , m a,m a,m ,求满足 a u ≡ u ( m o d m ) a^u \equiv u (mod\ \ m) au≡u(mod m) 的一个解。 ( 1 ≤ a , m ≤ 1 0 9 , 0 ≤ u ≤ 1 0 18 ) (1\leq a,m \leq10^9 ,0\leq u\leq 10^{18}) (1≤a,m≤109,0≤u≤1018) 题解 参考了讨论区 https://blog.nowcoder.net/n/576f9463036346f0a0fb04fee50fac75 的方法 求解 考虑使用欧拉定理,考虑 b > = ϕ p b>=\phi_p b>=ϕp​的情况。

ART-Pi程序下载

ART-Pi 原文地址 开发环境: RT-Thread版本:4.0.3 操作系统:Windows10 Keil版本:V5.30 开发板MCU:STM32H750XB 3.1引言 在开始本章之前,笔者先批评下自己,拿到板子后也没看官方的手册,直接凭着经验一通玩,结果导致板子的 boot_loader 被擦除了,出厂固件也烧写不了,使用Keil+STlink还会出现以下错误: 使用STM32CubeProgrammer也烧写不了,出现以下错误: 有问题咱就去找原因,想办法解决啊。这就是BootLoader错误或者工作不正常,另外就是未加载下载算法,导致应用程序固件不能刷入到W25Q64JV 存储器中导致的。因此第一步重新刷入BootLoader,第二步加载下载算法。 官方的回答以及解决办法: 未添加下载算法导致,下载算法在 "sdk-bsp-stm32h750-realthread-artpi\debug\flm\ART-Pi_W25Q64.FLM"然后把ART-Pi_W25Q64.FLM拷贝到MDK安装目录Keil_v5\ARM\Flash下,注意RAM for Algorithm 需要调整成 0x4000。STM32H750 执行片外 QSPI FLASH 上的程序需要有一个 bootloader 来跳转过去,出厂前已经默认烧录了 bootloader,所以可以运行,如果不小心擦除了,请重新烧录 bootloader。 3.2编译和烧写Bootloader 在 BSP 目录下打开 Env,首先进入工程目录,sdk-bsp-stm32h750-realthread-artpi \projects\art_pi_bootloader,如图所示以管理员身份打开 PowerShell: 依次输入如下三个命令: #cmd #mklink /D rt-thread ..\..\rt-thread #mklink /D libraries ..\..\libraries 123 使用 RT-Thread 官方提供的 env 工具按照 rt-thread 开发的正常流程创建 MDK 工程。输入 scons --target=mdk5 命令生成 MDK 工程。 然后打开MDK编译即可,ART-Pi带有烧写工具ST-link,因此可直接下载,但在下载前,注意下Debug的配置, 如果烧写不进去,有可能已经存在 bootloader,勾选 Dowload Function 中的 Erase Full Chip 选项先擦除重新烧写 bootloader,不过默认配置就是上图所示的配置。值得注意的是,Bootloader是烧写到片上Flash中,ART-Pi还另外配有外部存储,毕竟要跑操作系统,内部的Flash还是不够用的。

基于Docker配置Mysql主从同步

前言 该方式只能在主库同步到从库,不支持从库同步到主库 所以写的操作应该在主库进行,读的操作在从库执行 一、创建Mysql挂载目录 主库和从库目录如下 conf:mysql配置文件目录data:存储数据的目录 二、主从配置 分别在主从挂载目录conf创建my.cnf文件,启动容器时将配置文件挂载到容器中 1.主库配置 server-id:服务节点的唯一标识。需要给集群中的每个服务分配一个单独的ID。 log_bin:打开Binlog日志记录,并指定文件名。 log_bin-index:Binlog日志文件 [mysqld] server-id=99 #开启binlog log_bin=master-bin log_bin-index=master-bin.index skip-name-resolve # 设置连接端口 port=3306 # 允许最大连接数 max_connections=200 # 允许连接失败的次数。 max_connect_errors=10 # 服务端使用的字符集默认为UTF8 character-set-server=utf8 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # 默认使用“mysql_native_password”插件认证 #mysql_native_password default_authentication_plugin=mysql_native_password 2.从库配置 server-id:服务节点的唯一标识 relay-log:打开从服务的relay-log日志。 log-bin:打开从服务的bin-log日志记录。 [mysqld] #主库和从库需要不一致 server-id=88 #打开MySQL中继日志 relay-log-index=slave-relay-bin.index relay-log=slave-relay-bin #打开从服务二进制日志 log-bin=mysql-bin #使得更新的数据写进二进制日志中 log-slave-updates=1 # 设置3306端口 port=3306 # 允许最大连接数 max_connections=200 # 允许连接失败的次数。 max_connect_errors=10 # 服务端使用的字符集默认为UTF8 character-set-server=utf8 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # 默认使用“mysql_native_password”插件认证 #mysql_native_password default_authentication_plugin=mysql_native_password 三、拉取Mysql镜像( mysql5.

Postman通用接口加密解决方案

前言: 很对小伙伴对于psotman接口加密不知道如何解决,这里给大家出了一个全网最详细的解决方案,希望能帮助到大家 问题 postman内置加密Api,但不支持RSA加解密码。如何用postman进入rsa加解密?postman中request对象属性皆为只读,如何把提交时的明文变为密文? 解决问题一 postman支持eval函数,我们只要将rsa代码存入环境变量中,在需要的时候调用eval函数就可以解决 解决问题二 postman在每次请求时都会先执行pre-request scripts 中的脚本,在此处我们可以通过request对象拿到 此次请求的参数,但request中的参数只可读。 所以我们只能通过环境变量去占位然后在去加密变量中的值,于是在请求时的内容就会变成加密的内容。 针对postman对{{}}读取的方式,我们可以先在请求参数中将要加密的内容包裹进来,然后在动态创建此变量, 并将变量的加密内容写入此环境变量中,最后在执行请求完毕后将此变量清除 例子 AES加密参数 必需用{{}}将内容包起来,因为在进行请求后postman遇到{{}}时会从环境变量中读取,如果有该环境变量则会动态替换。 $符号后面是我们要加密的内容,可以直接填写内容或写入环境变量的名称 动态生成的环境变量 如果不想在环境变量夹中显示动态生成的环境变量可以将下方tests中的脚本加入到tests中 相关脚本 注意:将脚本加入到collections中会更好Pre-request Scripts // ------ 通用方法 ------ // 提取{{}}中内容 function getBracketStr(text) { let result = '' let regex = /\{\{(.+?)\}\}/g; let options = text.match(regex); if (options && options.length > 0) { let option = options[0]; if (option) { result = option.substring(2, option.length - 2) } } return result } // ------ 导入RSA ------ if(!

python实现视频抽帧代码

制作数据集时对视频流抽帧可使用以下代码: import cv2 import os def extract_frames(video_path, output_path, frame_rate): # 创建输出路径 os.makedirs(output_path, exist_ok=True) # 打开视频文件 video = cv2.VideoCapture(video_path) # 获取视频的帧率 fps = video.get(cv2.CAP_PROP_FPS) print(f"获取视频的帧率:{fps}") # 计算每隔多少帧抽取一帧 frame_interval = int(fps*frame_rate) # 初始化帧计数器 frame_count = 0 num = 0 while True: # 读取视频的一帧 ret, frame = video.read() # 如果无法读取到帧,则退出循环 if not ret: break # 如果帧计数器是frame_interval的倍数,则保存该帧 if frame_count % frame_interval == 0: # 构造保存路径 save_path = os.path.join(output_path, f"frame_{frame_count}.jpg") # 保存帧为图片 cv2.imwrite(save_path, frame) num = frame_count/82 #视频fps为25,设定为3.

linux发送邮件

已qq为例 首先登录qq邮箱开启smtp服务并且拿到授权登录密码 然后编辑 /etc/mail.rc 添加配置 set from= #授权登录的邮箱账号 set smtp=smtps://smtp.qq.com:465 #邮箱服务商地址 set smtp-auth-user= #授权登录的邮箱账号 set smtp-auth-password= #授权密码 set smtp-auth=login set ssl-verify=ignore set nss-config-dir=/root/.certs 背景:由遇到的问题1,和问题2可知阿里云服务器关闭了25端口,发送邮件才会显示链接超时,而且官方不允许打开该端口,而且大部分邮件都是通过25端口 详细的可以查看:常见邮箱端口 所以除了换邮箱之外(端口不是25的,要么是国外不好申请,要么收费,我们摸摸口袋…) 言归正传,我们以网易163邮箱为例,使用SSL下的465端口。 正文:具体操作如下 一、请求数字证书 依次完成以下命令 mkdir -p /root/.certs/ ####创建目录,用来存放证书 echo -n | openssl s_client -connect smtp.qq.com:465 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/.certs/qq.crt ####向163请求证书 certutil -A -n "GeoTrust SSL CA" -t "C,," -d ~/.certs -i ~/.certs/qq.crt ####添加一个SSL证书到证书数据库中 certutil -A -n "GeoTrust Global CA" -t "

day8 STM32数据搬运工 - DMA

DMA简介 DMA,全称为:Direct Memory Access,即直接存储器访问。 DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。 DMA功能框图和特性 5个独立的可配置通道,每个通道都直接连接专用的硬件DMA请求;在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:超高、高、中、低);独立数据 源和目标 数据区的传输宽度(字节、半字节、全字)源和目标 地址必须按数据宽度对齐;支持循环的缓冲器管理;每个通道有3个事件标志(DMA版传输、DMA传输完成和DMA传输出错);存储器和存储器间的传输;外设到存储器和存储器到外设,外设到外设间的传输;闪存、SRAM、APB、AHB外设均可作为访问的 源和目标;可编程的数据传输数目:最大为65536 STM32F0-DMA通道 注:可修改SYSCFG_CFGR1来配置通道的映射关系。 DMA通道优先级 仲裁器根据优先级管理着通道的请求和启动外设 / 存储器的访问; 优先级管理分两个方面: 软件方面:可通过DMA_CCRX寄存器配置每个通道的优先级,优先级分为4各等级: 最高等级; 高优先级; 中等优先级; 低优先级; 硬件方面:如果2个请求有相同的软件优先级,则较低编号的通道比较高编号的通道有较高的优先权。例如:通道2优先于通道4. STM32F0-DMA传输 DMA增量设置 通过设置DMA_CCRx寄存器中的PINC和MINC标志位,外设和存储器的指针在每次传输后可以有选择的完成自动增量当设置为增量模式时,下一个要传输的地址将是签一个地址加上增量值,增量值取决于所选的数据宽度为1、2或4。 DMA循环模式 循环模式用于处理循环缓冲区和连续的数据传输(如ADC的扫描模式)。在DMA_CCRx寄存器中的CIRC位用于开启这一功能。当启动了循环模式,一组的数据传输完成时,计数寄存器将会自动的被恢复成配置该通道是设置的初值,DMA操作将会继续进行。 STM32F0-DMA中断 每一个DMA通道都可以在DMA传输过半、传输完成和传输出错时产生中断。为应用的灵活性考虑,通过设置寄存器的不同位来打开这些中断。 注:这些标志位都在中断状态寄存器DMA_ISR中设置

爬虫获取电影数据----以沈腾参演电影为例

数据可视化&分析实战 1.1 沈腾参演电影数据获取 1.2 电影数据可视化分析 文章目录 数据可视化&分析实战前言1. 网页分析2. 构建数据获取函数2.1 网页数据获取函数2.2 网页照片获取函数 3. 获取参演影视作品基本数据4. 电影详细数据获取4.1 导演、演员、描述、类型、投票人数、评分信息、电影海报获取4.1.1 电影海报获取(以超能一家人为例):4.1.2 导演、演员信息获取:4.1.3 描述、类型、投票人数、评分信息获取: 4.2 IMDb号、感兴趣的人数,看过的人数信息获取4.2.1 IMDb号获取:4.2.2 感兴趣的人数,看过的人数信息获取: 4.3 详细信息获取全代码 总结 前言 大家好✨,这里是bio🦖。今天为大家带来的是数据获取的一种方法,网络爬虫(Web Crawler)。是一种自动化程序,用于在互联网上获取信息、抓取网页内容并进行数据收集。网络爬虫通过访问网页的链接,并从中提取信息和数据,然后将这些数据保存或用于后续处理和分析。可视化分析已更新:1.2 电影数据可视化分析 网络爬虫的工作流程通常包括以下几个步骤: 发送请求:网络爬虫首先发送HTTP请求到指定的URL,请求获取网页内容。获取响应:网站服务器接收到请求后,会返回相应的网页内容作为HTTP响应。爬虫会获取并接收这个响应内容。解析网页:爬虫会对网页内容进行解析,提取出需要的数据和信息。通常使用HTML解析器或XPath等技术来解析网页的结构和元素。数据提取:从解析的网页中,爬虫会提取出感兴趣的数据,如文字、图片、链接等。存储数据:爬虫将提取的数据保存到数据库、文件或其他存储介质中,以备后续分析和应用。 通过本文获取电影数据信息,为后续的数据可视化提供数据支撑~ 1. 网页分析 数据来源于豆瓣电影网,在豆瓣电影网搜索演员沈腾,找到他参演的所有作品(沈腾参演作品)。打开页面发现沈腾一共参演134部作品,其中第一页所有作品均未上映,所以之后获取数据时,可以不用关注第一页。其次应该关注网页链接,查看不同网页链接之间的差异,以便于批量获取数据。 下面是各个页面的链接,通过观察不难看出各个链接之间的差异在start=后的数字,第一页是0,第二页是1,第三页是2……最后一页是13。在上文中说到第一页的所有电影均未上映,未上映的电影没有后续数据可视化可用的数据,故不用获取。使用1到13的循环,便可获取沈腾参演的所有电影数据。 https://movie.douban.com/celebrity/1325700/movies?start=0&format=pic&sortby=time& https://movie.douban.com/celebrity/1325700/movies?start=10&format=pic&sortby=time& https://movie.douban.com/celebrity/1325700/movies?start=20&format=pic&sortby=time& … https://movie.douban.com/celebrity/1325700/movies?start=130&format=pic&sortby=time& 2. 构建数据获取函数 2.1 网页数据获取函数 由于网络爬虫的访问网站的速度很快,会给网站服务器增加负担,因此网站会设置反爬机制。 为了防止网站检测出来,使用header参数伪造浏览器信号。 然后使用requests包获取网页数据,对获得的文本数据使用gbk编码,同时遗忘不能被gbk编码的数据 最后使用BeautifulSoup对获取的数据转化成html格式。 # time: 2023.07.26 # author: bio大恐龙 # define a function to get website infomation with html format import requests from bs4 import BeautifulSoup def get_url_info(url): headers = {'User-Agent':'Mozilla/5.

抖音小程序页面链接/导航

一、navigator ​ <navigator url="" open-type="" hover-class=""></navigator> /* open-type属性 navigate 保留当前页面,跳转到应用内的某个页面,但是不能跳转到 tabBar 页面。 对应 tt.navigateTo redirect 关闭当前页面,跳转到应用内的某个页面,不能跳转到 tabBar 页面。 对应 tt.redirectTo switchTab 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面,目标 tabBar 页面需要在 app.json 中定义。 对应 tt.switchTab navigateBack 关闭当前页面,返回上一页面或多级页面。 对应 tt.navigateBack reLaunch 关闭所有页面,打开应用内的某个页面。 对应 tt.reLaunch */ ​ hover-class 默认值为 navigator-hover { background-color: rgba(0, 0, 0, 0.1); opacity: 0.7; } 示例: 二、页面导航 (1)tt.navigateTo 保留当前页面,跳转到应用内的某个页面,但是不能跳转到 tabBar 页面,使用 tt.navigateBack 可以返回到原页面。 ttml <button type="primary" bindtap="onItemClick">navigateTo跳转页面</button> ttss .title { background-color: white; padding: 20rpx 30rpx; } .

Docker搭建镜像仓库Harbor,并且登录使用

1.先安装好最新版的docker环境( 最新版默认安装了docker compose ) 2.到官网下载最新harbor安装包(最新版) https://github.com/goharbor/harbor/releases/download/v2.8.3/harbor-offline-installer-v2.8.3.tgz 3.将安装包上传到虚拟机中,进行解压 [root@docker-2 harbor]# tar xf harbor-offline-installer-v2.8.3.tgz [root@docker-2 harbor]# ls harbor harbor-offline-installer-v2.8.3.tgz [root@docker-2 harbor]# cd harbor [root@docker-2 harbor]# ls common docker-compose.yml install.sh prepare common.sh harbor.v2.8.3.tar.gz harbor.yml.tmpl LICENSE 4.将harbor.yml.tmpl文件复制一份并改名为harbor.yml [root@docker-2 harbor]# cp harbor.yml.tmpl harbor.yml [root@docker-2 harbor]# ls common docker-compose.yml harbor.yml install.sh prepare common.sh harbor.v2.8.3.tar.gz harbor.yml.tmpl LICENSE 5.更改配置文件harbor.yml [root@docker-2 harbor]# vim harbor.yml hostname: 192.168.118.138 #更改为自己主机的ip地址 http: # port for http, default is 80. If https enabled, this port will redirect to https port

时间序列自监督学习综述

时间序列自监督学习综述 原创 泳鱼 算法进阶 2023-08-15 00:02 发表于福建 收录于合集#时间序列13个 自监督学习(SSL)是一种机器学习方法,最近在各种时间序列任务上取得了令人印象深刻的表现。SSL最显著的优点是它减少了对标记数据的依赖。基于预训练和微调策略,即使是少量的标记数据也能实现高性能。 今天分享一篇来自浙大和阿里等研究者们关于自监督学习用于时间序列的综述文章,文中回顾了现有的与SSL和时间序列相关的调查,为现有的时间序列SSL方法提供了一种新的分类法(图1)。他们将自监督学习时间序列分析归纳为三类:基于生成性的、基于对比性的和基于对抗性的。所有的方法进一步都可以分为十个子类。为了便于时间序列SSL方法的实验和验证,文中还总结了时间序列预测、分类、异常检测和聚类任务中常用的数据集。 图1:所提出的时间序列SSL分类法。 时间序列自监督学习(SSL)的方法通常可以分为三类,这些类别的模型架构如图2所示: 基于生成的方法:这种方法首先使用编码器将输入x映射到表示z,然后使用解码器从z中重构x。训练目标是最小化输入x和重构输入ˆx之间的重构误差。 基于对比的方法:这种方法是应用最广泛的SSL策略(自监督学习)之一,它通过数据增强或上下文抽样来构建正样本和负样本。然后,通过最大化两个正样本之间的互信息(MI)来训练该模型。基于对比的方法通常使用对比相似度度量,如InfoNCE loss。 基于对抗的方法:这种方法通常由一个生成器和一个判别器组成。生成器生成假样本,而判别器用来将它们与真实样本区分开来。 图2:SSL的学习范式。 1 基于生成的方法 在这个类别中,预文本任务是基于给定数据的视图生成预期数据。在时间序列建模的背景下,常用的预文本任务包括使用过去的序列来预测未来的时间窗口或特定的时间戳,使用编码器和解码器来重构输入,以及预测掩码时间序列的不可见部分。 本节从基于自回归的预测、基于自编码器的重构和基于扩散模型的生成3个角度整理了现有的时间序列建模中的自监督表示学习方法(图3)。需要注意的是,基于自编码器的重构任务也被视为一种无监督框架。在SSL的背景下,我们主要将重构任务用作预文本任务,最终目标是通过自编码器模型获得表示。 图3:基于生成的时间序列SSL的三个类别。 1.1 基于自回归的预测 ARF任务是一种基于时间序列的预测任务,其目标是使用时间戳t之前的序列来预测长度为K的窗口。在ARF任务中,预测模型f(·)通常采用自回归模型,即将当前时刻的输出作为下一时刻的输入,以此类推。当K=1时,ARF任务是单步预测模型,即预测下一个时间步的值;当K>1时,ARF任务是多步预测模型,即预测未来多个时间步的值。 ARF任务的数学表达式为公式(1), 其中X[1:t]表示时间戳t之前的序列,ˆX[t+1:t+K]表示预测的目标窗口。预测模型f(·)通常采用自回归模型,即将当前时刻的输出作为下一时刻的输入,以此类推。ARF任务的应用场景包括股票价格预测、气象预测、交通流量预测等。 ARF任务的相关研究和应用。ARF任务可以通过自编码器模型进行无监督学习,从而得到更好的时间序列表示。此外,ARF任务还可以与其他任务结合,例如异常检测、分类和聚类等。 1.2 基于自编码器的重构 自编码器是一种无监督学习的人工神经网络,由编码器和解码器两部分组成 [56]。编码器将输入数据X映射到一个低维表示Z,然后解码器将该低维表示Z映射回原始数据空间,得到重构数据˜X。解码器的输出被定义为重构输入˜X。该过程可以表示为: 自编码器的目标是最小化重构误差,即输入数据与重构数据之间的差异。在时间序列数据的应用中,自编码器可以用于时间序列数据的重构和表示学习,从而提高时间序列数据的表达能力和预测性能。 自编码器模型的变种。例如去噪自编码器、谱分析自编码器、时序聚类友好的表示学习模型等。这些变种模型可以通过引入额外的约束和损失函数来提高自编码器模型的性能和适用性。例如,去噪自编码器可以通过在输入数据中添加噪声来提高模型的鲁棒性和泛化能力;谱分析自编码器可以通过在损失函数中引入频谱约束来提高模型的频域表示能力;时序聚类友好的表示学习模型可以通过在损失函数中引入聚类约束来提高模型的聚类性能。 自编码器模型在时间序列数据的应用场景。例如信号处理、图像处理、语音识别、自然语言处理等。自编码器模型在这些领域中已经取得了一定的成功,并且在未来的研究中仍然具有广泛的应用前景。 1.3 基于扩散模型的生成 扩散模型是一种基于概率的生成模型,它的核心思想是通过两个逆向过程来实现样本生成。具体来说,扩散模型包含两个过程:正向过程和逆向过程。正向过程是将随机噪声注入到数据中,然后逐步完成转移,最终得到一个状态。逆向过程是从噪声分布中生成样本,它通过使用逆向状态转移操作来实现。逆向转移核是逆向过程的关键,但通常很难确定。因此,扩散模型通过深度神经网络来学习逼近逆向转移核,从而实现高效的样本生成。 目前,扩散模型主要有三种基本形式:去噪扩散概率模型(DDPMs)、分数匹配扩散模型和分数随机微分方程(SDEs)模型。DDPMs模型通过去噪来逼近逆向转移核,分数匹配扩散模型通过匹配梯度来逼近逆向转移核,而SDEs模型则通过随机微分方程来逼近逆向转移核。这些模型的设计都是为了解决逆向转移核的问题,从而实现高效的样本生成。 扩散模型在图像合成、视频生成、语音生成、生物信息学和自然语言处理等领域取得了很大的成功。它是一种强大的生成模型,可以用于各种领域的数据生成和建模。扩散模型的优点包括:生成效果好、生成速度快、可扩展性强、可解释性好等。因此,扩散模型在深度学习领域中备受关注,成为了一种重要的生成模型。 2 基于对比的方法 对比学习是一种自监督学习策略,在计算机视觉和自然语言处理中表现出强大的学习能力。与其他模型不同,对比学习方法通过对比正负样本来学习数据表示,其中正样本应该相似,负样本应该不同。因此,对正负样本的选择对于对比学习方法非常重要。图4展示了基于对比的时间序列自监督学习的五个类别。 图4:基于对比的时间序列自监督学习的五个类别 2.1 采样对比法 采样对比方法,将时间序列分成多个固定长度的子序列,然后从每个子序列中随机选择两个不同的采样点作为正样本,同时从其他子序列中随机选择一个采样点作为负样本。通过对比正负样本,采样对比方法可以学习到时间序列的表示。该方法遵循时间序列分析中广泛使用的假设,即相邻的时间窗口或时间戳具有高度相似性。因此正负样本直接从原始时间序列中采样。 采样对比方法遵循时间序列分析中最常用的假设。它具有简单的原则,并且可以很好地模拟局部相关性,对于一些时间序列数据集,采样对比方法可以获得很好的性能。然而,它的缺点在于,在分析长期依赖性时可能会引入虚假的负样本对,导致表示不够优化。因此,在处理长期依赖性时,采样对比方法可能不是最佳选择。此外,采样对比方法需要选择合适的子序列长度和采样点数量,这可能需要一些经验和调整。 2.2 预测对比法 预测对比法用于学习时间序列的表示。该方法通过预测时间序列中未来的信息来学习有意义和信息丰富的表示。具体来说,该方法将时间序列分成多个固定长度的子序列,然后将每个子序列的最后一个时间步作为目标,将其余时间步作为上下文。然后,模型被训练来预测目标时间步的值,同时使用其他子序列的目标时间步作为负样本。通过对比正样本和负样本,预测对比方法可以学习到时间序列的表示。 预测对比方法的优点在于,它可以学习到时间序列中的有意义和信息丰富的表示,捕捉数据中的重要特征和模式。该方法更加关注时间序列数据中的缓慢变化趋势,并且可以提取缓慢的特征。此外,预测对比方法的实现非常简单,易于理解和实现。然而,预测对比方法的缺点在于,它主要关注局部信息,可能无法准确地建模时间序列数据中的长期依赖性。此外,该方法对噪声和异常值比较敏感,这可能会影响模型的表示能力和泛化性能。因此,在处理具有复杂长期依赖性的时间序列数据时,预测对比方法可能不是最佳选择。 2.3 增强对比法 增强对比方法是一种常用的对比学习框架,它通过数据增强技术生成输入样本的不同视图,然后通过最大化来自相同样本的视图的相似性和最小化来自不同样本的视图的相似性来学习表示。具体来说,该方法将每个输入样本分成两个视图,然后使用一个神经网络来学习将这两个视图映射到相同的表示空间中。然后,通过最大化来自相同样本的视图的相似性和最小化来自不同样本的视图的相似性来训练网络。这可以通过使用对比损失函数来实现,其中对于每个样本,网络将学习将其与其他样本区分开来。 增强对比方法的优点在于易于实现和理解,适用于各种类型的时间序列建模任务。此外,该方法可以通过使用各种数据增强技术来增加数据的多样性,从而提高模型的泛化性能。然而,该方法的缺点在于处理时间依赖性是一个挑战,因为增强对比的本质在于区分正样本和负样本对的特征表示,而不是显式地捕捉时间依赖性。选择适当的时间序列数据增强方法也是一个具有挑战性的问题。此外,采样偏差是另一个问题,因为它可能导致生成虚假的负样本,从而影响模型的性能。 2.4 原型对比法 原型对比方法是一种基于聚类约束的对比学习框架,它通过将样本与聚类中心进行对比来学习时间序列数据的表示。该方法可以减少计算量,并鼓励样本在特征空间中呈现出友好的聚类分布。具体来说,原型对比方法将样本分为不同的聚类,将聚类中心作为原型,然后将样本与原型进行对比,以学习时间序列数据的表示。该方法可以通过使用对比损失函数来实现,其中对于每个样本,网络将学习将其与其他样本区分开来。 原型对比方法引入了原型的概念,使样本可以被分配到有限数量的类别中。该方法利用高级语义信息,鼓励样本在特征空间中呈现聚类分布,而不是均匀分布,这更符合真实数据分布。然而,该方法的主要问题是原型的数量需要预先确定,这仍然需要一些先验信息。 2.5 专家知识对比法 专家知识对比方法是一种相对较新的表示学习框架,它可以在对比学习框架中引入先验知识,以帮助模型选择正确的正负样本。例如,在训练过程中,可以选择一个锚点样本和一个正样本,以及一些负样本。然后,网络将学习将锚点样本与正样本相似,并将锚点样本与负样本区分开来。这可以通过使用对比损失函数来实现,其中对于每个样本,网络将学习将其与其他样本区分开来,并将其分配到正确的正负样本中。 专家知识对比方法的特点是可以将领域专家的先验知识或信息引入深度神经网络中,以指导正负样本的选择或相似度的测量。其主要优点在于能够准确选择正负样本。然而,其局限性在于需要提供可靠的先验知识。在大多数情况下,为时间序列数据获取可靠的先验知识并不容易。不正确或误导性的知识可能会导致偏见的表示。 3 基于对抗的方法 基于对抗的方法利用生成对抗网络(GAN)构建预文本任务。GAN包含一个生成器G和一个判别器D。生成器G负责生成类似于真实数据的合成数据,而判别器D负责确定生成的数据是真实数据还是合成数据。因此,生成器的目标是最大化判别器的决策失败率,而判别器的目标是最小化其失败率。生成器G和判别器D是一种相互博弈的关系,因此学习目标是通过最小化损失函数L来优化生成器和判别器的性能。 根据最终任务,现有的基于对抗性的表示学习方法可以分为时间序列生成和插补,以及辅助表示增强。图5展示了基于对抗性的时间序列自监督学习的示意图。 图5:基于对抗性的时间序列自监督学习的三个类别

CSS3:图片边框

简介 图片也可以作为边框,以下是实例演示 注意 实现该效果必须添加border样式,且必须位于border-image-socure之前否则不会生效 实例 <html lang="en"> <head> <style> p { width: 600px; margin: 200px auto; border: 30px solid; //核心代码------------------- border-image-source: url(img.jpg);//设置图片来源 border-image-slice: 30; //设置切割大小 border-image-repeat: round; //设置填充模式 //核心代码------------------- padding: 35px; color: aliceblue; box-shadow: 15px 15px 10px #929696; } </style> </head> <body> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. A, consectetur? Dignissimos officiis iure beatae non ipsum sed temporibus nisi quas. Iste dolorem minus quis. Adipisci necessitatibus eligendi illo rerum recusandae.

RedissonClient入门及常用方法

一,依赖 <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.19.0</version> </dependency> 二,创建工具类 //redisson 配置类 @Configuration public class RedissonConfig { @Bean public RedissonClient redissonClient() { Config config =new Config(); //redis地址 config.useSingleServer().setAddress("redis://127.0.0.1:6379"); return Redisson.create(config); } } RedissonConfig常用方法 使用RedissonConfig配置创建RedissonClient对象: Config config = new Config(); config.useSingleServer() .setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config); 获取RBucket对象: RBucket<String> bucket = redisson.getBucket("myBucket"); bucket.set("Hello Redis"); String value = bucket.get(); 获取RMap对象: RMap<String, Object> map = redisson.getMap("myMap"); map.put("key", "value"); Object value = map.get("key"); 获取RSet对象: RSet<String> set = redisson.

在springboot中用easyexcel实现execl的导入导出功能

EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com) 先看数据,由于是学习数据量很小 1.导入maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency> 2.创建实体类 @Data是Lombook的注解 @TableName,@TableField则是mybatisplus的注解,@TableField是为了实现自动填充 @ExcelProperty @Data @TableName("users")//表user是postsql的内置关键字 public class User { @ExcelProperty("id")//用来标记数据是属于那个列的 private Integer id; @ExcelProperty("name") private String name; @ExcelProperty("age") private Integer age; @ExcelProperty("email") private String email; // 注意!这里需要标记为填充字段 @TableField(fill = FieldFill.INSERT) private Date create_time; @TableField(fill = FieldFill.INSERT_UPDATE) private Date update_time; } 自动填充的工具类 @Slf4j @Component//一定不要忘记把处理器加到IOC容器里面! public class MyMetaObjectHandler implements MetaObjectHandler { //插入时的填充策略 @Override public void insertFill(MetaObject metaObject) { log.

Win11系统更新后硬盘消失,怎么解决

由于Win11系统还不是非常的稳定,因此很多小伙伴都会选择更新推送的补丁,不过最近有小伙伴发现自己的电脑在更新完之后硬盘消失不见了,我们要是遇到这种情况应该怎么办呢? 下面就和小编一起来看看Win11更新后硬盘消失的解决方法吧。 Win11更新后硬盘消失的解决方法 方法一 1、首先右键我们的此电脑,打开“管理”。 2、接着点开左边栏的“磁盘管理”。 3、然后右键消失的硬盘,选择“更改驱动器好和路径”。 4、随后点击左下角的“添加”。 5、再随便分配一个驱动器好,并点击“确定”。 6、最后打开任务管理器,“重新启动”一下“资源管理器”就可以找回硬盘了。 方法二 1、如果在磁盘管理里也找不到消失的硬盘。 2、那么可能是安装win11的时候没有分盘,或选择了错误的格式。 3、那就需要重装一下win11系统,才可以将它找回来。 以上就是小编为大家带来的Win11硬盘消失的解决方法,希望对大家有所帮助。 来源:微点阅读 https://www.weidianyuedu.com/

idea控制台输出中文乱码解决

解决Intellij IDEA控制台logger.info,system.out.println等中文乱码问题 一 : 编写环境乱码二 : 控制台打印乱码(又包含3种): 当我们使用Intellij IDEA开发时,首当其冲就是中文乱码问题,造成中文乱码的根本原因是开发工具和系统环境编码格式不匹配,这篇文章能100%完美解决你所有乱码问题。 乱码主要分为如下2种大类 一 : 编写环境乱码 一 : 解决编写环境乱码 首先是编译器语言 file -> settings ->Appearance(外观) -> theme(主题设置) -> use custom font (最好不设置采用默认语言,或选择如下图能支持中文的语言,避免出现中文乱码) 设置工程项目编码 file -> settings -> Editor -> File Encodings-> 如下图通通UTF-8 二 : 控制台打印乱码(又包含3种): IDEA启动时控制台打印乱码 log4j的logger.info()控制台打印乱码 system.out.println()控制台打印乱码(sout是基于GBK编码的) 二 : 解决控制台打印乱码(3种) IDEA Tomcate启动时控制台打印乱码 根据Intellij IDEA控制台输出,Tomcat Catalina Log出现乱码,因此可以将问题定位到Tomcat上。那么,我们看看Tomcat控制台是否出现乱码。如老夫所料果然乱码,见下图。 解决IDEA Tomcat输出乱码一共两种方案任选一种即可,备注:如下(方案一)与(方案二)不能同时设置。 (方案一) 用Notepad++打开Tomcat安装源码conf文件夹下的logging.properties文件。 如下logging.properties文件内容,将下图标记的UTF-8改为GBK 备注:只修改第五个java.util.logging.ConsoleHandler.encoding = GBK,其它4个可以不修改,效果一样。 打开Intellij IDEA,乱码问题解决 再打开Tomcat控制台也不显示乱码 (方案二) 打开Intellij idea安装目录,在bin目录下的idea.exe.vmoptions和idea64.exe.vmoptions两个文件结尾添加 -Dfile.encoding=UTF-8(注意不要出现空格) 接着再修改idea配置Help ->Edit Custom VM Options

聊聊RedisTemplate的各种序列化器

[版权申明] 非商业目的注明出处可自由转载 出自:shusheng007 文章目录 概述序列化器作用和原理JDK 序列化方式多一点 String 序列化方式JSON 序列化方式 总结源码 概述 在SpringBoot中使用redis基本上都是通过Spring Data Redis,那就不得不说RedisTemplate了。在我刚接触它的时候比较懵逼的就是给其设置各种序列化器了,今天我们来唠唠他们。 序列化器 众所周知,使用RedisTemplate可以对Redis的各种数据结构进行操作,如下图所示。 作用和原理 那我们为什么需要序列化器呢,这是个啥玩意儿? 现在闭目思考一下我们是如何使用redis的?是不是先将数据存储在redis上,然后用的时候再读取出来? 那我们存储在redis里的内容是啥呢?有时是字符串,例如"ShuSheng007",大部分时间是对象,例如Student、List<Student>、Map<String,Student>等等。这些个对象肯定是不能直接存储到redis上的,我们需要想办法先把它们转成byte[]后才能存储到redis上,这就是所谓的序列化。等用的时候还的把byte[]转化为相应的对象,这就是所谓的反序列化。序列化器就是完成这两个功能的。 下面是Spring中Redis序列化器的接口,从源码中可以非常清晰的看到它就干了这两个事情。 public interface RedisSerializer<T> { @Nullable byte[] serialize(@Nullable T t) throws SerializationException; @Nullable T deserialize(@Nullable byte[] bytes) throws SerializationException; } 之所以存在这么多序列化器,是因为我们可以通过各种方式将对象转为byte[],也就是这个接口可以有各种实现类。总结一下,大概有如下几种: JDK 序列化方式 (默认)String 序列化方式JSON 序列化方式XML 序列化方式 其中XML序列化器不怎么用,我们就忽略它吧。 在讲解各种序列化器之前我们应该先搞清楚RedisTemplate都有哪些地方需要设置序列化器。 public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware { @SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null; @SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null; @SuppressWarnings("

全网小说下载器,只需书名,一键下载(Python爬虫+tkinter 实现)小白实战案例系统教学!

大家好,我是小曼呐 前言 ttkbootstrap是一个基于Python的开源库,用于创建漂亮且交互式的GUI应用程序。它是在Tkinter框架之上构建的,提供了一系列的Widget组件和样式,可以帮助开发者快速构建现代化的用户界面。 今天做的是这个东西,蓝色的是进度条 获取数据代码(附上代码) def get_response(html): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36', } response = requests.get(url=html, headers=headers) return response 源码、解答、教程、安装包等资料加V:xiaoyuanllsll 发送验证时记得备注 “M”噢 def search(key): search_url = f'https://www.xzmncy.com/api/search?q={key}' search_data = get_response(search_url).json() search_info = [] num = 1 for index in search_data['data']['search']: dit = { 'num': num, 'name': index['book_name'], 'author': index['author'], 'book': index['book_list_url'].split('/')[-2], } search_info.append(dit) num += 1 return search_info def get_info(book): link = f'https://www.

kubernetes中PV和PVC

目录 一、PV、PVC简介 二、PV、PVC关系 三、创建静态PV 1.配置nfs存储 2.定义PV 3.定义PVC 4.测试访问 四、 搭建 StorageClass + nfs-client-provisioner ,实现 NFS 的动态 PV 创建 1. 配置nfs服务 2.创建 Service Account 3.使用 Deployment 来创建 NFS Provisioner 3.1由于 1.20 版本启用了 selfLink,所以 k8s 1.20+ 版本通过 nfs provisioner 动态生成pv会报错,解决方法如下 3.2创建 NFS Provisioner 4.创建 StorageClass 5.创建 PVC 和 Pod 测试 一、PV、PVC简介 PV 全称叫做 Persistent Volume,持久化存储卷。K8S在指定存储设备空间中逻辑划分创建的可持久化的存储资源对象。 PVC 的全称是 Persistent Volume Claim,是持久化存储的请求。是对PV资源对象的请求和绑定,也是Pod能挂载使用的一种存储卷类型。 PV是集群中的资源。 PVC是对这些资源的请求,也是对资源的索引检查。 二、PV、PVC关系 PV和PVC之间的相互作用遵循生命周期: Provisioning(配置)---> Binding(绑定)---> Using(使用)---> Releasing(释放) ---> Recycling(回收) Provisioning,即 PV 的创建,可以直接创建 PV(静态方式),也可以使用 StorageClass 动态创建Binding,将 PV 分配给 PVCUsing,Pod 通过 PVC 使用该 Volume,并可以通过准入控制StorageProtection(1.

经典题目和算法

常见的解题算法 1.求矩阵中子矩阵元素和不大于K的个数 前缀和+双指针O(n^3) 思路: 1)枚举子矩阵的 左边界i 和 右边界j, 2)用快指针t枚举子矩阵的下边界,慢指针s维护子矩阵的上边界 (s≤t) 3)如果得到的子矩阵的权值和大于 k,则慢指针s 前进,而子矩阵和必将单调不增,慢指针s 继续前进(如图),直到子矩阵的和不大于k,慢指针没必要前进了,因为该子矩阵的所有宽度为 j - i + 1的子矩阵(总共 t - s + 1种)一定满足要求,更新该情况对答案的贡献 t - s + 1;反之,如果慢指针s越界(s > t),则不操作,直接进入下层循环 #include<iostream> using namespace std; typedef long long ll; const int N = 5e2+3; int n, m, k; int a[N][N]` int main(){ ios::sync_with_stdio(false); cin >> n >> m >> k; for(int i=1; i<=n; i++){ for(int j=1; j<=m; j++){ cin >> a[i][j]; a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1]; } } ll ans = 0; for(int i=1; i<=m; i++){ for(int j=i; j<=m; j++){ for(int s = 1, t = 1; t <= n; t ++ ){ while(s <= t && a[t][j] - a[s - 1][j] - a[t][i - 1] + a[s - 1][i - 1] > k) s ++ ; if(s <= t) ans += t - s + 1; } } } cout << ans << '\n'; } 2.

python一键导出百度网盘目录文件

找到百度网盘本地的数据库文件 D:\BaiduNetdisk\users\用户名\BaiduYunCacheFileV0.db 通过查询该数据库文件 获取网盘文件目录 from tkinter import * from tkinter.filedialog import askopenfilename from tkinter.filedialog import asksaveasfilename from tkinter.ttk import * import sqlite3 def select_db_file(): db_file = askopenfilename( title="请选择BaiduYunCacheFileV0.db文件", filetypes=[("db", "*.db")] ) db.set(db_file) def select_save_file(): save_file = asksaveasfilename(filetypes=[("文件", "*.txt")]) f.set(save_file + ".txt") def write_file(file_dict, f, item, gap=""): if item == "/": f.write("━" + "/" + "\n") for i in file_dict["/"]: f.write("┣" + "━" + i + "\n") i = item + i + "

Mysql - 配置Mysql主从复制-keepalived高可用-读写分离集群

目录 高可用: 为什么需要高可用呢? 高可用的主要作用: keepalived是什么?它用在哪里? 什么是VRRP协议,它的作用是什么? 搭建一个基于keepalived的高可用Mysql主从复制读写分离集群 一、项目中的IP地址配置表: 二、项目拓扑图: 项目步骤:(主从复制、读写分离、单vip高可用、双vip高可用) 1、搭建Mysql的主从复制功能: 2、使用Mysqlrouter搭建MySQL的读写分离功能 3、安装配置keepalived服务 4、修改keepalived的配置文件(从36行以下的全部都不需要)(配置单vip的高可用服务) 5、模拟测试:如果master挂掉了,那么vip是否会转移到backup上去呢? 7、外部连接测试keepalived实现的高可用效果: 8、配置双vip实现keepalived配置(跟MySQL的主主复制十分相似) 9、 负载均衡器的使用 10、进行Mysql的压力测试: 脑裂现象 脑裂有没有危害? 什么时候keepalived会产生脑裂现象呢? 情况一:vrid不一样 情况二:防火墙拦截了vrrp报文通信 情况三:修改认证密码,查看是否出现脑裂现象 高可用: 高可用性(High Availability,HA)是指系统或功能提供者在经过设计后,该系统或功能能够长时间的保持在正常状态运行的能力。在现代信息化的环境中,高可用性已经成为了一个必不可少的概念。 为什么需要高可用呢? 防止出现单点故障,主要是因为现代IT系统对于稳定性具有较高的要求,一旦系统出现故障(出现单点故障),将会影响到业务的正常运转,甚至会导致数据丢失等重大问题,从而造成严重的损失。所以,必须确保系统能够尽可能地持续稳定地运行,保证了业务的连续性与数据的可靠性。 高可用的主要作用: 高可用的主要作用包括: 提高系统的稳定性:高可用架构通过冗余、备份、灾备等措施,可以避免单点故障,提高系统的稳定性和可用性,保证服务的连续性。 提高业务的可靠性:高可用架构可以保证业务的可靠性,避免因为系统故障导致的数据丢失等问题,从而保证业务的正常运转。 改善用户体验:高可用架构可以提高系统的性能和响应速度,改善用户的体验,同时还可以提高系统的扩展性和可靠性。 降低维护成本:通过高可用架构降低应用程序的停机时间和维护成本,避免出现服务中断而导致的维护费用增加。 总之,高可用性是一种确保业务连续性的重要手段,它可以避免因为单点故障而带来的损失,并且可以保证业务的持续稳定运行。 keepalived是什么?它用在哪里? keepalived的官方网站:Keepalived for Linux keepalived是一种开源软件,它提供了一个简单而高效的方式来实现负载均衡和故障转移。keepalived能够监视可用服务器的状态,并确保将请求路由到可用服务器上,同时在服务器故障时能够及时切换到备用服务器,以保证服务的高可用性。 keepalived主要用于以下几个方面: 实现负载均衡:keepalived能够使用不同的算法,例如轮询(Round Robin)、加权轮询、最少连接数等,将客户端请求平均地分配到多个后端服务器上,以达到负载均衡的目的。 提高系统的可用性:keepalived可以对多台服务器进行监视,并自动切换到另一个可用的节点来避免单点故障。通过自动检测和切换,keepalived可以确保应用程序始终处于可用状态,从而提高系统的可用性。 构建高可用性架构:通过配合其他技术,例如虚拟IP地址(Virtual IP address)、虚拟路由器冗余协议(VRRP)等,keepalived可以帮助构建高可用性架构,从而保证服务的连续性和稳定性。 总之,keepalived是一款功能强大的开源软件,它可以帮助构建高可用性、可伸缩性和安全性的应用程序。它在各种Web应用程序、负载均衡设备、邮件服务器等系统中得到了广泛的应用。 什么是VRRP协议,它的作用是什么? VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)是一种网络协议,用于提高路由器系统的可用性和可靠性。它通过将多个路由器组合成一个虚拟路由器,只有一个路由器处于活动状态,其他路由器都是备份状态,从而达到提供冗余和故障转移的目的。 vip:virtual ip 虚拟IP地址,这个地址是对外提供服务的 参考文档:VRRP原理及配置 - 榕霖 - 博客园 (cnblogs.com) 具体来说,VRRP的作用包括: 提供冗余:通过将多个路由器组合成一个虚拟路由器,只有一个路由器处于活动状态,其他路由器都是备份状态,当活动路由器出现故障时,备用路由器可以自动接管其工作,确保网络服务不中断。 提高可用性:由于VRRP使用了路由器的冗余,所以即使在单个设备或链路出现故障时,也能够保持网络的连通性,从而提高了网络的可用性和可靠性。 支持负载均衡:当多个路由器同时处于活动状态时,VRRP可以自动将流量分布到各个路由器之间,实现负载均衡。

Mysql 搭建MHA高可用架构,实现自动failover,完成主从切换

目录 自动failover MHA: MHA 服务 项目:搭建Mysql主从复制、MHA高可用架构 实验项目IP地址配置: MHA下载地址 项目步骤: 一、修改主机名 二、编写一键安装mha node脚本和一键安装mha mangaer脚本,并执行安装 三、搭建Mysql主从复制集群(注意所有的Mysql主从复制机器都需要打开二进制日志,可以实现自动故障切换) 四、将安装包 mha4mysql-node和 脚本一键安装mha node脚本传输给Mysql主从复制集群,并运行脚本安装(下载依赖的时候最好翻墙下载) 4.1、mha_manger发送一键安装mha_node的脚本给mysql主从复制集群 4.2、mha_manger上需要配置有mha4mysql-manager-0.58.tar.gz和mha4mysql-node-0.58.tar.gz安装包和对应的一键安装脚本,首先执行一键安装mha4mysql-node-0.58的脚本 4.3、mysql主从复制集群运行一键安装mha4mysql-node-0.58的脚本 五、所有服务器互相建立免密通道 5.1、mha manager对所有mysql服务器建立免密通道 5.2、master对slave1、slave2建立免密通道 5.3、slave1对master、slave2建立免密通道 5.4、slave2对master、slave1建立免密通道 六、在Mysql的主从复制服务器里,配置mha相关信息 6.1、所有mysql服务器(master、slave1、slave2)将mysql命令和mysqlbinlog二进制文件操作命令软链接到/usr/sbin,方便manager管理节点,因为/usr/sbin/ 目录下可以被直接调用。 6.2、所有mysql服务器新建允许manager访问的授权用户mha,密码123456 七、在mha manager节点上配置好相关脚本、管理节点服务器 7.1、mha manager节点上复制相关脚本到/usr/local/bin下 7.2、复制自动切换时vip管理的脚本到/usr/local/bin下 7.3、修改master_ip_failover文件内容,配置vip(只配置vip(192.168.2.227)相关参数,其他默认不修改) 7.4、创建 MHA 软件目录并复制配置文件,使用app1.cnf配置文件来管理 mysql 节点服务器,配置文件一般放在/etc/目录下 7.5、master服务器上手工开启vip 7.6、测试:manager节点上测试ssh免密通道,如果正常最后会输出successfully 7.7、manager节点后台开启MHA 八、故障转移效果测试,模拟matser宕机,指定slave1成为新的master 8.1、模拟master宕机,停掉master 8.2、查看自动故障检测的效果 8.3、查看/etc/masterha/app1.cnf文件是否发生改变 8.4、再来看看slave2的master_info信息(确定master服务转移到了salve1上) 九、原master故障修复(原master转为slave,指向slave1) 9.1、原master开启mysqld 9.2、修复主从,原master修改master_info指向新的master(原slave1) 9.3、在 manager 节点上修改配置文件/etc/masterha/app1.cnf(再把这个记录添加进去,因为master宕机后原来的server1会被自动删除) 9.4、重启mha manager,并检查此时的master 自动failover 自动故障切换(Automatic Failover)是一种系统设计和配置策略,旨在在出现故障时自动将服务从一个失败的节点转移到另一个健康的节点,以保持系统的可用性。自动故障切换通常用于分布式系统、数据库集群、高可用性架构等场景,以减少系统停机时间并确保业务连续性。 MHA: MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL主从复制架构提供了 automating master failover (自动化主故障转移)功能。MHA 在监控到 master 节点故障时,会 提升其中拥有最新数据的 slave 节点成为新的master 节点,在此期间,MHA 会通过于其它从节 点获取额外信息来避免一致性方面的问题。MHA 还提供了 master 节点的在线切换功能,即按需 切换 master/slave 节点。 参考:MYSQL高可用架构之MHA实战一 数据库主从配置(真实可用)_51CTO博客_mysql数据库主从搭建

2023牛客暑期多校训练营9 I.Non-Puzzle: Segment Pair(tag:差分)

文章目录 题目大意题解参考代码 题目大意 1 ≤ n , l i , r i ≤ 5 ∗ 1 0 5 1 \leq n,l_i,r_i \leq 5*10 ^5 1≤n,li​,ri​≤5∗105 题解 这题 l / r l/ r l/r 的数据在 5 × 1 0 5 5\times 10^5 5×105 ,想到差分。 特殊的是它有两条线段,对于同一个点 ,一对线段的贡献可能为 0 / 1 / 2 0/1/2 0/1/2 。 相交的线段单点贡献为 2 2 2 ,不相交的单点贡献为 1 1 1 。 我们需要维护 0 / 1 / 2 0/1/2 0/1/2 的个数,对所有的点统计答案即可。

全网最牛,Appium自动化测试框架-关键字驱动+数据驱动实战(二)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 util 包 util 包属于第一层的测试工具层:用于实现测试过程中调用的工具类方法,例如读取配置文件、页面元素的操作方法、操作 Excel 文件、生成测试报告、发送邮件等。 global_var.py 本模块用于定义测试过程中所需的全局变量。 import os PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # APP配置信息路径 INI_FILE_PATH = os.path.join(PROJECT_DIR, "conf", "desired_caps_config.ini") # 异常截图路径 EXCEPION_PIC_PATH = os.path.join(PROJECT_DIR, "exception_pic") # 日志配置文件路径 LOG_CONF_FILE_PATH = os.path.join(PROJECT_DIR, "conf", "logger.conf") # 测试数据文件路径 TEST_DATA_FILE_PATH = os.path.join(PROJECT_DIR, "test_data", "test_case.xlsx") # 测试报告存放路径 TEST_REPORT_FILE_DIR = os.path.join(PROJECT_DIR, "test_report") # Appium server地址 APPIUM_SERVER = 'http://localhost:4723/wd/hub' # 测试数据文件中,测试用例sheet中部分列对应的数字序号 TESTCASE_CASE_NAME_COL_NO = 0 TESTCASE_FRAMEWORK_TYPE_COL_NO = 1 TESTCASE_CASE_STEP_SHEET_NAME_COL_NO = 2 TESTCASE_DATA_SOURCE_SHEET_NAME_COL_NO = 3 TESTCASE_IS_EXECUTE_COL_NO = 4 TESTCASE_TEST_TIME_COL_NO = 5 TESTCASE_TEST_RESULT_COL_NO = 6 # 用例步骤sheet中,部分列对应的数字序号 CASESTEP_NAME_COL_NO = 0 CASESTEP_ACTION_COL_NO = 1 CASESTEP_LOCATE_METHOD_COL_NO = 2 CASESTEP_LOCATE_EXPRESSION_COL_NO = 3 CASESTEP_OPERATION_VALUE_COL_NO = 4 CASESTEP_IS_EXECUTE_COL_NO = 5 CASESTEP_TEST_TIME_COL_NO = 6 CASESTEP_TEST_RESULT_COL_NO = 7 CASESTEP_EXCEPTION_INFO_COL_NO = 8 CASESTEP_EXCEPTION_PIC_DIR_COL_NO = 9 # 数据源sheet中,是否执行列对应的数字编号 DATASOURCE_DATA = 0 DATASOURCE_KEYWORD = 1 DATASOURCE_IS_EXECUTE = 2 DATASOURCE_TEST_TIME = 3 DATASOURCE_TEST_RESULT = 4 # 测试执行结果统计 TOTAL_CASE = 0 PASS_CASE = 0 FAIL_CASE = 0 if __name__ == "

write javaBean error, fastjson version 1.2.76

fastjson JSON.toJSONString 报错: > [0] JavaBeanSerializer.java->541: com.alibaba.fastjson.serializer.JavaBeanSerializer->write() > [1] JavaBeanSerializer.java->154: com.alibaba.fastjson.serializer.JavaBeanSerializer->write() > [2] JSONSerializer.java->360: com.alibaba.fastjson.serializer.JSONSerializer->writeWithFieldName() > [3] null->-1: com.alibaba.fastjson.serializer.ASMSerializer_8_FiveG2NetData->writeNormal() > [4] null->-1: com.alibaba.fastjson.serializer.ASMSerializer_8_FiveG2NetData->write() > [5] JSONSerializer.java->312: com.alibaba.fastjson.serializer.JSONSerializer->write() > [6] JSON.java->793: com.alibaba.fastjson.JSON->toJSONString() > [7] JSON.java->727: com.alibaba.fastjson.JSON->toJSONString() 报错位置: public Object get(Object javaObject) throws IllegalAccessException, InvocationTargetException { return method != null ? method.invoke(javaObject)//这里报错,method不为null,javaObject对应属性为null : field.get(javaObject); } method.invoke 是系统方法,不可能有错,可是我的数据和代码也看不出问题来。 我把属性对应的get方法去掉之后就没报错了。 此时我才发现: public Integer FrameSize=null; public int getPacketSize() { return PacketSize; } 我的属性是对象,而get方法返回的却是int!这就是原因了。所以只要改get的返回类型为Integer问题就解决了。

k8s ------存储卷(PV、PVC)

目录 一:为什么需要存储卷? 二:emptyDir存储卷 ​三:hostPath存储卷 四:nfs共享存储卷 五:PVC 和 PV 1、PVC 和 PV介绍 2、PV和PVC之间的相互作用遵循的生命周期 3、PV 的4 种状态 4、一个PV从创建到销毁的具体流程 六:静态创建pv和pvc资源由pod运用过程 ​1、配置nfs存储 ​2、定义PV ​3、定义PVC 4、测试访问 七、StorageClass + nfs-client-provisioner搭建动态创建pv 1、创建共享目录 2、创建 Service Account 3、使用 Deployment 来创建 NFS Provisioner 4、创建 StorageClass 5、创建 PVC 和 Pod 测试 一:为什么需要存储卷? 容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的Volume抽象就很好的解决了这些问题。Pod中的容器通过Pause容器共享Volume。 二:emptyDir存储卷 当Pod被分配给节点时,首先创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod 时,emptyDir中的数据将被永久删除。 emptyDir可实现Pod中的容器之间共享目录数据,但是emptyDir卷不能持久化数据,会随着Pod生命周期结束而一起删除。 mkdir /opt/volumes cd /opt/volumes vim pod-emptydir.yaml apiVersion: v1 kind: Pod metadata: name: pod-emptydir namespace: default labels: app: myapp tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 #定义容器挂载内容 volumeMounts: #使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷 - name: html #挂载至容器中哪个目录 mountPath: /usr/share/nginx/html/ - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent volumeMounts: - name: html #在容器内定义挂载存储名称和挂载路径 mountPath: /data/ command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.

leetcode 516. 最长回文子序列(JAVA)题解

题目链接https://leetcode.cn/problems/longest-palindromic-subsequence/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china 目录 题目描述: 暴力递归: 动态规划: 题目描述: 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 示例 1: 输入:s = "bbbab" 输出:4 解释:一个可能的最长回文子序列为 "bbbb" 。 示例 2: 输入:s = "cbbd" 输出:2 解释:一个可能的最长回文子序列为 "bb" 。 提示: 1 <= s.length <= 1000s 仅由小写英文字母组成 这道题的知识点是动态规划,可是如果直接从动态规划讲可能有点不容易理解。 所以本篇文章就是从暴力递归到动态规划。 从题目中我们可以得出:本题找的是可以不连续的回文子串然后返回其最大序列的长度。 也就是说: a2b42a 的最长回文子序列为:a2b2a或a242a 这两个都可以因为它们返回的都是5 暴力递归: 我们先写一个可以返回最长的回文子序列长度的函数: //主函数 public int longestPalindromeSubseq(String s) { char[] str = s.toCharArray(); return maxString(str, 0, str.length-1); } //假设该函数可以返回最长回文子序列的长度 public static int maxString(char[] str, int l, int r) {} 我们写的 maxString() 方法可以返回 str 字符串[l, r]区间的最长回文子序列的长度 。

samba的使用

一、samba的介绍 ​ Samba是一个开放源代码软件套件,用于在Linux和UNIX操作系统上实现文件和打印机共享。它可以与Windows操作系统无缝地协作,并支持各种不同的协议和功能,如SMB/CIFS、NetBIOS名称服务、Active Directory域控制器等。 ​ 使用Samba,您可以将Linux或UNIX计算机配置为文件服务器,以便Windows客户端可以访问共享文件和目录。您还可以将Samba配置为打印服务器,以便Windows客户端可以连接到打印机并打印文档。 ​ Samba也支持其他协议,如FTP和HTTP,以及一些高级功能,如用户身份验证、访问控制、加密和数据压缩等。 ​ Samba软件包通常由几个组件组成,例如smbd、nmbd、winbindd等,每个组件都提供不同的功能和服务。 smbd是一个守护进程(daemon),用于提供文件和打印机共享。nmbd是另一个守护进程,用于实现NetBIOS名称服务。winbindd是用于集成Samba服务器和Windows域控制器的组件。 二、实验简介 使用两台虚拟机,server(IP:192.168.189.133)和client1(IP:192.168.189.128),在server上配置samba服务,使用samba共享文件。使用客户机client1来挂载使用server上的共享文件夹 三、实验过程 1、装包,server和client都执行一下操作 ​ samba-client是一个Samba软件包中的软件,它包含用于在Linux和UNIX操作系统上访问远程Samba共享的命令行工具。使用samba-client,您可以在本地计算机上列出、挂载和卸载远程Samba共享。 yum -y install samba #安装samba,服务端工具 yum -y install cifs-utils #提供格式支持 yum -y install samba-client #samba的客户端工具 2、编辑配置文件 查看配置文件 [globe]、[homes]等称为节。 [global]节 1、[g1oba1]节定义 Samba 服务器的基本配置·在此节中应配置三项内容 workgroup 用于指定服务器的 Windows 工作组·大部分 Windows 系统都默认为 WORKGROUP但 Windows XP Home 默认为 SHOME·这用于帮助系统浏览对 TCP/IP 名称服务使用 NetBIOS的服务器。 要将工作组设置为 WORKGROUP,请将 /etc/samba/smb.conf 中的现有工作组条目更改为: workgroup= WORKGROUP 2、security 控制 Samba 对客户端进行身份验证的方式·对于 security = user,客户端使用本地 Samba 服务器管理的有效用户名和密码来登录·此设置是 /etc/samba/smb.