最近有个需求,要导出Excel模板。
这个模板需要具备多级表头以及有些列只能输入特定的字典值。
开发了一个工具类满足需求,记录一下。
一、定义一个注解,通过注解方式配置需要下拉的字段和下拉内容:
import java.lang.annotation.*; /** * 标注导出的列为下拉框类型,并为下拉框设置内容 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ExcelSelected { /** * 固定下拉内容 */ String[] source() default {}; /** * 设置下拉框的起始行,默认为第二行 */ int firstRow() default 1; /** * 设置下拉框的结束行,默认为最后一行 */ int lastRow() default 0x10000; } 二、通过反射解析注解,将数据动态添加到Class模板当中
import lombok.Data; import lombok.extern.slf4j.Slf4j; @Data @Slf4j public class ExcelSelectedResolve { /** * 下拉内容 */ private String[] source; /** * 设置下拉框的起始行,默认为第二行 */ private int firstRow; /** * 设置下拉框的结束行,默认为最后一行 */ private int lastRow; public String[] resolveSelectedSource(ExcelSelected excelSelected) { if (excelSelected == null) { return null; } // 获取固定下拉框的内容 String[] source = excelSelected.
python爬虫时 出现以上语句通常情况下需要检查以下几个地方:
1.if __name__ == "__main__"语句中的“__mian__"中下划线必须是两个,一个的话会出现Process finished with exit code 0的情况
if __name__ == "__main__":这个初学者最容易忽视 2.修改File》New project...》Existing interpreter
3.需要检查的地方: run>>Edit Configurations...中检查执行的文件是否一致
一般情况下检查这三个地方后都会显示成功。
一、vue-konva是什么? Vue Konva是一个JavaScript库,用于使用Vue绘制复杂的画布图形。
它提供了对Konva框架的声明性和反应性绑定。
所有vue-konva组件都对应于同名的KONVA组件,前缀为“ V-”。 KONVA对象可用的所有参数都可以添加为相应的VUE-KONVA组件的配置中的配置。
官网链接konva
中文链接:konva
中文官网:http://konvajs-doc.bluehymn.com/docs/
二、核心形状有: 【v矩形、v圆形、v椭圆、v线、v图像、v文本、v文本路径、v星形、v标签、v路径、
v规则多边形】。
v-rect, v-circle, v-ellipse, v-line, v-image, v-text, v-text-path, v-star, v-label, v-path, v-regular-polygon.
您也可以创建自定义形状。
三.安装引入 pnpm install vue-konva konva --save
import { createApp } from 'vue'; import App from './App.vue'; import VueKonva from 'vue-konva'; const app = createApp(App); app.use(VueKonva); app.mount('#app'); 四、组件模板中的引用 <template> <v-stage :config="configKonva"> <v-layer> <v-circle :config="configCircle"></v-circle> </v-layer> </v-stage> </template> <script> export default { data() { return { configKonva: { width: 200, height: 200 }, configCircle: { x: 100, y: 100, radius: 70, fill: "
sql 语句查询今天、昨天、近7天、近30天、一个月内、上一月 数据 MySQL 查询当天的所有数据
SELECT * FROM 表名 WHERE DATEDIFF(字段,NOW()) = 0 SELECT * FROM 表名 WHERE to_days(时间字段名) = to_days(now()); 查询昨天的所有数据
SELECT * FROM 表名 WHERE DATEDIFF(字段,NOW())=-1 SELECT * FROM 表名 WHERE TO_DAYS(NOW()) - TO_DAYS(时间字段名) = 1 查询未来第n天的所有数据
//当n为负数时,表示过去第n天的数据 SELECT * FROM 表名WHERE DATEDIFF(字段,NOW())=n 查询未来n天内所有数据
//n天内 SELECT * FROM 表名 WHERE DATEDIFF(字段,NOW())<n AND DATEDIFF(字段,NOW())>= 查询出今天,年月日
SELECT DATE_SUB(CURDATE(), INTERVAL 0 DAY) 几个小时内的数据
DATE_SUB(NOW(), INTERVAL 5 HOUR) 7天
SELECT * FROM 表名 wher DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(时间字段名) 近30天
存储性能软件加速库SPDK 和 virtio vhost & SPDK vhost 两篇文章分别介绍了SPDK和vhost在I/O虚拟化中的原理及架构,本篇将介绍SPDK vhost-user-scsi在QEMU中的IO加速
SPDK运行环境配置 NVMe内核驱动unbind相关部分,参见Linux存储漫谈(5)SPDK环境章节(第一、二步)
第一步,运行setup.sh绑定NVMe驱动,并配置大页内存
root@nvme:~# cd /data/github/spdk root@nvme:/data/github/spdk# HUGEMEM=8192 ./scripts/setup.sh 0000:02:00.0 (2646 5017): nvme -> vfio-pci root@nvme:/data/github/spdk# cat /proc/meminfo | grep -i huge ...... HugePages_Total: 4096 HugePages_Free: 4096 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB Hugetlb: 8388608 kB root@nvme:/data/github/spdk# 第二步,运行vhost启动SPDK自带vhost user target服务程序
root@nvme:/data/github/spdk# ./build/bin/vhost -S /var/tmp -s 1024 -m 0x3 [2023-05-21 01:50:54.338207] Starting SPDK v23.05-pre / DPDK 22.11.1 initialization... [2023-05-21 01:50:54.338370] [ DPDK EAL parameters: vhost --no-shconf -c 0x1 --huge-unlink --log-level=lib.
在《阿里巴巴Java手册》里有这样一条:
【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
简单来说使用线程池有以下几个目的:
线程是稀缺资源,不能频繁的创建解耦作用:线程创建时执行完全分开,方便维护可以将其放入一个池子中,方便给其他任务进行复用 一、线程池介绍 谈到线程池就会想到池化技术,其中最核心的思想就是把宝贵的资源放到一个池子中;每次使用都从里面获取,用完之后又放回池子供其他人使用,简单来说,池化技术就是提前保存大量的资源,以备不时之需。在机器资源有限的情况下,使用池化技术可以大大的提高资源的利用率,提升性能。
创建线程池并使用的简单例子:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class test { public static void main(String[] args) { ExecutorService executorService=new ThreadPoolExecutor(1,1, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)); executorService.execute(new Runnable() { @Override public void run() { System.out.println("test"); } }); executorService.shutdown(); } } jdk提供给外部的接口很简单,直接调用ThreadPoolExecutor构造一个就可以了,也可以通过Executors静态工厂构建。
二、线程池源码分析 ThreadPoolExecutors构造函数的源码如下:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.
PythonPopen介绍及使用方法 PythonPopen是Python标准库中的一个子进程管理模块,用于执行外部命令并与其进行交互。
Popen对象 使用PythonPopen时,需要创建一个Popen对象,它接受一些参数来定义如何运行子进程,例如:
import subprocess p = subprocess.Popen(["ls", "-la"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 这个例子中,我们传入一个参数列表以定义要执行的命令和选项。Popen对象也接受一些其他的参数,例如env指定环境变量。
Popen交互 为了与子进程进行交互,我们可以使用Popen的stdout 和 stderr属性。它们分别代表子进程的标准输出和标准错误输出。例如,我们可以通过以下方式获取子进程的输出:
output = p.stdout.read() 如果需要在子进程运行结束后等待它的返回值,可以使用Popen对象的wait()方法。例如:
p = subprocess.Popen(["ls", "-la"]) p.wait() 应用场景 PythonPopen在很多应用场景下非常有用,例如:
在Python中执行外部命令和脚本。例如,我们可以使用PythonPopen来启动一个本地Web服务器,或者作为一个交互式的命令行界面。
运行系统命令和工具。例如,我们可以使用PythonPopen来执行系统备份脚本、网络管理脚本、或者任何其他存在于外部的实用程序。
实现并行处理。例如,我们可以使用PythonPopen来启动多个子进程并行处理数据,从而提高处理效率。
结论 PythonPopen是Python标准库中的一个非常有用的子进程管理模块。它允许我们执行外部命令并与其进行交互,包括获取标准输出和标准错误输出。PythonPopen在很多应用场景下非常有用,例如在Python中执行外部命令和脚本、运行系统命令和工具,以及实现并行处理。如果你需要处理一些Python无法完成的任务,PythonPopen是值得尝试的一个选项。
最后的最后 本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。
对于颠覆工作方式的ChatGPT,应该选择拥抱而不是抗拒,未来属于“会用”AI的人。
🧡AI职场汇报智能办公文案写作效率提升教程 🧡 专注于AI+职场+办公方向。
下图是课程的整体大纲
下图是AI职场汇报智能办公文案写作效率提升教程中用到的ai工具
🚀 优质教程分享 🚀 🎄可以学习更多的关于人工只能/Python的相关内容哦!直接点击下面颜色字体就可以跳转啦! 学习路线指引(点击解锁)知识定位人群定位🧡 AI职场汇报智能办公文案写作效率提升教程 🧡进阶级本课程是AI+职场+办公的完美结合,通过ChatGPT文本创作,一键生成办公文案,结合AI智能写作,轻松搞定多场景文案写作。智能美化PPT,用AI为职场汇报加速。AI神器联动,十倍提升视频创作效率💛Python量化交易实战 💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
五. 简答题(共4题,34分) 31. (简答题, 8分) 某银行计划开发一个自动存提款机模拟系统(ATM System)。系统通过读卡器(CardReader)读取ATM卡;系统与客户(Customer)的交互由客户控制台(CustomerConsole)实现;银行操作员(Operator)可控制系统的启动(System Startup)和停止(System Shutdown);系统通过网络和银行系统(Bank)实现通信。
当读卡器判断用户已经将ATM卡插入后,创建会话(Session)。会话开始后,读卡器进行读卡,并要求客户输入个人验证码(PIN)。系统将卡号和个人验证码信息送到银行系统进行验证。验证通过后,客户可从菜单选择如下事务(Transaction):
1. 从ATM卡帐户取款(Withdraw);
2. 向ATM卡帐户存款(Deposit);
3. 进行转帐(Transfer);
4. 查询(Inquire)ATM卡帐户信息。
一次会话可以包含多个事务,每个事务处理也会将卡号和个人验证码信息送到银行系统进行验证。若个人验证码错误,则转个人验证码错误处理(Invalid PIN Process)。每个事务完成后,客户可选择继续上述事务或退卡。选择退卡时,系统弹出ATM卡,会话结束。
系统采用面向对象方法开发,使用UML进行建型。一次会话的序列图(不考虑验证)如图3-2所示。消息名称见表3-1。
表3-1 可能的消息名称列表
名称
说明
名称
说明
cardInserted()
ATM卡已插入
performTransaction()
执行事务
performSession()
执行会话
readCard()
读卡
readPIN()
读取个人验证码
PIN
个人验证码信息
create(atm,this,card,pin)
为当前会话创建事务
create(this)
为当前ATM创建会话
card
ATM卡信息
doAgain
执行下一个事务
ejectCard()
弹出ATM卡
图3-2 一次会话的序列图(无验证消息)
【问题】
根据说明中的描述,使用表3-1中的英文名称,给出图3-2中6~9对应的消息。
正确答案:
6: readPIN() 7: PIN 8: create(atm, this, card, pin) 9: performTransaction()
32. (简答题, 8分) 绘制“删除读者信息”用例的活动图。删除读者信息按照以下步骤进行:
学习java的过程中出现 \uff1b 错误代码,网上查发现是把英文(;)写成中文(;)
原因:行末分号为中文的状态(;)
解决方法:改成英文的状态分号(;)
序列信号发生器可由移位寄存器(74194)和反馈逻辑电路构成,如下图所示:
一、列出所要产生的序列(周期为8,最右边信号先输出)与移位寄存器状态的关系 如上图,序列下面的线段所对应的数码表示移位寄存器的状态 。a5 a6 a7 = 000 为寄存器初始状态,从最右端产生输出,由反馈电路形成右移串行输入端的输入。这样,便可在时钟脉冲作用下产生规定的输出序列。
二、作出电路状态变化表 电路在时钟作用下的状态变化过程及右移输入值如下表所示:
三、求出反馈函数的逻辑表达式 由表可得反馈函数F的逻辑表达式:
四、在Multisim上完成电路 如上图,探针X1与时钟脉冲相连,每亮一次就说明时钟脉冲作用一次(0→1),也代表着输出一个数字。探针右边显示数字0或1,表示输出的数字。这样,探针每亮8次就完成一个周期,然后继续循环下去。
五、总结与反思 本电路总体的设计方法,可以参照教材,“照葫芦画瓢”,可以说并不算太难。但是在模拟软件上连接电路时,出现了诸多问题,导致花费了大量时间和精力。以下是三点经验:
第一,两个元件在连接过程中,看起来是接在一起了,实际上是断开的,如下图所示。
这启示我们,尽量不要直接将两个元件相连,最好是分隔一定距离,再用导线连接,如下图。
第二,电路运行结果与预期不符,且从电路设计中找不出问题时,要学会从电路的每一个部分去排查错误,可运用探针等工具来输出中间结果, 如下图黑色框内的探针。
第三,Multisim中的芯片引脚可能与教材有所不同,不能一味照搬教材。拿74194的输出端举例,教材中从左到右是QD、QC、QB、QA,而Multisim中是QA、QB、QC、QD,两者刚好相反。如果不注意到这一点,实验就难以完成。具体请看我的另一篇文章:https://blog.csdn.net/Washington89757/article/details/130712176
本文如有错漏之处,敬请指正,同时也欢迎交流学习、共同进步。
目录
一、三极管的使用
二、三极管的种类
1、NPN
2、PNP
3、原理图符号
4、继续以N管讲解
三极管的导通电压(Ube>0.7V)
三极管的截至电压(Ube<0.7V)
三、三极管的三种状态
四、如何判断三极管的状态
五、三极管的钳位特性编辑
六、三极管Ib电流计算
七、三极管集电极电压,三极管Uce电压计算
八、三极管Rce计算
一、三极管的使用 一般可以当做开关管来使用,也可以利用三极管的放大特性,来搭建恒流源,恒压源等等,三极管当做开关管来使用的话,三极管输出的是高、低、高、低的方波信号
BUCK电源的开关频率在65KHz,也就是回路中的开关每秒钟开关6.5万次 ,使用人的手指去拨动机械开关的话,是达不到这样的速度的,就需要使用电子开关了,而电子开关是通过电流或者电压来控制电路的导通和关闭的,三极管就是一种电子式的开关
二、三极管的种类 三极管有两种类型:NPN型、PNP型。
1、NPN 习惯上把它称为N型三极管
对于上面的N型三极管来说,红色箭头所示的这个地方,可以看做是一个二极管
二极管的符号像不像一个箭头
下图是三极管的三个电极:分别是:B极,E极,C极
B极到E极之间相当于一个二极管,B极是二极管的正极,E极是二极管的负极
B极又叫做基极,C极又叫做集电极,E极又叫做发射极
那么,我们看,对于下面的N型三极管,既然BE极之间相当于一个二极管的话。
我们在BE极上加一个电源,当电源电压高于0.7V的时候,BE极之间这个二极管就导通了。
但是,当E极电位高于B极电位的时候,BE之间的二极管就反向截止了。
也就是说,和二极管一样,BE极之间也是具有单向导电性的
N型三极管是依靠BE极之间的电流Ibe来控制CE极之间的导通与断开的。
这里的BE极之间的电流既可以用Ibe来表示,也可以用Ib来表示
对于N型三极管来说,这个控制信号必须是从B流向E的电流。
三极管是流控流型的器件,它的Ib电流是可以控制Ic电流的,Ib电流控制Ic电流,所以三极管是流控流型的器件。
可以说,Ic电流把Ib电流放大了,就像一个喇叭,具有放大的作用,Ib和Ic是有一个放大关系的,一般我们使用一个叫做放大倍数的参数来描述这个放大关系,放大倍数用β表示,读作“贝塔”,用公式表示的话,就是Ib*β = Ic,不同的三极管,放大倍数是不同的 ,一般情况下,β是在30~300这样子的一个区间,三极管的型号不同,三极管的放大倍数也不同。
这里需要注意的是,即使是同一个型号的三极管,它的放大倍数也有差异,也就是做不到一致性很好
放大倍数如何在datasheet上寻找
2、PNP 下面这幅图是P型三极管,或者说是PNP型三极管
和N管一样,P管也是Ib控制Ic。
P管的电流怎么流的,下面是P管的电流流向
不管是N管还是P管,电流方向总是和箭头方向相同
上面这两个管子,首先,Ib电流方向和箭头方向相同,Ic电流方向也很好判断,也是看箭头方向
对左边的N管来说,Ic电流从集电极流向发射极,对右边的P管来说,Ic电流从发射极流向集电极
3、原理图符号 NPN型的三极管叫N管,PNP型的三极管叫P管
4、继续以N管讲解 三极管的导通电压(Ube>0.7V) 三极管要想导通,就得有Ib电流,如果没有Ib电流,三极管是截止的,有Ib电流,需要满足对于N管,要让BE极之间的电压差大于0.7V,BE之间的电压差大于0.7V,BE之间的二极管就导通了,也就是三极管就导通了
给三级管的BE极之间加上电压,BE极之间形成回路了,电流可以在这个回路中流通了,上面这个回路,还缺少限流电阻,不然电流I=U/R,电阻R=0,电流就非常大了,
这个回路中加一颗电阻,这样就构成了源、回路、阻抗了。
三极管的截至电压(Ube<0.7V) 假如电源的电压是0.6V的话,请问回路中有Ib电流吗?是的,没有。
要想让二极管导通,电压必须要 > 0.7V,而三极管的BE极之间就可以看成一个二极管,所以,三极管的导通条件是BE极之间的电压差Vbe > 0.7V,但是当Ib回路导通时,Vbe就会被钳位在0.7V,这是二极管的钳位特性,三极管的BE极导通压降Vbe和放大倍数β一样,也是有差异的,为了交流方便,就认为BE的钳位电压是0.7V
三、三极管的三种状态 一种是放大状态,一种是饱和状态,一种是截至状态。
四、如何判断三极管的状态 判断三极管是放大状态还是饱和状态,就要判断Ib电流和Ic电流是不是满足β 倍的关系,
如果满足 Ib*β = Ic ,那么就是放大状态。
1. 结论 很小的矩阵运算 cpu 更快
大矩阵运算 gpu 快很多
2. 代码样例 #%% import import torch import time print(torch.__version__) #%% test funcs def show_time_of_loopMatmulByDevice(loop_n, x0, x1, device_str="cpu"): if loop_n < 1: print("warn | bad loop num:", loop_n) return device = torch.device(device_str) # 指定 cpu 或 gpu x0 = x0.to(device) x1 = x1.to(device) t0 = time.time() for i in range(loop_n): # 循环多个 以便放大运行时间 且使结果更具说服力 y = torch.matmul(x0, x1) t1 = time.time() print("device:",y.device,"| run time:"
随着智能化生活的发展,手机成为人们生活的必需品,而蓝牙技术也随之应运而生。蓝牙技术作为现代移动设备与设备之间传输数据的一种主流方式,已经广泛应用于手表、耳机、车载系统等多种设备。在Android设备中,蓝牙技术也被大量使用,本篇文章将介绍Android中的蓝牙技术。
1. 蓝牙概述
蓝牙标准是一种短距离无线通信协议,其基于2.4GHz免费频段进行通信。蓝牙技术的优点在于低功耗、简单易用、可广泛应用于一些小型移动设备的通信。与其他无线技术相比,蓝牙技术支持各种不同的传输速率,以满足不同设备的需求。
2. Android中的蓝牙
Android设备可以作为蓝牙设备或主机来进行通信,并且可以在应用中使用蓝牙API。Android的蓝牙API允许您进行以下操作:
- 完成蓝牙设备的扫描并找到可用的设备
- 连接到现有的设备
- 在两个设备之间传输数据
- 向其他设备发送命令以控制其行为
3. 使用Android开发套件进行蓝牙开发
Android开发套件提供了蓝牙API,它可以帮助您在应用中实现蓝牙通信。以下是使用Android开发套件进行蓝牙开发的一些常用方法:
- 获取蓝牙适配器并在应用中启用蓝牙
- 发现蓝牙设备
- 连接到蓝牙设备
- 通过蓝牙输入和输出流发送和接收数据
下面是一个使用Android API进行蓝牙通信的代码示例:
```
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
// Device does not support Bluetooth
}
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
// Bluetooth is already enabled
}
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device : pairedDevices) {
找到最后一次成功备份的日期和时间,假设是在 2021-06-01 10:00:00 进行的备份。
登录到 MySQL 服务器,使用 mysqlbinlog 命令,查找从备份时间到误操作时间之间的 binlog 日志文件。命令格式如下: mysqlbinlog --start-datetime="2021-06-01 10:00:00" --stop-datetime="2021-06-02 10:00:00" /var/lib/mysql/binlog.000001 > mysqlbinlog.txt 其中,--start-datetime 表示起始时间,--stop-datetime 表示结束时间,/var/lib/mysql/binlog.000001 是 binlog 日志文件的路径,> mysqlbinlog.txt 表示将输出结果保存到 mysqlbinlog.txt 文件中。 打开 mysqlbinlog.txt 文件,查找误删除数据的操作。复制误删除操作的 binlog 日志。回到 MySQL 控制台,使用 mysqlbinlog 命令来还原误删除的操作。命令格式如下: mysqlbinlog --no-defaults mysqlbinlog.txt | mysql -u username -p dbname 其中,--no-defaults 表示不使用默认配置文件,mysqlbinlog.txt 是保存误删除操作的 binlog 日志文件,username 是 MySQL 用户名,dbname 是要还原的数据库名称。 恢复成功后,重启 MySQL 服务器。
目 录 一、主要功能
二、硬件资源
三、程序编程
四、实现现象
一、主要功能 基于51单片机,具有晶振电路、复位电路、DS18B20温度传感器、LED灯和蜂鸣器灯光报警模块、LCD1602显示模块、L298N驱动电机散热模块和按键模块。
主要功能:
系统开始运行,显示屏显示最大温度阈值和最小温度阈值,并且通过DS18B20温度传感器读取当前温度值显示出来,和显示当前的状态。可以通过按键来增减温度上限阈值和温度下限阈值,如果当前温度在阈值之内,显示状态位正常;温度超过最大阈值,灯光报警模块启动,散热模块启动,驱动电机转动,实现降温功能;温度低于最小阈值,灯光报警模块启动,加热模块启动,告知人们正在加热升温。
主要实现要求:
1、温度采集
2、温度上下限调值
3、超值报警,具有加热和降温功能
4、LCD1602液晶显示温度、状态
二、硬件资源 1、51单片机最小系统
2、电机模块
3、按键模块
4、蜂鸣器和LED灯模块
5、LCD1602显示模块
6、DS18B20温度传感器模块
三、程序编程 /***************************************************************************************************************************** CSDN 夜间去看海制作 *******************************************************************************************************************************/ #include <REGX52.H> #include<intrins.h> #include<stdio.h> #include "Delay.h" #include "LCD1602.h" #define uchar unsigned char #define uint unsigned int sbit led = P1^7; //LED灯引脚 sbit P22 = P2^5; //蜂鸣器引脚 sbit DS=P2^4; //DS18B20温度传感器 sbit Motor1_IN1 = P2^0; //电机IN口 sbit Motor1_IN2 = P2^1; sbit Motor1_EN = P2^3; //电机使能端 sbit key1=P3^2; sbit key2=P3^3; sbit key3=P3^4; sbit key4=P3^5; unsigned char count; typedef unsigned char u8; typedef unsigned int u16; static flag=1,flag1=1; static int n1=1; static uint temp; static float ftemp = 0.
数据结构有云:程序=数据+操作。从中可以看出,数据才是程序的核心对象,每个程序所有的操作和意图都是围绕数据展开的。每个程序的结构基本都分为三个部分:输入,处理,输出。输入是接收用户的数据,处理过程是通过不同的算法处理接收的数据,输出是将处理的结果返回给用户。
一、输入与输出
大家还记得在VBA我们一般通过什么方式接受用户的简单输入呢?没错,最简单的方式就是Msgbox与InputBox。
Msgbox:最简单的用户输入框
Msgbox太简单了,以至于大家用的最多的就是其显示信息的功能,其实它是有返回值的。它的语法如下所示:
MsgBox(Prompt[,Buttons][,Title][,Helpfile,Context]) As Integer
这里用户的输入就是他选择的按钮,也就是Integer值所代表的选项。这里用户的选择比较简单,所以不用验证。
InputBox:最简单的全能型用户输入框
VBA内置的InputBox方法
这个函数返回一个字符串,选择取消后返回空串(零个字节的字符串)。它不含有容错处理。例如你想要用户输入整数,结果用户输入了字符,这个时候InputBox并不会替你告诉用户错误的原因。
Application的InputBox函数
这个函数更强大,内置容错处理,选择取消后返回false。这个函数可以指定输入的类型,当用户输入的数据类型与参数中指定的类型不兼容的时候,这个函数会给出温馨的提示,告诉你输入的数据类型不对。
除了这两种最简单的输入方式外,还有其它一些重要的输入方式:
单元格输入:这种方式是最常见的,用户在单元格中输入数据,然后程序获取单元格中数据并处理。
用户窗口输入:这种方式最直观,比较适合处理结构化数据;利用窗口,我们可以提供专业的用户视觉体验和便利的用户输入体验。
文件输入:这种方式适合导入大量的数据或其它来源的数据。
说完了输入,再说说输出。VBA中输出也有相对应的几种方式:
Msgbox:最简单的输出信息方式。
单元格输出:可以显示大量的处理结果。
用户窗口输出:显示一些自定义的信息和格式,用户体验较佳。
文件输出:输出大量的信息和结果。
立即窗口输出:一般用于调试的时候显示信息(Debug.Print)。
上面我们简单总结了常见的输入与输出方式。用户输入的数据是我们工作的前提,那么这些数据是否符合我们的需求,我们就需要去验证。
二、简单数据验证
1.简单数据输入与类型验证
这个很好办,直接使用Application中的InputBox函数就可以达到这个目的。
2.内置函数验证
如果只是简单验证数据的类型,或者某些简单的判断也可以靠VBA中内置的一些函数来验证。我在前面的内置函数中已经总结了,主要有两类的内置函数:
VBA内置的验证函数有:
IsNumeric(x) - 是否为数字, 返回Boolean结果。
IsDate(x) - 是否是日期, 返回Boolean结果。
IsEmpty(x) - 是否为Empty, 返回Boolean结果。
IsArray(x) - 指出变量是否为一个数组。
IsError(expression) - 指出表达式是否为一个错误值。
IsNull(expression) - 指出表达式是否不包含任何有效数据 (Null)。
IsObject(identifier) - 指出标识符是否表示对象变量。
WorksheetFunction内置的验证函数有:
IsErr - 检查是不是除了#N/A外的错误值.
IsError - 检查是不是错误值(#N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME?,或者 #NULL!).
这是我第一次做博客,谢谢。
【1331:【例1-2】后缀表达式的值】
从键盘读入一个后缀表达式(字符串),只含有0-9组成的运算数及加(+)、减(—)、乘(*)、除(/)四种运算符。每个运算数之间用一个空格隔开,不需要判断给你的表达式是否合法。以@作为结束标志。
比如,16–9*(4+3)转换成后缀表达式为:16□9□4□3□+*–,在字符数组A中的形式为:
栈中的变化情况:
运行结果:-47
提示:输入字符串长度小于250,参与运算的整数及结果之绝对值均在2^64范围内,如有除法保证能整除。
【输入】 一个后缀表达式。
【输出】 一个后缀表达式的值。
【输入样例】 16 9 4 3 +*-@ 【输出样例】 -47 思路:很简单,将后缀表达式转为中缀即可。
注意事项:题目说是2^64,所以用long long(其实long long是2^62,但用long long是100分)
代码:
#include <bits/stdc++.h> using namespace std; stack <long long> s; int main() { string str; getline(cin, str); int len = str.length(); long long x; for (int i = 0; i < len - 1; i ++) { x = 0; long long a, b; if (str[i] == '+') { a = s.
目录 Jetson Nano安装Ubuntu20.04Ubuntu20.04 配置ROS2环境Set localeSetup SourcesInstall ROS2 packageEnvironment setup安装colconBuild ROS 2 Workspace Pixhawk配置Jetson Nano上MicroDDS-Agent配置及和pixhawk通讯 PX4在V1.14及后续版本中,将原本ROS2与PX4通讯的中间件micrortps模块删除了,优化成了MicroDDS模块。MicroDDS的使用相比之前也简化了许多。
本文在jetson nano板子上部署了Ubuntu20.04,并安装了ROS2,测试和Pixhawk4 mini之间的通讯。
Jetson Nano安装Ubuntu20.04 镜像用的是在github上找到的:https://github.com/Qengineering/Jetson-Nano-Ubuntu-20-image。
他上传了Ubuntu 20.04 带有 OpenCV, TensorFlow and Pytorch的镜像,但是我使用的时候配置环境报错。于是推荐用他上传的空白的Ubuntu20.04 Bare image镜像。
将内存卡用读卡器插入电脑,用balenaEtcher选择下载好的镜像,选择对应的内存卡烧写。完成后将内存卡插入jetson nano中就可以运行系统了。
(如果是之前烧写过系统的内存卡,可以用SDFormatter格式化清空后再烧入)
Ubuntu20.04 配置ROS2环境 基本步骤和之前写的教程Ubuntu20.04安装ROS2+ROS2-PX4框架搭建差不多。但是由于这个教程中也安装了PX4的开发环境,有些python的项在配置PX4环境的时候已经配置了。但是在jetson nano中,不需要配置PX4环境(配置了也会报错),所以需要额外单独安装一些python和colcon的依赖项。
Set locale sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 export LANG=en_US.UTF-8 Setup Sources sudo apt update sudo apt install curl gnupg2 lsb-release curl http://repo.ros2.org/repos.key | sudo apt-key add - sudo sh -c 'echo "
1.修改/etc/ppp/options文件 将其中的lcpe-echo-failure 的参数改为40
2.将无线网卡的power management 关掉 查看 $ sudo iwconfig lo no wireless extensions. wlp5s0 IEEE 802.11 ESSID:"\xE7\xA6\x8F\xE7\xBC\x98\xE5\x96\x84\xE5\xBA\x86" Mode:Managed Frequency:2.472 GHz Access Point: 44:97:5A:04:87:DA Bit Rate=15 Mb/s Tx-Power=22 dBm Retry short limit:7 RTS thr:off Fragment thr:off Encryption key:off Power Management:off Link Quality=22/70 Signal level=-88 dBm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:0 Invalid misc:18 Missed beacon:0 enp4s0 no wireless extensions. # 关闭 $ sudo iwconfig wlp5s0 power off
目录 前言一、单链表找三等分点(链表可能有环)二、讲几个熟悉的设计模式三、Spring IoC、AOP是什么,是如何实现的,Spring MVC是什么?四、怎么实现线程安全,各个实现方法有什么区别,synchronized是不是可重入锁?五、HashMap底层实现,怎么实现HashMap线程安全?六、JVM内存管理七、 怎么判断哪些对象需要被GC,GC的方法, HotSpot GC算法以及7种垃圾回收器。八、类加载机制九、线程和进程的区别十、HTTP有没有状态,如何理解HTTP的无状态,如何解决HTTP的无状态?十一、Java IO、NIO和异步IO十二、AJAX是什么,实现原理十三、设计一个线程池十四、MySQL优化、索引的实现十五、事务的隔离级别十六、Hibernate和MyBatis十七、Git十八、Linux常用指令十九、如果一个表特别大,怎么优化?后记 前言 “实战面经”是本专栏的第二个部分,本篇博文是第一篇博文,如有需要,可:
点击这里,返回本专栏的索引文章点击这里,前往下一篇《【Java校招面试】实战面经(二)》 一、单链表找三等分点(链表可能有环) public class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } } public class Solution { public ListNode findThreeEqualParts(ListNode head) { if (head == null || head.next == null) { return null; } // 快慢指针检查链表是否有环,将其转换为无环链表 ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { slow = slow.
YOLOv5 v8学生工程角度客观评价 写在最前:实验数据比较v5优势YOLOv5的边缘端部署YOLOv5的Web部署 v8优势 写在最前:实验数据比较 目前更新到v8版本,但是在国产边缘设备部署,厂商给的demo都是v5版本,开发之余比较一下异同。 本次实验使用的数据集为cub-200鸟类分类数据集,就目前博主最近的实验结果来看(工程角度),X模型训练中呈现出的精确度和召回率基本一致,但收敛速度大相径庭,可以看出v8 100轮就能呈现出一个很好的效果,快了将近一半时间:
200类 train19 yolov8x模型 100轮
200类 train19 yolov5x 200轮
x和l博主进行了多次实验,测试了三种数据集分别为cub-200,ap10k动物目标检测,fish分类检测,效果与以上展示的结果契合,v8的优势就是训练速度更快,更容易收敛。
论文图中真正碾压v5的是n和s模型,追求推理速度和FPS的同时也能有高精度
200类 yolov8n,可以看到n模型的精度几乎没有下降,在部署时推理速度极佳
v5优势 v5的目录结构简单,麻雀虽小五脏俱全,训练,检测,导出工程部署模型上手快,开发文档多,前人都把坑踩得差不多了,如果不是特殊需求例如追求极致的FPS或者精度,只需要跟着教程走,百度一下就能满足开发要求。
YOLOv5的边缘端部署 在部署RKNN给出的demo,边缘端部署YOLO,给出了v5版本,博主在部署时量化后达到了150+FPS。
有现成的开发文档,弱鸡必备!
YOLOv5的Web部署 GitHub也有许多Flask的部署方法,但是大多都是老旧版本的v5,可能会报错,结合新版本更改一下文件和方法就能实现部署。博主在web部署v5x模型时也有25+的FPS,大致能实现实时检测。
如果你只想实现功能,不妨多用一下v5
v8优势 v8相比于原始v5,一口气更新了分类,分割,检测,关键点四种任务,几乎能适用所有视觉方向的开发,并且封装的很好,训练与v5略有不同
就实验结果来看,v8超快的训练速度,v5是比不了的,英语不好外国论坛上的帖子很少去看,等国内大佬吧。。
V8目前博主正在尝试部署jetson nano端的边缘设备,GitHub也给出了YOLOv8-TensorRT
的文件,国产芯片的Git没有更新最新款的demo,部署效果待更新。。。
目录
1,结构体
2,创建函数
3,插入函数
4,删除函数
5,查找函数
6,取值函数
7,输出函数
8,退出函数
9,菜单函数
10,主函数
完整代码:
本文章不添加判断用户输入错误的代码,纯粹讲解顺序表。
完整代码在最后面。 1,结构体: typedef struct sqlist { int* arr; int length; }sqlist; 1.int* arr;定义指针数组,当然也可以定义为arr[10],静态开辟内存空间,定义为指针数组只是为了可以根据我们的需要分配空间大小,称为动态开辟内存空间,也就是创建函数里的L.arr = (int*)malloc(10 * sizeof(int)); 2.int length;为表的长度,插入时表长度+1,删除时表长度-1。 2,创建函数: void listcreat(sqlist& L) { L.arr = (int*)malloc(10 * sizeof(int)); int i; printf("请输入创建的顺序表的长度"); scanf("%d", &L.length); printf("请输入数字:"); for (i = 0; i < L.length; i++) { scanf("%d", &L.arr[i]); } printf("创建链表成功!\n"); } 1.sqlist& L;表示引用的意思,就是把sqlist取了一个名字叫L,后续就可以用L.什么什么去操作sqlist里的变量。 2.L.arr = (int*)malloc(10 * sizeof(int));10*代表开辟了十个int大小的内存空间。 3,插入函数: void listinsert(sqlist& L) { int i, j, e; printf("
1、需要知道另一台电脑的ip,即MySQL主机地址。
2、关闭自己的电脑及另一台电脑的防火墙。
3、修改另一台电脑MySQL连接权限。
1)首先确认MySQL服务开启,环境变量中PATH路径正确。win+r输入cmd打开命令窗口;
2)输入mysql -u root -p; 回车,之后输入密码;
3)输入user mysql; 切换到MySQL数据库;
4)输入update user set host='%' where user='root'; 修改root访问权限为%,使得所有人都可访问该数据库;
5)输入select user,host from user; 查看访问权限是否修改成功,成功则root对应的host是%;
6)输入flush privileges; 进行刷新,使修改生效;
4、此时,在sqlyog点击连接,自己的sqlyog即可成功连接到另一台电脑的MySQL。
通过http接口实现文件操作 SeaweedFs可通过filer的http接口/master中的http接口来进行文件上传
1.通过master的接口进行上传文件 通过各种方式进行请求接口:http://localhost:9333/submit, ip和端口号是master服务的信息。此接口通过post请求方式将文件的二进制流通过表单形式上传,表单文件key是file即可。
图片中表示的就是接口文件上传。返回的结果中fid是文件的唯一标识,其中15表示存储在volume的id是15的块中,fileUrl是可直接查看的文件的地址信息。
2.通过filer上传文件 1.首先需要通过接口给要上传的文件分配id http://localhost:9333/dir/assign
接口会返回类似15,0be8fa1578的id,此id就是文件的id了。
2.然后再通过接口(filer端口)通过post请求 http://localhost:8080/15,0be8fa1578
传递文件的二进制流数据,key为file类似第一种方式的submit方法上传。
3.上传完成之后通过地址(get请求方式) http://localhost:8080/15,0be8fa1578
即可查看文件
4.删除文件 通过delete的请求类型访问http://localhost:8080/15,0be8fa1578即可
关于这个其实可能是由于Redis版本过低导致,stream流是5.0版本的新特性,我这里用的是3.2.100的版本会出现这个错误
Solr是一个基于Lucene的搜索引擎,它能够快速、可靠、强大地处理大量数据。Solr提供了一个HTTP接口,可以通过Java、Python、PHP等多种编程语言进行访问。Solr是一个开源的项目,由Apache软件基金会维护。
Solr的主要特点包括:
快速:Solr使用Lucene的索引技术,能够快速地处理大量的数据。
可扩展:Solr支持分布式架构,能够处理海量数据。
高可靠性:Solr具有高可靠性,能够处理数据的备份和恢复。
易于使用:Solr提供了丰富的API,可以方便地进行数据查询和修改。
支持多种数据格式:Solr支持多种数据格式,包括XML、JSON、CSV等。
具有强大的搜索功能:Solr提供了强大的搜索功能,包括全文搜索、过滤器、分面搜索等。
总之,Solr是一个功能强大、可靠性高、易于使用的搜索引擎,适合用于处理大量的数据。
题目要求 罗马数字转整数
解题步骤 方法一 package subject13; /** * @author chenqian * @version 1.0 * @data 2023/5/19 22:35 * 罗马数字转整数 * 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 * * 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: * * I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 * X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 * C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 * 给定一个罗马数字,将其转换成整数。 * * 思路:通过题目可知特殊情况就只有6种我们可以把这些情况一一列举出来并进行判断 */ public class Subject { public static void main(String[] args) { String s = "
实验目的 利用虚拟机搭建一个局域网,其中一台作为DHCP服务器为主机动态分配IP
实验环境 DHCP服务器:winserver 2003客户机一:windows7 x64客户机二:windows10 x64交换机:VMnet0(主机上启用VMnet0的虚拟网卡) 实现流程 环境准备 检查交换机设置:特定虚拟网络
检查主机设置
windows7
将连接网络改为VMnet0,特定虚拟网络(模拟一个局域网环境),改为VMnet0之后网络会断开连接,主机处于由VMnet0构成的封闭局域网内
检查IP信息:会发现主机上存在IP地址 -(169.254.x.x/16:微软的保留地址) 系统自动分配的IP用于局域网下的通信 windows10 x64
设置网络连接模式
查看IP信息
服务器设置
修改网络连接模式 检查IP配置 为服务器配置IP:DHCP服务器必须要配置静态IP
找到网络连接里面的本地连接,配置静态IP地址 配置IP(这里使用的是网段的第一个有效IP,因为模拟一台交换机相连下的局域网环境通信可以不配置网关和DNS)
确认配置无误
搭建DHCP服务器
找到 点击添加或删除角色,选择自定义配置(进入服务器类型选择) 选择DHCP服务器,点击下一步 进入新建DHCP作用域 名称自定义,描述可以不写
选择要分配的网段(起始IP和结束IP都使用网段内的有效IP)
排除地址范围(其它的服务器或者网管使用的IP— 已经规划好的ip)
租约期限:超过租约时间IP就会完全失效,不过一般在租约期限到之前会自动发起续约请求
可以先跳过,后面再服务器选项中设置
服务器搭建好之后,启动作用域 验证端口开放:netstat -an:查看本地开放端口情况
```bat UDP 10.1.1.1:67 *:* UDP 10.1.1.1:68 *:* ``` 配置DHCP服务器
- 地址池 - 可以查看当前服务器租约地址的范围和排除的IP地址 - 根据需求增加排除IP地址和将排除地址拿来使用 - 地址租约 - 可以查看当前服务器有多少主机签订了租约 - 保留选项 - 保留操作可以使DHCP客户端拿到固定的IP地址,通过新建保留,配置保留地址、名称、绑定MAC地址和描述(BOOTP是DHCP的前身),最后选择添加 - 服务器选项 - DHCP除了为区域内的主机自动分配IP信息以外还可以分配一些特定服务器的信息 动态获取IP
2023 年 5 月 17 日参加的频蓝的python比赛,留点题目给后来者
1.想要输出“人生苦短,我用Python”,应该使用( )?
printf() print() println(); Print() 2.print(100 - 25 * 3 % 4)输出的结果是( )。
1 97 25 0 3.在Python中,以下哪个变量的命名是不合法的?
x123 _name post@abc post_abc 4.Str1 =“Python is beautiful!”,表达式 str1.isnumeric() 的结果是。
True 1 0 False 5.下列选项中不是Python合法的标识符的是( )。
int32 40XL self name 6.Python解释器执行’1234’.find(‘5’)的结果是( )。
-1 None 空 报错 7.Python的输出函数是________。
input() print() math() turtle() 8.( )是体现Python代码逻辑关系的重要方式,同一个代码块必须保证相同的( )。
缩进,缩进量 字母大小写,格式 格式,格式 常量,变量 9.Python中,以下所列运算符不能用于元组运算的是( )。
- + * in 10.
目录
一.ncurses库基本使用方法
输入输出的应用:
二 构建地图:
三 蛇身体:
1.先让蛇头显示在地图里:
2.显示整个蛇身体
1.测试
2.动态创建链表
3.让蛇移动
1.先试试向右移动
2.move() 函数
3.全向移动的完善,撞墙找死,咬自己自杀和退出游戏
4.自行开始游走
1.Linux线程
2.实现游走:
5.食物
1.简单实现
2.实现食物的随机位置
6.完结
一.ncurses库基本使用方法 函数类似原版c库
# include <curses.h> int main(){ initscr(); //ncurses界面的初始化函数 /* noecho(); //时输入不显示在交互界面中 cbreak(); */ printw("This is a ncurses window!"); //在ncurse模式下的打印函数 getch(); //等待用户输入 endwin(); //退出程序,调用函数来恢复shell终端显示,否则shell终端字乱码 } 运行
gcc 【文件名】 -lcurses
如 gcc snake2.c -lpthread -lcurses
输入输出的应用: #include <curses.h> int main(){ initscr(); char c; while(c != 'q'){ c = getch(); printw("
动态规划 动态规划背包问题AcWing 2.01 背包问题(0-1 背包问题模板题)思想解法代码 AcWing 3. 完全背包问题( 完全背包问题模板题)思想解法代码 AcWing 4. 多重背包问题 I ( 多重背包朴素法模板题)思想解法代码 AcWing 5. 多重背包问题 II ( 多重背包二进制优化模板题)思想解法代码 AcWing 9. 分组背包问题(分组背包模板题)思想解法代码 线性DPAcWing 898. 数字三角形AcWing 895 最长上升子序列AcWing 896 最长上升子序列 IIAcWing 897 最长公共子序列AcWing 902 最短编辑距离AcWing 899 编辑距离 区间DPAccWing 282 石子合并 计数类DPAcWing 900 整数划分 数位统计DPAcWing 338 计数问题 状态压缩DPAcWing 291 蒙德里安的梦想AcWing 最短Hamilton路径 树形DPAcWing 285 没有上司的舞会 记忆化搜索AcWing 901 滑雪 动态规划 动态规划重要的是思想,虽然没有模板,但有套路,根据实际问题进行相应变化,具体问题具体分析。
背包问题 背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V?它是在1978年由Merkle和Hellman提出的。
背包问题主要分类
图片来自糖豆爸爸
AcWing 2.01 背包问题(0-1 背包问题模板题) 思想 yxc 套路-分析法
基因测序技术发展历史:
自1970年代以来,基因测序技术经历了长足发展,分成了一、二、三代测序技术。最早期的测序技术是Sanger测序法,采用化学方法测序,具有高精度的优点。但是其瓶颈是低通量,因此需要更高效的测序技术。此后,Illumina公司发明的二代测序技术、Oxford Nanopore Technologies公司发明的第三代测序技术逐渐崭露头角。
一、二、三代测序技术原理和应用:
1. 一代测序技术: 一代测序技术主要是指质粒测序和Sanger测序技术。它们基于序列单一碱基的化学反应,通过在DNA多聚酶作用下逐步合成完整的DNA序列,然后通过对放射性核苷酸进行标记来进行测序。一代测序技术具有高精度和可信性的优点,但是通量低,成本高昂,速度缓慢,不能同时处理大量的样品。因此,一代测序技术主要被用于特别关键的测序任务,如人类基因组计划和医学诊断等。
2. 二代测序技术:
二代测序技术也被称为高通量测序技术,它分为两大主要技术:合成扩增测序和桥式扩增测序。其中合成扩增测序主要由Illumina公司研发,通过使用碱基转接荧光技术,实现了高效的并行测序。桥式扩增测序主要由Applied Biosystems公司(现已被Thermo Fisher Scientific收购)研发,使用PCR技术扩增DNA,然后通过荧光标记来实现测序。二代测序技术大大提高了测序效率、速度和 AI都知道大白话: 通量,可以在几天或几小时内完成基因组或转录组测序。它被广泛应用于功能组学、癌症研究、作物杂种性状驯化和微生物生态等研究领域。
3. 三代测序技术:
第三代测序技术被称为单分子测序技术,其基于直接读取单个DNA分子而不需要PCR扩增,因此能够实现测序的同时读取长的DNA分子,避免了二代测序中的多次PCR扩增带来的误差和片段化。常见的第三代测序技术包括Pacific Biosciences(PacBio)公司的SMRT产品和Oxford Nanopore Technologies(ONT)公司的MinION产品。
第三代测序技术在许多领域有着广泛的应用,例如环境微生物学、癌症研究、人类基因组学、重要经济作物的基因组学和基因组进化学研究中的很多方面。
总之,随着技术的不断发展,基因测序技术的效率、速度和精度都有了很大的提升。这些技术被广泛用于各种生命科学领域的研究,为了解生命的基础性问题和解决重要的生物学问题,提供了强大的工具和方法。
前言
今天分享的是一篇2021年发表在Applied Sciences上的关于机器人参数辨识的文章综述,涵盖了一众机器人参数辨识方法,包括了逆动力学辨识模型结合普通最小二乘法(OLS)、加权最小二乘法(WLS)、迭代重加权最小二乘法(IRLS)和总体最小二乘法(TLS)的辨识方法,还包括了如辅助变量法(IV)、最大似然估计法(ML),还有其他一系列的方法,我就不一一列举了。也是第一次见到对辨识方法总结很全,而且代码和数据都开源的工作。这个开源代码的可食用性较差一点,需要花费一定的时间才能去理清整个代码架构,直接拿出来照搬可能也得花点功夫。
下面是文章的相关链接:
文章标题:Inertial Parameter Identification in Robotics: A Survey
文章链接:https://www.mdpi.com/2076-3417/11/9/4303(开源期刊,自行下载)
开源数据:https://zenodo.org/record/4728085
开源程序:https://github.com/TUM-ICS/BIRDy
关于上面这个开源数据的网站,是需要挂梯子才能进去,而且晚上的下载速度贼慢,好像白天会好一点。
我已经下载下来放在网盘上了,有兴趣的同学可以试试哈。
百度网盘:
链接:https://pan.baidu.com/s/1QBzVj1rkSfSn_PRtx20MQg
提取码:4y9m
–来自百度网盘超级会员V3的分享
SPDK及环境准备篇分别介绍了SPDK及我本地的环境信息,本篇将基于我的测试环境配置SPDK iSCSI Target并测试其性能,并对比Linux-IO iSCSI Target vs NFS的测试数据,展示SPDK的性能提升
SPDK运行环境配置 环境准备篇中我们曾提及Ubuntu 22.04中如何开启iommu,这是进行SPDK iSCSI Target测试的前提,在这个过程中我个人就被折磨了很久,/sys/kernel/iommu_groups/目录下就是空空如也,网上google了很久也没能解决,再次强调一下,CLEAN的环境会少很多坑,环境准备篇中相关内容如下:
2. 修改Linux启动参数启用iommu 修改/etc/default/grub文件GRUB_CMDLINE_LINUX行,然后执行grub-mkconfig后重启操作系统,使修改生效。 root@nvme:~# cat /etc/default/grub | grep "^GRUB_CMDLINE_LINUX=" GRUB_CMDLINE_LINUX="quiet intel_iommu=on" root@nvme:~# root@nvme:~# grub-mkconfig -o /boot/grub/grub.cfg 通过如下命令检查iommu,注意,开启iommu后/sys/kernel/iommu_groups目录是不为空 root@nvme:~# dmesg | grep "DMAR: Intel" [ 1.493774] DMAR: Intel(R) Virtualization Technology for Directed I/O root@nvme:~# ls /sys/kernel/iommu_groups/ 0 1 2 3 4 5 6 7 8 root@nvme:~# 第一步,先找到NVMe设备PCI信息
root@nvme:~# lspci 00:00.0 Host bridge: Intel Corporation Comet Lake-S 6c Host Bridge/DRAM Controller (rev 03) .
从1991年Linux首次发行到现在的30多年时间里,存储的介质、接口、协议都演进了几个代际,存储容量和传输速率也几乎遵循摩尔定律的发展,然而,人们对高性能的追求是无止境的,从持续满足高性能的角度来看,有两种途径,一是更高性能的硬件设备,二是减少软件处理的开销,更高性能硬盘设备依赖硬件厂商的不懈努力,软件处理是指存储软件栈,即Linux Storage Stack,见图,
Linux Storage Stack主要包括,VFS、Block Layer、driver等,Linux Storage Stack因为其通用性的设计为主,即不同硬件设备实现一个通用的驱动块设备驱动,不一定能够发挥共性能硬盘的优势,逐渐成为高性能存储的瓶颈。
提供软件处理性能,以整体上提高上层应用的高性能需求,SPDK就是Intel为了解决高性能访问而开发的存储性能软件加速库
SPDK SPDK是由Intel发起的,用于加速NVMe SSD作为后端存储使用的软件加速库。SPDK并不是一个通用的适配解决方案,实现了一套基于用户态软件驱动的完整IO栈,很显然内核的文件系统如ext4、brtfs等都不能使用了,也不支持可移植操作系统接口,提供了blobfs/blobstore并使用类似于AIO的异步读写方式。
SPDK的核心是用户态、异步、轮询、无锁的NVMe驱动,并提供了零拷贝、高并发等功能。SPDK用户态驱动最大化的发挥NVMe SSD性能优势,大幅降低NVMe command的延迟,提高单CPU核的IOps,形成高性价比的解决方案,如SPDK vhost target,以很小的性能损耗将NVMe SSD透传给qemu虚拟机,如此高性能解决方案在高性能计算中一定极受欢迎
SPDK的应用场景 SPDK比较好的应用场景包括:
1. 提供块设备接口的后端存储应用,如iSCSI Target、NVMe-OF Target
2. 对虚拟化IO加速,主要是指Linux系统下的QUME/KVM作为Hypervisor的管理虚拟化场景,使用vhost交互协议,实现基于共享内存通道的高效vhost用户态Target。如vhost iSCSI/blk/NVMe Target,从而加速虚拟机中的virtio SCSI/blk即Kernel Native NVMe协议的IO驱动,缩短了host OS中的IO栈
3. SPDK加速数据库引擎,通过实现RocksDB中的抽象文件类,SPDK的blobfs/blobstore可以和RocksDB集成,用于加速在NVMe SSD上使用RocksDB引擎,其实质是bypass kernel文件系统
SPDK NVMe驱动 Linux 内核NVMe驱动
内核态的NVMe驱动的设计以通用性为主,实现通用的块设备驱动,同时和内核其它模块深度集成,需要一些隔离的方法,比如信号量、锁、临界区等来保证操作的唯一性,这样设计有很好的兼容性和可维护性
内核驱动是如何与用户态应用程序交互呢,当内核驱动模块在被内核加载成功后,会被标识成是块设备还是字符设备,同时定义相关的访问接口,包括管理接口、数据接口等。这些接口直接或间接于文件系统子系统结合,提供给用户态的程序,通过系统调用的方式发起控制或读/写操作。
用户态应用程序和内核驱动的交互离不开用户态和内核态的上下文切换,以及系统调用的开销。参见Linux Storage Stack
SPDK NVMe驱动
不同于内核态NVMe驱动,SPDK NVMe驱动就是从性能的角度出发,减少软件所产生的开销,包括上下文切换、系统调用等。SPDK同时支持UIO(Userspace I/O)和VFIO(Virtual Function I/O)等机制绕过内核I/O栈实现对高速NVMe SSD盘的访问和控制
UIO解决两个核心问题,其一,如何访问设备内存,Linux通过映射物理设备的内存到用户态来提供访问。其二,如何处理中断,中断本身需要在内核进行处理,UIO通过一个小的内核模块完成最基本的中断服务程序处理,用户态驱动与内核模块通过/dev/uioX设备完成最基本的交互,同时使用sysfs来得到相关设备的内存映射、内核驱动等信息,UIO架构见下图
相对于UIO,VFIO不仅提供了UIO所能提供的两个基本功能,更多是从安全角度考虑,通过IOMMU(如同常规MMU,需要芯片上支持,如Intel VT-d)支持DMA重映射等技术,把设备I/O、中断、DMA暴露到用户空间从而可以在用户空间完成设备驱动的框架
有了Linux内核模块UIO、VFIO的支持,SPDK还引入异步轮询方式取代中断处理、通过绑定CPU核避免核间缓存同步及资源的无锁化、使用大页内存+hugetlb优化缺页异常引起的性能下降
SPDK 用户态应用框架
为了更好地发挥底层NVMe SSD的性能优势,除了用户态驱动,SPDK还提供了一套编程框架
总的说来,SPDK的应用框架可以分为:1.对CPU core和线程的管理;2. 线程间的高效通信;3. I/O的处理模型;4.数据路径的无锁化机制
SPDK的原则是使用最少的CPU核和线程来完成最多的任务,使用DPDK的EAL库,通过CPU核绑定函数的亲和性,限制对CPU的使用,每个核上运行一个reactor thread,SPDK提供了一个Poller机制,所谓Poller其实就是一个用户定义函数的封装,通过spdk_poller_register()注册,并在Reactor的while循环中检查Poller的状态,并进行调用。
SPDK放弃了传统的、低效的加锁方式进行线程间通信,是同一个线程只执行自己所管理的资源SPDK提供了事件调用机制,本质是每个Reactor对应的数据结构维护一个Event事件的环,这个环是多生产者但消费者模型,这个环上有锁的机制保证,相比于线程间的锁机制,要高效的多
fio(Flexible I/O Tester)正是非常常用的文件系统和磁盘 I/O 性能基准测试工具。提供了大量的可定制化选项,可以用来测试,裸盘、一个单独的分区或者文件系统在各种场景下的 I/O 性能,包括了不同块大小、不同 I/O 引擎以及是否使用缓存等场景。
ubuntu安装fio非常简单
root@nvme:~# apt install -y fio fio选项比较多,可以通过man fio查看,下面是比较常用的几个参数及说明
direct,表示是否跳过系统缓存,1表示跳过系统缓存。iodepth,表示使用异步 I/O(asynchronous I/O,简称 AIO,ioengine=libaio)时,同时发出的 I/O 请求上限。rw,表示 I/O 模式。read/write 分别表示顺序读 / 写,而 randread/randwrite 则分别表示随机读 / 写,randrw配合rwmixwrite分别表示混合测试及写占比。ioengine,表示 I/O 引擎,它支持同步(sync)、异步(libaio)、内存映射(mmap)、网络(net)等各种 I/O 引擎bs,表示 I/O 的大小。默认值是4KiBfilename,表示文件路径,可以是磁盘路径(测试磁盘性能),也可以是文件路径(测试文件系统性能) size,寻址空间,IO会落在 [0, size)这个区间的硬盘空间上。这是一个可以影响IOPS的参数。一般设置为硬盘的大小
runtime,运行时间
numjobs,并行job数,默认1
group_reporting,聚合job的测试结果
四个核心磁盘IO性能指标 介绍完工具,我们来介绍一下IO的性能指标,工具只是直观的给出测试结果,对指标的解读才是评估IO性能的依据,磁盘I/O的核心指标包括,
使用率,是指磁盘忙处理 I/O 请求的百分比
IOPS(Input/Output Per Second),是指每秒的 I/O 请求数
吞吐量,是指每秒的 I/O 请求大小
响应时间,是指从发出 I/O 请求到收到响应的间隔时间
如果孤立的看通过工具得来的指标数据是没有意义的,也就是说一定要结合场景及硬件特性来观测指标数据,如我的测试环境金士顿NVME SSD盘(下图截自金士顿官网)明确标出读/写速度3500MB/秒和2100MB/秒(MB=10^6)
先来一个read测试
# fio job文件nread.fio root@nvme:~/fio# cat nread.fio [global] bs=4096 rw=read ioengine=libaio size=50G direct=1 iodepth=256 iodepth_batch=128 iodepth_low=128 iodepth_batch_complete=128 userspace_reap group_reporting [test] numjobs=1 filename=/dev/nvme0n1 # 执行测试及输出结果 root@nvme:~/fio# fio nread.
k8s环境搭建 环境初始化 环境初始化 这里以三台主机为例,一台master节点,两台node节点
检查操作系统版本,kubeadm要求版本在7.5以上
cat /etc/redhat-release 主机名解析,编辑三台服务器在 /etc/hosts 文件下,添加一下内容
#主机名解析 cat >> /etc/hosts <<EOF #你每台主机的IP地址 和你自己设置的主机名或者域名 IP1 master IP2 node1 IP3 node2 EOF 时间同步 #时间同步 #k8s要求集群中节点时间必须精确一致,这里直接使用chronyd 同步网络时间 systemctl start chronyd systemctl enable chronyd 关闭防火墙,k8s和docker运行过程中会产生大量的iptables规则,为了让系统不混淆,直接关闭规则 #关闭firewalld systemctl stop firewalld systemctl disable firewalld 禁用selinux selinux时linux下的安全服务,如果不关闭可能在部署集群时,产生各种各样的问题
sed -i '/SELINUX/{s/enforcing/disabled/}' /etc/selinux/config 禁用swap分区 swap分区是指虚拟内存分区,作用是物理内存使用完之后,将磁盘空间虚拟成内存使用,启用swap分区会对系统性能产生负面影响
注释掉/etc/fstab
[root@vm1 ~]# cat /etc/fstab # # /etc/fstab # Created by anaconda on Thu May 18 03:22:16 2023 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 UUID=f4523fee-7f93-4a46-b24c-e66979053a29 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0 sed -i '/\/dev\/mapper\/centos-swap/s/^/#/' /etc/fstab 修改linux内核参数,添加网桥过滤和地址转发功能 编辑/etc/sysctl.
文章目录 前言了解数组数组名下标引用 数组的使用数组的创建数组的初始化 数组在内存中的存储二维数组存储顺序二维数组的初始化下标引用数组名 数组越界数组作为函数参数结尾 前言 数组(Array)是有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。这些有序排列的同类数据元素的集合称为数组。
所以,数组是用于储存多个相同类型数据的集合。
了解数组 数组名 int a;
int b[10];
我们可以确定a就是一个整型变量,那么b[10]就是一个整型类型的数组,b就是表示数组名,那么数组名的类型又是什么?在C语言中,数组名b实际上就是一个指针常量,即数组第一个元素的地址,类型取决于数组元素的类型;当然,在这里,不能把数组看作是指针,数组具有一些与指针完全不同的特征,数组在内存中是连续存放的,而指针只是一个标量。所以数组名表示的就是数组首元素的地址,但是,有两种情况是例外的:sizeof(数组名)和取地址&数组名,这里sizeof(数组名)表示整个数组的字节长度,而不是指针的字节长度;
int b[10];
printf(“%d”,sizeof(b));
结果:40
解释:整型数组中,一个元素表示4个字节,一个数组就是4*10=40个字节
int b[10];
printf(“%p\n”,b);
printf(“%p\n”,&b);
printf(“%p\n”,b+1);
printf(“%p\n”,&b+1);
结果:
000000000061FDF0
000000000061FDF0
000000000061FDF4
000000000061FE18
下标引用 在数组中,我们可以通过引用数组元素下标来找到指定元素。C语言规定:数组下标从0开始。
例如,我们想找到第五个元素,那么我们就直接引用b[4]即可。实际上,在C语言中,b[4]是用解引用来调取的,即*(b+4),C语言用[]来表示,使表达上更加简洁了。
来看下面代码:
#include <stdio.h> int main() { int arr[10] = {0};//数组的不完全初始化 //计算数组的元素个数 int sz = sizeof(arr)/sizeof(arr[0]); //对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以: int i = 0;//做下标 for(i=0; i<10; i++) { arr[i] = i; } //输出数组的内容 for(i=0; i<10; ++i) { printf("
性能测试概要 性能测试是软件测试中的一种,它可以衡量系统的稳定性、扩展性、可靠性、速度和资源使用。它可以发现性能瓶颈,确保能满足业务需求。很多系统都需要做性能测试,如Web应用、数据库和操作系统等。
性能测试种类非常多,有些概念也很相近:
Load Testing
Baseline Testing
Smoke Testing
Stress Testing
Soak Testing
Endurance Testing
Capacity Testing
Longevity Testing
Peak Testing
Spike Testing
Volume Testing
Capacity Tests
Reliability Testing
Scalability Testing
性能测试的工具 同样,性能测试的工具也非常多:
Apache JMeter
HP LoadRunner
Gatling
Blazemeter
k6
NeoLoad
TestComplete
Silk Performer
Rational Performance Tester
Apica LoadView
AppDynamics
Dynatrace
New Relic
很难说哪个工具是最好的,这取决于你的需求和预算。如果你想要开源易用的,那JMeter是一个不错的选择。如果你想要一个商用的工具,不妨试试LoadRunner和NeoLoad。重要的一点是,没有任何一款工具可以应对所有性能测试,很多时候我们需要组合使用。
JMeter的分布式测试 我将在本文详细介绍JMeter的分布式测试,我们经常会通过它来做性能测试。
在分布式测试角色中,我们需要一个控制节点Controller,还有多个工作节点Workers。如果你想你的请求增加,那可以通过不断增加工作节点来实现。Controller控制Workers,但它不跑具体的测试案例。Workers是连接目标系统来做具体测试的。
整个系统架构大概如下:
Worker可以在不同的服务器上,所以叫分布式,也因此可以利用多台电脑的资源来模拟足够的请求。
详细步骤 我将一步步介绍如何使用JMeter分布式测试来做性能测试,大致架构如下:
Controller我放在Mac上跑,Workers我是通过两台Ubuntu服务器来跑,要注意它们的IP是在同一内网上的。目标系统为了省事,我直接请求 Bing, stackoverflow, QQ。
Step 1: 安装JDK Apache JMeter是用Java写的,运行它需要Java运行环境。在Ubuntu安装如下:
1、本地电脑快捷键WIN+R 打开运行窗口
2、输入 \\IP地址\磁盘$。如下:
3、上一步点击确定,即远程到了相应的磁盘,可在本地进行复制粘贴。
文章目录 1 控制器介绍2 控制器工作流程3 控制器中的方法4 匹配请求路径到控制器方法5 RequestMapping6 控制器方法参数类型与可用返回值类型7 接收请求参数8 验证参数8.1 Bean Validation8.2 分组校验8.3 ValidationAutoConfiguration 1 控制器介绍 (1)什么是控制器?
控制器是一种由Spring 管理的 Bean 对象,赋予角色是“控制器”。作用是处理请求,接收浏览器发送过来的参数,将数据和视图应答给浏览器或者客户端 app 。
控制器是一个普通的 Bean,使用@Controller 或者@RestController 注释。@Controller 被声明为@Component。所以它就是一个 Bean 对象。
(2)如何创建控制器
在java类上加入@Controller或者@RestController。
其中@RestController包含@Controller,@RestController在@Controller基础上加入了@ResponseBody
2 控制器工作流程 3 控制器中的方法 注解@RequestMapping(value=“请求的url地址”):表示这个url的请求由当前方法去处理
@GetMapping @PostMapping @PutMapping @DeleteMapping控制器方法的形参,接收请求参数,多种方法接收请求参数控制方法的返回值,表示应答的结果(包括数据,或者视图)。 4 匹配请求路径到控制器方法 (1)路径匹配策略
有path_pattern_parser(性能好)和ant_pattern_parser
(2)path_pattern_parser规定的关于uri的定义
通配符:
? : 一个字符
* : 0 或多个字符。在一个路径段中匹配字符
**:匹配 0 个或多个路径段,相当于是所有
正则表达式: 支持正则表达
(3)RESTFul 的支持路径变量
{变量名}{myname:[a-z]+}: 正则匹配 a-z 的多个字面,路径变量名称“myname”。@PathVariable(“myname”){*myname}: 匹配多个路径一直到 uri 的结尾 通配符匹配?匹配只有一个字符*匹配一个路径段中的 0 或多个字**匹配 0 或多段路径@GetMapping(“/order/{*id}”){*id} 匹配 /order 开始的所有请求, id 表示 order 后面直到路径末尾的所有内容。id 自定义路径变量名称。与@PathVariable 一样使用@GetMapping(“/pages/{fname:\\w+}.
物理内存:
当在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching,
因此很有必要手动清理系统缓存释放内存。
1.先执行sync,先把buffe中的数据先写入到硬盘中。
2.输入手动释放内存的命令
echo 3 > /proc/sys/vm/drop_caches
drop_caches的值可以是0-3之间的数字,代表不同的含义:
0:不释放(系统默认值)
1:释放页缓存
2:释放dentries和inodes
然后我们可以执行 free -m,先观察到内存已经被释放
SAWP分区使用率
原理:
控制swap使用的系统参数:swappiness
Swappiness:表示使用物理内存限度
Swappiness为0(100%-0=100%)表示物理内存使用到100%的时候使用swap空间(这种风险太高,因为swap分配空间本来就很小,容易触发OOM)
Swappiness为60(100%-60%=40%)表示物理内存使用到40%的时候使用swap空间,默认值是60,对应的配置文件是/proc/sys/vm/swappiness
如果swappiness设置太大(内存的速度会比磁盘快很多),这样子会加大系统io,同时造的成大量页的换进换出,严重影响系统的性能,
所以我们在操作系统层面,要尽可能使用内存,对该参数进行调整。
如SAWP分区使用率过高:
1.使用TOP命令查看进程分析是什么进程占用内存使用率过高
解决思路
1.首先明白是什么导致的内存使用率过高,如果是应用进程使用率过高就联系开发由开发提供解决方案,可能是内存泄漏等
2.如应用进程使用率不高,那么需要释放swap分区,在释放swap分区之前必须必须要确保服务器物理内存剩余使用率高于目前swap分区已使用的内存量,
(如剩余物理内存还有10G,swap分区总共3G,已使用2G,那么释放swap分区后剩余物理内存可用值是8G)
3.释放swap分区操作命令
(1)查看swap分区挂载的文件系统路径 swapon -s (默认都是/dev/dm-1)
(2)关闭sqap分区 swapoff /dev/dm-1(该过程其实就是释放自身内存到物理内存,比较慢,释放2G大约要6分钟时间,期间可以另起一个窗口,执行top命令查看swap分区释放的进度值)
(3) swapon -s 如果查询不到挂载点,表示已经全部释放到物理内存
(4) swapon /dev/dm-1 重新把交换分区挂载上去,实际分配的总内存和释放前是一样的,已使用的内存清零
(5)swapon -s查看是否挂载上去
或者可以用以下两个命令清除刷新swap
swapoff -a
swapon -a
一、swap概念&设置大小参考值
当Linux系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap中恢复保存的数据到内存中。这样,系统总是在物理内存不够时,才进行Swap交换。直接从内存读写数据要比从硬盘读写数据快得多,因此更希望所有数据的读取和写入都在内存中完成,然而内存是有限的,这样就引出了物理内存与虚拟内存的概念。物理内存就是系统硬件提供的内存大小,是真正的内存。相对于物理内存,在 Linux 下还有一个虚拟内存的概念,虚拟内存是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存。用作虚拟内存的磁盘空间被称为交换空间(又称 swap 空间)作为物理内存的扩展,Linux 会在物理内存不足时,使用交换分区的虚拟内存,更详细地说,就是内核会将暂时不用的内存块信息写到交换空间,这样一来,物理内存得到了释放,这块内存就可以用于其他目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。Linux 的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存
要深入了解 Linux 内存运行机制,需要知道下面提到的几个方面:
首先,Linux 系统会不时地进行页面交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux 也会交换出暂时不用的内存页面,因为这样可以大大节省等待交换所需的时间。
其次,Linux 进行页面交换是有条件的,不是所有页面在不用时都交换到虚拟内存,Linux 内核根据“最近最经常使用”算法,仅仅将一些不经常使用的页面文件交换到虚拟内存
远程桌面连接是一种非常有用的技术,它可以让用户从任何位置远程访问到其它计算机。然而,当你尝试连接到一个计算机时,你有可能会遇到远程桌面连接黑屏的问题。这个问题很常见,但是它可能会给你带来很多麻烦。在本文中,我们将会介绍一些解决远程桌面连接黑屏问题的方法。
方法一:检查本地电脑屏幕
当你在远程计算机的时候突然出现黑屏,有时候可能并不是因为远程引起的,这时候我们可以首先检查本地的电脑屏幕,尝试调整屏幕分辨率或者改变显示器的选项来解决问题,如果排查了不是本地电脑屏幕的问题,再去考虑其他的解决方法。
方法二:检查远程计算机的网络连接
当你在进行远程桌面连接的时候,其实网络的连接质量也可能会影响远程桌面的性能。这时候如果黑屏的话,我们可以选择检查远程计算机的网络连接,确保其网络连接质量良好。
你可以使用 ping 命令测试远程计算机的网络连接。如果出现了连接超时或其他问题,那么联网就可能存在问题,需要联系管理员进行处理。
方法三:尝试重新启动远程计算机
如果你的远程计算机的网络连接正常,那么可以尝试重新启动远程计算机。在新的连接中,确认电脑的用户名和密码以确保凭据输入的正确。重新启动远程计算机之后,重新连接远程桌面。如果还是显示黑屏,再尝试一下其他办法。
方法四:更改远程桌面连接的设置
在 "选项" 中设置本地资源,连接协议,显示等级可以更改这些问题,我们可以尝试更改这些设置来解决问题,来看看是否能够修复远程桌面连接黑屏问题。
方法五:使用远程桌面协议
如果你已经尝试了所有这些方法,并且仍然遇到远程桌面连接黑屏问题,那么你可以考虑使用不同的远程桌面协议来连接远程计算机。例如,你可以尝试使用RayLink这种远程管理工具,这些工具具有不同的协议和传输方式,能会更有效地解决远程桌面连接黑屏问题。
结论
总的来说,远程桌面连接黑屏问题是一个比较常见的问题,如果你遇到这个问题,可以先检查本地电脑屏幕和远程计算机的网络连接,如果问题仍然存在,可以尝试重新启动远程计算机和更改远程桌面连接的设置。如果这些方法都不起作用,那么你可以尝试使用RayLink远程桌面软件来连接远程计算机。
背景 在项目中经常需要用到自定义弹窗,类似于UI组件的Dialog、Alert等,以下为自定义的alert全局弹窗
$alert({ title: '审核未通过', message: '审核未通审核未通审核未通审核未通审核未通', isCloseIcon: true, closeOnClickOverlay: false, cancelBtnClass: 'm-red', // 取消按钮的class callback: () => { console.log('确定按钮') } }) 步骤 1、在/src/components/新建global文件夹,用于存放自定义全局组件 2、在global文件夹下新建 alert.vue、alert.ts 两个文件 alert.vue
<template> <div class="custom-alert" :class="customClass" ref="customAlert"> <div class="custom-alert-bg" @click="clickOverlay"></div> <div class="custom-alert-content"> <div class="custom-alert-title" v-html="title" v-if="title"></div> <img class="custom-alert-close" src="@/assets/img/icon-close.png" v-if="isCloseIcon" @click="handleCancel" /> <div class="custom-alert-detail"> <div v-html="message" v-if="message" class="custom-alert-message"></div> </div> <div class="flex-right custom-alert-btn-group"> <button :class="['custom-alert-btn-cancel', cancelBtnClass]" @click="handleCancel" v-if="!hideCancel" > {{ cancelBtnText }} </button> <button class="
如果您常用远程桌面连接工具来远程访问其他计算机,您可能会在某些情况下遭遇到连接凭据无法工作的问题。在这种情况下,您可能无法访问目标计算机并执行所需的任务。在本文中,我们将告诉您如何解决这个问题。
首先,让我们了解一下远程桌面连接凭据的工作原理。当您使用远程桌面连接工具连接到另一台计算机时,您需要提供包括用户名和密码在内的凭据。这些凭据将用于验证您的身份,并允许您访问目标计算机上的内容和执行操作。
如果您的远程桌面连接凭据无法工作,则可能是以下原因导致的:
1. 输入凭据时出现错误或输入的凭据不正确。
2. 凭据存储文件已损坏或遭到破坏。
3. 计算机上的安全策略不允许远程连接。
现在,小编将介绍一些解决方案可以用来解决远程桌面连接凭据无法工作的问题。
1. 检查输入的凭据是否正确
首先,需要确认您输入的凭据是否正确。确保您输入的凭据与远程计算机的凭据匹配。
如果您输入的凭据不正确,远程桌面连接将无法通过验证,因此您将无法访问目标计算机。
2. 重置存储凭据的文件
如果您输入了正确的凭据但仍无法登录,可能是因为凭据存储文件已损坏。
在这种情况下,您可以尝试删除存储凭据的文件并重置它。
删除凭据存储文件的方法:
按Win+R键打开运行窗口,输入rundll32.exe keymgr.dll,KRShowKeyMgr并按Enter键,就可以打开凭据管理器。
在凭据管理器中,找到存储凭据的项目,单击。然后单击“删除”按钮,并确认删除对话框。就可以重新启动远程桌面连接,最后重新输入凭据,应该就可以解决了。
3. 检查计算机上的安全策略
最后,如果您在远程桌面连接时遇到问题,可能是因为计算机上的安全策略不允许远程连接。在这种情况下,需要检查计算机上的安全策略,确保是允许远程连接的。
检查计算机上的安全策略方法:
Win+R键打开运行窗口,输入gpedit.msc并按Enter键。就可以打开本地组策略编辑器。
在组策略编辑器中,导航到计算机配置->管理模板->系统->远程桌面服务->远程桌面会话主机->安全策略。确保“允许针对远程服务器控制的用户连接”和“允许远程桌面服务使用NTLM身份验证”选项都已启用。如果是没有启用的,请开启启用。
总之,当您在使用远程桌面连接时遇到连接凭据无法工作的问题时,请尝试上述解决方案。
技术栈 项目部署 简历上可写的点 集中处理系统异常,自定义统一的错误码, 并封装了全局异常处理器,屏蔽了项目冗余的报错细节、便于接口调用方理解和统一处理。
基于静态ThreadLocal封装了线程隔离的全局上下文对象,便于在请求内部存取用户信息,减少用户远程查询次数。
为兼容请求参数date类型的序列化,定义Jackson对象映射器处理日期;并扩展SpringMVC的消息转换器,实现自动序列化。
自定义MyBatis Plus的MetaObjectHandle,配合全局上下文实现写数据前的创建时间、用户id字段的自动填充。
遵循Restful设计规范编写接口,降低前后端接口沟通和理解成本。
为解决原胜Jdk例化器导致的缓存key乱码问题,自定义RedisTemplate Bean的Redis Key列化器为StringRedisSerializer.
使用Knife4j + Swagger自动生成后端接口文档,并通过编写ApiOperation等注解补充接口注释,避免了人工编写维护文档的麻烦。
为省复编写用户校验的麻烦,基于WebFilter实现全局登录校验;通过AntPathMatcher匹配动态请求路径,实现灵活的可选鉴权。
为保证数据的完整性和一致性,使佣@Transactional实现数据库事务,并配置rollbackFor = Exception.class支持受检异常的事务回滚。
为提高XX信息页加载速度,基于Spring Cache注解+ Redis 实现对XX信息的自动缓存,大幅降低数据库压力的同时将接口响应耗时由0.8s减少至50ms (数值自己再测一下)
为降低开发成本,使佣MyBatis Plus框架自动生成业务的增删改查重复代码,并使用LambdaQueryWrapper实现更灵活地自定义查询。
为降低用户注册成本、保证用户真实性,二次封装XX云SDK接入短信服务,并通过Redis来集中缓存验证码,防止单手机号的重复发送。
为提高数据库整体读写性能,配置MySQL主从同步,并使用sharding-jdbc实现业务无侵入的读写分离。
封装全局Axios请求实例,添加全局请求拦截和全局异常响应处理器,减少重复的状态码判断、提升项目可维护性。
关于项目 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.xz</groupId> <artifactId>angong_takeout</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.
今天在使用DBever连接本地Mysql数据库发生该错误,即Public Key Retrieval is not allowed(不允许进行公钥检索),解决办法如下所示:
问题展示 解决办法 Win + R打开cmd命令行窗口,输入mysql -uroot -p回车后输入MySQL密码进行登录,在打开DBever尝试连接本地MySQL数据库,即可成功!
如上图,打开cmd进行本地mysql服务登录后,即可测试连接成功!
前言 原文:Paddle Square
在学习Catlikecoding的Paddle Square时,对其中“5.1 Glowing Ball”的笔记
如何使用Shader Graph为小球发光 1、创建unlit shader graph,如图,在Project空白右键创建Unlit Shader Graph
2、双击打开Unlit Shader Graph,如图,新建一个Color的Property;然后从左侧拖到中间来,并连上Fragment的Base Color;单击链接好的Color后,在右侧Node Settings里设置Mode为HDR,并选择一个颜色;然后左上角Save Asset保存。
3、把此shader graph拖拽给一个新建的Material材质球 。
4、打开材质球,如图,设置HDR Color的Intensity参数,这样球就可以发光了
本地效果图 疑问? 最后一段话,打开URP Asset设置Grading Mode为HDR后,“We can also set Post-processing / Volume Update Mode to Via Scripting. ”这个操作在URP Asset页面找不到对应的,不过在相机的Environment里能找到,如图,不知道这句话是不是指的这个
前言 原文:Paddle Square
在学习Catlikecoding的paddle square的第五步时的一个小笔记
原文提到,启用相机的反锯齿为FXAA,但是在我相机的设置里怎么都找不到,后来偶然发现需要先安装URP
简单提一下URP安装流程 1、打开Unity编辑器顶部菜单栏 Window 》 Package Manager
2、如图,设置Unity Registry以显示在Unity注册的所有包;右边搜索输入univer;点击左侧Universal RP;点击右下角安装
3、如图,在Project空白处,右键新建URP Asset 4、如图,打开Edit 》 Project Settings,设置Graphics刚刚新建的URP Asset
这样URP就简易安装配置完毕
设置FXAA URP安装配置好后,打开场景中的相机,就能看到如图原文中提到的配置
1:记录 最近在公司开发遇到一个小需求,在级联查询时, 当ON.... AND .... 时,ON后面的条件为NULL ,AND 后面的条件不为NULL。要求返回A表与B表匹配上的数据。
2:遇到问题 当ON 后面的条件为NULL,AND 后的条件不为NULL。
例:
ON NULL = NULL AND 6 = 6 使用级联查询时,只返回主表中的数据,次表中的数据却没有匹配上显示都是NULL(可是明明都有数据)
3:解决过程 3.1 临时表A SQL:
SELECT PROD_TYPE, CAST(COUNT(WORK_ORDER_ID) AS float) AS 计划数量, SUBSTR(START_DATE, 1, 7) AS START_DATE, MAX(TO_CHAR(DATA_TIME, 'YYYY-MM')) AS 统计日期, MAX(STAT_TIME) AS 创建时间 FROM DWS_WORK_ORDER_INFO GROUP BY SUBSTR(START_DATE, 1, 7), PROD_TYPE 3.2 临时表B SQL:
SELECT CAST(COUNT(WORK_ORDER_ID) AS float) AS 完成数量, SUBSTR(START_DATE,1,7) AS START_DATE, PROD_TYPE FROM BRAIN.DWS_WORK_ORDER_INFO WHERE IF_COMP = '是' GROUP BY SUBSTR(START_DATE,1,7), PROD_TYPE 此时我想通过LEFT JOIN 左关联查出 PROD_TYPE = NULL 时的计划数量和完成数量关联条件为:
最近在学习深度学习的相关知识,阅读了经典的pix2pix论文:
论文原址:[1611.07004] Image-to-Image Translation with Conditional Adversarial Networks (arxiv.org)
下面是我学习论文和代码部分的总结,因为没有很多代码基础所以进度缓慢。这次是代码部分;
1.从原材料数据开始:
提供了facade库,里面有606张图片;
需要对图片文件进行分类和处理。才能获得训练所用的数据集。
由于文件中提供的是名字相同jpg与png格式的图片,所以我对源代码进行了修改,以能够进行图像的拼接。
我的文件例分类,暂时不分为test, train , val ;先使用 combine_A_and_B.py 文件进行处理整个文件。
文件夹A为 数据集里的jpg文件,即真实图形,文件夹B为png文件,即彩色轮廓图。文件夹dataset是预置的存放生成训练的图像文件夹。另外要注意在A,B的文件夹下还要各建立一个相同名的子文件夹,图像文件存放其中。我这里取名为base。
存放完毕后,学习并修改代码。
import os import numpy as np import cv2 import argparse import multiprocessing from multiprocessing import Pool if __name__ == '__main__': multiprocessing.freeze_support() # 确保多进程功能在冻结的可执行文件中正常工作 def image_write(path_A, path_B, path_AB): im_A = cv2.imread(path_A, 1) # python2: cv2.CV_LOAD_IMAGE_COLOR; python3: cv2.IMREAD_COLOR im_B = cv2.imread(path_B, 1) # python2: cv2.CV_LOAD_IMAGE_COLOR; python3: cv2.IMREAD_COLOR im_AB = np.
总体来说,整个神经网络可以理解为三个部分的组合:Backbone提取原始数据的特征,Neck融合特征,Head进行分类或回归使得数据更加准确。每个部分的设计都需要根据具体任务需求来进行,以获得最佳性能。 1.backbone 翻译为主干网络的意思,既然说是主干网络,就代表其是网络的一部分。这个主干网络大多时候指的是提取特征的网络,其作用就是提取图片中的信息,生成特征图feature map,供后面的网络使用。这些网络经常使用的是ResNet、VGG、MobileNet等,而不是我们自己设计的网络,因为这些网络已经证明了在分类等问题上的特征提取能力是很强的。在用这些网络作为backbone的时候,都是直接加载官方已经训练好的模型参数,后面接着我们自己的网络。让网络的这两个部分同时进行训练,因为加载的backbone模型已经具有提取特征的能力了,在我们的训练过程中,会对他进行微调,使得其更适合于我们自己的任务。
在神经网络中,尤其是CV领域,一般先对图像进行特征提取,生成特征图feature map,这一部分是整个CV任务的根基,因为后续的下游任务都是基于提取出来的图像特征去做文章(比如分类、生成等)。backbone用于前端提取图片信息,供后面的网络使用。因为这些backbone的特征提取能力是很强,并且可以加载官方在大型数据集(Pascal、Imagenet)上训练好的模型参数,然后接自己的网络,进行微调就可以。 2.head head是获取网络输出内容的网络,利用之前提取的特征,head利用这些特征,做出预测。
Head是网络结构的顶部部分,它通常包括全连接层、softmax层等线性分类器层,用于将特征向量进行分类或回归等任务。Head的设计通常根据具体的任务需求来进行,例如,如果需要完成二分类任务,那么Head可能只需要一个sigmoid层即可;如果需要进行分类,那么Head则需要多个softmax层等。
3.neck neck是放在backbone和head之间的,是为了更好的利用backbone提取的特征,可以理解为对backbone生成的特征图做进一步处理,使得head能够更好的做下游任务。
Neck位于Backbone和Head之间,通常用于将两者之间的特征相互融合。Neck通常是由分类与回归之类的模块组成,它也可以是卷积层、池化层等。Neck有时也被称为特征金字塔处理(Feature Pyramid Network)。
4.bottleneck bottleneck是瓶颈的意思,通常指的是网网络输入的数据维度和输出的维度不同,输出的维度比输入的小了许多,就像脖子一样,变细了。经常设置的参数 bottle_num=256,指的是网络输出的数据的维度是256 ,可是输入进来的可能是1024维度的。
5.GAP 在设计的网络中经常能够看到gap这个层,我之前不知道是干啥的,后了解了,就是Global Average Pool全局平均池化,就是将某个通道的特征取平均值,经常使用AdaptativeAvgpoold,在pytorch中,这个代表自适应性全局平均池化,说人话就是将某个通道的特征取平均值。
6.Embedding 深度学习方法都是利用使用线性和非线性转换对复杂的数据进行自动特征抽取,并将特征表示为“向量”(vector),这一过程一般也称为“嵌入”(embedding)
7.downstream task 用于预训练的任务被称为前置/代理任务(pretext task),用于微调的任务被称为下游任务
8.temperature parameters 在论文中经常能看到这个温度参数的身影,他可以起到平滑softmax输出结果的作用,举例子如下:
import torch x = torch.tensor([1.0,2.0,3.0]) y = torch.softmax(x,0) print(y) x1 = x / 2 # beta 为2 y = torch.softmax(x1,0) print(y) x2 = x/0.5 # beta 为0.5 y = torch.softmax(x2,0) print(y) #输出结果如下: tensor([0.0900, 0.2447, 0.6652]) tensor([0.1863, 0.3072, 0.5065]) tensor([0.
DoS是Denial of Service的简称,即拒绝服务,造成DoS的攻击行为被称为DoS攻击,其目的是使计算机或网络无法提供正常的服务。最常见的DoS攻击有计算机网络带宽攻击和连通性攻击。
DoS攻击是指故意的攻击网络协议实现的缺陷或直接通过野蛮手段残忍地耗尽被攻击对象的资源,目的是让目标计算机或网络无法提供正常的服务或资源访问,使目标系统服务系统停止响应甚至崩溃,而在此攻击中并不包括侵入目标服务器或目标网络设备。这些服务资源包括网络带宽,文件系统空间容量,开放的进程或者允许的连接。这种攻击会导致资源的匮乏,无论计算机的处理速度多快、内存容量多大、网络带宽的速度多快都无法避免这种攻击带来的后果。
DoS到底是什么?接触PC机较早的同志会直接想到微软磁盘操作系统的DOS--DiskOperationSystem?不,此DoS非彼DOS也,DoS即DenialOfService,拒绝服务的缩写。
作个形象的比喻来理解DoS。街头的餐馆是为大众提供餐饮服务,如果一群地痞流氓要DoS餐馆的话,手段会很多,比如霸占着餐桌不结账,堵住餐馆的大门不让路,骚扰餐馆的服务员或厨子不能干活,甚至更恶劣……相应的计算机和网络系统则是为Internet用户提供互联网资源的,如果有黑客要进行DoS攻击的话,可以想象同样有好多手段!今天最常见的DoS攻击有对计算机网络的带宽攻击和连通性攻击。带宽攻击指以极大的通信量冲击网络,使得所有可用网络资源都被消耗殆尽,最后导致合法的用户请求无法通过。连通性攻击指用大量的连接请求冲击计算机,使得所有可用的操作系统资源都被消耗殆尽,最终计算机无法再处理合法用户的请求。
传统上,攻击者所面临的主要问题是网络带宽,由于较小的网络规模和较慢的网络速度的限制,攻击者无法发出过多的请求。虽然类似“the ping of death”的攻击类型只需要较少量的包就可以摧毁一个没有打过补丁的UNIX系统,但大多数的DoS攻击还是需要相当大的带宽的,而以个人为单位的黑客们很难使用高带宽的资源。为了克服这个缺点,DoS攻击者开发了分布式的攻击。攻击者简单利用工具集合许多的网络带宽来同时对同一个目标发动大量的攻击请求,这就是DDoS(Distributed Denial of Service)攻击。 无论是DoS攻击还是DDoS攻击,简单的看,都只是一种破坏网络服务的黑客方式,虽然具体的实现方式千变万化,但都有一个共同点,就是其根本目的是使受害主机或网络无法及时接收并处理外界请求,或无法及时回应外界请求。其具体表现方式有以下几种:
1,制造大流量无用数据,造成通往被攻击主机的网络拥塞,使被攻击主机无法正常和外界通信。
2,利用被攻击主机提供服务或传输协议上处理重复连接的缺陷,反复高频的发出攻击性的重复服务请求,使被攻击主机无法及时处理其它正常的请求。 3,利用被攻击主机所提供服务程序或传输协议的本身实现缺陷,反复发送畸形的攻击数据引发系统错误的分配大量系统资源,使主机处于挂起状态甚至死机。
使用僵尸电脑进行DOS攻击
僵尸电脑(Zombiecomputer),简称“僵尸(zombie)”,有些人称之为“肉鸡”,接入互联网的电脑被病毒感染后,受控于黑客,可以随时按照黑客的指令展开拒绝服务(DoS)攻击或发送垃圾信息。通常,一部被侵占的电脑只是僵尸网络里面众多中的一环,而且会被用来去运行一连串的或远端控制的恶意程序。很多“僵尸电脑的拥有者”都没有察觉到自己的系统已经被“僵尸化”,就仿佛是没有自主意识的僵尸一般。 攻击流程
要理解dos攻击,首先要理解TCP连接的三次握手过程(Three-wayhandshake)。在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。 第一次握手:建立连接时,客户端发送SYN包((SYN=i)到服务器,并进入SYNSEND状态,等待服务器确认;
第二次握手:服务器收到SYN包,必须确认客户的SYN (ACK=i+1 ),同时自己也发送一个SYN包((SYN=j)}即SYN+ACK包,此时服务器进入SYN_RECV状态;[1] 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=j+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。 在上述过程中,还有一些重要的概念: 半连接:收到SYN包而还未收到ACK包时的连接状态称为半连接,即尚未完全完成三次握手的TCP连接。
半连接队列:在三次握手协议中,服务器维护一个半连接队列,该队列为每个客户端的SYN包(SYN=i )开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于SYN_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
Backlog参数:表示半连接队列的最大容纳数目。 SYN-ACK重传次数:服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息、从半连接队列中删除。注意,每次重传等待的时间不一定相同。 半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时也称半连接存活时间为Timeout时间、SYN_RECV存活时间。[1] 上面三个参数对系统的TCP连接状况有很大影响。 SYN洪水攻击属于DoS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。SYN攻击除了能影响主机外,还可以危害路由器、防火墙等网络系统,事实上SYN攻击并不管目标是什么系统,只要这些系统打开TCP服务就可以实施。从图4-3可看到,服务器接收到连接请求(SYN=i )将此信息加入未连接队列,并发送请求包给客户端( SYN=j,ACK=i+1 ),此时进入SYN_RECV状态。当服务器未收到客户端的确认包时,重发请求包,一直到超时,才将此条目从未连接队列删除。配合IP欺骗,SYN攻击能达到很好的效果,通常,客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN 请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。过程如下:
攻击主机C(地址伪装后为C&apos)-----大量SYN包---->被攻击主机 C&apos<-------SYN/ACK包----被攻击主机,由于C&apos地址不可达,被攻击主机等待SYN包超时。攻击主机通过发大量SYN包填满未连接队列,导致正常SYN包被拒绝服务。另外,SYN洪水攻击还可以通过发大量ACK包进行DoS攻击。
常见攻击与防范
SYN Flood攻击
问题就出在TCP连接的三次握手中,假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这 种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒 -2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。实际上如果服务器的TCP/IP栈不够强大,最 后的结果往往是堆栈溢出崩溃---即使服务器端的系统足够强大,服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求(毕竟客户端的正常请求比率非常之小),此时从 正常客户的角度看来,服务器失去响应,这种情况我们称作:服务器端受到了SYN Flood攻击(SYN洪水攻击)。
防范:
第一种是缩短SYN Timeout时间
第二种方法是设置SYN Cookie,就是给每一个请求连接的IP地址分配一个Cookie,如果短时间内连续受到某个IP的重复SYN报文,就认定是受到了攻击,以后从这个IP地址来的包会被一概丢弃。
>netstat -n -p tcp >result.txt
Smurf攻击:
发送伪装的ICMP数据包,目的地址设为某个网络的广播地址,源地址设为要攻击的目的主机,使所有收到此ICMP数据包的主机都将对目的主机发出一个回应,使被攻击主机在某一段时间内收到 成千上万的数据包
防范:
在cisco路由器上配置如下可以防止将包传递到广播地址上:
Router(config-if)# no ip directed-broadcast
文章目录 概要代码实现小结 概要 最近要实现一个对全局sql的修改的需求,之前看mybatis源码的时候记得有个拦截器可以实现这样的功能,于是结合着网上写了下面的代码
代码实现 这是针对查询操作的拦截:
package com.xxx.common.data.interceptor; import com.xxx.common.core.exception.ServiceException; import com.xxx.common.core.utils.StringUtils; import com.xxx.common.data.config.SqlInterceptorConfig; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.reflection.DefaultReflectorFactory; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import java.lang.reflect.Field; import java.sql.Connection; /** * @author * @since 2023-05-15 15:46 * @desc sql查询拦截器 */ @Intercepts( {@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})} ) @Slf4j public class SqlQueryInterceptor extends AbstractSqlInterceptor implements Interceptor { private SqlInterceptorConfig config; public SqlQueryInterceptor(SqlInterceptorConfig config) { this.
//可以输入空格
<el-input class=‘left-text’ type=“textarea” v-model=“a” placeholder=“请输入” clearable :disabled=“disabled” @change=“aChange()”>
//v-model.trim="a"不可以输入空格
<el-input class=‘left-text’ type=“textarea” v-model.trim=“a” placeholder=“请输入” clearable :disabled=“disabled” @change=“aChange()”>
1.链路追踪 在一次调用链路中,可能设计到多个微服务,如果在线上,某个微服务出现故障,如何快速定位故障所在额微服务呢。可以使用链路追踪技术。
1.1链路追踪介绍 在大型系统的微服务化构建中,一个系统被拆分成了许多微服务。这些模块负责不同的功能,组合成系统,最终可以提供丰富的功能。在这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心【区域】,也就意味着这种架构形式也会存在一些问题:
l 如何快速发现问题?
l 如何判断故障影响范围?
l 如何梳理服务依赖?
l 如何分析链路性能问题以及实时容量规划
分布式链路追踪(Distributed Tracing),就是将一次分布式请求还原成调用链路,进行==日志记录==,==性能监控==并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上IP、每个服务节点的请求状态200 500等等。 1.2 链路追踪使用的组件由哪些? 1.cat 由大众点评开源,基于Java开发的实时应用监控平台,包括实时应用监控,业务监控 。 集成 方案是通过代码埋点的方式来实现监控,比如: 拦截器,过滤器等。 对代码的侵入性很大,集成成本较高。风险较大。
2.pinpoint Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点 是支持多种插件,UI功能强大,接入端无代码侵入。 你开源
3.skywalking 【未来企业会使用的多】
SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多
种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器--开源。
4.Sleuth **(日志记录每一条链路上的所有节点,以及这些节点所在的机器,和耗时。)
zipkin** 由Twitter公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微 服务架构中的延迟问题,包括:==数据的收集、存储、查找和展现《图形化》==。该产品结合spring-cloud-sleuth 使用较为简单, 集成很方便, 但是功能较简单。
SpringCloud 提供的分布式系统中链路追踪解决方法
1.3 介绍sleuth springCloud Sleuth主要功能就是在分布式系统中提供追踪解决方案。它大量借用了Google Dapper的设计, 先来了解一下Sleuth中的术语和相关概念。
*1.Trace* *(一条完整链路--包含很多span(微服务接口))*
由一组Trace Id(贯穿整个链路)相同的Span串联形成一个树状结构。为了实现请求跟踪,当请求到达分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的标识(即TraceId),同时在分布式系统内部流转的时候,框架始终保持传递该唯一值,直到整个请求的返回。那么我们就可以使用该唯一标识将所有的请求串联起来,形成一条完整的请求链路。
*2.Span*
代表了一组基本的工作单元。为了统计各处理单元的延迟,当请求到达各个服务组件的时候,也通过一个唯一标识(SpanId)来标记它的开始、具体过程和结束。通过SpanId的开始和结束时间戳,就能统计该span的调用时间,除此之外,我们还可以获取如事件的名称。请求信息等元数据。
*3. Annotation*
用它记录一段时间内的事件,内部使用的重要注释:
l cs(Client Send)客户端发出请求,开始一个请求的命令
l sr(Server Received)服务端接受到请求开始进行处理, sr-cs = 网络延迟(服务调用的时间)
l ss(Server Send)服务端处理完毕准备发送到客户端,ss - sr = 服务器上的请求处理时间
文章转载:
文件上传下载:https://www.cnblogs.com/yingyujyf/p/6933823.html
创建目录:FtpClient切换、创建目录不成功的问题(makeDirectory、changeWorkingDirectory)_ftp.changeworkingdirectory_weixin_40582761的博客-CSDN博客
目录绝对路径相对路径:java FTPClient中的相对路径和绝对路径_ftp相对路径,绝对路径_野猿新一的博客-CSDN博客
通过FTPClient对象操作上传下载需要引入jar包commons-net-1.4.1.jar,maven依赖如下
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.3</version> </dependency> ftpClient.retrieveFile方法用于下载文件
ftpClient.storeFile方法用于上传文件
ftpClient.makeDirectory创建目录(只能逐级创建,下面详细说明)
ftpClient.changeWorkingDirectory("/"); // 切换到根目录,绝对目录
String dir = ftpClient.printWorkingDirectory(); // 获取当前工作目录
ftpClient.changeWorkingDirectory(dir); // 切换到当前目录
所以,上传下载的方法需要将这两个方法封装进去
ftp工具类:
package ftp.ftp2; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import sun.net.TelnetOutputStream; import sun.net.ftp.FtpProtocolException; import java.io.*; import java.net.SocketException; import java.util.Properties; public class FtpUtil { /** * 获取FTPClient对象 * * @param ftpHost FTP主机服务器 * @param ftpPassword FTP 登录密码 * @param ftpUserName FTP登录用户名 * @param ftpPort FTP端口 默认为21 * @return */ public static FTPClient getFTPClient(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort) { FTPClient ftpClient = new FTPClient(); try { ftpClient = new FTPClient(); ftpClient.
要实现百万并发连接的 Nginx 集群,可以考虑以下几种方案: 横向扩展:使用多台 Nginx 服务器来处理并发连接。通过将流量分发到多个节点,每个节点处理一部分连接,从而实现并发连接的处理能力扩展。可以使用负载均衡器(如硬件负载均衡器、Nginx 负载均衡模块、HAProxy 等)来将请求均匀地分发给多个 Nginx 节点。
反向代理集群:配置多个 Nginx 反向代理服务器,将请求转发给后端服务器集群。每个反向代理服务器负责一部分连接的转发,通过增加反向代理服务器来扩展并发连接处理能力。可以使用 Nginx 的反向代理配置、负载均衡模块或者其他反向代理软件来实现。
缓存加速:配置 Nginx 缓存来减轻后端服务器的负载。将静态文件或者频繁访问的数据缓存在 Nginx 的本地缓存中,从而提高响应速度并降低后端服务器的压力。可以使用 Nginx 的 proxy_cache 模块来配置缓存。
分布式架构:将应用程序进行分布式架构设计,将数据和请求处理分散到多个节点和服务器上。可以采用微服务架构、分布式缓存、分片数据库等技术来实现分布式并发处理。
CDN 集成:结合使用 CDN(内容分发网络)来缓存和分发静态内容。将静态文件部署在 CDN 上,可以减轻 Nginx 集群的负载,提高全球范围内的访问速度。
网络加速:确保服务器之间的网络连接具备高速和低延迟。使用高速网络设备、优化网络拓扑、调整操作系统网络参数等方法可以提高集群之间的通信性能。
需要注意的是,实现百万并发连接是一个复杂的任务,需要综合考虑应用程序、硬件资源、网络架构等多个方面。具体的方案需要根据您的应用需求和环境来设计和调整。建议在实施前进行性能测试和负载测试,以评估和验证所选方案的可行性和性能。
如果在云端,那就不用这么麻烦了。在不缺钱的情况下,为了稳定性,可全部采用阿里云或腾讯云,华为云等。 通过 SLB(Server Load Balancer)实现负载均衡是一种常见且有效的方法。以下是使用 SLB 实现负载均衡的一般步骤: 注册和配置 SLB:选择一个云服务提供商(如阿里云、腾讯云等),注册并创建一个负载均衡实例。按照提供商的指引,配置负载均衡实例的基本信息,例如监听端口、协议类型等。
创建后端服务器池:在 SLB 中创建一个后端服务器池,将您的服务器添加到该池中。确保所有后端服务器都已正确配置并可以接收流量。您可以选择添加多台服务器来分担负载。
配置负载均衡策略:根据您的需求选择适当的负载均衡算法。常见的负载均衡算法包括轮询、加权轮询、最小连接数等。配置负载均衡策略可以确保流量均匀地分发到后端服务器。
健康检查:配置健康检查来监测后端服务器的可用性。健康检查可以定期检测服务器的健康状态,并将请求转发到正常的服务器。如果服务器不可用,负载均衡器将自动将流量转发到其他可用的服务器。
监控和调优:使用提供商的监控工具来监测负载均衡实例的性能和状态。根据监测结果进行调优,例如根据负载情况增加或减少后端服务器的数量,或者调整负载均衡策略。
配置域名解析:将您的域名解析指向负载均衡实例的 IP 地址。这样,所有通过域名访问的请求都会经过负载均衡器进行流量分发。
安全设置:根据需求配置安全组规则,以确保只有经过负载均衡器的流量能够访问后端服务器。
请注意,具体的步骤和配置选项可能因不同的云服务提供商而有所差异。建议您参考提供商的文档和最佳实践来完成 SLB 的配置和部署。
MySQL中grant all privileges on远程连接授权 记录MySQL远程连接所踩的坑
当你的帐号不允许从远程登陆,只能在localhost连接时。这个时候只要在mysql服务器上,更改 mysql 数据库里的 user 表里的 host 项,从localhost"改成%即可实现用户远程登录
授权法 MySQL 5.0+版本
mysql -u root -p -- 给root账户授权(root默认只有本机访问的权限,要通过其他机器访问,必须授权) grant all privileges on *.* to root@'%' identified by 'root' with grant option; -- 最后刷新数据库服务 flush privileges; MySQL8.0版本不能按照grant all privileges on *.* to "root"@"%" identified by "xxxx";去修改用户权限,会报错
MySQL 8.0+版本
#先创建远程用户,再授权 create user 'root'@'%' identified by 'root'; grant all privileges on *.* to 'root'@'%' with grant option; flush privileges; 注意授权后必须FLUSH PRIVILEGES;否则无法立即生效。
一、模拟退火算法(SA) 1.1 固体退火的原理 加热使得固体融化,然后缓慢地降低温度,以此来让固体内部的粒子排布更加均匀。
分为四个阶段:
升温阶段、降温阶段、等温阶段、达到目标温度退火完成
等温阶段就是在塑造形状。
1.2 Metropolis准则 概率接受新状态,称为Metropolis准则。
假设前一状态为 f(n),系统受到一定扰动,状态变为 f(n+1),相应地,系统能量由 f(n) 变为 f(n+1)。 定义系统由 f(n) 变为 f(n+1) 的接收概率为 p(probability of acceptance):
p = { 1 f(n+1) < f(n) e − f ( n + 1 ) − f ( n ) T f(n+1) >= f(n) p = \begin{cases} 1& \text{f(n+1) < f(n)} \\ e^{-\frac{f(n+1) - f(n)}{T}}& \text{f(n+1) >= f(n)} \end{cases} p={1e−Tf(n+1)−f(n)f(n+1) < f(n)f(n+1) >= f(n)
1.3 算法流程 1.
shell grep 详解说明 当您使用Shell中的grep命令时,它允许您在文本文件或标准输入中搜索匹配某个模式的行,并输出结果。下面是grep命令的详细说明和参数介绍表格:
参数描述-i忽略大小写进行匹配。默认情况下,grep区分大小写。-v反转匹配,只输出不匹配模式的行。-c统计匹配到的行数,而不是显示匹配的行。-l仅显示包含匹配项的文件名,而不是匹配的行。-n显示匹配行的行号。-r递归地在目录及其子目录中搜索匹配项。-w仅匹配整个单词,而不是匹配包含该模式的部分单词。-A <num>显示匹配行及其后<num>行的内容。-B <num>显示匹配行及其前<num>行的内容。-C <num>显示匹配行及其前后各<num>行的内容。-e <pattern>指定匹配的模式。可以使用多个-e选项来指定多个模式。-f <file>从指定的文件中读取模式,每行一个模式。--color在匹配的行中显示颜色高亮。--exclude排除特定文件模式,不进行搜索。您可以使用通配符进行模式匹配,例如--exclude=*.txt将排除所有扩展名为.txt的文件。--exclude-dir排除特定目录模式,不进行递归搜索。同样可以使用通配符进行模式匹配,例如--exclude-dir=logs将排除名为logs的目录及其子目录。--help显示grep命令的帮助信息。 这些参数可以根据您的需求组合使用。例如,要在文件example.txt中搜索包含模式hello的行并显示行号,您可以运行以下命令:
grep -n "hello" example.txt 要成为grep的真正神,您可以掌握以下技巧和实践: 熟练掌握正则表达式:了解并熟练使用正则表达式的语法和常用模式,可以更精确地匹配和提取所需的文本。
熟悉grep的各种参数:深入了解grep命令的各个参数及其使用方法,能够灵活组合参数来实现复杂的搜索和过滤需求。
学习与其他命令结合使用:结合其他Shell命令(如sed、awk、cut等)和管道操作,可以进行更复杂的文本处理任务,提高工作效率。
阅读grep的文档和示例:深入阅读grep命令的文档和示例,了解更多高级用法和技巧,以及一些实际场景中的应用示例。
反复练习和实践:通过反复练习和实践,不断熟悉和掌握grep的用法,探索不同场景下的应用,从而逐渐成为grep的真正神。
下面是grep命令各参数的具体用途和示例说明: -i 参数用途:
用途:忽略大小写进行匹配。示例:在搜索时不区分大小写。grep -i "hello" example.txt -v 参数用途:
用途:反转匹配,只输出不匹配模式的行。示例:搜索不包含指定模式的行。grep -v "error" log.txt -c 参数用途:
用途:统计匹配到的行数,而不是显示匹配的行。示例:统计包含指定模式的行数。grep -c "warning" log.txt -l 参数用途:
用途:仅显示包含匹配项的文件名,而不是匹配的行。示例:搜索包含指定模式的文件。grep -l "success" *.txt -n 参数用途:
用途:显示匹配行的行号。示例:显示包含指定模式的行号。grep -n "TODO" project.py -r 参数用途:
用途:递归地在目录及其子目录中搜索匹配项。示例:在指定目录及其子目录中搜索指定模式。grep -r "pattern" /path/to/directory -w 参数用途:
用途:仅匹配整个单词,而不是匹配包含该模式的部分单词。示例:仅搜索完全匹配的单词。grep -w "word" text.txt -A <num> 参数用途:
用途:显示匹配行及其后<num>行的内容。示例:显示包含指定模式的行及其后两行内容。grep -A 2 "
文章目录 SQL SELECT TOP 子句SQL LIMIT 子句SQL ROWNUM 子句SQL LIKE 操作符SQL 通配符SQL IN 操作符SQL 别名SQL 连接(JOIN)SQL UNION SQL SELECT TOP 子句 在某些情况下,我们可能只需要返回结果集中的前几行。SQL 提供了 SELECT TOP 子句来实现这一目的。
在不同的数据库系统中,语法稍有不同:
在 SQL Server 中,可以使用 TOP 关键字来选择前几行:SELECT TOP N 列名1, 列名2, ... FROM 表名; 这将返回结果集中的前 N 行。在 MySQL 中,可以使用 LIMIT 子句来选择前几行:SELECT 列名1, 列名2, ... FROM 表名 LIMIT N; 这将返回结果集中的前 N 行。 SQL LIMIT 子句 类似于 MySQL 中的 LIMIT 子句,其他数据库系统(如 PostgreSQL、SQLite)也提供了类似的功能来限制结果集的行数。
在通用的 SQL 语法中,可以使用 LIMIT 子句来选择前几行:
GC回收算法之分代回收 GC回收垃圾主要有三个算法,分别是标记清除,复制算法以及标记整理。
三种算法各有优缺点,其中标记清除的优点就是简单高效,缺点就是很容易带来内存碎片化问题。
复制算法的话,优点确实解决了内存碎片化问题,但是同时也带来了空间利用率不高,当垃圾少,有效对象多时,效率比较低的问题。
标记整理的话,优点是解决了空间利用率的问题,缺点是还是没解决效率问题。
而分代回收则是基于上述三种回收算法的一种复合回收策略,将垃圾回收分成不同的场景,不同的场景应用不同的回收算法。下边则是对分代回收工作过程的梳理。
1.分代规则 这里是根据Java对象生命周期的长短进行划分(以老为尊),这里给对象引入了一个概念——年龄,年龄就是对象熬过GC的轮次,这句话怎么理解呢,其实就是对象经过GC可达性遍历分析当前对象还被确定为可达的轮数。
GC主要是针对堆来讲的,这里的分代将堆划分成了几个区域,分别是伊甸区、幸存区以及老年区。
其中这里的两个幸存区大小是1:1的。
2.工作流程 刚new出来的,年龄是0的对象,放到伊甸区。
熬过一轮GC,对象就放到幸存区,这里放的方法就使用的复制算法。根据经验规律,大部分Java对象生命周期都非常短,所以我们都认为能够放的下。
进入幸存区的对象也要经过GC的周期性考验,如果变成垃圾,就要被释放掉;如果不是垃圾,就会和其他不是垃圾的对象一同拷贝到另一个幸存区,这里使用的也是复制算法。因为这里的幸存区体积不大,存在一些空间浪费也能接受。
如果当前对象已经在两个幸存区之间拷贝很多次了,就进入老年代。老年代中的对象都是比较大的对象,生命周期普遍长。
多次了,就进入老年代。老年代中的对象都是比较大的对象,生命周期普遍长。
进入老年区的对象也要经过GC的周期性扫描,但是频率更低了。如果老年代的对象是垃圾了,就使用标记整理的方式进行释放。
文章目录 一、环境准备1.1 node.js 安装1.2 包管理工具安装:可选 二、创建项目2.1 使用 npm2.2 使用 yarn 三、配置项目3.1 安装初始依赖3.2 增加依赖3.2 配置自动导包3.3 配置 eslint 规则3.4 .vue 文件导入报错解决 四、路由配置4.1 路由类型定义4.2 index.ts 路由主入口4.3 system.ts 自定义路由4.4 routerGuard.ts 路由守护 五、常用类型定义5.1 response.d.ts5.2 user.d.ts 自定义返回类型 六、工具类6.1 二次封装 axios6.1.1 httpClient.ts6.1.2 httpClient 实例 6.2 浏览器本地存储6.3 系统设置工具 七、本地响应式存储7.1 定义7.1.1 user.ts7.1.2 permission.ts7.1.3 auth.ts 7.2 调用 八、全局样式8.1 样式重置8.1.1 index.scss8.1.2 reset.scss8.1.3 样式引入 8.2 样式常量8.2.1 variables.scss8.2.2 常量使用 九、layout9.1 面包屑9.2 导航栏9.3 侧边栏9.4 页脚9.5 主体结构 十、错误页面10.1 404页面10.2 401页面 十一、系统设置11.1 setting.ts11.2 App.vue11.3 main.ts 技术栈
最近有个需求需要操作后多个库进行同步数据等处理,若依自带可配置多数据源,但是需要做很多固定配置,也不能满足动态配置
1、添加多数据源
@Bean(name = "dynamicDataSource") @Primary public DynamicDataSource dataSource(DataSource masterDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); for (String item : dataList) { setDataSourceSync(targetDataSources, item); } return new DynamicDataSource(masterDataSource, targetDataSources); } 2、多数据源配置
public void setDataSourceSync(Map<Object, Object> targetDataSources, String sourceName) { Properties properties = new Properties(); properties.put("url", "jdbc:sqlserver://192.168.3.13:1433;SelectMethod=Cursor;DatabaseName=" + sourceName); properties.put("username", "sa"); properties.put("driverClassName", "com.microsoft.sqlserver.jdbc.SQLServerDriver"); properties.put("password", "pp"); DataSource dataSource = null; try { dataSource = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.
输入首页的连接信息后点 ”连接测试“就会弹出下载驱动文件的页面,找到驱动文件后面的Version列,点击下拉选择和你本地安装版本一致的版本下载即可。
1、通俗的服务状态 有了持久化存储 PersistentVolume,应用就可以把一些运行时的关键数据落盘,相当于有了一份“保险”,如果 Pod 发生意外崩溃,也只不过像是按下了暂停键,等重启后挂载 Volume,再加载原数据就能够满血复活,恢复之前的“状态”继续运行。
所以从这个角度来说,理论上任何应用都是有状态的。
只是有的应用的状态信息不是很重要,即使不恢复状态也能够正常运行,这就是我们常说的“无状态应用”。“无状态应用”典型的例子就是 Nginx 这样的 Web 服务器,它只是处理 HTTP 请求,本身不生产数据(日志除外),不需要特意保存状态,无论以什么状态重启都能很好地对外提供服务。
还有一些应用,运行状态信息就很重要了,如果因为重启而丢失了状态是绝对无法接受的,这样的应用就是“有状态应用”。
“有状态应用”的例子也有很多,比如 Redis、MySQL 这样的数据库,它们的“状态”就是在内存或者磁盘上产生的数据,是应用的核心价值所在,如果不能够把这些数据及时保存再恢复,那绝对会是灾难性的后果。
理解了这一点,我们结合目前学到的知识思考一下:Deployment 加上 PersistentVolume,在 Kubernetes 里是不是可以轻松管理有状态的应用了呢?
是的,这样是可以是实现的,用 Deployment 来保证高可用,用 PersistentVolume 来存储数据,确实可以部分达到管理“有状态应用”的目的。
但是, Kubernetes 的眼光则更加全面和长远,它认为“状态”不仅仅是数据持久化,在集群化、分布式的场景里,还有多实例的依赖关系、启动顺序和网络标识(例如PodIP的变化)等问题需要解决,而这些问题恰恰是 Deployment 力所不及的。
因为只使用 Deployment,多个实例之间是无关的,启动的顺序不固定,Pod 的名字、IP 地址、域名也都是完全随机的,这正是“无状态应用”的特点。
但对于“有状态应用”,多个实例之间可能存在依赖关系,比如 master/slave、active/passive,需要依次启动(这个时候就要保证PodIP是固定的)才能保证应用正常运行,外界的客户端也可能要使用固定的网络标识来访问实例,而且这些信息还必须要保证在 Pod 重启后不变。
所以,Kubernetes 就在 Deployment 的基础之上定义了一个新的 API 对象,名字也很好理解,就叫 StatefulSet,专门用来管理有状态的应用。
2、专业的服务状态 从数据层面看状态,数据的状态往往受2个维度有关,一是与时间相关或者顺序相关的,不同的操作顺序可能导致同一个时间点上的数据状态大于1个,二是与数据的副本状态相关的。也就是数据的位置,数据落在多个副本上,可能出现多种数据状态的组合。
从服务层面看,服务层面的状态取决于实例是单独维护数据还是共享数据,或者说是否存在多个数据闭环让数据的流向产生了多条路径。有状态的服务往往比较难进行水平拓展,在现在容器盛行的环境,把服务设计成无状态的更加高效,即便是有状态的服务,也要将状态内敛在系统的某个范围,比如分布式的存储,对于业务服务,我不需要关心数据在多个副本的状态,数据的状态由分布式存储这个服务本身解决。
差异维度有状态服务无状态服务服务本身服务本身依赖或者存在局部的状态数据,这些数据需要自身持久化或者可以通过其他节点恢复。服务不依赖自身的状态,实例的状态数据可以维护在内存中。节 点一个请求只能被某个节点(或者同等状态下的节点)处理。任何一个请求都可以被任意一个实例处理。数据状态存储状态数据,实例的拓展需要整个系统参与状态的迁移。不存储状态数据,实例可以水平拓展,通过负载均衡将请求分发到各个节点。系统中在一个封闭的系统中,存在多个数据闭环,需要考虑这些闭环的数据一致性问题。在一个封闭的系统中,只存在一个数据闭环。架构中通常存在于分布式架构中。通常存在于单体架构的集群中。相关资源statefulSet,由于是有状态的服务,所以每个pod都有特定的名称和网络标识。比如pod名是由statefulSet名+有序的数字组成(0、1、2..)ReplicaSet、ReplicationController、Deployment等,由于是无状态服务,所以这些控制器创建的pod序号都是随机值。并且在缩容的时候并不会明确缩容某一个pod,而是随机的,因为所有实例得到的返回值都是一样,所以缩容任何一个pod都可以。相关服务有状态服务 可以说是 需要数据存储功能的服务、或者指多线程类型的服务,队列等。(mysql数据库、kafka、zookeeper等)多个实例可以共享相同的持久化数据。例如:nginx实例,tomcat实例等
问者模式概念:封装作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
通俗的解释就是,系统中有一些固定结构的对象(元素),在其内部提供一个accept()方法用来接受访问者对象的访问,不同的访问者对同一元素的访问内容不同,所以使得相同的元素可以产生不同的元素结果。
比如在一个人事管理系统中,有多个工种的员工和多个老板,不同的老板对同一个员工的关注点是不同的,CTO可能关注的就是技术,CEO可能更注重绩效。
员工就是一个稳定的元素,老板就是变化的,对应概念就是:封装员工的一些操作,可以在不改变员工类的前提下,增加新的老板访问同一个员工。
在访问者模式中包含五个角色,抽象元素、具体元素、抽象访问者、具体访问者、结构元素。
抽象元素:定义一个接受访问的方法accept,参数为访问者对象。
具体元素:提供接受访问者访问的具体实现调用访问者的访问visit,并定义额外的数据操作方法。
抽象访问者:这个角色主要是定义对具体元素的访问方法visit,理论上来说方法数等于元素(固定类型的对象,也就是被访问者)个数。
具体访问者:实现对具体元素的访问visit方法,参数就是具体元素。
结构对象:创建一个数组用来维护元素,并提供一个方法访问所有的元素。
二、案例实现 在一个公司有干活的工程师和管理者,也有抓技术的CTO和管绩效的CEO,CTO和CEO都会访问管理员和工程师,当公司来了新的老板,只需要增加访问者即可。
工程师和管理者就是元素、公司就是结构体、CEO、CTO就是访问者。
抽象元素:
1 2 3 4 5 6 7 8 /** * 员工 抽象元素 被访问者 * @author tcy * @Date 29-09-2022 */ public interface ElementAbstract { void accept(VisitorAbstract visitor); } ASPECTJ
具体元素-工程师:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 /** * 工程师 具体元素 被访问者 * @author tcy * @Date 29-09-2022 */ public class ElementEngineer implements ElementAbstract { private String name; private int kpi; ElementEngineer(String name){ this.
在项目中使用了VueSeamlessScroll,实现了数据滚动,但是数据的点击事件,只有第一遍循环的时候生效,后面循环出来的数据都不生效,解决如下:
1、给外面div添加事件委托
上代码
<div class="broadcast-content-list" @click="viewRecords($event)"> <VueSeamlessScroll :data="listData" h-168 of-hidden :class-option="classOption" ref="seamlessScroll"> <div class="broadcast-content-list-item" v-for="(item, index) in listData" :key="index"> <ul> <li leading-12 max-h-12 flex="~" space="x-2" class="listItem" :data="JSON.stringify(item)" b="0 b-1 gray dashed" cursor="pointer"> <LazyTootip class="w-110px" :text="item.earlyWarnDate" /> <LazyTootip class="flex-1" :text="item.sevenOrgName" /> <LazyTootip class="flex-1" :text="item.nineOrgName" /> <LazyTootip class="w-22" :text="item.waringTypeName" /> <LazyTootip class="w-22" :text="item.txCode" /> <LazyTootip class="w-22" :text="item.txCodeName" /> </li> </ul> </div> </VueSeamlessScroll> </div> 、、、 listData:[] //接收后端返回的数据 、、、 computed: { //这个是配置项 classOption: function () { return { // step: 1, //步长 越大滚动速度越快 limitMoveNum: 14, //启动无缝滚动最小数据量,默认是5,我这里需要展示14条数据 hoverStop: true, //是否启用鼠标hover控制 direction: 1, //1 往上 0 往下 openWatch: true, //开启data实时监听 singleHeight: 0, //单条数据高度有值hoverStop关闭 waitTime: 1000 //单步停止等待时间 } } } methods:{ viewRecords(e) { const path = e.
ssh安装与使用 Welcome to unique_Hang’s blog.
鲁迅说过:看unique_Hang博客的人颜值都很高!
打不开图片可以鼠标右键点击“复制图片地址”在新窗口中打开
作者邮箱:unique_hang@qq.com
喜欢的小伙伴可以关注我的b站账号(https://space.bilibili.com/290100464)
1.说明 SSH 分客户端 openssh-client和 openssh-server。如果只是想登陆别的机器的 SSH 只需要安装 openssh-client(ubuntu 有默认安装,如果没有则 sudoapt-get install openssh-client),如果要使本机开放 SSH 服务就需要安装 openssh-server。
2. 安装客户端(登陆别的机器) sudo apt-get install ssh 或者 sudo apt-get install openssh-client ssh-keygen 根据提示按回车,(按回车设置默认值)
按缺省生成 id_rsa和 id_rsa.pub 文件,分别是私钥和公钥。
说明:如果 sudo apt-get insall ssh 出错,无法安装可使用 sudo apt-get install openssh-client 进行安装。
假定服务器 IP 为 192.168.0.128,服务器上用户为 ujs;
用 ssh 登录服务器的命令为:
ssh ujs@192.168.0.128 按照提示输入服务器密码即可远程连接。
3. 安装服务端(开放 SSH 服务) Ubuntu 缺省没有安装 SSH Server,使用以下命令安装:
1、什么是kubernetes
Kubernetes是一个开源的容器编排平台,它通过跨主机集群的方式来管理容器化应用程序。Kubernetes旨在简化容器的部署、扩展和管理,并提供自动化的操作(如负载均衡、自我修复、自动缩放等),以确保应用程序在容器化环境中的高可用性和稳定性。
以下是Kubernetes的一些重要概念:
Pod:是Kubernetes中最小的部署单元,一个Pod中包含一个或多个容器。Pod是Kubernetes中最小的可调度单元。
Service:用于暴露一个应用程序的网络服务。Service能够提供负载均衡、服务发现和集群内部DNS等功能,并将流量带到运行该服务的后端Pod。
ReplicaSet:用于管理多个Pod副本,以确保指定数量的Pod副本正在运行。
Deployment:用于在Kubernetes中部署和更新应用程序。Deployment管理一个或多个ReplicaSet,当进行更新时,会自动逐步滚动更新副本集。
Namespace:用于在Kubernetes中划分集群的资源。它可以用来将资源隔离开,在一个集群中使用多个Namespace从而更好地管理资源。
Volume:用于在Pod中提供持久化存储,它可以将存储与Pod一起编排。Volume可以使用各种后端存储(如本地存储、网络存储、云存储等)。
Node:是集群中的一个工作节点,它可以部署和运行一个或多个Pod,它们使整个Kubernetes集群能够工作。
这些概念是理解Kubernetes的基础,它们共同构建了Kubernetes的核心组件和功能。
2、kubeadm,kubelet,kubectl是什么?
kubeadm、kubelet和kubectl是Kubernetes的三个重要组件,分别用于管理集群的安装、节点的管理和Kubernetes API的操作。以下是它们的具体介绍:
kubeadm:是Kubernetes的集群安装工具,用于快速,轻松地启动和管理Kubernetes集群。kubeadm提供了一种简单,可靠且可重复的方式来安装Kubernetes,并支持从头开始构建集群或添加新节点到现有集群。
kubelet:是Kubernetes的节点代理,在每个节点上运行,并负责管理该节点上的容器化应用程序。kubelet监控Pod的状态,确保Pod中的容器始终处于运行状态,以及在必要时重新启动它们。
kubectl:是控制Kubernetes集群的命令行接口工具。kubectl可用于管理Kubernetes中的Pod,Deployment,Service等其他对象,并与Kubernetes API进行交互。通过kubectl,管理员可以对集群进行各种配置和管理操作,例如创建,修改和删除Pod对象。
这些工具共同构成了Kubernetes的完整工具链,使管理Kubernetes集群变得简单、高效和可靠。
3、kubernetes网络模式是怎样的?
Kubernetes网络模型是以容器为中心的,它为容器提供了一个虚拟网络,使得在同一个Pod或跨越集群的不同Pod中的容器之间能够互相通信,同时还提供了负载均衡和服务发现的功能。
以下是Kubernetes网络模型的主要组件:
Pod网络:Kubernetes使用flat模型的Pod网络,即每个Pod都有一个唯一的IP地址。这个IP地址是由Kubernetes内部的CNI插件根据不同的网络方案动态分配的。
容器网络接口(CNI):CNI插件是Kubernetes网络模型的核心组件之一,它负责为Pod和容器分配IP地址,并将它们连接到虚拟网络中。CNI插件可以支持各种网络方案,如flannel,Calico和Weave等。
Service:Kubernetes的Service是一个抽象的逻辑概念,用于将一组Pod公开为一个单一的网络端点。Service可以通过负载均衡将流量带到服务所代表的所有后端Pod中,同时还提供了DNS解析的功能。
Ingress:Ingress是Kubernetes中用于公开HTTP和HTTPS服务的一种资源对象。Ingress通过将规则映射到Service和后端Pod之间的路由规则,来提供负载均衡,服务发现,安全和路由等功能。
Kubernetes的网络模型是高度灵活的,可以支持各种不同的网络部署模式。由于CNI插件和Service等网络组件的支持,Kubernetes可以提供强大的网络特性,如负载均衡,服务发现和动态网络配置等,使Kubernetes成为一种强大的容器编排平台。
4、flanel原理是怎样的?
Flannel是一种Kubernetes网络插件,它可以提供容器网络的解决方案。Flannel利用虚拟网络接口(VNI)实现在整个Kubernetes集群中创建一个覆盖网络(Overlay Network),使得在不同节点的容器可以互相连通。其核心原理如下:
IP分配:Flannel通过etcd或者其他后端存储来分配唯一的overlay网络IP地址给每个节点,通常采用CIDR(Classless Inter-Domain Routing)地址段来分配。每个节点在启动时都会从etcd中获取分配的IP地址。
虚拟网络接口(VNI):Flannel在每个节点上创建一个虚拟网络接口,即flannel.1或flannel.0,这个接口用于在节点之间传递网络数据包。VNI使用UDP协议将数据包封装并传输到目标节点,以实现跨节点间的通信。
IP反向路由:在节点之间传递数据包时,Flannel还需要设置反向路由来确保数据包能够正确传输。每个节点都要在它的路由表中添加反向路由,以便将容器的互联流量通过VNI发送到目标节点的容器。
Flannel的工作原理比较简单,但是它可以为Kubernetes提供跨节点的容器通信能力,并且支持多种网络类型,包括VXLAN、GRE、IPsec等。通过这种方式,Flannel能够实现高性能,高可用性和可扩展性的容器网络。
5、详细说说kubernetes中的service
Kubernetes的Service是一种抽象的逻辑概念,用于将一组Pod公开为一个单一的网络端点。Service提供了负载均衡、服务发现和DNS解析等功能,使得客户端可以方便地和后端Pod进行通信,无需知道Pod的IP地址和端口号。
Kubernetes的Service有以下特点:
服务发现:Service可以在Kubernetes集群中发现和连接到运行实例的Pod。当Pod发生变化时,Service还可以自动更新其端点信息。
负载均衡:Service将客户端请求分发到后端Pod中,可以平衡负载和优化应用程序的性能。Kubernetes支持各种负载均衡器,例如使用iptables实现的基于轮询或者随机算法的负载均衡器,也可以使用外部负载均衡器来替换默认的机制。
网络代理:Service还可以作为一个网络代理,将应用程序暴露给集群外的客户端或其他服务。
外部服务的代理:Service可以将外部服务作为内部服务,并暴露在Kubernetes内部。这种方式可以使得监控Kubernetes中的应用程序变得简单,而不需要在不同的服务中间增加逻辑。
创建一个Service需要以下步骤:
定义Service:使用Kubernetes的API和yaml文件来定义Service对象,指定服务名称、端口和IP地址等参数。
创建Selector标签:将Service和一个或多个Pod关联起来。通过Selector标签选择需要关联的Pod,并将其配置为Service的后端。
创建Endpoint:Endpoint是Service的背后实际运行的Pods IP和端口的集合体。它可以在创建一个Service时自动生成,或者通过手动创建Endpoint来对Pod进行更精细的控制。
Kubernetes的Service是集群中实现服务发现和负载均衡的核心组件之一。在Kubernetes中,Service不仅是将应用程序暴露出去的方式,还在一定程度上革新了应用程序的部署方式,使得基于容器的应用程序变得更加易于管理和扩展。
6、service、pod、deoplyment有什么区别?
Service、Pod和Deployment是Kubernetes中的三个重要组件,它们各自扮演着不同的角色,下面是它们之间的区别:
Pod是Kubernetes中最小的可调度单元,它是容器的一种抽象,在Kubernetes中被用作部署应用的基本单位。Pod中可以包含多个紧密相关的容器,这些容器共享网络命名空间和存储卷,可以彼此访问。
Service是Kubernetes中的网络抽象,用于提供网络服务对后端Pod的访问。服务是指一组具有相同功能的Pod的集合,通过Service来监听访问请求,然后将请求转发给后端的Pod。Service提供负载均衡,自动发现,服务注册,负担差配,服务映射和DNS解析等实现服务发现的功能。
Deployment用于管理ReplicaSet以及ReplicaSet所管理Pod的生命周期。Deployment定义应用程序的期望状态,创建ReplicaSet并将其调整到期望的状态。Deployment还支持Rolling Update,指在滚动升级或回滚时,可以以一种优雅的方式更新应用程序的状态。
综上所述,Pod、Service和Deployment都是Kubernetes中的核心组件,但它们有不同的作用和功能。Pod是最基本的部署单元,用来包含容器;Service提供一种抽象的方式来访问后端Pod;Deployment则更专注于管理应用程序的状态,并通过期望和实际状态的对比实现滚动更新和回滚等操作。
7、详细说说deoplyment
Deployment是Kubernetes中的一种资源对象,用于管理Pod的部署和更新。Deployment定义了一个应用程序的期望状态,即所需的副本数、容器镜像和配置信息等,并通过在它的管理下创建、扩展和缩放ReplicaSet来实现该状态。Deployment自动管理Pod和ReplicaSet的生命周期,确保应用程序的状态始终保持在期望状态中,同时提供了滚动更新、回滚和暂停部署等高级管理功能。
Deployment的主要特点包括:
滚动更新:Deployment支持滚动升级,即在不停机的情况下逐步升级Pod的容器镜像版本或配置文件,以保持应用程序的高可用性。同时,还可以选择回滚到以前的某个版本。
自发现:在Kubernetes中,Pods通常不会直接与其他Pods通信,而是通过Service来进行通信。Deployment允许Pods自动注册到Service,从而使整个系统具有服务发现功能。
弹性伸缩:Deployment可以通过水平伸缩来根据应用程序负载自动增加或减少Pod的数量,以保证负载均衡和高可用性。
统一部署:Deployment为多个Pod提供了一个统一的配置文件,使得应用程序的部署更加一致和可靠。
使用Deployment可以简化应用程序的部署和管理,同时支持高效和可靠的滚动更新,保证了应用程序在Kubernetes集群中的高可用性和可伸缩性。当修改应用程序代码或配置时,只需更新Deployment的参数即可,Deployment将自动升级Pod和ReplicaSet,而不需要手动操作。
8、最后介绍下ingress
Ingress是Kubernetes中用于公开HTTP和HTTPS服务的一种资源对象。它通过将规则映射到Service和后端Pod之间的路由规则,来提供负载均衡,服务发现,安全和路由等功能。Ingress将网络流量路由到Service,而Service将流量路由到后端Pod。
以下是Ingress的主要特点:
路由:Ingress可以根据不同的域名、路径和HTTP方法将流量路由到不同的服务和Pod。通过Ingress规则,可以轻松地实现负载均衡、服务路由和容器间通信等功能。
TLS/SSL支持:Ingress支持TLS和SSL,可以保护HTTP和HTTPS流量的安全性。Ingress可以使用自签名证书或使用许可颁发机构(CA)颁发的证书来保护连接。
前言 大麦网,是中国综合类现场娱乐票务营销平台,业务覆盖演唱会、 话剧、音乐剧、体育赛事等领域。
但是因为票数有限,还有黄牛们不能丢了饭碗,所以导致了,很多人都抢不到票
那么,今天带大家用Python来制作一个自动抢票的脚本小程序
知识点: 面向对象编程selenium 操作浏览器pickle 保存和读取Cookie实现免登陆time 做延时操作os 创建文件,判断文件是否存在 开发环境: 版 本:anaconda5.2.0(python3.6.5)编辑器:pycharm 先导入本次所需的模块 import os import time import pickle from time import sleep from selenium import webdriver 第一步,实现免登录 确定目标,设置全局变量
# 大麦网主页 damai_url = "https://www.damai.cn/" # 登录页 login_url = "https://passport.damai.cn/login?ru=https%3A%2F%2Fwww.damai.cn%2F" # 抢票目标页 target_url = 'https://detail.damai.cn/item.htm?spm=a2oeg.search_category.0.0.77f24d15RWgT4o&id=654534889506&clicktitle=%E5%A4%A7%E4%BC%97%E7 初始化加载
class Concert: def __init__(self): self.status = 0 # 状态,表示如今进行到何种程度 self.login_method = 1 # {0:模拟登录,1:Cookie登录}自行选择登录方式 self.driver = webdriver.Chrome(executable_path='chromedriver.exe') # 默认Chrome浏览器 登录调用设置cookie
~~~python def set_cookie(self): self.
Jetson TX2 NX(Ubuntu 18.04) + ROS melodic + turtlebot功能包 + realsense d455 + ORB-SLAM2 1. 安装ROS melodic 更换中科大源 $ sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ $DISTRIB_CODENAME main" > /etc/apt/sources.list.d/ros-latest.list' 设置key $ sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 更新软件源 sudo apt-get update 安装ROS桌面完整版 sudo apt-get install ros-melodic-desktop-full 初始化并更新 sudo apt-get install python3-pip sudo pip3 install rosdepc sudo rosdepc init rosdepc update 在sudo pip3 install rosdepc时遇到错误
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xe8VLqC7-1684312007284)(C:\Users\chenl\AppData\Roaming\Typora\typora-user-images\image-20230510182544491.png)]
今天在新电脑上刚下的python和pycharm,运行的时候遇到一点问题,就是报这个ModuleNotFoundError的错误。
尝试了很多方法都失败了,最后找到解决的办法,大家可以按我这个步骤一步一步来找问题。
(1)是否下载了numpy库?
start+R打开命令行,在里面输入以下命令下载numpy库:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy 中间加了一个镜像,这样下载更快,numpy这个库下得比较慢容易超时,用镜像下更方便一点,也可以用以下的普通下载:
pip install numpy 下载完之后,用pip list查看是否下载成功,出现numpy就是成功了。
(2)现在回到pycharm再运行代码,如果还是弹出ModuleNotFoundError的错误,就检查一下这两个位置的路径是否相同:
file->setting->project->project interpreter
可以看到这个路径里面是有numpy库的,那么就是另一个地方出了问题。如果你的这里没有numpy,试试换一个python interpreter,换成那个有numpy的。
run->edit configurations->python interpreter
观察图上圈起来那个位置,应该和前面的路径相同,不同的话要改成一样的,因为之前下载的numpy应该是下载到另一个路径里去了,两个路径不同的话就会报错,所以把这一个改到和前一个相同,因为前一个路径里是有numpy库的。
修改完毕,顺利运行!
一、mysql主从复制原理 1、master将操作语句记录到binlog日志中,然后授予slave远程连接的权限(master一定要开启binlog二进制日志功能;通常为了数据安全考虑,slave也开启binlog功能)。
2、slave开启两个线程:IO线程和SQL线程。其中:IO线程负责读取master的binlog内容到中继日志relay log里;SQL线程负责从relay log日志里读出binlog内容,并更新到slave的数据库里,这样就能保证slave数据和master数据保持一致了。
3、Mysql复制至少需要两个Mysql的服务,当然Mysql服务可以分布在不同的服务器上,也可以在一台服务器上启动多个服务。
4、Mysql复制最好确保master和slave服务器上的Mysql版本相同(如果不能满足版本一致,那么要保证master主节点的版本低于slave从节点的版本)
5、master和slave两节点间时间需同步
二、安装mysql 1、检查安装环境 1.1、检查是否安装过mysql [root@localhost ~]# rpm -qa | grep mysql #如果有就使用 rm -rf 命令删除 [root@localhost ~]# whereis mysql mysql: /usr/lib64/mysql /usr/share/mysql [root@localhost ~]# rm -rf /usr/lib64/mysql /usr/share/mysql #删除 [root@localhost ~]# find / -name mysql /etc/selinux/targeted/active/modules/100/mysql [root@localhost ~]# rm -rf /etc/selinux/targeted/active/modules/100/mysql #删除 1.2、检查是否有mysql用户 若用户及用户组已存在,则略过这一步,没有则创建
[root@localhost ~]# id mysql id: mysql: no such user [root@localhost ~]# groupadd mysql [root@localhost ~]# useradd -r -g mysql mysql 1.
一、环境搭建 android studio2021.2.1
jdk版本1.8
二、jni中日志输出配置 1.build.gradle配置
ndk下配置,ldLibs "log"
2.在.c文件的配置
(1)头文件的配置
#include <android/log.h> #define LOG_TAG "TAG" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) (2)输出日志
LOGD("value===%d\n",value); LOGI("value===%d\n",value); Rebuild Project后报错,如下图所示:
需在Android.mk文件上配置
(3)Android.mk日志配置
#打印日志库 LOCAL_LDLIBS := -llog 根据以上三步骤,则可输出jni的native的日志 ,不同的AS、JDK版本报错可能处理方法会不一样。
文章目录 实验目的题目Code 实验目的 掌握采用Handler+Thread编写多线程序掌握AsyncTask编写多线程序的方法 题目 采用Handler+Thread多线程方式编写程序一个模拟从网络下载文件的程序,点击“点击加载”按钮,在子线程中执行100次循环,每次循环休眠50毫秒,并通过进度条显示循环执行的进度。
Code Activity.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="165dp" android:layout_height="32dp" android:layout_marginStart="111dp" android:layout_marginTop="324dp" android:layout_marginEnd="135dp" android:layout_marginBottom="375dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="152dp" android:layout_marginBottom="64dp" android:text="加载" app:layout_constraintBottom_toTopOf="@+id/progressBar" app:layout_constraintStart_toStartOf="parent" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="152dp" android:layout_marginTop="40dp" android:text="取消" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/progressBar" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="158dp" android:layout_marginTop="27dp" android:layout_marginBottom="18dp" android:text="TextView" app:layout_constraintBottom_toTopOf="@+id/progressBar" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button" /> </androidx.constraintlayout.widget.ConstraintLayout> MainActivity.java
package com.
该通用平台于2022年8月15日至9月23日进行了落地试验,来自中国香港和大陆、阿联酋与泰国的20家商业银行使用各自中央银行在mBridge平台上发行的CBDC,代表其企业客户进行了支付以及外汇(FX)同步交收(PvP)交易。“互操作性是CBDC发挥其全部潜力的关键因素。”纳扎罗夫如是说。
Python-PyEchart绘制地图Map
一、简介
参考官网地址:
https://pyecharts.org/#/zh-cn/intro 相关数据准备:
关注上面公众号,回复“地图”即可获取相关数据。
图对象具体配置参考:
全局配置参考:
JSON数据参考:
1、全国疫情可视化地图案例参考:
绘制地图工具模块:
#绘制地图通用模块from pyecharts.charts import Mapfrom pyecharts.options import VisualMapOpts def fun_map(title,maptype,data): """ :fun_map:绘制地图函数 :param title: 添加数据 series_name系列名称 :param data: 地图相关数据 :param maptype: 地图类型 :return: """ #1、开始绘制地图 print("开始绘制地图") # 2.准备地图对象 map = Map() # 3.准备数据,所用数据都是列表嵌套元组 data已经传 # 4.添加数据 series_name系列名称,用于 tooltip 的显示,legend 的图例筛选 # data_pair 数据项 (坐标点名称,坐标点值) # 地图类型,具体参考 pyecharts.datasets.map_filenames.json 文件 map.add(series_name=title,maptype=maptype,data_pair=data) # 5.设置全局选项 map.set_global_opts( # 视图功能 visualmap_opts=VisualMapOpts( # 该参数设置视图开启 is_show=True, # 该参数改变视图模式 是否为分段型 is_piecewise=True, # 颜色和表签的设置 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式 pieces=[ {"
端口隔离:端口隔离是为了实现报文之间的二层隔离,可以将不同的端口加入不同的VLAN,但会浪费有限的VLAN资源。采用端口隔离特性,可以实现同一VLAN内端口之间的隔离。用户只需要将端口加入到隔离组中,就可以实现隔离组内端口之间二层数据的隔离。端口隔离功能为用户提供了更安全、更灵活的组网方案。
PC1、PC2、PC3主机的IP地址分别为192.168.1.1/24 、192.168.1.2/24、192.168.1.3/24
要实现PC1不能访问PC2,但PC1可以访问PC3
SW1配置:
# interface GigabitEthernet0/0/1 port-isolate enable group 1 //group 1组里的成员端口启用端口隔离,成员端口间相互隔离不能访问 # interface GigabitEthernet0/0/2 port-isolate enable group 1 PC>ping 192.168.1.2 Ping 192.168.1.2: 32 data bytes, Press Ctrl_C to break From 192.168.1.1: Destination host unreachable From 192.168.1.1: Destination host unreachable From 192.168.1.1: Destination host unreachable From 192.168.1.1: Destination host unreachable From 192.168.1.1: Destination host unreachable --- 192.168.1.2 ping statistics --- 5 packet(s) transmitted 0 packet(s) received 100.00% packet loss PING 192.
jquery动画:动画效果,有基本动画显示和隐藏、滑动、淡入淡出、自定义动画
1.1 显示和隐藏
show([speed,[easing],[fn]])
显示隐藏的匹配元素。
hide([speed,[easing],[fn]])
隐藏显示的元素
注意参数分析:
speed速度
speed:三种预定速度之一的字符串("slow","normal", or "fast")或表示动画时长的毫秒数值(如:1000)
我们把 速度 写到 show() 和 hide() 方法里, 动画切换的时候,有过渡效果,比较好看。
.box { width: 300px; height: 300px; background-color: red; margin-bottom: 20px; display: none; } <div class="box"></div> <button id="btn1">显示</button> <button id="btn2">隐藏</button> <script src="./jquery-3.5.1/jquery-3.5.1.min.js"></script> <script> $(function(){ $('#btn1').click(function(){ $('.box').show(250); }) $('#btn2').click(function(){ $('.box').hide(250) }) }) </script> 预览:
1.2 滑动
slideUp([speed,[easing],[fn]]) 向上滑动
通过高度变化(向上减小)来动态地隐藏所有匹配的元素,在隐藏完成后可选地触发一个回调函数。
slideDown([speed,[easing],[fn]]) 向下滑动
通过高度变化(向下增大)来动态地显示所有匹配的元素,在显示完成后可选地触发一个回调函数。
优化图的显示效果:
我们让 图 包裹在 一个div盒子中,就可以实现 在滑动的时候,只是 高度在变!!!
<style> *{ margin: 0; padding: 0; } .
最近看了文章FXAA和FXAA算法演义 - 知乎,对Edge Blending有些迷糊,做分析记录一下。
Edge Blending目的是为了解决类似下面图1和图2展示的阶梯形走样,图1是原始的结果,图2是对上面的图做了双线性差值的结果。具体看渲染过程是不是使用了Bilinear的中间颜色缓存,FXAA前会做后处理,一般都会使用Bilinear,所以大多数是图2的情况。
图1
图2
两者的差别是,第一种FXAA边缘厚度是2,第二种因为多了一个中间层厚度是3。为了方便,下面都是基于无中间层的情况分析。 惯例先给出FXAA基于图1处理的结果,效果还是比较明显的。
这是用来分析的图片,红色是三角形的采样点,蓝色是背景采样点,绿色表示像素的边缘,青色为三角形的边缘线。
我们要分析Edge Blending,以下图中的123三个红点做参考,这三个点形成了明显的走样。
显然123点的Blend方向是向下,按照FXAA的方法,123点依次向下移动0.5个像素到中间位置然后做采样,其实就是123和下面对应的蓝点取平均值。
这里提一个坑的地方,我在自己的电脑上直接采样中间点,结果却和手动采样两次求平均值差不少(差值在0.1范围内),如果你有出现相同问题的话,建议手动采样两次求平均值,这样可以减少误差效果好一些。(这个问题已经找到原因和解决方法,参考我的另一篇博客Unity Editor绘制时分辨率减一_paserity的博客-CSDN博客)
线性差值采样中间点,和手动采样两个边界点求平均值的差值
我们考虑平均后的结果是什么。为了分析方便,不妨设红点数值为1,蓝点数值为0。上面的5个采样点依次标记为0,1,2,3,4,5,那么易知从左到右求得的平均值分别为1,0.5,0.5,0.5,0。
理想情况下我们想要的目标,是可以根据上下两点分别占边缘两侧的区域来决定BlendFactor。计算方法可以参考下图,同样是红点和蓝点,黄色的是边缘线。边缘线和像素边界将两个像素分成了4块区域,设其面积为S1~S4, 红点和蓝点数值分别为R和G,那么红点处计算应该是,蓝点处是。
这样我们得到123点的BlendFactor大概是1,0.8,0.6,这样也就理解了为什么只要权重超过了0.5,就会切换到另一种颜色,因为这时边缘线肯定过像素中心了。
然后看看面积是怎么计算的,以红点为例,S4等于,显然不是线性关系。
假设α=45度,做出面积变化曲线如下,可以看出用线性拟合差别不大(实际上要精确计算也是不可能的,因为α是未知的)
那么如何做线性拟合呢?FXAA使用的方法是沿着边缘方向找到边界点,然后跟当前采样点根据位置Blend。这里最左边的0点是1,中间三个点都是0.5,最右边是0,很显然边界点就是0和5。然后根据中间的相对位置来计算。
再看下混合式,R代表红点颜色值,B代表蓝点颜色值,f为最终的颜色
当BlendFactor为0.5时,f=0.5(R+B),就是平均值,BlendFactor越小,R占的权重就越大。所以123点的BlendFactor应该是递增的(0~0.5)。当然这实际上是因为现在的边缘方向是斜上方的,如果边缘是朝斜下方,那么BlendFactor就应该是递减(0.5~0)。
要怎么确定边缘方向呢?FXAA里给的方法是判断终点是不是和当前点在同一个区域,比如这里都从左侧的红点向右查找终点,就会发现根据倾斜方向不同终点位于红色或者蓝色区域:
判断终点区域是否相同具体实现是计算(起点值-中间值),然后计算(终点值-中间值),判断这两者符号是不是相同,如果符号相同,代表终点没有区域变化(左图的情况),否则代表右图的情况。简单理解就是看终点值和起点值颜色是不是一样。
另外需要注意的一点是,我们之前都是在考虑红点,实际上蓝点也会做类似的计算,只是混合方向相反。
有了以上的铺垫,FXAA计算BlendFactor的算法流程如下图所示,s代表查找起点,e代表终点,中间的1234四个点需要计算BlendFactor:
1点距离起点长度1,距离终点长度4,距离最近的是起点s,起点没有区域变化,返回0;
2点距离起点长度2,距离终点长度3,距离最近的是起点s,起点没有区域变化,返回0;
3点距离起点长度3,距离终点长度2,距离最近的是终点e,终点有区域变化,返回2/5=0.4;
4点距离起点长度4,距离终点长度1,距离最近的是终点e,终点有区域变化,返回1/5=0.2;
我们来分析一下为什么这个流程可以解决正确计算出BlendFactor:
首先为什么3点有BlendFactor而2没有呢?这是因为2点像素范围内还没有接触到蓝色区域,而到3点时才开始有。接触到蓝色区域可以简化为像素范围有没有越过水平的中线,就是上图中灰色的线条,灰色线条既是像素的中线,同时也是s~e区域范围内黄色边缘线的水平中线(根据对称性),那么很显然s和e的中间位置((s+e)/2)就是判断像素范围开始接触到蓝色区域的临界点。所以在s和e中间的点中,必定一半需要Blend,一半不需要。
那要怎么判断是哪边需要Blend呢?如果我们计算出离这些点最近的边界点记作t(s或者e),需要Blend的点一定和t位于不同的区域,例如上面的3和4。这是因为这些点更接近边界点,肯定更加需要Blend),至于怎么判断终点属于不同的区域,前面已经给了方法。之后把上一步计算出来的BlendFactor处理一下,0.5-BlendFactor就是最终的BlendFactor了。
还有一点是判断Blend方向的计算,FXAA判断垂直方向的权重是:
abs(lumaW + lumaE - 2 * lumaM) 为什么不用简单的abs(lumaW-lumaE)呢?我们分别用0和1代表luma值,不考虑等价情况,那么左中右三个点有这些情况:
000,001,010
其中000和001用abs(lumaW-lumaE)是可以得到一样的结果的,差异就在010,这种情况出现在中间点像素值和左右不同的情况,会导致出现异常噪点,是我们需要消除的。所以这种情况下需要让中间值跟两侧值做Blend,所以权重不能为0。
在导师的严格指导下,我的毕业设计终于完成了,毕设被推优算是给大学生活画上了圆满的句号,几个月的努力也没白费。在开发的过程中收获了很多,也遇到很多问题,但因怕时间来不及(根本不知道截止时间TvT)没有及时记录,等之后有机会再补上好了。在此简单记录下本项目的详细设计。
文章目录 用户功能模块实现1.用户注册登录2.用户个人设置3.用户个人空间4.用户搜索商品5.用户浏览商品6.用户收藏商品7.用户留言8.用户购买商品9.用户商品管理10.用户订单 管理员功能模块实现1.管理员登录2.用户管理3.商品管理4.留言管理 本项目是基于SringBoot+Vue的校园闲置物品交易平台,分为前台和后台,用户角色主要分为管理员和正式用户,功能算是较为完整,参考了一些二手软件。 用户功能模块实现 1.用户注册登录 用户通过网址进入到校园闲置物品交易平台的首页。此时用户没有注册账户,其角色为游客,作为游客,只能浏览首页,搜索商品,不能进行发布、购买商品等操作。
通过登录页面上的“注册新用户”链接,可以跳转到注册页面进行注册。根据要求填入相关信息后,点击“注册”按钮即可。若学号已被注册则不会注册成功。注册成功后会返回登录页面,正确输入学号、密码和验证码就可以成功登录。
用户若忘记密码,可以通过登录页面下方的“忘记密码?”进入找回密码的页面。
2.用户个人设置 在首页页面上方用户昵称处有下拉菜单可以操作。
在下拉菜单中点击“个人中心”跳转页面,左侧导航栏中将默认选中“我的资料”,就可以查看和修改个人资料。
在个人中心页面,点击上方导航栏“修改密码”进入页面,输入新密码保存即可。
在个人中心页面,点击上方导航栏“修改头像”进入页面,点击头像上传文件,保存后才能成功更换头像。
3.用户个人空间 在下拉菜单中点击“个人空间”进入用户的个人空间页面,用户可以编辑个人介绍和查看发布的闲置商品。
在用户个人空间页面,还可以查看其他买家购买该用户的闲置物品后,对其交易结果的评价,点击“Ta的评价”就可以查看评价。
4.用户搜索商品 点击首页上方搜索按钮就可以进入搜索商品页面,输入商品标题关键字就可以查找相关物品,且默认按发布时间由近到远排序。
5.用户浏览商品 用户在首页可以按照商品类别查看对应商品列表。
这时可以点击商品图片即可进入商品详情页面,在该页面中,可以查看该商品的描述、类别、状态、交易地点、发布时间和卖家,点击卖家昵称处可跳转到对应用户的空间页面。
6.用户收藏商品 在商品详情页面,可收藏感兴趣的商品,如不需要可取消收藏。
此外,在“个人中心”页面的“我的收藏”可以查看用户收藏商品列表。在列表中,可对已收藏的商品进行取消收藏操作;若想查看商品详情,点击商品图片即可跳转查看。
7.用户留言 在商品详情页面下滑有留言区,用户可以发布留言和回复其他用户留言。
在留言区,若要删除留言,点击删除图标即可删除。
在“个人中心”页面的“我的留言”即可查看用户收到和发出的所有留言。点击商品标题可跳转到商品详情页面。
在“我的留言”页面,点击删除图标可以删除留言。
8.用户购买商品 在商品详情页面,点击“立即购买”会跳出对话框询问,确认后将跳转到支付宝提供的沙箱环境进行模拟支付。
支付成功后跳转到支付成功页面。
在商品详情页面,若购买到违规用户的闲置物品,则无法购买。
9.用户商品管理 在首页通过页面上方的“发布商品”按钮就可以跳转到发布闲置物品的页面。
在“个人中心”页面的“我的闲置”即可查看用户发布的所有闲置物品。对于未售出的商品,可进行擦亮(即刷新发布时间)、编辑和删除商品,已售出的商品则不能进行操作。
10.用户订单 在“个人中心”页面的“我的订单”即可查看“我买到的”和“我卖出的”。在用户“我买到的”页面中,点击商品图片可以查看商品详情。点击“联系卖家”查看卖家联系方式。
在“我买到的”页面中,若已收到货,可以点击确收货后进行评价。
在“我卖出的”页面中,同样也可以查看买家联系方式和商品详情。
管理员功能模块实现 1.管理员登录 拥有管理员权限的用户在本平台的登录页面输入正确的学号和密码就可以登录。
2.用户管理 成功登录后,直接进入后台管理页面,默认展示用户管理。
在用户管理页面中,管理员可以查看所有用户的信息,不仅可以筛选查看对应角色的用户,还可以通过昵称或姓名查找用户。
作为拥有最高权限的管理员,能修改用户的角色权限。在用户管理页面中,点击“更改权限”选择角色,如管理员、正式用户或违规用户,点击“保存”就可成功修改。
管理员还可以查看和删除非管理员用户。在用户管理页面中,当点击“查看”按钮,会进入对应用户的空间页面。
通过“删除”按钮可以删除该用户涉及的所有信息,包括其发布的商品和留言。
3.商品管理 在商品管理页面中,点击相应按钮可以对所有商品进行查看详情和下架删除。
在商品管理页面中,当商品数量过多,可以通过上方的搜索栏,根据商品标题关键词快速查找到需要查找的商品。
4.留言管理 在留言管理页面中,通过搜索栏输入留言内容的关键字可以查找留言。
在留言管理页面,点击“屏蔽”按钮会改变用户留言的内容为“该留言已被屏蔽”。
k8s管理工具--Kubectl(二) 一、项目生命周期1、项目生命周期2、创建kubectl run命令3、发布kubectl expose命令(1) Service的作用(2)Service的类型(3)查看Pod网络状态详细信息和Service暴露端口(4)查看关联后端的节点(5)查看service的描述信息(6)查看日志 二、更新kubectl set1、获取修改模板2、查看当前nginx版本3、将nginx版本更新为1.15 三、回滚kubectl rollout1、查看历史版本2、执行回滚到上一个版本3、执行回滚到指定版本4、检查回滚状态 四、实现负载均衡1、首先在node1 node2节点安装ipvsadm2、在master01节点分别在3个pod内写入网页文件 五、删除kubectl delete1、删除副本控制器2、删除service 六、金丝雀发布1、更新deployment的版本,并配置暂停deployment2、查看更新3、确保更新的pod没问题了,继续更新 一、项目生命周期 1、项目生命周期 创建–>发布–>更新–>回滚–>删除
2、创建kubectl run命令 创建并运行一个或多个容器镜像
创建一个deployment或job来管理容器
kubectl run --help查看使用帮助
启动nginx实例,暴露容器端口80,设置副本数3
[root@master01 ~]#kubectl create deployment nginx --image=nginx:1.14 --port=80 --replicas=3 3、发布kubectl expose命令 将资源暴露为新的Service
为Deployment的nginx创建Service,并通过Service的80端口转发至容器的80端口上,Service的名称为nginx-service,类型为NodePort。
[root@master01 ~]#kubectl expose deployment nginx --port=80 --target-port=80 --name=nginx-service --type=NodePort (1) Service的作用 Kubernetes之所以需要Service,一方面是因为Pod的IP不是固定的(Pod可能会重建),另一方面是因为一组Pod实例之间总会有负载均衡的需求。Service通过Label Selector实现的对一组的Pod的访问。对于容器应用而言,Kubernetes提供了基于VIP(虚拟IP)的网桥的方式访问Service,再由Service重定向到相应的Pod。 (2)Service的类型 ClusterIP:提供一个集群内部的虚拟IP以供Pod访问(Service默认类型)NodePort:在每个Node上打开一个端口以供外部访问,Kubernetes将会在每个Node上打开一个端口并且每个Node的端口都是一样的,通过NodeIP:NodePort的方式LoadBalancer:通过外部的负载均衡器来访问,通常在云平台部署LoadBalancer还需要额外的费用。 (3)查看Pod网络状态详细信息和Service暴露端口 (4)查看关联后端的节点 (5)查看service的描述信息 (6)查看日志 二、更新kubectl set 1、获取修改模板 2、查看当前nginx版本 3、将nginx版本更新为1.15 注:更新规则可通过“kubetl describe deployment nginx”的“RollingUpdateStrategy”查看,默认配置为“25% max unavailable, 25% max surge”,即按照25%的比例进行滚动更新。
gcc编译器
gdb调试器
make工程管理器
shell 脚本
预处理:#include包含文件内容替换语句,定义的宏被展开, GCC预处理阶段可以生成.i的文件,通过选项-E可以使编译器在预处理结束时就停止编译:gcc -E -o hello.i hello.c
编译: 编译器对源码进行词法分析、语法分析、优化等操作,最后生成汇编代码。可以通过选项-S使GCC在进行完编译后停止,生成.s的汇编程序: gcc -S -o hello.o hello.c
汇编:这一阶段使用汇编器对汇编代码进行处理,生成机器语言代码,保存在后缀为.o的目标文件中。gcc -c -o hello.o hello.c
链接: 经过汇编以后的机器代码还不能直接运行。为了使操作系统能够正确加载可执行文件,文件中必须包含固定格式的信息头,还必须与系统提供的启动代码链接起来才能正常运行,这些工作都是由链接器来完成的。
gcc 使用 gcc [options] [filenames] options:编译器所需要的编译选项 filenames:要编译的文件名
-c:只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件
-o :output_filename:确定可执行文件的名称 为output_filename。如果不给出这个选项,gcc就给出预设的可执行文件a.out。(只生成可执行文件,无关文件命名) :gcc hello.c -o hello.o 生成名为hello.o的可执行文件。
-g:产生调试工具(GNU的gdb)所必要的符号信息,要想对编译出的程序进行调试,就必须加入这个选项。
-O: 对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
-O2:比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
-Idirename: 将dirname所指出的目录加入到程序头文件目录列表中
-Ldirename: 将dirname所指出的目录加入到库文件的目录列表中
-lname: 在连接时装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。 例如,-lm表示连接名为“libm.a”的数学函数库
-static:静态链接库文件
静态库:是在执行程序之前就已经加入到执行代码中,成为执行程序的一部分来执行的,后缀名:.a 动态库:是在执行程序启动时加载到执行代码中,后缀名:.so 静态库的创建:
创建: gcc –c 源文件.c
ar rcs 静态库名 目标文件1 目标文件2 rc:静态库不存在,就创建该库文件 s:更新库文件 ar -t 静态库名 查看.
Tomcat跟Apache 1.Apache是什么? Apache是一种开源的Web服务器软件,它是目前全球使用最广泛的Web服务器软件之一。Apache的全称是Apache HTTP Server,它最初由美国国家超级计算机应用中心(NCSA)开发,后来由Apache软件基金会接手开发和维护。Apache的特点包括:
可靠性:Apache是一种稳定可靠的Web服务器软件,已经在全球范围内得到了广泛应用。可扩展性:Apache支持多种模块化的扩展方式,可以根据需要添加各种功能模块,例如PHP、SSL、CGI等。跨平台性:Apache可以运行在多种操作系统上,包括Linux、Windows、Unix等。易用性:Apache提供了简单易用的Web管理界面,可以方便地进行配置和管理。 除了作为Web服务器软件,Apache还可以作为反向代理服务器、负载均衡器、缓存服务器等多种用途。总的来说,Apache是一种强大、灵活、可靠的Web服务器软件,是Web开发和运维人员必备的工具之一。
2.Tomcat是什么? Tomcat是一种开源的Java Servlet容器,它是目前全球使用最广泛的Java Web应用服务器之一。Tomcat的全称是Apache Tomcat,它最初由Apache软件基金会开发,后来成为了独立的项目。Tomcat的特点包括:
支持Java Servlet和JavaServer Pages(JSP):Tomcat是一种Java Web应用服务器,可以处理Java Servlet和JSP等Web应用程序。易于使用:Tomcat提供了简单易用的Web管理界面,可以方便地进行配置和管理。轻量级:Tomcat是一种轻量级的Java Web应用服务器,占用资源较少,启动速度快。易扩展性:Tomcat支持多种模块化的扩展方式,可以根据需要添加各种功能模块,例如SSL、JDBC等。 除了作为Java Web应用服务器,Tomcat还可以作为反向代理服务器、负载均衡器等多种用途。总的来说,Tomcat是一种强大、灵活、易于使用的Java Web应用服务器,是Java Web开发和运维人员必备的工具之一。
3.Apache跟tomcat有什么区别 Apache和Tomcat都是Web服务器软件,但它们的工作方式和用途略有不同。举个例子来说:
假设你要开发一个Java Web应用程序,这个应用程序需要处理用户的请求,生成动态的HTML页面并将其返回给用户。在这种情况下,你可以选择使用Apache或Tomcat。
如果你选择使用Apache,那么Apache会处理静态资源(例如HTML、CSS和JavaScript文件),并将动态请求转发给Tomcat。Tomcat会处理这些动态请求,生成动态HTML页面,并将其返回给Apache,最后由Apache将其返回给用户。这种方式被称为“Apache + Tomcat”架构。
如果你选择使用Tomcat,那么Tomcat将直接处理所有的请求,包括静态资源和动态请求。Tomcat会生成动态HTML页面,并将其直接返回给用户。这种方式被称为“Tomcat独立部署”架构。
总的来说,Apache和Tomcat都是非常优秀的Web服务器软件,具有各自的特点和优势,可以根据实际需求选择使用。但需要注意的是,如果你需要处理Java Web应用程序,那么Tomcat可能会更适合你的需求。
总结:Tomcat更多的用于java类型的应用程序,而Apache的应用范围会更广一些
4.安装配置apache 按照以下步骤来安装Apache:
更新系统:
yum update 安装Apache:
yum install httpd 启动Apache:
systemctl start httpd.service 配置Apache开机自启动:
systemctl enable httpd.service 验证Apache是否正常运行:
在浏览器中输入服务器的IP地址或域名,如果能够看到Apache的默认页面,则说明Apache已经成功安装并运行。
http://your_server_IP_address/ 配置防火墙:
如果系统开启了防火墙,需要打开80端口,以允许外部访问Apache。
特别如果是云服务器,要开放安全组
firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --reload 以上就是基于CentOS 7.5安装Apache的步骤
5.安装配置tomcat 5.1 命令下载tomcat 首先确保已经安装了Java环境。可以通过以下命令检查:
java -version 如果没有安装Java环境,可以通过以下命令安装:
C++是一种高级编程语言,它被广泛应用于软件开发、游戏制作、嵌入式系统等领域。本文将为读者提供一份超详细、超完整的C++教程,帮助初学者掌握C++的基础知识,同时给出十个实例,并一一解释分析。最后,我们将为读者提供一道编程题,并给出解答。
目录:
第一章:C++基础
在本章中,我们将介绍C++的基础语法和数据类型,包括变量、常量、运算符、控制语句等。我们将通过简单易懂的例子来帮助读者理解这些概念,并解释它们在C++编程中的应用。
第二章:函数和数组
在本章中,我们将介绍C++中的函数和数组。我们将讲解如何定义和调用函数,以及如何使用数组存储和处理数据。我们还将给出一些实用的例子,帮助读者更好地理解这些概念。
第三章:指针和内存管理
在本章中,我们将介绍C++中的指针和内存管理。我们将讲解指针的基本概念和使用方法,以及如何使用动态内存分配来管理内存。我们还将给出一些实用的例子,帮助读者更好地理解这些概念。
第四章:面向对象编程
在本章中,我们将介绍C++中的面向对象编程。我们将讲解类、对象、继承、多态等概念,并给出一些实用的例子,帮助读者更好地理解这些概念。我们还将讲解C++中的异常处理和文件操作等高级特性。
第五章:编程练习
在本章中,我们将为读者提供一道编程题,并给出解答。这道题将涉及前面章节中介绍的各种概念和技巧,帮助读者更好地巩固所学知识。
通过本文的阅读,读者将能够全面掌握C++的基础知识,并能够运用所学知识解决实际问题。我们相信,只要勤奋学习,任何人都可以成为一名优秀的C++程序员。
第一章:C++基础 C++是一种面向对象的编程语言,它继承了C语言的基本语法和数据类型,并增加了许多新的特性。在本章中,我们将介绍C++的基础语法和数据类型,包括变量、常量、运算符、控制语句等。我们将通过简单易懂的例子来帮助读者理解这些概念,并解释它们在C++编程中的应用。
我们必须先知道什么是文件头,因为我懒,所以直接上万能文件头框架:
#include<bits/stdc++.h> using namespace std; #define int long long int n; signed main(){ 在这里写你的代码!!! return 0; } 首先,我们来介绍变量和常量。在C++中,变量是用于存储数据的容器,而常量是不可改变的值。变量的定义方式为:类型 变量名 = 值;例如:
int age = 20; //定义一个整型变量age,并赋值为20 常量的定义方式为:const 类型 常量名 = 值;例如: const double PI = 3.14159; //定义一个双精度常量PI,并赋值为3.14159 接下来,我们来介绍C++中的运算符,包括算术运算符、关系运算符、逻辑运算符等。运算符是用于在表达式中执行特定操作的符号。例如:
int a = 10, b = 20; int c = a + b; //使用加法运算符计算a和b的和,赋值给变量 在C++中,控制语句用于控制程序的执行流程,包括条件语句和循环语句。条件语句用于根据条件执行不同的代码块,而循环语句用于重复执行特定的代码块。例如:
if (a > b) { cout << "
2022年11月底,ChatGPT引爆了新一轮AI的革命,也让人们意识到AI真的能够大幅度提高人们的工作效率,甚至有人担心自己的工作会因为AI不保。这种居安思危的意识是正确的,但是正如锛凿斧锯的出现,并没有让木匠这个行业消失,而是让这个行业以更高效的方式工作。所以作为一种工具,我们应当对ChatGPT有一个正确认知,我们不要把自己定位成ChatGPT,而是要站在更为宏观的角度上,将自己定位成利用工具的人,才不会出现被AI淘汰的局面。
那么如何才能更好的利用chatGPT呢?为什么同时利用这种工具,有的人效率高,有的人却感觉没什么用呢?秘密就在如何写好提示词上,本文通过一些最佳实践,帮助大家更好的掌握ChatGPT提示词的使用技巧,让你效率提升,以一敌十。
与ChatGPT交互的基本常识 ”工欲善其事必先利其器“,在我们使用前,还是要对ChatGPT的一些基本原理进行了解,这样才能更好的利用他。
ChatGPT已经通过许多语言的数据进行了训练,但是训练材料中,英语文本的数量要高得多。如果有一定的英语基础,可以直接用英语进行查询,再利用ChatGPT进行翻译成中文,这样得到的结果可能会更准确。虽然如此,但在实际中文处理能力上,ChatGPT表现一点也不弱,所以即使你的英文不好,也不用过分担心,直接用中文进行交流即可。
ChatGPT在输入中可以处理多达4,096个令牌(GPT-3.5,如果是GPT-4可以更多),超过此限制的任何字符都将被忽略,不会有任何消息。一个令牌大致相当于一个单词,具体取决于用例。
如果您注意到ChatGPT正在走错方向,可以随时使用停止按钮停止响应生成。 如果在聊天期间交换了太多的知识,可以启动一个新的聊天,以便后续的回复不会受到破坏。 虽然与ChatGPT聊天有时会感觉几乎像是与人类交流,但“请”和“谢谢”之类的礼貌用语并不必要。 与ChatGPT对话并不需要很高的语言造诣,唯一要做的就是把你的需求说清楚,如果连你自己都说不清楚需求,没有人能知道你想干什么。
技巧一:角色扮演 ChatGPT可以扮演Linux终端、哲学家、品茶师或圣经翻译等多种角色。
这些提示的结构总是相同的:
首先,ChatGPT接收一个提示,告诉它AI应该扮演什么角色。然后提示说明用户提供了什么信息,接着说明AI应该如何处理这些信息,包括大致的指引方向。最后,开发人员在引号中放置第一个具体的指令。
我们以翻译为例,ChatGPT不但可以帮助我们准确的进行翻译,还可以进行优化,比如我们可以这样提问:
我希望你能充当英语翻译、拼写纠正和改进者。我会用任何语言和你交流,你会检测语言、翻译并用修正和改进后的中文回答我的文本。我希望你能用更美丽、更优雅、更高级的中文词汇和句子代替我的简化的A0级词汇和句子。保持意思不变,但使它们更具文学性。我希望你只回复纠正、改进,不要写解释。我的第一句话是“We’ve trained a model called ChatGPT which interacts in a conversational way. The dialogue format makes it possible for ChatGPT to answer follow-up questions, admit its mistakes, challenge incorrect premises, and reject inappropriate requests.”。
通过下面的截图,我们很清楚的看到ChatGPT帮助我们准确的翻译了英文,同时,利用上下文能力,你无须再发出相同的指令,只需要输入新的要翻译的语句,很高效的可以完成大批量翻译工作。
技巧二:明确回复内容的使用目标 明确文本使用的目标,例如,ChatGPT在输出文本作为博客文章、商店页面、LinkedIn帖子、推文、TikTok或YouTube脚本时会有很大的区别,这样ChatGPT能更有效的提供相关信息。例如:
我需要一个有关ChatGPT机会和风险的抖音脚本。使用简短的句子。直接面向观众。要求使用幽默一些的语言,更容易理解
技巧三:合理利用上下文,分批输出 ChatGPT不同于传统AI聊天机器人的一个显著特点就是对于上下文的理解能力,这样可以将一个超级大的问题,分成多次提问,多次返回,避免了由于模型的参数限制导致的输出不完整,最近流行的AutoGPT也是基于这样的思路实现的。
我们以一篇文章为例,可能最简单的连锁提示形式是首先询问文章的结构。然后您可以告诉ChatGPT制定相应的要点。这种方法还可以节省时间:如果您发现AI在大纲中走了错误的路,您可以在生成完整文本之前进行必要的调整。例如:
写一篇关于ChatGPT的文章。首先给我一个由标题、引语和几个副标题组成的大纲。 [输出] 现在为每个副标题编写五个关键信息。 [输出] 为每个副标题的关键信息添加五个关键词。 [输出] ......
技巧四:修改输出内容 利用ChatGPT的上下文能力,您还可以修改已经输出的内容,当然这不会覆盖之前的回答,只会在之前的基础上再作答,甚至一些基本替换操作都可以命令ChatGPT帮你完成。
例如,我们可以利用ChatGPT为不同渠道生成相同的内容,并且表明不同的语气和格式:
示例新浪微博: 将生成的文本分成多个推文。记住每个推文的最大长度为140个中文字符。使用简短的句子,不要将其跨越多个推文。以一致的编号方案开始推文。
示例今日头条: 将生成的文本制作成今日头条帖子。请注意,最大长度为3000个字符。将文本的主要要点结构化为一个项目列表。以一个令人兴奋的引子句开始,以一个呼吁更多参与的行动结束。
DHCP有两种配置模式:
目录
一.全局配置模式
二.接口配置模式
在ENSP上搭好top图如下:左边我用的是10.1.1.0/24网段,右边用的是20.1.1.0/24网段
图中10.1.1.254 和20.1.1.254的地址是全局配置模式的网关地址
配置DHCP需要有:IP,网络掩码,默认网关(gateway-list),DNS
此次实验的DNS选用:左边(PC1,PC2) 61.134.1.4 8.8.8.8(备用DNS)
右边(PC3,PC4)8.8.8.8 8.8..4.4 (备用DNS)
全局配置模式: 步骤:
1.进入接口先配好IP地址(接口地址和网关地址可以选择一样)
2.在系统视图启用DHCP服务
3.创建地址池(上图需要创建两个地址池,一边一个),定义地址池范围
4.创建网关地址
5.创建DNS地址
6.进入接口选择全局模式
配置代码:
[Huawei]sys R1 [R1]user-interface console 0 [R1-ui-console0]idle-timeout 0 0 [R1-ui-console0]q [R1]int g 0/0/0 [R1-GigabitEthernet0/0/0]ip address 10.1.1.254 24 [R1-GigabitEthernet0/0/0]int g 0/0/1 [R1-GigabitEthernet0/0/1]ip address 20.1.1.254 24 [R1]dhcp enable [R1]ip pool 10 [R1-ip-pool-10]network 10.1.1.0 mask 24 [R1-ip-pool-10]gateway-list 10.1.1.254 [R1-ip-pool-10]dns-list 61.134.1.4 8.8.8.8 [R1-ip-pool-10]q [R1]int g 0/0/0 [R1-GigabitEthernet0/0/0]dhcp select global 以上代码则是左边PC1和PC2的DHCP的配置
点击PC1,PC2,点击基础配置,点击DHCP,点击应用
获取当前日期的前一天,可以使用 Java 自带的 Calendar 类,这里提供两种实现方式:
使用 Calendar 类
// 获取 Calendar 实例 Calendar calendar = Calendar.getInstance(); // 设置为当前日期 calendar.setTime(new Date()); // 将日期减去一天 calendar.add(Calendar.DATE, -1); // 获取前一天日期 Date yesterday = calendar.getTime(); 使用 Java 8 新特性 LocalDate
// 获取当前日期 LocalDate today = LocalDate.now(); // 获取前一天日期 LocalDate yesterday = today.minusDays(1); // 转换为 Date 类型 Date date = Date.from(yesterday.atStartOfDay(ZoneId.systemDefault()).toInstant()); 第二种方法使用了 Java 8 中引入的新日期时间 API,可以更方便地进行日期计算,不过需要注意,由于其是在 Java 8 中引入的,如果你的项目使用的是旧版本的 Java,则该方法不可用。
希望能够帮助你解决问题。
访问kubernetes dashboard时提示你的链接不是私密链接
解决方法:
在浏览器页面上,直接键盘输入 :thisisunsafe
不论是chrome还是edge,都可以解决。
1.首先 自定义类 直接复制过去用
package io.bgxt.utis; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.util.Collections; import java.util.Enumeration; import java.util.Map; public class CustomHttpServletRequest extends HttpServletRequestWrapper { private Map<String, String[]> parameterMap; public CustomHttpServletRequest(HttpServletRequest request, Map<String, String[]> parameterMap) { super(request); this.parameterMap = parameterMap; } @Override public String getParameter(String name) { String[] values = getParameterValues(name); if (values != null && values.length > 0) { return values[0]; } return null; } @Override public Map<String, String[]> getParameterMap() { return Collections.
Centos7 搭建 GitLab 一:安装sshd 1.1 安装sshd yum install -y curl policycoreutils-python openssh-server 2.2 接下来我们启用并启动 sshd: systemctl enable sshd systemctl start sshd 2.3 接下来我们配置下防火墙: 2.3.1 打开 /etc/sysctl.conf 文件,在文件最后添加新的一行 net.ipv4.ip_forward = 1 vim /etc/sysctl.conf 2.3.2 启用并启动防火墙 systemctl enable firewalld systemctl start firewalld 2.3.4 防火墙对http放行 firewall-cmd --permanent --add-service=http 2.3.5 重启防火墙 systemctl reload firewalld 二:安装 postfix GitLab 需要使用 postfix 来发送邮件。当然,也可以使用 SMTP 服务器。
2.1 安装postfix yum install -y postfix 打开 /etc/postfix/main.cf 文件,在第 119 行附近找到 inet_protocols = all,将 all 改为 ipv4
要将一个C类网络地址192.189.25.0划分为不同的子网,其子网主机数不超过25台。首先需要确定可以容纳多少个主机的子网掩码,根据题意,需要容纳25个主机,则需要的IP数量为25+2=27个IP地址(其中2个IP地址分别用于网络ID和广播地址)。27可以用二进制表示为11011,需要的二进制位数为5位。因此,子网掩码为255.255.255.248,表示一个子网可以容纳8个IP地址。
根据子网掩码,可以计算出可以划分的子网数量。子网掩码中1的位数即为网络位数,0的位数即为主机位数。对于子网掩码255.255.255.248来说,其中有5个0位,可以容纳2^5=32个子网。但是,由于题目要求每个子网的主机数不超过25台,因此需要舍去可以容纳超过25个主机的子网。即,最少可以分为2^3=8个子网,每个子网可以容纳8个IP地址,其中6个是可用的主机地址。
因此,最少可以分为8个子网,子网掩码为255.255.255.248。
进制是一种数学计数系统,用于表示数字的值和数量。通常使用在数字中的符号数量叫做基数或底数,它定义了该进制中可用的数字。
最常见的是十进制(即基数为10),使用10个不同的符号(0到9)来表示数字的数量。其他的进制包括二进制(基数为2,使用两个符号0和1)、八进制(基数为8,使用符号0到7)和十六进制(基数为16,使用符号0-9、a-f)。不同的进制对应于不同的行业和应用,在计算机科学、电子工程、数学和物理等领域都有广泛的应用。
ipv4 地址(internet protocol version 4)是一个32位二进制数字,通常用十进制表示为四个8位字节组成的形式,每个字节之间使用句点分隔。ipv4地址根据其范围分为以下五类:
- a类地址:以0开头,范围为1.0.0.0 ~ 126.255.255.255,主要用于大型网络。
- b类地址:以10开头,范围为128.0.0.0 ~ 191.255.255.255,适合中等规模的网络。
- c类地址:以110开头,范围为192.0.0.0 ~ 223.255.255.255,主要用于小型网络。
- d类地址:以1110开头,范围为224.0.0.0 ~ 239.255.255.255,用于多播传输。
- e类地址:以1111开头,范围为240.0.0.0 ~ 255.255.255.255,保留未来使用。
其中a、b、c三类地址是最常用的地址类型。根据规定,一个ip地址属于哪种分类取决于其首位数字的范围,不同类别的地址的前缀长度是固定的。这些地址分类规则能够使得它们在计算机网络中有不同的应用。
首先用到cell-mouse-enter和cell-mouse-leave这两个属性, 不清楚的可以看下方链接 elementui
@cell-mouse-enter="moseoverTabel" @cell-mouse-leave="moseoutTabel" 代码展示: // 鼠标移入事件,暂停计时器 moseoverTabel() { // 清除定时器 window.clearInterval(this.timer); }, // 鼠标移出事件,开启自动滚动 moseoutTabel() { this.scrollAutomatic(); }, scrollAutomatic() { //这里判断表格数据过少,就不滚动 if (this.tableData33.length <= 4) { return; } // 计算滚动高度--获取内容区dom var tabelBodyDom = window.document.querySelector( ".table_father_1 .el-table__body" ); //获取滚动条最大滚动高度---156px指内容区的高度 var scrollHiehgt = this.tableData33.length * 39 - 156; // 实现滚动 if (scrollHiehgt > 0) { // 获取实时margin-top var i = 0 - window.getComputedStyle(tabelBodyDom).marginTop.replace("px", ""); // 定时器滚动 this.timer = window.setInterval(() => { //当滚动到最上方时从头开始,否则使 marginTop++ if (i === scrollHiehgt) { i = 0; } tabelBodyDom.
A股上市公司担保数据 一、数据简介 “对外担保”,是指上市公司为他人提供的担保,包括上市公司对控股子公司的担保。“上市公司及其控股子公司的对外担保总额”,是指包括上市公司对控股子公司担保在内的上市公司对外担保总额与上市公司控股子公司对外担保总额之和。被纳入证券监管机构监管的上市公司提供担保事项,从主体上看,担保方包括上市公司及其控制的子公司,被担保方则包括上市公司及其子公司、关联方、无关联第三方等,即,只要是上市公司或其子公司非因自身债务提供的担保均属于提供担保,为自身债务提供担保则不属于,但第三方为上市公司提供担保后要求上市公司提供反担保的,仍属于监管范畴的提供担保。
CnOpenData推出A股上市公司担保数据,包含了担保方、被担保方、担保方式、担保金额、担保期限等字段。
二、时间区间 2001-2022
三、字段展示 四、样本数据 五、数据更新频率 年度各=更新
六、数据来源网站 https://www.cnopendata.com/data/m/recent/listedco-guarantee.html
什么是拼音模块? 拼音模块是一种用于将中文字符转换为拼音表示的工具。它可以将中文文本转换为相应的拼音字符串,方便在程序中进行处理和使用。拼音模块提供了简单易用的接口,可以轻松地实现中文拼音转换功能。
安装拼音模块 首先,我们需要安装拼音模块。在 Node.js 环境中,可以使用 npm 包管理器来安装拼音模块。打开终端或命令行界面,运行以下命令进行安装:
npm install pinyin@alpha --save 使用拼音模块进行中文拼音转换 让我们看一个示例,演示如何使用拼音模块将中文文本转换为拼音表示。首先,我们需要在代码中导入拼音模块:
const pinyin = require('pinyin'); function convertToPinyin(text) { const options = { style: 'normal', // 普通风格,不带声调 heteronym: false // 无多音字模式 }; const result = pinyin(text, options).join(' '); return result; } 在上述代码中,我们使用了拼音模块的 pinyin 函数来进行拼音转换。我们指定了一些选项,例如风格为普通风格,不带声调,以及无多音字模式。然后,我们将拼音结果使用空格连接起来,得到最终的拼音字符串。
现在,我们可以调用 convertToPinyin 函数,将中文文本传递给它,并得到相应的拼音表示:
const chineseText = '你好,世界!'; const pinyinText = convertToPinyin(chineseText); console.log(pinyinText); 到此为止,按照官方文档的步骤就ok了,但是,运行会报错!
根本原因是,导入方法存在问题。
在使用 require 导入模块时,通常会有两种导入方式:默认导出和命名导出。
默认导出:模块直接导出一个默认的值或对象。可以使用以下方式导入: const moduleName = require('module-name'); 命名导出:模块导出多个命名的值或对象。在这种情况下,需要使用大括号 {} 来指定要导入的具体名称。 使用拼音模块的导入需要使用第二种方法导入:
manifest.json 文件是 UniApp 开发中用来配置应用信息的重要文件。通过修改 manifest.json 文件,开发者可以配置应用的名称、图标、启动页面、权限等信息。本文将为您提供详细的教学,介绍如何使用 manifest.json 文件进行应用配置,并提供示例代码帮助您更好地理解。
步骤1: 创建 manifest.json 文件 在您的 UniApp 项目根目录下,创建一个名为 manifest.json 的文件。这个文件将包含您的应用的配置信息。
示例代码:
{ "name": "MyUniApp", "description": "这是一个使用 manifest.json 进行配置的 UniApp 示例应用", "app-plus": { "id": "com.example.myuniapp", "name": "My UniApp" }, "pages": [ "pages/index/index", "pages/about/about" ], "window": { "navigationBarTitleText": "UniApp 示例应用", "navigationBarBackgroundColor": "#ffffff", "navigationBarTextStyle": "black", "backgroundTextStyle": "dark" }, "tabBar": { "color": "#999999", "selectedColor": "#007aff", "list": [ { "pagePath": "pages/index/index", "text": "首页", "iconPath": "static/tabbar/home.png", "selectedIconPath": "static/tabbar/home-selected.png" }, { "