摄像头噪声产生原因及应对方法

什么是摄像头电源噪声 摄像头普遍存在电源噪声问题。电源噪声是sensor供电电源上的频率噪声干扰了sensor的像素采集导致成像上面出现横条、竖条或者带状的亮暗条纹。随着用户对拍照质量要求的逐渐提高,摄像头电源噪声必须要进一步的压制。本文借鉴摄像头sensor厂商应对电源噪声的经验,总结整理成文,旨在提供一些基础的可遵循的经验。分别从什么是电源噪声,电源噪声是如何产生的,sensor、供电、板级、FPC级如何尽量规避电源噪声的引入几个方面着手分析。 在摄像头预览时可见明显的条纹噪声,如下图所示。但是测试AVDD电源的纹波,干净且不见任何可疑噪声。通过用频谱仪测试摄像头AVDD的频谱,发现在10KHz到10MHz,每隔300KHz出现一个噪声,如下图所示。原因是后摄AVDD与LCD、光感共用,导致AVDD混杂了一些能干扰摄像头sensor的噪声,造成电源噪声问题。 电源噪声 摄像头FPC为了刻意的满足MIPI走线的100ohm差分阻抗,设计走线过细,导致走线容易断裂而出现预览黑屏的问题。 在项目堆叠时没有注意摄像头的散热问题,导致摄像头预览时sensor过热,预览图像出现竖条纹,加入散热措施后解决。 过热导致的条纹 H噪声 摄像头的H噪声一般都是由摄像头的电源噪声引起的,供电电源的噪声波动通常都会以成像中的水平条纹或带状条纹表现出来。如下图所示,可见明显的带状横条纹噪声。 条纹噪声 摄像头sensor以行为单位一行一行的读取像素信息,在读每一行时,先读出复位态(零态)的数值,再读出当前信号值,然后做差分处理,做差分处理能有效的消除直流偏差与其它相关的噪声源。如果当采集复位态数值时的供电电源VDD与采集当前信号值时的供电电源VDD不相同,两个VDD之间的插值ΔVDD就会叠加在差分信号上。在同一行不同像素点之间的差分信号是变化的,但是叠加的ΔVDD噪声在整行都是不变的。如果ΔVDD是导致信号值偏高,或者导致复位态信号偏低,这一整行都会变得比真实情况偏亮;如果ΔVDD噪声导致信号值偏低,或者导致复位态信号偏高,这一整行都会变得比真实情况偏暗。传感器一行一行的读取阵列的像素值,同时ΔVDD也一行一行的发生变化。对于一个均匀的成像物体某些行会更亮一点,某些行会更暗一点,从而形成行状条纹。供电电源更容易在较暗的环境下产生条纹噪声,因为在暗态下信号值会非常低。例如在很暗的环境下,条纹噪声是±1,像素信号值输出是4,因为行与行之间的波动达到±25%,条纹噪声就会非常的明显。在很亮的环境中,假设像素信号值输出是100,那行与行之间的波动就只有±1%,条纹噪声就微乎其微了。 但也不是说电源有噪声波动就一定有条纹噪声,当行扫描周期与电源噪声波动周期一致时。就不会产生条纹噪声,如下图所示。当行扫描周期与电源噪声波动周期不一致时,基本上都会产生条纹噪声了。 Sensor的PSRR值 sensor的PSRR曲线代表了其对不同频段噪声的抑制能力。以频率为横轴,以db为纵轴单位。不同频段的电源噪声需要用不同的方法解决。所以在选择降噪方法之前最需要做的事情就是如何检查出这些电源噪声的频率。一种比较简单的噪声分类如下: 行噪声基本上都是中频噪声,在10KHz~1MHz之间。在PCB layout时,非常重要的一个措施就是尽量降低电源线上阻抗(<1%)。降低中频电源噪声,最常用的器件是一些电容与电感,还有非常关键的器件就是具有比较高电源噪声抑制比的供电LDO。在sensor方面,也需要具备较高的电源噪声抑制能力,应对来自系统内部的电源噪声。具备比较高的电源噪声抑制比的sensor能极大的帮助摄像头抑制由于sensor内部、或者系统内部产生的电源噪声,降低行条纹。Sensor、DVDD、DOVDD、AVDD都有可能是噪声的来源。同时在供电电源消耗的电流变化时,也会在DVDD、DOVDD、AVDD等上产生噪声,从而引起条纹噪声。如下图所示OV8858的DVDD在工作时的电流变化曲线。 如下图所示为一款摄像头sensor的PSRR曲线。在600KHz以下频段有相对较高的抑制比。但是最大都在10db左右,噪声抑制能力不强。 如下图所示为另外一款sensor的PSRR曲线,在中低频段有高达40db以上的噪声抑制能力。在摄像头sensor选择时,需要厂家提供对应的PSRR曲线,如果中低频PSRR值比较低,那就需要更换sensor,或者在PCB板设计时更加注意电源的设计了。 低噪LDO 在板级电源线路设计中,供电电源LDO的选取显得更为重要。LDO在中高频段的PSRR电源噪声抑制比一般都比较差,对噪声来说有点像高通滤波器。在选取LDO时,重点对比关注中低频段的PSRR值,如下图所示为两款LDO的PSRR曲线,左边的LDO在1MHz以下频段只有在100KHz左右有比较低的PSRR,约40db,而右边的LDO在10KHz以上时PSRR就已经下降到30db以下。 对于LDO的选择,输出响应能力也需要重点关注,响应能力不仅可能会影响sensor的正常工作,还会引入更多的电源噪声,影响sensor采集图像的质量。如下图所示为两款不同LDO的输出响应曲线,明显的左边的LDO输出上下冲都比较大,而右边的LDO是比较好的选择。 PCB板设计 1 在AVDD、DVDD、DOVDD供电线路上,至少需要2颗电容,一颗靠近供电PMU或者LDO放置,另外一颗靠近摄像头连接器放置。空间充足条件下可放置多颗不同容值(谐振频率在10K~1MHz之间)的电容,组合滤除不同频段的电源噪声。 2 靠近连接器放置的AVDD上电容,推荐建议在4.7uF或者以上,注意该电容的GND脚与连接器的AGND引脚连接在一起后需要单点到系统主地。 3 为降低行噪声,建议供电电源走线压降小于1%。假设铜厚是1盎司/平方英尺,峰值电流为100mA,那么电源走线最小的宽长比至少为1:400,即如果走线长3英寸(1英寸=2.54cm),线宽至少是7.5mil(1mil=0.0254mm);如果峰值电流为200mA,电源走线最小的宽长比至少为1:200。 4 AVDD的回流地建议使用AVDD临层做回流地,且最好不要有断差、走线隔开。最小的回流路径引入干扰的可能性就会更小。 5 数字电源与模拟电源尽量隔开,不要交叉、平行、共回流地等。 6 AVDD与AFVDD不可共用。 7 摄像头连接器附近的AGND与DGND应该尽可能的大,做到尽量多的吸收噪声信号。 8 在摄像头模组内部AGND与DGND是相互分开的,在连接器位置通过主板上实现单点接地。 9 AFVDD与AFGND通过连接器引入的时候,尽量和sensor的走线分开。AFGND单点直接到主板主地,不要与摄像头连接器的AGND或者DGND表层连接;或者采用0ohm电阻到主板DGND,不要与摄像头连接器的AGND连接。采用0ohm电阻到DGND时,注意电阻靠近连接器放置。 FPC设计 FPC在整个摄像头中起到承载元器件的作用,包括Sensor、电容电阻、连接器等电子元器件;还起到电气连接的作用,包括电源线、各种信号线的连接.FPC是使用FPC基材,通过曝光、显影、蚀刻等工序形成线路,再通过表面处理对裸露铜面进行保护,并增强其焊接、抗氧化等能力。针对摄像头模组FPC的设计我们需要关心以下问题,并协助检查厂家FPC设计。 1 MIPI走线需包地:MIPI线对间隔地,相邻层重叠区域铺地; 2 MIPI过孔需要用GND线包起来; 3 MIPI阻抗需要在100+/-10%以内; 6.4 MIPI走线对内线长差小于10mil(极限情况15mil); 5 MIPI走线对间线长差小于40mil(极限情况45mil);尽量保证信号不会因为线长不同而出现不同时间到达的问题。 6 MIPI走线不能有直角,如遇直角情况,需要走弧形线; 7 MIPI主要走线需要布在同一层; 8 MIPI尽量不走蛇形线,如果一定要走,平行间距S尽量大,最好大于MIPI线宽的3倍; 9 XMCLK需要左右包地,上下层如果有信号,必须是GND信号; 10临层的平行信号线走线要错开,错位方式走线。 11 注意FPC边缘最好都有地线包裹,尤其是信号线比较靠近边缘时。 12 DVDD走线注意线上阻抗不能太大。根据不同sensor的供电要求,计算DVDD(DVDD耗电较大)需要的电流大小,进而判断走线宽度。 13 AVDD和AGND要并排走线;给AVDD提供最短的回流路径。 14 电源线和信号线距离要尽量远,空间允许条件下用地线隔离。

nodejs事件循环与多进程(三)——多进程和多线程介绍 & 一个进程由几个线程组成 & node利用cluster开启多进程 & 多进程的性能要明显好于单进程-ab是apache自带的压力测试工具

nodejs事件循环与多进程(三)——多进程和多线程介绍 & 一个进程由几个线程组成 & node利用cluster开启多进程 & 多进程的性能要明显好于单进程-ab是apache自带的压力测试工具 第四章 nodejs多进程 本章概要 为什么要使用多进程多进程和多线程介绍nodejs开启多线程和多进程的方法cluster原理介绍 为什么需要多进程 nodejs单线程,在处理http请求的时候一个错误都会导致整个进程的退出,这是灾难级的。 多进程和多线程介绍 进程是资源分配的最小单位,线程是CPU调度的最小单位 “进程——资源分配的最小单位,线程——程序执行的最小单位” 线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程由几个线程组成,线程与同属一个进程的其他的线程共享进程所拥有的全部资源。 一个进程下面的线程是可以去通信的,共享资源 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉。 谷歌浏览器 进程: 一个tab就是一个进程线程: 一个tab又由多个线程组成,渲染线程,js执行线程,垃圾回收,service worker 等等 node服务 ab是apache自带的压力测试工具。 ab -n1000 -c20 '192.168.31.25:8000/' 进程:监听某一个端口的http服务线程: http服务由多个线程组成,比如: 主线程:获取代码、编译执行编译线程:主线程执行的时候,可以优化代码Profiler线程:记录哪些方法耗时,为优化提供支持其他线程:用于垃圾回收清除工作,因为是多个线程,所以可以并行清除 到底选择多进程还是多线程? 多进程还是多线程一般是结合起来使用,千万不要陷入一种非此即彼的误区。 1)需要频繁创建销毁的优先用线程 这种原则最常见的应用就是Web服务器了,来一个连接建立一个线程,断了就销毁线程,要是用进程,创建和销毁的代价是很难承受的 2)需要进行大量计算的优先使用线程 所谓大量计算,当然就是要耗费很多CPU,切换频繁了,这种情况下线程是最合适的。 这种原则最常见的是图像处理、算法处理。 3)强相关的处理用线程,弱相关的处理用进程 什么叫强相关、弱相关?理论上很难定义,给个简单的例子就明白了。 一般的Server需要完成如下任务:消息收发、消息处理。“消息收发”和“消息处理”就是弱相关的任务,而“消息处理”里面可能又分为“消息解码”、“业务处理”,这两个任务相对来说相关性就要强多了。因此“消息收发”和“消息处理”可以分进程设计,“消息解码”、“业务处理”可以分线程设计。 4)可能要扩展到多机分布的用进程,多核分布的用线程 5)都满足需求的情况下,用你最熟悉、最拿手的方式 总结: 线程快而进程可靠性高。 nodejs多线程 伴随10.5.0的发布,Node.js 新增了对多线程的实验性支持(worker_threads模块)。2018年 nodejs主流还是只有多进程的方案,多线程可以等api稳定之后再使用。 参考文章:https://blog.csdn.net/azard5/article/details/85016412 创建多进程 利用cluster开启多进程 var cluster = require('cluster'); var http = require('http'); var numCPUs = require('os').cpus().length; // 获取CPU的个数 if (cluster.

kali-渗透攻击tomcat服务:

​ kali-渗透攻击tomcat服务: Apache tomcat的理解: Apache tomcat是世界上使用最广泛的java web应用服务器之一,绝大多数人都会使用tomcat的默认配置。默认配置中会有一个向外网开放的web应用管理器,管理员可以利用它在服务器中启动、停止、添加和删除应用。 1.打开靶场中的Tomcat Server 靶机中有一个Tomcat Server服务在运行,端口是8080,通过浏览器进行访问。 2.在Kali linux中启动msf并加载爆破模块 打开msfconsole控制台 命令:use auxiliary/scanner/http/tomcat_mgr_login 3.下面对刚刚使用的Tomcat_mgr_login模块进行详解: 1 BALNK_PASSWORDS:为每个账号提供一个空密码测试 2 PASSWORD:设置这个可以只针对该密码进行多用户测试 3 PASS_FILE:输入你想要使用的密码字典路径 4 Proxies:为了避免被检测到源地址,可以使用代理功能 5 RHOSTS:填写要被测试的主机地址(可以是多个,以空格分隔。也可以是一个清单文件) 6 RPORT:设置目标Tomcat运行的端口 7 STOP_ON_SUCCESS:当破解成功后停止攻击 8 TARGERURI:可设置管理界面的目录路径 9 USERNAME:设置要测试的用户名字(可以是单个,也可以是一个字典)10USER_PASS_FILE:使用 “用户名/密码” 格式的字典文件11USER_AS_PASS:尝试使用测试中的用户名作为密码 GetShell 4.如何理解show options 1.显示选项 backtrack 渗透命令 svn update 升级 show options 显示选项 show payloads 显示装置 2.查看选项 . setg function 全局设置 show options 查看选项 show advanced 查看高级选项 … show options —— 显示需要设置的项 show target —— 显示适用的系统版本

5K字讲清楚SpringBoot核心配置全面总结

Spring Boot的核心配置文件用于配置Spring Boot程序,文件名字必须以application开始。这个既是底层源码的强制要求,也是SpringBoot的一种代码规约,有助于在开发层面利于代码规范管理。 说明:以下内容接着i前面的SpringBootCase项目就行演示。 1、application. properties核心文件 格式:以键值对的方式进行配置,key=value 示例:name=xintu 我们修改application.properties配置文件。比如修改默认tomcat端口号及项目上下文件根。 设置内嵌Tomcat端口号 server.port=8888 设置项目上下文根路径,这个在请求的时候需要用到 server.servlet.context-path=/springbootcase 配置完毕之后,启动测试。 浏览器输入地址:http://localhost:8888/springbootcase/hello?name=lw , 页面验证结果如下。 2、 application.yml配置文件(推荐配置风格) yml 是一种 yaml 格式的配置文件,主要采用一定的空格、换行等格式排版进行配置。格式如下, key: 空格+value, 表示一对键值对。 配置YNML时,需要注意以下4点: 1)以空格的缩进来控制层级关系。 2)只要是左对齐的一列数据,都是属于同一层级。 3)空格必须有。 4)属性和值对大小写敏感。 yml 复制代码 server: port: 8888 # 设置内嵌Tomcat端口号 servlet: context-path: /SpringBootCase # 设置项目上下文根路径,这个在请求访问的时候需要用到 特点:与 application. properties 相比,yaml更能直观地被计算机识别,而且容易被人类阅读。 yaml 类似于 xml,但是语法比xml 简洁很多,值与前面的冒号配置项必须要有一个空格, yml 后缀也可以使用 yaml 后缀。当两种格式配置文件同时存在,使用的是 .properties 配置文件,为了演示yml,可以先将其改名,重新运行SpringbootApplication,查看启动的端口及上下文根。 我们在后面的学习过程中,均使用 .yml格式 。如果想改.properties形式也可以,按照自己喜欢的风格 或 团队约定即可。 3、SpringBoot多环境配置 在实际开发的过程中,我们的项目会经历很多的阶段,开发、测试、上线, 尤其时很大厂,在进行一些重要需求迭代时,还会包括预发、灰度等。每个阶段的配置会因应用所依赖的环境不同而不同,例如:数据库配置、缓存配置、依赖第三方配置等,那么这个时候为了方便配置在不同的环境之间切换,SpringBoot提供了多环境profile配置功能。 命名格式:application-环境标识.yml(或 .properties)。 下面我们为每个环境创建3个配置文件,分别命名为:application-dev.yml(开发环境)、application-dev.yml(测试环境)、application-dev.yml(生产环境)。 各配置文件内容如下,

2021 RoboCom 世界机器人开发者大赛-高职组(初赛)

编程题得分:100 总分:100 目录 7-1 机器人打招呼 (5分) 输入格式: 输出格式: 输入样例: 输出样例: 7-2 人脸识别 (10分) 输入格式: 输出格式: 输入样例 1: 输出样例 1: 输入样例 2: 输出样例 2: 7-3 月份输出 (10分) 输入格式: 输出格式: 输入样例: 输出样例: 7-4 字母串 (15分) 输入格式: 输出格式: 输入样例: 输出样例: 7-5 增一数 (15分) 输入格式: 输出格式: 输入样例: 输出样例: 7-6 答题卡 (20分) 输入格式: 输出格式: 输入样例: 输出样例: 7-7 救救倒霉鬼 (25分) 输入格式: 输出格式: 输入样例: 输出样例: 7-1 机器人打招呼 (5分) 机器人小白要来 RoboCom 参赛了,在赛场中遇到人要打个招呼。请你帮它设置好打招呼的这句话:“ni ye lai can jia RoboCom a?

一篇文章彻底搞懂websocket协议的原理与应用(一)

注:本文转自知乎https://zhuanlan.zhihu.com/p/581974844 前言 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。 WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。 一、WebSocket简介 webSocket是什么: 1、WebSocket是一种在单个TCP连接上进行全双工通信的协议 2、WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据 3、在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输 4、需要安装第三方包:cmd中:go get -u -v github.com/gorilla/websocket WebSocket 是一种标准协议,用于在客户端和服务端之间进行双向数据传输。但它跟 HTTP 没什么关系,它是一种基于 TCP 的一种独立实现。 以前客户端想知道服务端的处理进度,要不停地使用 Ajax 进行轮询,让浏览器隔个几秒就向服务器发一次请求,这对服务器压力较高。另外一种轮询就是采用 long poll 的方式,这就跟打电话差不多,没收到消息就一直不挂电话,也就是说,客户端发起连接后,如果没消息,就一直不返回 Response 给客户端,连接阶段一直是阻塞的。 而 WebSocket 解决了 HTTP 的这几个难题。首先,当服务器完成协议升级后( HTTP -> WebSocket ),服务端可以主动推送信息给客户端,解决了轮询造成的同步延迟问题。由于 WebSocket 只需要一次 HTTP 握手,服务端就能一直与客户端保持通讯,直到关闭连接,这样就解决了服务器需要反复解析 HTTP 协议,减少了资源的开销。 WebSocket协议支持(在受控环境中运行不受信任的代码的)客户端与(选择加入该代码的通信的)远程主机之间进行全双工通信。用于此的安全模型是Web浏览器常用的基于原始的安全模式。 协议包括一个开放的握手以及随后的TCP层上的消息帧。 该技术的目标是为基于浏览器的、需要和服务器进行双向通信的(服务器不能依赖于打开多个HTTP连接(例如,使用XMLHttpRequest或和长轮询))应用程序提供一种通信机制。 websocket 是一个基于应用层的网络协议,建立在tcp 协议之上,和 http 协议可以说是兄弟的关系,但是这个兄弟有点依赖 http ,为什么这么说呢?我们都知道 HTTP 实现了三次握手来建立通信连接,实际上 websocket 的创始人很聪明,他不想重复的去造轮子,反正我兄弟已经实现了握手了,我干嘛还要重写一套呢?先让它去冲锋陷阵呢,我坐收渔翁之利不是更香 吗,所以一般来说,我们会先用 HTTP 先进行三次握手,再向服务器请求升级为websocket 协议,这就好比说,嘿兄弟你先去给我排个队占个坑位建个小房子,到时候我在把这房子改造成摩天大楼。而且一般来说 80 和 443 端口一般 web 服务端都会外放出去,这样可以有效的避免防火墙的限制。当然,你创建的 websocket 服务端进程的端口也需要外放出去。

Mysql 行锁(记录锁、间隙锁、临键锁)研究,基于InnoDB

行锁简介 通过上一章可以了解到,InnoDB下行锁可细分为记录锁(Record Lock)、间隙锁(Gap Lock)、临键锁(Next_Key Lock),是基于索引实现的,其本质上是三种加锁算法。ps:若不声明,默认采用RR隔离级别。 注:有些把记录锁理解为行锁,RL,GL,NKL属于同一级别,都是排他锁的一种。 记录锁:锁精确加在某一行上。 间隙锁:锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前(负无穷,first-key)或最后一个索引之后(last-key,正无穷)的无限空间,是一个双开空间。 临键锁:间隙锁与记录锁与组合起来用就叫做Next-Key Lock,是一个左开右闭区间。 利用Next-Key Lock可以阻止其它事务在锁定区间内插入数据,因此在一定程度上解决了幻读问题。 eg:构建表test(id pk,num key)。 idnum33557710714916102013 在该表中,针对键id: 记录:3、5、7、10、14、16、20 间隙:(负无穷,3)、(3,5)、(5,7)、… (16,20)、(20,正无穷) 临键:(负无穷,3]、(3,5]、(5,7]、… (16,20]、(20,正无穷) 在innodb的RR模式,innodb_locks_unsafe_for_binlog=0(即启用间隙锁算法)背景下: 1)加锁的基本单位是 next-key lock,next-key lock 是前开后闭区间。 2)查找过程中访问到的对象才会加锁。 3)索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁,比如id=7,只锁id=7。 4)索引上的等值查询,给非唯一索引加锁的时候,当前next-key lock不变,向右遍历时且最后一个值不满足等值条件的时候,其next-key lock 退化为间隙锁,比如num=7,当前next-key lock(5,7],向右遍历得到的间隙锁(7,9),最终锁定(5,9)。 5)索引上的绝对范围查询(>,<),给唯一索引加锁的时候,当前行不会加锁(比如id>7,id=7这行不加锁,即临键锁(5,7]不生效),,最终锁定(7,正无穷)。 6)索引上的绝对范围查询,给非唯一索引加锁的时候,next-key lock 退化为行锁(比如num>7,即临键锁(5,7]退化为只锁num=7),最终锁定[7,正无穷]。 7)索引上的非绝对范围查询(>=,<=),将上面的等值和绝对范围查询综合起来即可。 8)对于等值查询,记录不存在时,给唯一索引加锁的时候,next-key lock 退化为间隙锁,如id=18,最终锁定间隙(16,20)。 9)对于等值查询,记录不存在时,给非唯一索引加锁的时候,next-key lock 退化为间隙锁。 10)对于给非唯一索引加锁,边缘记录允许更新但不允许插入,如num=7,最终锁定(5,9),此时可以更新num=5的行,但不能插入新的num=5的行。 记录锁 记录锁很好理解,一般要通过主键或唯一索引加锁,就可以较好的实现。 select * from test where id=7 for update;//该句可以准确且只锁id=7这一行,注意id必须已存在,否则就变成间隙锁了 间隙锁 间隙锁锁定的时一个开区间,而不是某个键,它是基于非唯一索引。需要注意的是用非唯一索引时,要explain下,确保sql走了索引(mysql查询优化器认为全表扫描比用索引更快时会锁表)。那么什么情况下出现间隙所呢? 首先:InnoDB存储引擎,采用RR隔离级别,参数innodb_locks_unsafe_for_binlog=0(静态参数,默认为0,表示启动gap lock,如果设置为1,表示禁用gap lock,该参数最新版本已被弃用)。 innodb默认使用了next-key lock算法,这种算法结合了record锁和gap锁。正因为这样的锁算法,innodb在可重复读这样的默认隔离级别上,可以避免幻读的产生。innodb_locks_unsafe_for_binlog最主要的作用就是控制innodb是否使用gap锁。 1:唯一索引/主键+范围查询 锁住范围内的已存在的符合要求的行,还会加上范围内的gap,例子如下: select * from test where id between 6 and 16 for update;//该句锁id=7,10,14这三行, 还会锁id=8,9,11,12,13,15这几行, 此时另一个事务是插不进去id=8,9,11,12,13,15的数据的。 2:普通索引+绝对范围(不存在等于的情况)查询

2023最全自动化测试框架讲解,不会真不行!

无论是在自动化测试实践,还是日常交流中,经常听到一个词:框架。之前学习自动化测试的过程中,一直对“框架”这个词知其然不知其所以然。 最近看了很多自动化相关的资料,加上自己的一些实践,算是对“框架”有了一些理解,这篇博客,就聊聊自动化框架的一些事吧。。。 一、什么是框架 框架(framework)是一个框子——指其约束性,也是一个架子——指其支撑性。是一个基本概念上的结构,用于去解决或者处理复杂的问题。 在软件工程中,框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法; 另一种定义认为,框架是可被应用开发者定制的应用骨架,前者是从应用方面而后者是从目的方面给出的定义。 上面的概念比较抽象,换另一个角度解释: 1、框架本身一般不完整到可以解决特定问题; 2、框架天生就是为扩展而设计的; 3、框架里面可以为后续扩展的组件提供很多辅助性、支撑性的方便易用的工具,也就是说框架是配套了一些帮助解决某类问题的库(libraries)或工具(tools)。 约束性:针对解决特定问题的软件框架会首先定义问题的边界,进而将相关的软件组件约束在这个边界内,保持框架在解决问题方面上的内聚性。 支撑性:框架本身不解决什么问题,但给了解决问题的相关组件一个组合底子,这个底子的科学性和易用性直接影响在此之上进一步开发的科学性和方便性。 上面的2个对框架的解释和定义,看起来也并没有很简单直白的说清楚什么是框架,下面是我的一些理解: 定义:为解决某些特定问题而约束边界,支撑整个问题解决方案,配套了一些解决问题的组件而构成的工具。 特定问题:什么问题?——自动化测试 约束边界:为什么约束?——明确测试范围和目的 解决方案:用什么方案解决问题?——编程语言+工具+其他 构成工具的组件:哪些组件?—— 用例、脚本、数据、日志、报告、通知 工具:特点是什么?—— 灵活性、可扩展性、高内聚低耦合 二、自动化测试 1、为什么要进行自动化测试? ①、黑盒测试回归效率低 ②、手动测试的偶然性和不确定性 ③、回归的覆盖率不足 ④、交付的产品质量无法保证,全靠评估 ⑤、系统越复杂,问题越多 ⑥、上线时间长、构件失败率高导致的蝴蝶效应(迭代快,加班多) 2、自动化测试能解决什么问题? ①、提高出现问题后的响应速率 ②、降低回归成本 ③、提高回归覆盖率 ④、提高回归效率 ⑤、提高回归的稳定性 3、自动化测试的不足有哪些? ①、无法减少成本投入,而是为了加快测试结果反馈,提升测试质量 ②、自动化适用于回归和冒烟,而不是发现BUG ③、录制回放功能是鸡肋,可视化并不是一个很好的做法 ④、不是所有所有系统所有功能都适合做自动化测试 三、自动化测试框架 构成框架的组件,最起码应该具备以下的功能: Log:日志记录和管理功能,针对不同的情况,设置不同的日志级别,方便定位问题; Report:测试报告生成和管理以及即时通知,测试结果快速响应; Source:配置文件、静态资源的管理,遵循高内聚低耦合原则; Common:公共函数、方法以及通用操作的管理,遵循高内聚低耦合原则; TestCase:测试用例管理功能,一个功能点对应一个或者多个case,尽可能的提高覆盖率; TestData:测试数据管理功能,数据与脚本分离,降低维护成本,提高可移植性; TestSuite:测试组件管理功能,针对不同场景不同需求,组装构建不同的测试框架,遵循框架的灵活性和扩展性; Statistics:测试结果统计管理功能,每次执行测试的结果统计、分析、对比以及反馈,数据驱动,为软件优化和流程改进,提供参考; Continuous:持续集成环境,即CI环境,包括测试文件提交、扫描编译、执行测试、生成报告及时通知等功能,持续集成是自动化测试的核心! 四、常见的自动化测试框架 1、接口自动化框架: ①、java+testNG/Junit+Maven/Ant/Gradle+Jenkins+MySQL+testlink/redmine ②、python+unittest/pytest+Git+Jenkins+MySQL+testlink/redmine ③、python+rebot framework+unittest/pytest+Git+Jenkins+MySQL+testlink/redmine ④、jmeter+Maven/Ant+Jenkins+MySQL+testlink/redmine 2、UI自动化测试框架 ①、java+selenium/appium+testNG/Junit+Maven/Ant/Gradle+Jenkins+MySQL+testlink/redmine ②、python+selenium/appium+unittest/pytest+Git+Jenkins+MySQL+testlink/redmine ③、python+rebot framework+unittest/pytest+Git+Jenkins+MySQL+testlink/redmine 通过上面的一些常见框架,你发现了什么? 它们都拥有共同特性:编程语言+单元测试框架+扫描编译工具+持续集成工具+数据库+项目管理工具。 编程语言:编写测试脚本、日志记录和输出; 单元测试框架:提供测试脚本运行、异常校验等一些列的配置; 扫描编译工具:测试文件扫描编译,一般配合持续集成工具使用效果更佳; 持续集成工具:Jenkins,经典的持续集成工具;

【教程】在 Visual Studio 2015 上对 C++ 进行单元测试

更新中 目录 前言环境Visual Studio 2015 提供的单元测试工具创建 C++ 测试框架在测试项目内测试一个函数测试另一个 Project 的函数测试一个类 参考 前言 本文的测试环境是 Visual Studio 2015,高级别版本(如,2017,2022)的操作略有不同,但提供了更强大的测试功能,这两种版本 IDE 下的测试方式,可以阅读官方文档 环境 os:win10IDE:Visual Studio 2015 Visual Studio 2015 提供的单元测试工具 Test Explorer:可视化的测试辅助工具,可以在这个工具里查看测试的结果,它取代了以前版本的单元测试窗口。Test Explorer 可以适配包括第三方测试框架在内的各种测试框架Microsoft unit test framework for managed code:提供给托管代码的测试框架(托管代码一般是微软环境下的特定用于,是指可以运行在 .Net 平台上的,诸如 C#,F# 等语言)Microsoft unit test framework for C++:提供给 C++ 的测试框架IntelliTest:智能测试工具,仅供 C# 使用 创建 C++ 测试框架 在本节中,我们利用 Test Explorer 和 Visual Stuido 自带的 C++ 测试框架来完成一个简单语句的测试。 第一步,创建测试框架项目:在 solution 上右键,选择 [ Add ] - [ New Project ]

【解决】VS2019各种乱码的情况

关于Visual Studio 2019控制台输出中文出现乱码问题及解决办法 1、从.txt文件中读取输出出现乱码2、从中文字符串中读取输出出现乱码3、上传git时,gitee/github里出现乱码总结: 环境: Windows11 Visual studio 2019 中文输出出现乱码,分为2种情况 1、从.txt文件中读取输出出现乱码 结果如下图所示: 分析出现乱码的原因 首先我们先得知道windows下的中文是GBK编码,VS2019也是GBK编码,所以在windows里编程中文最好就是用GBK编码。 中文乱码的本质就是编码不匹配的问题,就好像明明是utf-8的编码你用GBK去理解当然是无法匹配的。 解决办法 我们知道原因就解决办法就显而易见了:将.txt文件utf-8的编码改为和VS2019一样的GBK编码 第一步: 第二步: 第三步: 第四步: 重新运行代码,进行测试 输出正确 2、从中文字符串中读取输出出现乱码 运行test.c文件出现乱码 char s[20] = "中文乱码问题"; printf("%s\n", s); 打开test.c文件所在位置用右键选择用文本文件方式打开与上面第一种操作相同,把编码改为GBK编码,请参考上面进行修改删除线格式 3、上传git时,gitee/github里出现乱码 解决这个问题,只需要下载一个插件并退出VS2019重新启动即可。 方法:打开扩展中的管理扩展,搜索:Force UTF-8(NO BOM)并进行安装即可。 总结: 前两种问题的解决方式可以有效的防止乱码,但是我觉得每一次都要手动修改很麻烦,除了这个方法我暂时没有找到更有效的方式,或许以后尽量使用VScode进行操作吧。

ChatGPT介绍 (文末有彩蛋)

一、chatGPT简介 ChatGPT是一种基于GPT(Generative Pre-train Transformer)模型的大型语言模型,由OpenAI公司开发。它是目前世界上最先进的自然语言处理技术之一。 GPT是一种基于神经网络的语言模型,使用了非常大的数据集进行预训练,然后可以应用到各种自然语言处理任务中。ChatGPT是基于GPT-3.5架构进行训练的,拥有1750亿个参数,是目前公开的最大的语言模型之一。 ChatGPT可以用于各种对话应用,包括智能客服、聊天机器人等。它可以实现自然的对话流程,并能够回答各种类型的问题。除此之外,ChatGPT还可以进行文本生成、摘要、翻译等任务。 二、chatGPT特点 ChatGPT是一种非常强大和多功能的自然语言处理技术,具有广泛的应用前景。它可以大大提升人们和机器之间的交互效率和便利性,推动人工智能技术的不断发展和进步。 1、非常强大的语言生成能力 ChatGPT拥有非常强大的语言生成能力,可以自动生成符合语法规范和逻辑的文本,使得机器生成的文本更加自然流畅。 2、可以适应不同的对话场景 ChatGPT可以根据对话场景的不同而进行相应的调整,比如在智能客服中,它可以根据用户的问题给出相应的答案;在聊天机器人中,它可以模拟人类的对话风格,让用户感觉和 3、可以进行多语言处理 ChatGPT支持多种语言的处理,包括英语、中文、日语等。这使得它可以应用于不同国家和地区的市场,并且可以处理不同语言之间的翻译和交流。 4、可以用于文本生成、摘要和翻译 除了对话应用之外,ChatGPT还可以用于文本生成、摘要和翻译等任务。它可以生成符合语法规范和逻辑的文章,可以对长篇文章进行自动摘要,也可以进行跨语言的翻译。 5、对于数据的敏感性 ChatGPT的开发者非常重视对于数据的敏感性,因此对于一些可能引起争议的数据集(如暴力、种族歧视等),OpenAI公司已经禁止了它们的使用,以确保ChatGPT的安全和公正性。 三、chatGPT优缺点 1、优点: 自然的对话流程。ChatGPT可以像人类一样自然地进行对话,使得机器生成的文本更加流畅和易于理解。 多功能性。除了对话应用之外,ChatGPT还可以进行文本生成、摘要、翻译等任务,使得它可以应用于广泛的领域和场景。 多语言支持。ChatGPT支持多种语言的处理,可以处理跨语言的翻译和交流。 预训练模型。ChatGPT是基于预训练模型进行训练的,因此可以大大减少训练时间和成本,同时还可以提高模型的效率和性能。 2、缺点: 对话质量有限。虽然ChatGPT的对话质量已经非常高,但是在某些情况下,它可能会出现回答不准确或者回答无法理解的问题。 需要大量的训练数据。ChatGPT的训练需要非常大的数据集,因此对于某些应用场景,可能无法满足训练数据的要求。 难以解释。由于ChatGPT是基于深度学习模型进行训练的,因此它的决策过程和判断依据难以解释,这也是人们对于它的信任度存在疑虑的原因之一。 四、应用场景 ChatGPT在自然语言处理领域有着广泛的应用场景,可以应用于智能客服、聊天机器人、智能语音助手、文本生成、摘要和翻译等领域。随着技术的不断进步和发展,ChatGPT的应用场景还将不断扩展和深化。 智能客服:ChatGPT可以用于智能客服中,帮助企业与客户进行自然的交互。它可以理解客户的问题,并给出准确的回答,同时还可以学习客户的反馈,不断优化回答质量,提升客户满意度。 聊天机器人:ChatGPT可以用于构建聊天机器人,使得机器人可以像人类一样自然地进行对话,为用户提供有价值的信息和服务。 智能语音助手:ChatGPT可以与语音识别技术相结合,构建智能语音助手,使得用户可以通过语音与机器人进行自然的交互,提高用户体验。 文本生成:ChatGPT可以用于文本生成领域,例如自动生成文章、新闻、广告等。这种技术可以提高内容生产的效率和质量,同时还可以实现个性化的文本生成,为用户提供更好的服务。 摘要:ChatGPT可以用于文本摘要领域,自动提取文章或文本的主要内容,并生成简洁、精练的摘要,帮助用户快速获取信息。 翻译:ChatGPT可以用于自然语言翻译,可以处理多种语言之间的翻译,例如中英文翻译、法英文翻译等,帮助用户跨越语言障碍,实现全球化交流。 情感分析:ChatGPT可以用于情感分析领域,可以自动识别文本中的情感倾向,例如判断一段文本是积极的还是消极的,帮助企业了解用户的情感需求,以此改善产品和服务。 语言模型:ChatGPT可以用于语言模型领域,可以预测一个句子中的下一个单词,从而实现智能输入、自动补全等功能,为用户提供便利。 信息抽取:ChatGPT可以用于信息抽取领域,自动从大量的文本中提取有价值的信息,例如从新闻报道中提取人物、事件、时间等信息,帮助企业快速了解市场动态。 语音合成:ChatGPT可以用于语音合成领域,可以生成自然流畅的语音,例如自动生成语音新闻播报、语音导航等。 智能写作助手:ChatGPT可以用于智能写作助手领域,可以根据用户提供的关键词、主题和写作风格,自动生成文章、段落、句子等内容,帮助用户提高写作效率和质量。 智能推荐系统:ChatGPT可以用于智能推荐系统领域,可以通过学习用户的历史行为和兴趣偏好,为用户推荐符合其兴趣的商品、新闻、电影等内容,提高用户的消费体验。 Fine-tuning技术:ChatGPT采用Fine-tuning技术,可以根据用户的具体需求,通过调整模型参数,快速定制出适合特定任务的模型,提高模型的精度和效率。 零样本学习:ChatGPT支持零样本学习(Zero-shot learning),即在没有任何相关数据的情况下,仍然可以通过模型的泛化能力,预测出与特定主题相关的答案,这为实际应用提供了很大的便利。 生成式对话系统:ChatGPT可以作为生成式对话系统,可以根据用户的输入生成自然流畅的对话内容,实现智能对话和智能客服等功能。 多语言支持:ChatGPT支持多语言处理,可以处理中文、英文、日文、德文、法文、西班牙文等多种语言,并且可以进行跨语言翻译和文本生成。 语义理解:ChatGPT可以实现语义理解,可以识别文本中的实体、关系、事件等信息,从而帮助企业了解用户需求和行为。 自然语言生成:ChatGPT可以实现自然语言生成,可以生成自然流畅的语言,例如自动生成新闻报道、电影剧情、诗歌等内容。 https://wfscknagql.feishu.cn/docx/HzzCdMPoZorWHUxacpZcnIEHnMe 

同一VLAN不同交换机之间的数据转发

实验环境: 思科模拟器,Cisco Packet Tracer 实验拓扑: 配置步骤: (1)配置四台PC的IP地址 双击PC选择Desktop,然后选择IP Configuration配置ip (2)配置交换机 双击交换机,选择CLI输入配置命令 Sitch>en Switch#config t Switch(config)#vlan 10 /**创建VLAN 10 */ Switch(config-vlan)#exit Switch(config)#vlan 20 /**创建VLAN 20 */ Switch(config-vlan)#exit Switch(config)#int f0/2 Switch(config-if)#switch access vlan 10 /**将端口分配给VLAN 10*/ Switch(config-if)#exit Switch(config)#int f0/3 Switch(config-if)#switch access vlan 20 Switch(config-if)#exit Switch(config)#int f0/1 Switch(config-if)#switchport mode trunk /**定义trunk端口实现同一VLAN跨不同交换机*/ 测试: PC0可以ping通PC2,PC1可以ping通PC3

C++引用计数

文章目录 1. 什么是引用计数2. 引用计数的实现3. 示例代码 1. 什么是引用计数 引用计数(reference count)的核心思想是使用一个计数器来标识当前指针指向的对象被多少类的对象所使用(即记录指针指向对象被引用的次数)。它允许有多个相同值的对象共享这个值的实现。引用计数的使用常有两个目的: 简化跟踪堆中(也即C++中new出来的)的对象的过程。一旦一个对象通过调用new被分配出来,记录谁拥有这个对象是很重要的,因为其所有者要负责对它进行delete。但是对象所有者可以有多个,且所有权能够被传递,这就使得内存跟踪变得困难。引用计数可以跟踪对象所有权,并能够自动销毁对象。可以说引用计数是个简单的垃圾回收体系。 节省内存,提高程序运行效率。如果很多对象有相同的值,为这多个相同的值存储多个副本是很浪费空间的,所以最好做法是让左右对象都共享同一个值的实现。C++标准库中string类采取一种称为”写时复制“的技术,使得只有当字符串被修改的时候才创建各自的拷贝,否则可能(标准库允许使用但没强制要求)采用引用计数技术来管理共享对象的多个对象。 2. 引用计数的实现 使用引用计数实现智能指针的关键是,引用计数应该存在哪里。引用计数应该是某个类对象和其复制对象共享的, 而指针成员恰好有这样的特性, 故可以在类中多声明一个size_t* 的成员,用来表示引用计数。 构造函数中创建类的新对象时,初始化引用计数为1;拷贝构造函数复制指针,并使相应的引用计数增加1;赋值操作减少左操作数所指对象的引用计数,增加右操作数所指对象的引用计数;析构函数使引用计数减少1,并且当引用计数为1时,释放指针所指向的对象; 3. 示例代码 #include <iostream> #include <string> using std::string; using std::ostream; using std::cout; using std::size_t; class HasPtr { friend ostream& print(ostream&, const HasPtr&); public: // string():构造空的string类对象,既空字符串 HasPtr(const string& s = string()) : ps(new string(s)), i(0), use(new size_t(1)) { } // constructor ~HasPtr(); // 析构函数 HasPtr(const HasPtr& rhs) : ps(rhs.ps), i(rhs.i), use(rhs.use) { ++* use; } // 拷贝构造函数 HasPtr& operator=(const HasPtr&); // 运算符重载 private: string* ps; // ps是一个指针,指向string类型 int i; size_t* use; // use是一个指针,指向size_t类型 }; // 析构函数的定义 HasPtr::~HasPtr() { if (-- * use == 0) { // 如果引用计数为变0 delete ps; // 释放string内存 delete use; // 释放计数器内存 } } // 运算符重载的定义 HasPtr& HasPtr::operator=(const HasPtr& rhs) { ++* rhs.

线程基础、线程之间的共享和协作(初篇)

什么是进程和线程? 进程是操作系统进行资源分配的最小单位。资源包括cpu,内存空间,磁盘io等。同一进程里的多个线程共享该进程的全部系统资源。而进程与进程之间是相互独立的。 线程是cpu调度的最小单位,必须依托于进程而存在。 CPU 核心数和线程数的关系? 核心数、线程他们是1:1的关系,当intel引入超线程技术后 核心数、线程他们是1:2的关系。 什么是CPU 时间片轮转机制? 我们平时在开发的时候,感觉并没有受 cpu 核心数的限制,想启动线程就启 动线程,哪怕是在单核 CPU 上因为操作系统提供了一种 CPU 时间片轮转机制。时间片轮转调度是一种最古老、最简单、最公平且使用最广的算法,又称 RR调度。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。如果在时间片结束时进程还在运行,则 CPU 将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结来,则 CPU 当即进行切换。而CPU的调度切换就是CPU上下文切换。 什么并行和并发? 并行是指同时能够执行不同的任务。并发是指能够交替的执行任务。 两者区别 : 一个是交替执行 , 一个是同时执行。其中 并发统计通常和时间单位挂钩的。某一时间段并发量是多少。 线程的优点及缺点? 线程的创建会进行资源分配:栈空间(1M)+ 句柄(文件描述符)等 优点: 1.充分利用cpu资源。 2.加快用户响应时间。 3.代码的异步话,模块化,简单化。 缺点: 1.多个线程共享该进程的所有资源,共享资源的安全性。 2.为了保证共享资源的安全性,肯定会加锁,容易产生线程与线程之间死锁。 3.线程数量增加会加重系统cpu资源的消耗。 线程创建的方式? 线程的创建方式就只有2种,这个是官方Thread类注释声明了的。可以去Thread源码看下。 1.继承Thread类 2.实现Runnable接口 Thread和Runnable的区别? Thread是对线程的抽象,而Runnable是对任务调度的抽象。Thread可以接收任意Runnable的实例执行。 线程终止的方式? 1.调用线程的stop方法,stop方法不建议使用,它不能保证线程资源的释放。除非把线程的资源都释放了才调用stop方法。 2.调用interrupt方法,它不能保证线程马上终止,它只是给线程一个中断的通知,修改线程的中断标志位。interrupt方法通常和isInterrupted()和静态方法Thread.interrupted()联合调用。 代码示例: 线程通过检测自身的中断标识位是否设置为true而响应中断。通常通过调用isInterrupted()和静态方法Thread.interrupted()方法来判断是否被中断。isInterrupted()与interrupted()区别在于返回值不一样,isInterrupted()会返回true而interrupted()会把标志位修改成false来返回。通常情况下都选择使用isInterrupted方法。 线程在堵塞中(线程调用wait(),sleep(),join())也会执行interrupt和isInterrupted/Thread.interrupted()方法,但该线程并不会中断。线程处于堵塞状态,它对检测当前中断标志位是否设置为true,会在阻塞方法调用处抛出中断异常并把中断标识为马上设置成false。如果要把堵塞的线程中断必须在catch代码块里再次调用interrupt()方法。相当于要调用两次interrupt()方法; 示例: 线程的run方法和start()方法的区别? Thread类是对java线程的抽象,new Thread()实例只是把线程挂载起来,并没有真正的执行。当线程调用start()方式时,线程才是真正的启动起来。start()方法让线程处于就绪状态等待cpu分配资源,分配到cpu资源时才会调用run方法。start()方法不能重复调用,否则抛出异常,而run()可反复调用它相当于类里的一个成员方法。 其他线程方法? join():可以将两个交替执行的线程合并为顺序执行。 比如在线程 B 中调用了线程 A 的 Join()方法,直到线程 A 执行完毕后,才会继续执行线程 B。 yield():使当前线程让出 CPU 占有权,但让出的时间是不可设定的。也不会释放锁资源。注意:并不是每个线程都需要这个锁的,而且执行 yield( )的线程不一定就会持有锁,我们完全可以在释放锁后再调用 yield 方法。所有执行 yield()的线程有可能在进入到就绪状态后会被操作系统再次选中马上又被执行。

windows下kafka安装

一:需要安装jdk环境,此处就省略安装步骤了。 二:需要安装 zookeeper https://dlcdn.apache.org/zookeeper/zookeeper-3.8.1/apache-zookeeper-3.8.1-bin.tar.gz 注意要安装带bin的版本 下载完解压,进入conf cp zoo_sample.cfg zoo.cfg dataDir=D:\kafka\apache-zookeeper-3.8.1-bin\data 打开命令行运行 zkserver 启动 三:安装kafka https://downloads.apache.org/kafka/3.5.0/kafka_2.12-3.5.0.tgz 解压后进入config 修改server.properties 为log.dirs=./logs 打开命令行进入kafka根目录运行 .\bin\windows\kafka-server-start.bat .\config\server.properties 启动 四:安装php扩展 https://windows.php.net/downloads/pecl/releases/rdkafka/6.0.1/php_rdkafka-6.0.1-7.4-nts-vc15-x64.zip 解压扩展.dll文件到ext目录

【电源设计】18650电池电源串并联设计——改变电压或容量

有时我们有需要改造电池电源的需要,比如增大容量,增大电压之类的,本文介绍18650锂电池,以及如何用18650锂电池串并联设计电源,达到增大容量或者增大电压的效果: 目录 一、18650锂电池基本知识: 二、18650电池的串并联改造知识: 并联锂电池的特点是:电压不变,电池容量相加,内阻减小,可供电时间延长。 串联锂电池的特点是:电压变大,电池容量变为最小的,内阻增大,可供电时间减小。 三、实例改造: 改造目标: 手绘电路图: 实操焊接与结果: 一、18650锂电池基本知识: 这是一节18650电池: 容量是2500mAh 额定电压:3.7V 充电参数:恒流,恒压,充电电流为1625mA,充电到4.2V,需要4小时 这是一节充的比较满的18650电池,它是4V左右: 18650电池使用范围广:笔记本电脑、对讲机、便携式DVD ,仪器仪表、音响设备、航模、玩具、摄像机、数码照相机等电子设备都可以见到它的影子。 18650电池内阻小,使用寿命很长。 18650电池没有记忆效应,在充电前也不必将剩余电量放空,使用方便。 18650电池可串联或并联组合成 18650 锂电池组。 二、18650电池的串并联改造知识: 并联锂电池的特点是:电压不变,电池容量相加,内阻减小,可供电时间延长。 并联充电的核心内容是并联电流的大小及其作用。根据并联理论,干路电流等于各支路电流之和,因此,已经组合为电池组的n节并联锂电池要达到与单节电池相同的充电效率,充电电流应为n个锂电池电流之和,在欧姆定律:I=U/R的公式下,这个设计是合理的。 但是,并联后的电池内阻也会起变化,按照并联内阻公式,两个并联锂电池的总内阻等于两个电池内阻乘积与其内阻相加之和的比值,并联电阻会随着并联电池数量的增加而递减。 所以,锂电池并联充电的效率可以在电流小于n个并联锂电池电流之和的基础上实现。 锂电池并联要注意电池的一致性问题,因为,一致性差的并联锂电池会在充电过程中出现充不进电或者过充现象,从而破坏电池结构,影响整组电池的寿命。因此,选用并联电池时应避免将不同品牌、不同容量和不同新旧程度的锂电池混用。对电池一致性的内在要求是:锂电池电芯电压差≤10mV,内阻差≤5mΩ,容量差≤20mA。 串联锂电池的特点是:电压变大,电池容量变为最小的,内阻增大,可供电时间减小。 三、实例改造: 改造目标: 此处我有一四节18650锂电池盒子,装上后发现电压竟然高达15V以上: 这样的电池组的各项参数为: 1.容量=2500mAh 2.电压=4V*4约等于16V 现在我需要将电池盒改造,将其变为: 1.容量=5000mAh 2.电压约等于8V 手绘电路图: 原理就是俩俩串联,再并联: 实操焊接与结果: 改造成功!

JavaScript常用的5种排序算法,你都掌握了吗?

今天给大家带来5种最常见的前端排序算法,注释非常详细,欢迎讨论~ 1. 冒泡排序(Bubble Sort) 定义:冒泡排序是一种简单的比较排序算法。它重复地比较相邻的元素,并将顺序错误的相邻元素交换位置,直到整个序列排序完成。 代码示例: function bubbleSort(arr) { const len = arr.length // 每一次外循环固定一个最大值在最后(因为是作比较,次数是数组长度-1) for(let i = 0; i < len - 1; i++) { // 每一次内循环两两比较 for(let j = 0; j < len -1 - i; j++) { if(arr[j] > arr[j + 1]) { // 交换元素,大的放后面 [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]] } } } return arr } const nums = [4, 5, 2, 7, 8] console.

c++分布式网络通信框架【万字拆解】

文章目录 前言介绍使用到的技术栈 一、集群与分布式二、RPC通讯原理三、protobuf的编写1、protobuf简介2、protobuf格式介绍3、protobuf的序列化与反序列化例子4、头格式protobuf的编写 四、RPC通信框架设计1、配置文件读取类 五、分布式协调1、zookeeper简介2、zookeeper工具类定义3、zookeeper工具类的实现4、服务发布5、服务发现 六、异步日志系统1、为什么需要异步记录日志2、保证线程安全的日志队列类3、日志类4、定义宏记录日志 七、服务提供者1、服务提供者整体框架2、服务注册3、使用muduo库提供网络通讯支持a、连接以及读写事件回调函数b、网络服务启动 4、编写服务方法和启动服务 八、服务调用者1、caller整体流程2、通信渠道类的定义3、CallMethod方法的重写 前言 介绍 基于c++的分布式网络框架,项目基于muduo高性能网络库+Protobuf开发,实现的主要功能了是通过zookeeper实现服务注册以及发现,muduo网络库以及Protobuf实现远程RPC调用,异步日志。 分布式网络通信整个流程框架如下: 使用到的技术栈 集群和分布式概念以及原理 RPC远程过程调用原理以及实现 Protobuf数据序列化和反序列化协议 ZooKeeper分布式一致性协调服务应用以及编程 muduo网络库编程 conf配置文件读取 异步日志 CMake构建项目集成编译环境 一、集群与分布式 集群:每一台服务器独立运行一个工程的所有模块。缺点是:虽然用户的并发量得到了增加但是,有一个api,函数的修改整个项目代码都需要进行重新的编译并且需要进行多次部署。 分布式:一个工程拆分了很多模块,每一个模块独立部署运行在一个服务器主机上,所有服务器协同工作共同提供服务,每一台服务器称作分布式的一个节点,根据节点的并发要求,对一个节点可以再做节点模块集群部署。比如说一些模块使用量少,并发量少,只需要部署到一台服务器就行了。 二、RPC通讯原理 RPC是Remote Procedure Call(远程过程调用)的缩写,该技术可以让一台服务器上的服务通过网络调用另一台服务器上的服务,简单来说就是让不同网络节点上的服务相互调用。.因此 RPC框架会封装网络调用的细节,让调用远程服务看起来像调用本地服务一样简单。由于微服务架构的兴起,RPC的概念得到广泛应用,在消息队列、分布式缓存、分布式数据库等多个领域都有用到。可以将RPC理解为连接两个城市的高速公路,让车辆能够在城市之间自由通行。由于 RPC屏蔽了远程调用和本地调用的区别,因此程序开发者无须过多关注网络通信,可以把更多精力放到业务逻辑的开发上。 rpc工作原理如下: 1、客户端调用本地代理:客户端通过调用本地代理来访问服务器上的方法。这个代理通常是在客户端和服务器之间建立起来的一个桥梁,可以将远程方法调用转化成本地方法调用。 2、代理封装请求:本地代理把对远程对象的调用封装成一种标准格式的消息,然后将消息发送给服务端。 3、消息传输到服务端:消息通过网络传输到服务端。 4、服务端解析请求:服务端接收到消息后,需要进行解析,找到对应的远程方法,并处理请求得到结果。 5、服务端封装响应:服务端将处理的结果打包成一个返回消息,同样按照标准格式发送到客户端。 6、消息传回客户端:消息通过网络返回给本地代理。 7、代理解析响应:本地代理接收响应消息后解析,返回给调用者。 总结:rpc的工作逻辑就是客户端调用代理时,代理封装请求并发送给服务端,服务端处理完成后将结果发送给代理,代理解析响应后返回给调用者,让调用者看上去好像是直接调用了本地方法一样 rpc 协议栈 rpc 协议需要使用以下协议层: 应用层:由 rpc 库或框架提供,支持编程语言各自的数据类型和序列化、反序列化实现 传输层:通常基于 tcp 或 udp 实现,以提供可靠的数据传输 网络层:负责在不同的网络之间传输数据,通常使用 ip 协议 数据链路层和物理层:实现寻址、帧传输和物理接口等功能 工作原理图: 黄色部分:设计rpc方法参数的打包和解析,也就是数据的序列化和反序列化,使用Protobuf。 绿色部分:网络部分,包括寻找rpc服务主机,发起rpc调用请求和响应rpc调用结果。 rpc的主要优势:它可以让不同编程语言的应用程序之间进行通信,只需要客户端和服务器都支持相同的协议即可。另外,无论使用哪种语言,开发人员都可以将远程方法调用看 三、protobuf的编写 1、protobuf简介 protobuf(protocol buffer)是google 的一种数据交换的格式,它独立于平台语言。 google 提供了protobuf多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语

如何高效实现 MySQL 与 elasticsearch 的数据同步

MySQL 自身简单、高效、可靠,是又拍云内部使用最广泛的数据库。但是当数据量达到一定程度的时候,对整个 MySQL 的操作会变得非常迟缓。而公司内部 robin/logs 表的数据量已经达到 800w,后续又有全文检索的需求。这个需求直接在 MySQL 上实施是难以做到的。 原数据库的同步问题 由于传统的 mysql 数据库并不擅长海量数据的检索,当数据量到达一定规模时(估算单表两千万左右),查询和插入的耗时会明显增加。同样,当需要对这些数据进行模糊查询或是数据分析时,MySQL作为事务型关系数据库很难提供良好的性能支持。使用适合的数据库来实现模糊查询是解决这个问题的关键。 但是,切换数据库会迎来两个问题,一是已有的服务对现在的 MySQL 重度依赖,二是 MySQL 的事务能力和软件生态仍然不可替代,直接迁移数据库的成本过大。我们综合考虑了下,决定同时使用多个数据库的方案,不同的数据库应用于不同的使用场景。而在支持模糊查询功能的数据库中,elasticsearch 自然是首选的查询数据库。这样后续对业务需求的切换也会非常灵活。 那具体该如何实现呢?在又拍云以往的项目中,也有遇到相似的问题。之前采用的方法是在业务中编写代码,然后同步到 elasticsearch 中。具体是这样实施的:每个系统编写特定的代码,修改 MySQL 数据库后,再将更新的数据直接推送到需要同步的数据库中,或推送到队列由消费程序来写入到数据库中。 但这个方案有一些明显的缺点: 系统高耦合,侵入式代码,使得业务逻辑复杂度增加 方案不通用,每一套同步都需要额外定制,不仅增加业务处理时间,还会提升软件复复杂度 工作量和复杂度增加 在业务中编写同步方案,虽然在项目早期比较方便,但随着数据量和系统的发展壮大,往往最后会成为业务的大痛点。 解决思路及方案 调整架构 既然以往的方案有明显的缺点,那我们如何来解决它呢?优秀的解决方案往往是 “通过架构来解决问题“,那么能不能通过架构的思想来解决问题呢? 答案是可以的。我们可以将程序伪装成 “从数据库”,主库的增量变化会传递到从库,那这个伪装成 “从数据库” 的程序就能实时获取到数据变化,然后将增量的变化推送到消息队列 MQ,后续消费者消耗 MQ 的数据,然后经过处理之后再推送到各自需要的数据库。 这个架构的核心是通过监听 MySQL 的 binlog 来同步增量数据,通过基于 query 的查询旧表来同步旧数据,这就是本文要讲的一种异构数据库同步的实践。 改进数据库 经过深度的调研,成功得到了一套异构数据库同步方案,并且成功将公司生产环境下的 robin/logs 的表同步到了 elasticsearch 上。 首先对 MySQL 开启 binlog,但是由于 maxwell 需要的 binlog_format=row 原本的生产环境的数据库不宜修改。这里请教了海杨前辈,他提供了”从库联级“的思路,在从库中监听 binlog 绕过了操作生产环境重启主库的操作,大大降低了系统风险。 后续操作比较顺利,启动 maxwell 监听从库变化,然后将增量变化推送到 kafka ,最后配置 logstash 消费 kafka中的数据变化事件信息,将结果推送到 elasticsearch。配置 logstash需要结合表结构,这是整套方案实施的重点。

如何使用Python内置缓存装饰器: @lru_cache,@cache 与 @cached_property

1. 为什么需要缓存技术? 使用缓存是优化Python程序速度的重要方法之一。如果使用得当,可以大幅减少计算资源的负载,有效加快代码运行速度 Python 的内置库 functools 模块附带了@lru_cache,@cache, @cached_property 装饰器,使用非常简便,不需要安装第3方库,不需要 redis 等数据库保存对象等,通常只需要1行代码,就可以对函数运算结果、类成员方法运算结果进行缓存。 本文将介绍这3种缓存工具的使用步骤及实例。 2. @lru_cache 缓存装饰器的使用 @lru_cache 是最常见的缓存装饰器。lru_cache 是: Last recently used cache 的简写,可以将该函数最近调用的输入参数以及结果进行缓存。如果有新的调用,先检查缓存是否有相同的输入参数,如果存在,则直接返回对应结果。如果是无参函数,第1次调用后,以后每次调用,直接返回缓存结果。 先看1个例子 from functools import lru_cache from math import sin @lru_cache def sin_half(x): return sin(x)/2 print('first call result:',sin_half(60)) print('second call result:',sin_half(60)) 上例中,第1次运行函数后,lru_cache会缓存调用参数及返回结果。第2次运行时,lru_cache都会检查输入,发现缓存中存在相同输入参数60,则从缓存中返回结果。如果函数执行的是计算量很重的任务,对于相同输入,可以明显地节省系统资源。 装饰器参数 lru_cache默认不清除缓存内容,因此缓存会无限增长,如果程序是长期运行的服务,可能存在耗尽内存的风险。 因此,必须添加1个maxsize参数: @lru_cache(maxsize) 的参数maxsize 表示要缓存的最近调用次数. 如 @lru_cache(360) 表示,只缓存最近360次的函数调用结果。 @lru_cache(360) def sin_half(x): return sin(x)/2 缓存操作 查看缓存报告: sin_half.cache_info() 强制清除缓存内容: sin_half.cache_clear() 当然也可以使用 python的 garbage collection 清除缓存。 下面使用1个示例来演示上述内容: