对于给定授权网站的渗透,可以通过漏洞扫描工具进行扫描,也可以通过手工挖掘,特别是获取sql注入漏洞,通过注入漏洞配合其它漏洞来逐步获取webshell,甚至服务器权限,在本文中涉及详细信息收集、sql注入、后台密码加密分析、redis漏洞利用等,算是一篇经典的手工漏洞挖掘渗透案例,具有学习价值。
1.1信息收集 1.域名信息收集
(1)nslookup查询
通过nslookup对 qd.******.*****.cn进行查询,如图1所示,获取的信息是cdn,无法获取真实IP地址信息,后面通过https://www.yougetsignal.com/tools/web-sites-on-web-server/进行域名查询,每次查询的域名对应IP地址结果都在变化,说明用了cdn加速技术。
图1dns查询
(2)toolbar.netcraft.com
还以用toolbar.netcraft.com进行检测:https://toolbar.netcraft.com/site_report?url=qd.******.*****.cn#last_reboot,其结果如图2所示,IP地址为122.72.**.1**。
图2toolbar查询ip地址
2.获取真实IP地址
目标站点**.******.*****.cn使用账号和密码(1773**5216 /zyl**29122)进行登录,通过burpsuite进行抓包,发现有一个获取websocket url的ajax请求:
ws://***.**.**.**:1234?uid=304519&subscribe=1&ticks=636570586031103379&stock=&key=89853473962f954c0c9aa96e13f55f22
3.使用masscan进行端口扫描
(1)masscan安装
git clone https://github.com/robertdavidgraham/masscan.git
cd masscan
make
make install
(2)使用masscan扫描目标所有端口地址
masscan -p 1-65535 ***.**.**.** 扫描后可以看到其端口开放情况,如图3所示。
图3端口开放情况
通过实际访问,1234、1235和7780对外提供web服务,61315为远程终端,3357和26379经过telnet或者nc 发送keys *,能确定其中有两个redis端口,其中3357端口是redis并且存在认证,通过auth “123456” 简单尝试弱口令失败。
4.获取物理路径信息
输入地址**.********.com/Integral/My/ProductDetail.aspx?id=1在出错信息中获取其真实目录地址为d:\www\font\Plugins\IntegralMall.Plugins\Integral\My\ProductDetail.aspx,如图4所示。
图4获取真实地址信息
1.2sql注入 1.主站登录框注入
通过burpsuite对登录过程进行抓包,发现其存在sql注入,构造playload进行测试:
POST /account/Login HTTP/1.1
Host: www.******.*****.cn
Content-Length: 97
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://www.******.*****.cn
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门
💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博主哦🤞 Spark Shuffle Map 和 Reduce 在Shuffle过程中. 提供数据的称之为Map端(Shuffle Write) 接收数据的 称之为 Reduce端(Shuffle Read) 在Spark的两个阶段中, 总是前一个阶段产生 一批Map提供数据, 下一阶段产生一批Reduce接收数据。 Spark 提供2种Shuffle管理器: • HashShuffleManager • SortShuffleManager 优化后 基本和未优化的一致,不同点在于 1. 在一个Executor内, 不同Task是共享Buffer缓冲区 2. 这样减少了缓冲区乃至写入磁盘文件的数量, 提高性能 SortShuffleManager SortShuffleManager的运行机制主要分成两种,一种是普通运行机制,另一种是bypass运行机制。 bypass运行机制的触发条件如下: 1)shuffle map task 数量小于 spark.shuffle.sort.bypassMergeThre shold=200 参数的值。 2) 不是聚合类的 shuffle 算子 ( 比如 reduceByKey) 。 同普通机制基本类同 , 区别在于 , 写入磁盘临时文件的时候不会在内 存中进行排序 而是直接写 , 最终合并为一个 task 一个最终文件 所以和普通模式 IDE 区别在于 : 第一,磁盘写机制不同; 第二,不会进行排序。也就是说,启用该机制的最大好处在于, shuffle write 过程中,不需要进行数据的排序操作,也就节省掉了 这部分的性能开销。 1.
Vue.js是一个渐进式JavaScript框架,它以其简洁的数据绑定和组件系统而闻名。在构建具有多个组件层次的Vue应用时,组件间的通信成为一个关键的话题。Vue提供了一种名为$emit的方法,允许子组件向父组件发送消息。本文将详细介绍如何在Vue中使用$emit方法,以及如何在父组件中监听这些事件。
什么是$emit? $emit是Vue实例的一个方法,它用于触发自定义事件。这些事件可以被父组件监听到,从而实现子组件向父组件的通信。这种方法的好处在于,它可以让数据的流动保持单向,有助于维护组件之间的清晰界限。
如何触发事件 在子组件中,你可以通过调用this.$emit('event-name', payload)来触发一个事件。'event-name'是你想要触发的事件名称,而payload是你想要随事件发送的数据。下面是一个简单的例子:
// ChildComponent.vue <template> <button @click="sendToParent">Click Me!</button> </template> <script> export default { methods: { sendToParent() { // Trigger an event named 'custom-event' with some data this.$emit('custom-event', { message: 'Hello from the child component!' }); } } } </script> 在这个例子中,当用户点击按钮时,sendToParent方法会被调用,并触发一个名为custom-event的事件,同时传递一个包含消息的对象作为载荷。
如何监听事件 在父组件中,我们可以使用v-on指令(或其缩写@)来监听子组件触发的事件。在父组件的模板中,你需要在子组件的标签上添加监听器。
// ParentComponent.vue <template> <child-component @custom-event="handleCustomEvent"></child-component> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, methods: { handleCustomEvent(payload) { console.log('Event received!
文章目录 第1关:机器人操控(一)第2关:机器人操控(二)第3关:机器人操控(三)第4关:机器人操控(四) 第1关:机器人操控(一) 示例代码如下:
#coding=utf-8 from Robot import Robot def drive(robot:Robot): ###### Begin ###### robot.SteerRightForward(2) robot.SteerLeftForwad(1.25) robot.Forward(1.9) ###### end ###### return 第2关:机器人操控(二) 示例代码如下:
#coding=utf-8 from Robot import Robot def drive(robot:Robot): ###### Begin ###### robot.Forward(3.38) robot.Stop() robot.PickUp() ###### end ###### return 第3关:机器人操控(三) 示例代码如下:
#coding=utf-8 from Robot import Robot def drive(robot:Robot): ###### Begin ###### robot.SteerLeftForwad(0.8) robot.Forward(1) robot.SteerRightForward(1.2) robot.SteerLeftForwad(0.3) robot.Forward(0.92) robot.Stop() robot.PickUp() ###### end ###### return 第4关:机器人操控(四) 示例代码如下:
#coding=utf-8 from Robot import Robot def drive(robot:Robot): ###### Begin ###### robot.
目 录
摘要 1 绪论 1.1 研究背景及意义 1.2国内外研究现状 1.3系统开发的内容 1.4论文结构与章节安排 1.5小程序框架以及目录结构介绍 2 网上书城小程序系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分析 3.4本章小结 3 网上书城小程序总体设计 3.1 系统架构设计 3.2 系统模块设计 3.3 数据库设计 3.3.1 数据库概念结构设计 3.3.2 数据库逻辑结构设计 3.4本章小结 4 网上书城小程序详细设计与实现 4.1用户功能模块 4.2管理员功能模块 5系统测试 5.1 系统测试用例 5.2 系统测试结果 结论 参考文献 致 谢 摘要
自小程序诞生以来,大受广大开发者追捧,它是一种新的开放能力,它可以在微信内被便捷的获取和传播,拥有出色的用户使用体验。本设计旨在倡导全民阅读、发现好书和读透好书,提供最新图书资讯,拓展并培养读者阅读爱好,并为广大书虫提供交流和学习平台。
本文针对网上书城小程序进行研究分析,然后开发设计出网上书城小程序以解决问题。网上书城小程序主要功能模块包括:商城管理(书籍商城、分类列表、订单列表)资源管理(书籍资讯、资讯分类列表)系统用户(管理员、会员用户)等功能模块,采取本系统此次设计前端视图界面选择Java开发语言来完成,系统功能设计采取MySQL作为后台数据的主要存储单元,采用Springboot框架进行系统的开发,实现了本系统的全部功能。本次报告,首先分析了研究的背景、作用、意义,为研究工作的合理性打下了基础。针对网上书城小程序的各项需求以及技术问题进行分析,证明了系统的必要性和技术可行性,然后对设计系统需要使用的技术软件以及设计思想做了基本的介绍,最后来实现网上书城小程序和部署运行使用它。
关键词:Java;MYSQL;网上书城
Abstract
Since the birth of the small program, it has been greatly sought after by the majority of developers.
目录
一、影院管理项目
二、外观模式
(一)基本介绍
(二)原理类图
(三)解决影院管理
(四)注意事项和细节
(五)外观模式在MyBatis框架应用的源码分析
一、影院管理项目 传统方式解决影院管理就是直接用一个类来操作各个设备,类似代码如下:
ClientTest { public static void main() { //1. 创建相关的对象 //2. 调用创建的各个对象的一系列方法 // 3. 调用DVDPlayer 对象的play方法 } } 分析:
1) 在 ClientTest 的 main 方法中,创建各个子系统的对象,并直接去调用子系统 ( 对象 )相关方法,会造成调用过程混乱,没有清晰的过程 2) 不利于在ClientTest 中,去维护对子系统的操作 3) 解决思路:定义一个高层接口,给子系统中的一组接口提供一个 一致的界面 ( 比 如在高层接口提供四个方法 ready, play, pause, end ) ,用来访问子系统中的一群接口 4) 也就是说 就是通过定义一个一致的接口 (界面类) ,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节 => 外观模式 二、外观模式 (一)基本介绍 1) 外观模式( Facade ),也叫“过程模式:外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用 2) 外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节 (二)原理类图 1) 外观类(Facade): 为调用端提供统一的调用接口, 外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当子系统对象 2) 调用者(Client): 外观接口的调用者 3) 子系统的集合:指模块或者子系统,处理Facade 对象指派的任务,他是功能的实际提供者 外观模式可以理解为转换一群接口,客户只要调用一个接口,而不用调用多个接口才能达到目的。比如:在pc 上安装软件的时候经常有一键安装选项(省去选择安装目录、安装的组件等等),还有就是手机的重启功能 (把关机和启动合为一个操作)。 外观模式就是解决多个复杂接口带来的使用 困难,起到简化用户操作的作用 (三)解决影院管理 类图如下:
题目描述:
给定一个二叉树,每个节点上站着一个人,节点数字表示父节点到该节点传递悄悄话需要花费的时间。
初始时,根节点所在位置的人有一个悄悄话想要传递给其他人,求二叉树所有节点上的人都接收到悄悄话花费的时间。
输入描述:
给定二叉树 0 9 20 -1 -1 15 7 -1 -1 -1 -1 3 2
注:-1表示空节点
输出描述:
返回所有节点都接收到悄悄话花费的时间38
补充说明:
示例1
输入:
0 9 20 -1 -1 15 7 -1 -1 -1 -1 3 2 输出:
38 说明:
1. 使用Docker镜像 1.1 获取镜像 主要命令:
docker pull NAME[:TAG]
NAME 为镜像名称,后跟:版本号,如果没有跟后面的版本号,默认拉取最新的稳定版本
例子:
上述命令相当于:docker.io/library/ubuntu:latest
1.2 查看镜像信息 使用images查看已有镜像 docker images
支持子命令如下:
使用tag命令添加镜像标签 docker tag [已有镜像] [新镜像名]
整体来说,docker tag命令添加的标签实际上起到了类似链接的作用.
使用inspect查看详细信息 docker inspect [镜像名]
可以使用-f来指定主要获取的属性。
docker inspect -f {{“.Architecture”}}
使用history查看历史镜像 docker history [镜像名]
1.3 搜索镜像 docker search [名称]
支持的命令:
名称默认作用–automatedfalse仅显示自动创建的镜像–no-truncfalse输出信息不截断-s,–star0指定星级以上的镜像 1.4 删除镜像 docker rmi [镜像名]
如果你正在使用一个容器,该镜像无法删除
此刻你可以使用-f参数来强行删除,但是这并不正确,默认情况您要先停止容器,删除容器,再删除镜像,
1.5 创建镜像 docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
OPTIONS内容:
-a,–author=“”,表示作者信息-c,–change=[],表示提交时候执行的DockerFile指令-m,–message=“”,表示消息-p,–pause=true,表示提交时暂停容器运行 首先启动一个容器:
接着执行:
查看到有test标签为0.1的镜像即为成功。
本地模板导入 cat [本地模板] | docker import - [自己定义的镜像名]
语言:Python
框架:django/flask可以定制
软件版本:python3.7.7
数据库:mysql 数据库工具:Navicat
开发工具pycharm/vscode都可以
前端框架:vue.js
系统使用过程主要涉及到管理员和用户两种角色,主要包含个人中心、用户管理、商品类别管理、热卖商品管理、投诉建议、系统管理、订单管理等功能。
系统开发主要在 Windows 系统下进行,采用支持跨平台的 python语言开发完成,因此可以运行在任意开发环境下。系统采用mysql数据库和B/S结构的方式,按照django框架进行开发。2、重点及难点:
(1) 系统的接口连接
(2) 如何设计系统中的各类操作界面,使其更易于用户使用与操作
(3) 怎么很好的设计各类用户的权限
(4) 数据库的设计和模块之间的动态连接
(5) 如何建立一个合理有效,查询速度快的数据库
(6) 怎样创建有效的操作数据库,并且能够快速无误的进行数据的读写
(7) 如何组织系统,怎样去提高程序运行的效率
对购物商城管理的流程进行科学整理、归纳和功能的精简,通过软件工程的研究方法,结合当下流行的互联网技术,最终设计并实现了一个简单、易操作的购物商城系统。内容包括系统的设计思路、系统模块和实现方法。综合购物商城管理经历和对网上信息归纳整理的结果,在实际应用中,将用户分为两种:管理员和用户两个角色。其中用户可以操作的内容是有限的,管理员可以进行的操作最多。了解系统用户的分类以及可以进行的操作,对于接下来实现相关的功能具有重要的意义。
关键词:购物商城; B/S结构; MySQL
目 录
第一章 绪 论 1
1.1研究背景 1
1.2系统研究现状 1
1.3研究意义 2
第二章 系统开发技术 3
2.1 python语言 3
2.2 django框架简介 3
2.3 MySQL数据库技术 4
2.4 B/S架构 4
第三章 需求分析 6
3.1需求描述 6
3.2系统角色需求分析 6
3.3系统功能需求分析 6
3.4非功能性需求分析 7
3.4.1 先进性 8
STM32CubeMX学习(二) USB CDC 双向通信 简介CubeMX新建工程(串口+LED)测试串口和LED串口接收测试USB CDC通信 简介 利用正点原子F407探索者开发板,测试基于USB CDC的双向数据通信。
CubeMX新建工程(串口+LED) 设置时钟源
设置调试器
设置LED
设置串口
设置USB OTG
Pinout预览
工程管理
在上图里,可以把Heap Size和Stack Size改大点,使得USB数据通信更流畅。
选中红框里的选项主要是为了工程打包后给他人直接使用。
最后点击GENERATE CODE生成工程。
测试串口和LED 在usart.h中引入头文件stdio.h
/* USER CODE BEGIN Includes */ #include "stdio.h" //引入此文件,为重定向printf /* USER CODE END Includes */ 在usart.c中添加重定向代码
/* USER CODE BEGIN 1 */ // 重定向printf函数 int fputc(int ch,FILE *f) { uint8_t temp[1]={ch}; HAL_UART_Transmit(&huart1,temp,1,2); return 0; } /* USER CODE END 1 */ 为了方便调试,在main.c中加入以下宏定义
/* USER CODE BEGIN PD */ #define USER_MAIN_DEBUG #ifdef USER_MAIN_DEBUG #define user_main_printf(format, .
1--安装指令 sudo yum install epel-release sudo yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm sudo yum install ffmpeg ffmpeg-devel ffmpeg -version 2--版本信息
目标是为了完成小区团购平台的设计和实现,在疫情当下的环境,方便小区业主购入生活所需,减小居民的生活压力
采用B/S模式架构系统,开发简单,只需要连接网络即可登录本系统,不需要安装任何客户端。开发工具采用VSCode,前端采用Vue+ElementUI,后端采用Node.js,数据库采用MySQL。
涉及的技术栈
1) 前台页面:
页面结构布局采用Vue框架,可能会使用到第三方组件库Element-ui或View Design组件库、axios发送请求、html和less语法。
2) 后台服务器:
服务器搭建采用基于node的Express框架快速搭建服务器,需要引入mysql模块进行对数据库的操作
3) 数据库:
mysql数据库,Navicat可视化工具辅助操作数据库 1. 系统前台:
用户的账号注册与登录:用户需要先进行账号密码的注册,才能进行平台的登录。
商品的查找与浏览:用户可以用搜索的功能,对所需商品进行查询,可以浏览商品的基本信息。
商品购买:用户可以对想购买的商品进行下单以及对不想要的进行取消订单
2. 系统后台:
商品管理:管理员对商品的的增删改查
用户管理:管理员对用户信息的管理,如信息查询和修改
订单管理:管理员对用户订单的增删改查
该系统的有点在于,方便小区居民在疫情期间购进生活所需,减小接触传染风险。
运行软件:vscode
前端nodejs+vue+ElementUi
语言 node.js
框架:Express/koa
前端:Vue.js
数据库:mysql
开发软件:VScode/webstorm/hbuiderx均可
干城小区团购平台,主要的模块包括管理员;系统首页、个人中心、用户管理、商品类别管理、热卖商品管理、系统管理、订单管理,用户;系统首页、个人中心、我的收藏管理,前台系统首页;首页、热卖商品、优惠资讯、后台管理、在线客服、购物车、个人中心等功能。系统中管理员主要是为了安全有效地存储和管理各类信息,还可以对系统进行管理与更新维护等操作,并且对干城小区团购平台有相应的操作权限。这种个性化的平台特别注重交互协调与管理的相互配合,激发了管理人员的创造性与主动性,对干城小区团购平台而言非常有利。本次课题做的是:干城小区团购平台的设计与实现
软件采用B/S结构,软件系统前台主要实现的功能是:用户的注册与登录,商品的查找与浏览,商品的购买。后台实现的功能是:商品管理,用户管理,订单管理。
目 录
第一章 绪 论 1
1.1背景及意义 1
1.2国内外研究概况 2
1.3 研究的内容 2
第二章 关键技术的研究 3
2.1 相关技术 3
第三章 系统分析 5
3.1 系统设计目标 6
3.2 系统可行性分析 6
3.3 系统功能分析和描述 7
3.4系统UML用例分析 8
3.4.1管理员用例 9
目录
准备数据
在 Dev Tools 里进行查询
基本语法
ES|QL 源命令
查询数据
针对 ip 进行搜索:
文本搜索
计算值
使用 DISSECT
使用 GROK
聚合
编辑
创建直方图
针对数字字段的桶分析
丰富数据
元数据运用
ES|QL 多值字段
在 Discover 中进行查询
Clean up
这篇文章是继我昨天完成的文章 “Elasticsearch:ES|QL 函数及操作符” 的另外一篇文章。我将继续使用之前文章 “Elasticsearch:ES|QL 快速入门” 中的例子来结合 ES|QL 函数来做更进一步的展示。希望能对之前的文章做一个更进一步的展示。在这里,我将主要使用 Dev Tools 来进行展示。
特别值得注意的是:在进行如下的例子之前,你需要至少安装 Elastic Stack 8.11 及以上版本。
准备数据 我们还是仿照之前的文章里的例子来进行展示。我个人比较喜欢较少的文档做为例子来进行展示。这里的原因是,文档较少,容易设置,同时容易看清。只要能说明问题,就是好的例子。针对之前的 DSL 查询,我们可以参阅以前的文章 “开始使用 Elasticsearch (2)”。里面展示的文档也不是很多。
我们先到 Dev Tools 里打入如下的命令:
PUT sample_data { "mappings": { "properties": { "client.ip": { "
课题主要分为两大模块:即管理员模块和用户模块,主要功能包括个人中心、用户管理、菜品类型管理、菜品信息管理、留言反馈、在线交流、系统管理、订单管理等;
运行软件:vscode
前端nodejs+vue+ElementUi
语言 node.js
框架:Express/koa
前端:Vue.js
数据库:mysql
开发软件:VScode/webstorm/hbuiderx均可
前台页面:若进入本网站,需要注册自己的账号和密码,输入正确的账号和密码,用户才可以进入网上订餐系统主页面进行操作,进入订餐管理页面后,用户可以在搜索栏中对自己想要的订餐信息进行查看或收藏,在个人中心用户可以修改自己的个人详细信息。
后台管理页面:主要是管理员登录本系统。管理员输入用户名和密码后,校验无误后方可进入后台管理主界面,对用户使用的权限管理,设置用户等管理以及对系统信息进行管理。
采用B/S模式架构系统,开发简单,只需要连接网络即可登录本系统,不需要安装任何客户端。开发工具采用VSCode,前端采用Vue+ElementUI,后端采用Node.js,数据库采用MySQL。
涉及的技术栈
1) 前台页面:
页面结构布局采用Vue框架,可能会使用到第三方组件库Element-ui或View Design组件库、axios发送请求、html和less语法。
2) 后台服务器:
服务器搭建采用基于node的Express框架快速搭建服务器,需要引入mysql模块进行对数据库的操作
3) 数据库:
mysql数据库,Navicat可视化工具辅助操作数据库 快速发展的社会中,人们的生活水平都在提高,生活节奏也在逐渐加快。为了节省时间和提高工作效率,越来越多的人选择利用互联网进行线上打理各种事务,通过线上管理订餐也就相继涌现。与此同时,人们开始接受方便的生活方式。他们不仅希望页面简单大方,还希望操作方便,可以快速锁定他们需要的订餐管理方式。基于这种情况,我们需要这样一个界面简单大方、功能齐全的系统来解决用户问题,满足用户需求。为了实现当前网络的分析功能和便利性,网上订餐系统使管理员和用户能够在平台上直接查看他们需要的数据信息,不仅可以节省管理时间,还可以改变传统的管理模式。如果用户想要交换信息,他们需要满足双方交换信息的需要。由于时间有限,很难亲自会面和沟通,因此很难满足用户的需求。因此,迫切需要开发一个网上订餐系统,以满足用户的需求,提高用户的使用率。网上订餐系统必须更快、更有效地向用户或潜在用户提供信息。为网上订餐系统建立更好的沟通平台,提高用户信息交流的服务效率。该系统可以满足大多数用户提出的问题,用户可以根据自己的需要获得相应的服务,为网上订餐系统提供了一条快捷的途径。
关键词:订餐;简洁方便直观; 摘 要 1
Abstract 2
目录 1
1绪论 3
1.1 研究背景 3
1.2国内外研究现状 3
1.2.1国内研究现状 3
1.2.2国外研究现状 3
1.3研究的目的和意义 3
1.3.1研究目的 3
1.3.2 研究意义 4
1.4 论文的内容和结构 4
2系统相关技术概述 5
2.3 Mysql数据库 5
2.4 B/S结构 6
3系统需求分析 7
3.1需求分析概述 7
3.2系统可行性分析 7
3.2.1技术可行性 7
讲时间管理的书很多,但这本是专门讲给管理者的时间管理。
在职场中,许多管理者都会碰到工作计划执行不下去、组织目标难于实现的问题,搭进了自己所有可以支配的时间,仍旧是焦头烂额,顾此失彼;而下属则因为被授权的层次过低,乐得静候差遣,无事一身轻。
为了避免授权失灵、管理不当,管理者应该将注意力放在任务指派、分配与掌控猴子的工作上——主管必须与下属一起协同照顾并且负担起喂养猴子的责任。
如何避免猴子跳到背上 避免猴子源源不断的跳上来,首先需要搞清楚猴子是从哪里、怎么跑过来的。书中用了很多实例描述猴子跳到背上的场景,非常形象。总结起来,大部分原因是混淆了问题的归属/责任人。下属提出问题,并有意无意的将管理者划为问题的责任人,于是猴子就抛给上级去照看了,自己只需要等待结果即可。
认识清楚了这一点,可以更清楚的定义“猴子”的概念:猴子就是两人谈话结束时的下一个行动步骤,即PDCA中的A(Action)。所以管理者需要认识到,无论问题是什么,下属永远是承接下一步骤的一方,他背上的猴子必须待在他那里。
和教育孩子一样,管理者需要采取一些行动,让下属没有选择1、2自由层级的机会,推动其将自由层级提高到3级以上;同时,保证猴子待在下属背上的同时,需要通过业务对话的动作,保证猴子不被饿死(任务得到推进)。书中对此也给出了一些建议,如利用好工作内容报告、共识任务的自由层级、授之以渔而非授之以鱼等。
如何喂养猴子 确定了猴子的归属,还需要明确照顾猴子的责任,要达到的效果是:给予下属明确的行动自由,足以让猴子存活,却不足以让猴子茁壮成长,这样才能让下属和猴子在喂养的过程中共同成长。书中提出了6大原则,帮助管理者实现上述目标。
规则1:不要让猴子活活饿死,要么喂养,要么射杀。规则2:不要让猴子过量。 上面两条规则有一定的相关性。就像我们经常讲好的产品需要聚焦一样,领导和员工的可支配的时间无法无限增长,如果产生的猴子过多,最终的结果必然是有很多猴子无法得到照顾,会被饿死,散发出异味,影响整体环境。因此,管理者需要控制猴子的总量,确保其数量在可负荷范围内;对于选出的猴子进行喂养,其余的杀掉。对于需要喂养的猴子,明确其归属,和下属沟通喂养的优先程度,明确喂食进度表。
规则3:喂养猴子的责任必须落在下属身上。 明确了猴子的归属后,管理者需要放手,因为按照进度表的时间地点喂猴子是下属的责任,管理者不应该再沿途追逐即将饿死的猴子,胡乱喂食。管理者需要做的只是按照检查喂食进度表,确认没有猴子被饿死。
规则4:更改预定的喂食时间需要双方沟通同意;事情没有进展不能作为重新安排时间的借口。 重点在后半句:如果事情没有进展可以作为重新安排喂食时间的借口,那人的惰性往往会导致喂食一拖再拖,然后猴子被饿死。类似的事情在我们日常工作中可以说屡见不鲜。管理者坚持这个原则,才是对下属和猴子的负责。
规则5:尽可能面对面喂养猴子,避免遭到误解。 很多管理者出于忙碌或偷懒的原因,忽视了面谈的重要性,代之以邮件、备忘录等间接的形式进行沟通。这种间接的方式很容易造成误解和误用,因为一方面有些文字会让人产生模棱两可的理解,另一方面“弦外之音”(真正需要了解的内容)很难通过面对面以外的方式表现出来。
规则6:展开即时的对话。 企业应以活动为中心,所以活动才是有意义的。即时的对话有助于管理者快速掌握喂养结果的中心主旨,从而确定下一个步骤——为了要达成目标所需采取的特定行动。下一步骤应以可量化的语句来表达,执行时的不确定度才会降低,表现才能改进。
总结 回顾这本书的整个内容,其实都是在讲如何明确管理者的定位。管理者需要明确自身的工作职责,不要让本该属于下属的问题落到自己身上,通过辅导下属提高自由层级的方式来帮助其提升,同时推进问题解决。处理问题的6个原则则很好的说明了正确执行业务对话和PDCA的方式。
目录
一、什么是迁移学习
二、迁移学习和VAE
三、迁移学习的分类
3.1 按迁移内容分类:
3.2 按迁移方法分类:
3.3 按学习形式分类:
3.4 按目标域有无标签分类:
3.5 按学习方法分类:
3.6 按特征分类:
四、迁移学习的应用场景
五、迁移学习的举例
一、什么是迁移学习 迁移学习(Transfer Learning)是机器学习中的一种方法,它的核心思想是利用已有的知识或模型,来帮助解决新的、相关的问题。换句话说,迁移学习允许我们将一个已经训练好的模型作为起点,针对新的任务进行微调,而不是从头开始训练一个新的模型。这种方法可以节省大量的时间和计算资源,尤其是在新任务与原始任务有相似之处时。
用一个通俗易懂的比喻来解释:假设一个人已经学会了弹钢琴,现在想要学习弹吉他。虽然钢琴和吉他是两种不同的乐器,但它们之间也有一些共通之处,比如都需要掌握基本的音乐理论和节奏感。因此,这个人可以利用之前学习钢琴的经验,更快地学会弹吉他。这里,弹钢琴的经验就相当于预训练模型,而弹吉他则是新的任务。迁移学习的过程就是将弹钢琴的技能迁移到弹吉他上,从而加速学习进程。
在实际应用中,迁移学习通常涉及以下几个步骤:
选择一个预训练模型:这个模型通常是在大量数据上训练得到的,具备很强的泛化能力。对预训练模型进行微调:根据新任务的需求,对预训练模型的某些层进行调整或优化。训练和调整模型:使用新任务的数据集对模型进行训练,并根据性能表现进行调整。评估模型:使用测试集评估模型的性能,确保模型在新任务上具有良好的表现。 迁移学习的应用场景非常广泛,包括图像识别、自然语言处理、语音识别等领域。通过迁移学习,我们可以充分利用已有的知识和资源,更快地解决新问题,推动人工智能技术的发展和应用。
二、迁移学习和VAE 迁移学习和变分自编码器(VAE)是两种不同但相关的机器学习技术。它们之间的联系和区别如下:
联系:
知识迁移:迁移学习和VAE都涉及到知识或特征的迁移。在迁移学习中,我们利用预训练模型的知识来帮助解决新任务;而在VAE中,编码器学习到的潜在空间表示可以被解码器用于生成新的数据,这也可以看作是一种知识的迁移。特征提取:VAE通常用于无监督学习,通过编码器从输入数据中提取有用的特征。这些特征可以被用于后续的监督学习任务,类似于迁移学习中利用预训练模型进行特征提取。 区别:
目标不同:迁移学习的目标是利用已有的知识来解决新的、相关的问题,而VAE的目标是学习数据的潜在空间表示并生成新的数据。方法不同:迁移学习通常涉及到对预训练模型的微调或使用其进行特征提取,而VAE则通过编码器和解码器的结构来学习数据的生成模型。应用场景不同:迁移学习广泛应用于各种监督学习任务,如图像分类、自然语言处理等;而VAE则更多用于无监督学习任务,如数据生成、降维等。模型结构不同:迁移学习中的预训练模型可以是任何类型的神经网络,而VAE则具有特定的模型结构,包括编码器、解码器和潜在变量。 虽然迁移学习和VAE都涉及到知识的迁移和特征提取,但它们在目标、方法、应用场景和模型结构等方面存在显著的差异。
三、迁移学习的分类 迁移学习可以根据不同的标准进行分类,以下是一些常见的分类方式:
3.1 按迁移内容分类: 知识迁移:从一个任务或领域中学到的知识应用到另一个任务或领域中。技能迁移:从一个任务或领域中学到的技能应用到另一个任务或领域中。任务迁移:从一个任务中学到的经验应用到另一个任务中。基础迁移:从一个领域或知识体系中学到的基础知识应用到另一个领域或知识体系中。形式迁移:从一种形式、媒介或表达方式中学到的技能或知识应用到另一种形式、媒介或表达方式中。概念迁移:从一种概念或理论框架中学到的知识应用到另一种概念或理论框架中。语言迁移:从一种语言中学到的知识或技能转化到另一种语言中。环境迁移:从一个环境中学到的知识或技能应用到另一个环境中 3.2 按迁移方法分类: 数据分布自适应:通过一些变换,将不同的数据分布的距离拉近,包括边缘分布自适应、条件分布自适应、以及联合分布自适应。特征选择法:选择出源域和目标域共享的特征,即可依据这些特征构建模型。子空间学习法:假设源域和目标域数据在变换后的子空间中会有着相似的分布,包括基于统计特征变换的统计特征对齐方法,以及基于流形变换的流形学习方法。 3.3 按学习形式分类: 离线迁移学习 (Offline Transfer Learning):源域和目标域均是给定的,迁移一次即可。在线迁移学习 (Online Transfer Learning):数据的动态加入,迁移学习算法也可以不断地更新。 3.4 按目标域有无标签分类: 监督迁移学习:目标域数据有标签。半监督迁移学习:目标域数据中部分有标签。无监督迁移学习:目标域数据无标签。 3.5 按学习方法分类: 基于样本的迁移学习方法(权重重用)。基于特征的迁移学习方法(变换特征到表征一致的空间,或者使其相似)。基于模型的迁移学习方法(参数共享)。基于关系的迁移学习方法(挖掘和利用关系进行类比迁移,研究较少)。 3.6 按特征分类: 同构迁移学习:特征语义和维度都相同。异构迁移学习:特征语义和维度都不同,如图片到文本的迁移。 这些分类方式有助于我们理解和应用迁移学习的不同方面,从而在实际问题中选择合适的方法和技术。
四、迁移学习的应用场景 迁移学习的应用场景十分广泛,可以应用于自然语言处理、图像识别、推荐系统等多个领域。
在自然语言处理中,通过迁移学习,可以利用已经学习到的知识或技能更快地理解新的语言,从而更好地完成翻译或文本分类等任务。在图像识别中,迁移学习可以帮助我们利用已经学会的模型在新的领域中快速进行识别,例如将动物园中的物种识别模型应用到野外环境中。迁移学习也可以应用于推荐系统,将用户的历史行为信息进行迁移,从而更好地推荐相似的商品或服务。 此外,当拥有海量的数据资源时,机器学习系统可以很容易地从海量数据中学习到一个很稳健的模型,自然不需要迁移学习。然而,通常情况下,很少有人从头到尾训练一个深度卷积网络,原因可能是数据量问题、时间成本和计算资源的问题。在这种场景中,迁移学习就显示出了其巨大的价值。例如,假设有两个任务系统A和B,任务A拥有海量的数据资源且已经训练好,但任务B才是目标任务,这种场景便是典型的迁移学习的应用场景。
另外,基于迁移学习技术,互联网公司可以将旗下的视频、电商业务场景智能推荐知识迁移至广告、应用程序等其他产品的推荐业务中。一些电子产品的用户评价模型也可用于视频、游戏等产品的舆情分析中。这些案例都充分展示了迁移学习在实际应用中的巨大潜力和价值。
五、迁移学习的举例 让我们选择一个相对简单的场景:图像分类,并使用迁移学习来提高模型的性能。以下是一个使用Python和TensorFlow的代码片段,展示了如何使用预训练的模型(例如VGG16)进行迁移学习。
import tensorflow as tf from tensorflow.
广告和推荐算法的技术框架比较相似,在线计算时都分为召回(candidates generating)和排序(candidates ranking)两个阶段(这似乎是计算资源有限条件下,所有检索问题的通用架构)。
在某角度上可以把推荐系统理解成计算广告的一部分。不考虑品牌广告等其他广告形式,在我看来,计算广告和推荐系统的联系在于业务上的融合和技术上的重合。
搜推广要解决的问题区别:
回到根本问题上来,三个方向解决的问题本身是不一样的
广告:一个公司要搭建广告系统,它的商业目的非常直接,就是要解决公司的收入问题。所以广告算法的目标就是为了直接增加公司收入。
推荐:推荐算法虽然本质上也是为了增加公司收入,但其直接目标是为了增加用户的参与度。只有用户的参与度高了,才能让广告系统有更多的inventory,进而增加公司营收。
搜索:搜索要解决的关键问题全部是围绕着用户输入的搜索词展开的。虽然现在搜索越来越强调个性化的结果,但是一定要清楚的是,推荐算法强调的个性化永远只是搜索算法的补充。“围绕着搜索词的信息高效获取问题“才是搜索算法想解决的根本问题。
正是因为三者间要解决的根本问题是不同的,带来了三者算法层面的第一个区别,那就是优化目标的区别。
一、搜推广优化的目标区别 广告:广告算法的预估目标非常统一,就是预估CTR和CVR。这是跟当前效果类广告的产品形态密切相关的。因为CPC和CPA计价仍是效果类广告系统的主流计价方式。所以只有预估出CTR和CVR,才能反向推导出流量的价值,并进一步给出合理的出价。所以针对这样的目标,广告算法非常看重把预估偏差当作首要的评价指标。
因为广告的主要收入就是,在将商家的roi平衡的前提下,增加公司广告收入的优化目标,而广告收入是来源于商家的广告出价的,因此,提高预估的CTR和CVR,根据出价模式排列分布更合理的PV,才能为公司带来更多的收入。广告更关注估的更准,才能分散更准的流量。
推荐:推荐算法的预估目标就不尽相同,视频类更多倾向于预测观看时长,新闻类预测CTR,电商类预估客单价等等这些跟用户参与度最相关的业务指标。而且由于推荐系统的推荐场景是生成一个列表,所以更加关注item间的相对位置,因此评估阶段更倾向于用AUC,gAUC,MAP这些指标作为评价标准。
推荐更关注于用户的参与度,即如何抓住用户的兴趣,因此个性化比较重要。推荐更关注排的更好,提升用户兴趣。
搜索:搜索的预估目标又有所不同,因为相比广告和推荐,搜索某种意义上说是存在着“正确答案”的。所以搜索非常看重能否把这些正确答案给召回回来(广告和推荐也关注召回率,但重要性完全不同)。所以搜索系统往往会针对召回率,MAP,NDCG这些指标进行优化。
二、算法模型设计中的区别 广告:由于广告算法要预测“精准”的CTR和CVR,用于后续计算精确的出价,因此数值上的“精准”就是至关重要的要求,仅仅预估广告间的相对位置是无法满足要求的。这就催生了广告算法中对calibration方法的严苛要求,就算模型训练的过程中存在偏差,比如使用了负采样、weighted sampling等方式改变了数据原始分布,也要根据正确的后验概率在各个维度上矫正模型输出。此外,因为广告是很少以列表的形式连续呈现的,要对每一条广告的CTR,CVR都估的准,广告算法大都是point wise的训练方式。
推荐:推荐算法的结果往往以列表的形式呈现,因此不用估的那么准,而是要更多照顾一个列表整体上,甚至一段时间内的内容多样性上对于用户的“吸引力”,让用户的参与度更高。因此现在很多头部公司在算法设计时,不仅要考虑当前推荐的item的吸引力,甚至会有一些list level,page level的算法去衡量整体的效果进行优化。也正因为这一点,推荐算法有大量不同的训练方式,除了point-wise,还有pair-wise,list-wise等等。此外为了增加用户的长期参与度,还对推荐内容的多样性,新鲜度有更高的要求,这就让探索与利用,强化学习等一些列方法在推荐场景下更受重视。
搜索:对于搜索算法,我们还是要再次强调搜索词的关键性,以及对搜索词的理解。正因为这样,搜索词与其他特征组成的交叉特征,组合特征,以及模型中的交叉部分是异常重要的。对于一些特定场景,比如搜索引擎,我们一定程度上要抑制个性化的需求,更多把质量和权威性放在更重要的位置。
三、搜推广辅助策略上的区别 广告系统中,CTR等算法只是其中关键的一步,估的准CTR只是一个前提,如何让广告系统盈利,产生更多收入,还需要pacing,bidding,budget control,ads allocation等多个同样重要的模块协同作用,才能让平台利益最大化,这显然是比推荐系统复杂的。
推荐系统中,由于需要更多照顾用户的长期兴趣,需要一些补充策略做出一些看似“非最优”的选择,比如探索性的尝试一些长尾内容,在生成整个推荐列表时要加入多样性的约束,等等。这一点上,广告系统也需要,但远没有推荐系统的重视程度高。
搜索系统中,大量辅助算法还是要聚焦在对搜索词和内容的理解上。因此搜索系统往往是应用NLP模型最重的地方,因为需要对大量内容进行预处理,embedding化,进而生成更理解用户语义的结果。比如最典型的例子就是airbnb对搜索词embedding化后,输入滑雪skiing,会返回更多滑雪胜地的地点,而不是仅仅是字面上的匹配。
四、模型本身的选择上 在广告模型中,用户的兴趣是不那么连贯的,因此容易造成sequential model的失效,attention机制可能会更加重要一些。
推荐模型中,如果不抓住用户兴趣的连续变化,是很难做好推荐模型的,因此利用sequential model来模拟用户兴趣变化往往是有收益的。
搜索模型中,搜索词和item之间天然是一个双塔结构,因此在模型构建的时候各种交叉特征,模型中的各种交叉结构往往是搜索类模型的重点。当然,在构建良好的交叉特征之后,使用传统的LTR,GBDT等模型也往往能够取得不错的结果。
推荐阅读 轻松驾驭JDBC:一篇文章帮你搞定数据库连接
ChatGPT爆火一周年,快来拥有专属你的ChatGPT应用!
文章目录 推荐阅读安装测试配置仓库 安装 第一步检查电脑环境
首先先检查jdk是否安装
第二步下载maven
官网:https://maven.apache.org/download.cgi
下载完成后,解压到一个空的文件夹最好(文件路径中最好不要有中文,不然之后可能会出现啥玄学问题)
第三步配置maven
打开电脑系统属性,配置maven的环境变量。
在系统变量下点击新建,变量名输入%MAVEN_HOME%,变量值为maven的安装目录,确定即可。
将该变量新建到系统Path路径下,新建变量,填入%MAVEN_HOME%\bin即可。
测试 win+R 输入cmd 输入 mvn -v
得到下面页面即成功了。
配置仓库 打开maven安装目录\conf\setting.xml,在localRepository标签下添加自己的仓库地址。
添加阿里云配置下载jar包
可以添加阿里云的镜像到maven的setting.xml配置。完成后即可。
<mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>
1.5 window 滚动窗口+滑动窗口
window操作就是窗口函数。Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作。每次掉落在窗口内的RDD的数据,会被聚合起来执行计算操作,然后生成的RDD,会作为window DStream的一个RDD。比如下图中,就是对每三秒钟的数据执行一次滑动窗口计算,这3秒内的3个RDD会被聚合起来进行处理,然后过了两秒钟,又会对最近三秒内的数据执行滑动窗口计算。所以每个滑动窗口操作,都必须指定两个参数,窗口长度以及滑动间隔,而且这两个参数值都必须是batch间隔的整数倍。 红色的矩形就是一个窗口,窗口hold的是一段时间内的数据流。
这里面每一个time都是时间单元,在官方的例子中,每隔window size是3 time unit, 而且每隔2个单位时间,窗口会slide一次。
所以基于窗口的操作,需要指定2个参数:
window length - The duration of the window (3 in the figure)
slide interval - The interval at which the window-based operation is performed (2 in the figure).
窗口大小,个人感觉是一段时间内数据的容器。
滑动间隔,就是我们可以理解的cron表达式吧。
案例实现
package com.qianfeng.sparkstreaming import org.apache.spark.SparkConf import org.apache.spark.streaming.dstream.DStream import org.apache.spark.streaming.{Seconds, StreamingContext} /** * 统计,截止到目前为止出现的每一个key的次数 * window窗口操作,每个多长M时间,通过过往N长时间内产生的数据 * M就是滑动长度sliding interval * N就是窗口长度window length */ object Demo05_WCWithWindow { def main(args: Array[String]): Unit = { val conf = new SparkConf() .
-v ${local_path}:${docker_path} Docker提供了三种不同的方式将数据从宿主机挂载到容器中:volume、bind mounts、tmpfs mounts
volume:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)
bind mounts:可以存储在宿主机系统的任意位置
tmpfs mounts:挂载存储在宿主机的内存中,不会写入宿主机的文件系统
volume
oot@prometheus204:~# docker volume create for_nginx for_nginx root@prometheus204:~# docker volume ls DRIVER VOLUME NAME local 18ac2738fb4027ebd0c3a4ba0bc6fafdce8d0376ef3df43707a357c2ca321cba local docker-prometheus_grafana_data local docker-prometheus_prometheus_data local for_nginx root@prometheus204:~# docker run --name munginx -d -p 80:80 --mount type=volume,source=for_nginx,target=/usr/share/nginx/html nginx:1.23.3 61545a6faf3e4884bb14c6d7d268ac9d104f4ef7a250d434c65399fee03cf990 root@prometheus204:~# cd /var/lib/docker/volumes/for_nginx/ root@prometheus204:/var/lib/docker/volumes/for_nginx# ls _data root@prometheus204:/var/lib/docker/volumes/for_nginx# cd _data/ root@prometheus204:/var/lib/docker/volumes/for_nginx/_data# ls 50x.html index.html root@prometheus204:/var/lib/docker/volumes/for_nginx/_data# echo hello,123 > index.html root@prometheus204:/var/lib/docker/volumes/for_nginx/_data# # 访问nginx 显示 hello,123 bind mounts(绑定数据卷)
1前言
在前面的压力测试过程中,主要关注的是对接口以及服务器硬件性能进行压力测试,评估请求接口和硬件性能对服务的影响。但是对于多数Web应用来说,整个系统的瓶颈在于数据库。
原因很简单:Web应用中的其他因素,例如网络带宽、负载均衡节点、应用服务器(包括CPU、内存、硬盘、连接数等)、缓存,都很容易通过水平的扩展(俗称加机器)来实现性能的提高。而对于MySQL,由于数据一致性的要求,无法通过增加机器来分散向数据库写数据带来的压力;虽然可以通过前置缓存(Redis等)、读写分离、分库分表来减轻压力,但是与系统其它组件的水平扩展相比,受到了太多的限制
2常见的数据库压测指标
与接口压测指标类似,数据库相关指标如下:
TPS/QPS:衡量吞吐量。
响应时间:包括平均响应时间、最小响应时间、最大响应时间、时间百分比等,其中时间百分比参考意义较大,如前95%的请求的最大响应时间。。
并发量:同时处理的查询请求的数量。
3使用sybench进行数据库压测
1、基本介绍
sysbench是跨平台的基准测试工具,支持多线程,支持多种数据库;主要包括以下几种测试:
cpu性能
磁盘io性能
调度程序性能
内存分配及传输速度
POSIX线程性能
数据库性能(OLTP基准测试)
该工具可以自动帮你在数据库里构造出来大量的数据,你想要多少数据,就自动给你构造出来多少条数据。同时还可以模拟几千个线程并发的访问数据库,模拟使用各种各样的 SQL 语句,包括模拟出来各种事务提交到你的数据库里去,甚至可以模拟出几十万的 TPS 去压测数据库。
2、安装sysbench:
curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
sudo yum -y install sysbench
sysbench --version
3、基于 sysbench 构造测试表和测试数据:
首先需要在自己的数据库里创建好一个测试库,我们可以取个名字叫做 test,同时创建好对应的测试账号,可以叫做 root,密码是 123456,让这个用户有权限可以访问 test。
基于 sysbench 构建 20 个测试表,每个表里有 100 万条数据,接着使用 100 个并发线程去对这个数据库发起访问,连续访问 5 分钟,也就是 300 秒。命令如下:
sysbench --db-driver=mysql --time=300 --threads=100 --report-interval=1 -- mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql- password=123456 --mysql-db=test --tables=20 -- table_size=1000000 oltp_read_write --db-ps-mode=disable prepare 4、执行测试:
1.数据库操作 MySQL数据库 + pymysql import pymysql # 1.连接MySQL conn = pymysql.connect(host="127.0.0.1", port=3306, user='root', passwd="root123", charset='utf8', db='unicom') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 2.发送指令 cursor.execute("insert into admin(username,password,mobile) values('wupeiqi','qwe123','15155555555')") conn.commit() # 3.关闭 cursor.close() conn.close() Django开发操作数据库更简单,内部提供了ORM框架。
1.1 安装第三方模块 pip install mysqlclient 1.2 ORM 创建、修改、删除数据库中的表(不用你写SQL语句)。 【无法创建数据库】操作表中的数据(不用写SQL语句)。 1.2.1 自己创建数据库 启动MySQL服务自带工具创建数据库 create database gx_day15 DEFAULT CHARSET utf8 COLLATE utf8_general_ci; 1.2.2 django连接数据库 在settings.py文件中进行配置和修改
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'gx_day15', # 数据库名字 'USER': 'root', 'PASSWORD': 'root123', 'HOST': '127.
动态规划 动态规划就像是解决问题的一种策略,它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题,并将每个小问题的解保存起来。这样,当我们需要解决原始问题的时候,我们就可以直接利用已经计算好的小问题的解,而不需要重复计算。
动态规划与数学归纳法思想上十分相似。
数学归纳法:
基础步骤(base case):首先证明命题在最小的基础情况下成立。通常这是一个较简单的情况,可以直接验证命题是否成立。
归纳步骤(inductive step):假设命题在某个情况下成立,然后证明在下一个情况下也成立。这个证明可以通过推理推断出结论或使用一些已知的规律来得到。
通过反复迭代归纳步骤,我们可以推导出命题在所有情况下成立的结论。
动态规划:
状态表示:
状态转移方程:
初始化:
填表顺序:
返回值:
数学归纳法的基础步骤相当于动态规划中初始化步骤。
数学归纳法的归纳步骤相当于动态规划中推导状态转移方程。
动态规划的思想和数学归纳法思想类似。
在动态规划中,首先得到状态在最小的基础情况下的值,然后通过状态转移方程,得到下一个状态的值,反复迭代,最终得到我们期望的状态下的值。
接下来我们通过三道例题,深入理解动态规划思想,以及实现动态规划的具体步骤。
139. 单词拆分 - 力扣(LeetCode)(C++实现) 题目解析 状态表示 状态表示通常由经验+题目要求得到。
经验一般是指,以某个位置为结尾或者以某个位置为开始。
我们很容易可以定义这样一个状态表示,定义dp[i]表示,s字符串中,下标0到下标i这段字符串,是否可以进行单词划分。
状态转移方程 根据状态表示,dp[i]表示,s字符串中,下标0到下标i这段字符串,是否可以进行单词划分。
dp[i-1]表示,s字符串中,下标0到下标i-1这段字符串,是否可以进行单词划分。
我们思考如果dp[i]为true,应该如何得到。
如果(j,i)表示一个单词,这个单词能够在wordDirt中被找到,且(0,j-1)可以进行单词划分,则表示(0,i)可以进行单词划分。
根据这个思路,我们可以将(0,i)部分划分为两个部分,
(0,j-1)子串
(j,i)子串
如果(j,i)能够在wordDirt中被找到,dp[i]=dp[j-1]。
因此我们填写dp[i]需要让j遍历(0,i)。
故,当我们在从 0 ~ i 枚举 j 的时候,只要 dp[j - 1] = true ,
并且后面部分的子串 s.substr(j, i - j + 1) 能够在字典中找到,那么 dp[i] = true 。
我们判断(j,i)单词是否可以被找到时,可以用hash表进行优化,将wordDirt中所有的单词都存放在hash表中,当我们需要判断(j,i)单词是否可以被找到的时候,只需要访问hash表即可。
unordered_set<string> hash; for (auto& s : wordDict) hash.
💥💥💞💞欢迎来到本博客❤️❤️💥💥
🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。
⛳️座右铭:行百里者,半于九十。
📋📋📋本文目录如下:🎁🎁🎁
目录
💥1 概述
📚2 运行结果
🎉3 参考文献
🌈4 Matlab代码及文章下载
💥1 概述 摘要:在具有离散信号的可重构智能表面(RIS)辅助通信系统中,优化互信息(MI)的主要困难在于无法以分析可处理的方式来表述这一优化问题。因此,我们建议使用截断速率(CR)作为更易处理的度量来优化MI,并引入两种优化方法来最大化CR,假设对信道状态信息(CSI)具有完美的了解。第一种方法基于投影梯度法(PGM),而第二种方法源自于连续凸逼近原理(SCA)。模拟结果表明,所提出的优化方法显著提高了CR和相应的MI。
最近开发的可重构智能表面(RIS)具有塑造和控制无线网络中的无线电波传播的潜力,使其成为未来5G以后通信系统的有前途的候选者。RIS由大量小型、低成本和几乎被动的元素组成,每个元素都可以通过可调相移反射入射信号,从而改变散射波的波前[1]。改变反射信号的波前使我们能够塑造无线电波通过信道的传播方式,从而改善可实现的速率等关键系统性能指标。这一领域的主要研究工作集中在单用户[2]和多用户[3]多输入单输出(MISO)通信系统的可实现速率优化上。另一个重要的研究方向是针对装备有RIS的多输入多输出(MIMO)系统的可实现速率优化,包括单用户[4]、[5]和多用户[6]、[7]通信。在上述论文中,传输符号按照圆对称复高斯分布进行分布,这是一种容量实现分布。然而,在实践中,传输符号通常是从离散信号星座中选择的,因此目前的解决方案无法用于在实际RIS辅助通信系统中建立可实现数据速率的现实界限。
📚2 运行结果 可视化代码:
diagnotics = optimize(abs(mytheta_variable)<=1,obj,solversettings);
if(diagnotics.problem==0)
mytheta = value(mytheta_variable);
end
objSCA(iSCA+1) = 2*double(obj)+Ns;
objSCA_MI(iSCA+1) = computeMI((Hdirt + H2t*diag(mytheta)*H1t)*P*x,N0);
end
plot(1:length(objSCA),-log2(objSCA/Ns^2),'r','DisplayName','$R_0$, SCA');
hold on plot(1:length(objSCA_MI),objSCA_MI,'r--','DisplayName','MI, SCA');
xlabel('Iteration'); ylabel('Cut-off rate / MI [bpcu]');
legend('show','Location','SouthEast','Interpreter','latex');
部分代码:
no_mat = 1; % number of channel realizations
K = 1; % Rician K factor f = 2000e6; % frequency
💥💥💞💞欢迎来到本博客❤️❤️💥💥
🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。
⛳️座右铭:行百里者,半于九十
📋📋📋本文目录如下:🎁🎁🎁
目录
💥1 概述
📚2 运行结果
🎉3 参考文献
🌈4 Matlab代码、数据、文章
💥1 概述 文献来源:
摘要:
在无线传感器网络中,利用无人机(UAV)作为传感器节点(SNs)的移动数据收集器是一种节能的技术,可以延长网络的寿命。在本文中,考虑了传感器节点和无人机之间的一般衰落信道模型,我们联合优化传感器节点的唤醒时间表和无人机的轨迹,以最小化所有传感器节点的最大能量消耗,同时确保可靠地从每个传感器节点收集所需数量的数据。我们将我们的设计建模为一个混合整数非凸优化问题。通过应用逐步凸优化技术,提出了一种高效的迭代算法,用于找到一个次优解。数值结果表明,与基准方案相比,所提出的方案实现了显著的网络节能。
无线传感器网络(WSNs)通常由大量成本低廉的传感器节点(SNs)组成,这些节点通常由电池等有限能源供电,一旦耗尽就很难充电[1]。因此,对于传感器节点而言,节能的感知和通信技术对于延长WSNs的寿命至关重要。最近在利用无人机(UAV)作为WSN中地面传感器节点的移动数据收集器方面引起了越来越多的兴趣[2]。通过利用其高度的移动性,无人机能够高效地从传感器节点收集数据,因为它可以依次访问传感器节点,并且只有当它移动到足够靠近每个传感器节点时才从它们那里收集数据。因此,每个活跃传感器节点到无人机的链路距离显著缩短,这节省了所有传感器节点的传输能量。已经表明,无人机和地面终端之间的短距离的直射(LoS)通信链路可以通过适当设计无人机的轨迹在各种无人机启用的无线网络中有效利用,以提高性能[3]–[5]。对于无人机启用的WSNs,睡眠和唤醒机制是另一种有用的技术,可节省传感器节点的能量消耗[6]。
对于无人机(UAV)启用的无线传感器网络(WSNs),睡眠和唤醒机制是另一种有用的技术,可用于节省传感节点(SNs)的能耗[6]。通过这种机制,传感节点在未收到来自附近无人机的良好信号强度的唤醒信标之前会保持睡眠状态,一旦收到信标,它们将唤醒并开始向无人机发送数据,传输完成后又返回睡眠状态。在设计用于数据收集的无人机启用的无线传感器网络时,存在两个关键问题。第一个问题是由于传感节点的有限电池能量。因此,传感节点的唤醒计划应该得到适当设计,以便每个传感节点在最小能耗下完成数据传输。第二个问题是由于传感节点和移动无人机之间的高度动态的无线信道,这些信道容易出现数据包丢失[7],特别是在实际情况下,当存在多径引起的信道衰落时。因此,无人机的轨迹应该得到适当设计,以确保每个传感节点在唤醒状态时能够以较低的中断概率传输数据。详细讲解见第4部分。
📚2 运行结果 部分代码:
clear all
close all
addpath('./src')
global u q0 qF
istrain = 0
if istrain == 1
%% Optimization
Q = {};
X = {};
Theta = {};
Lo = {};
for T = [40 50 100]
disp(['T =' num2str(T) ', start'])
[q, x, th, lo]= solveP1('T', T,'Sk',10*(10^6),'epsilon',10^-2); disp(['T =' num2str(T) ', end'])
给大伙介绍一个实用的Wrapper类,面向对象,接口清晰,使用方便,再也不怕中文乱码问题了!
An Easy to Use Wrapper for SQLite3 (Totally Free Embedded Database Engine!) - CodeProject
很实用的ChatGPT网站——http://chat-zh.com/ 今天介绍一个好兄弟开发的ChatGPT网站,网址[http://chat-zh.com/]。这个网站功能模块很多,包含生活、美食、学习、医疗、法律、经济等很多方面。下面简单介绍一些部分功能与大家一起分享。
登录和注册页面 主页面 1. 左侧功能区 ChatGPT问答 示例:我儿子的婚礼邀请函,如下图所示。
GPT4高清绘图 示例:编程、读书、咖啡、书房,AI生成的图片如下所示。
MJ高清绘图 示例:fruits dropping in water, AI生成的图片如下所示。
2. 右侧功能区 全能问答助手 示例问题:怎样学好爬虫? 给出的答案如下图所示。
办公自动化助手 示例问题:word批量修改文字,AI给出答案如下图所示。
爆款文书 如图所示
表格生成 如图所示
功能模块很多,不挨个推荐了。我重点推荐一下编程学习辅助模块。
编程学习辅助 示例问题:用python语言编写一段查询域内存活的主机。
AI给出代码如下:
import socket def check_host(ip, port): try: # 创建一个socket对象 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置连接超时时间为1秒 sock.settimeout(1) # 尝试连接主机 result = sock.connect_ex((ip, port)) # 如果返回0,则表示主机存活 if result == 0: print(f"Host {ip}:{port} is alive") # 关闭socket连接 sock.close() except socket.error as e: print(f"
背景 为了维持flink的正常运行,对flink的日常监控就变得很重要,本文我们就来看一下flink中要监控的几个重要的指标
重要的监控指标 1.算子的处理速度的指标:numRecordsInPerSecond/numRecordsOutPerSecond,这有助于你了解到算子的是否正在合理运行
2.应用的监控度: uptime表示应用已经持续运行的时间,numRestarts表示job被重启的次数,重启的原因很多种,比如内存占用过多被killed等
3.检查点健康度: numberOfCompletedCheckpoints表示已经完成的检查点数目, numberOfFailedCheckpoints表示未能完成的检查点数目(比如因为状态太多导致超时等未能完成checkpoint操作),
numberOfInProgressCheckpoints表示正在进行中的检查点数目,lastCheckpointDuration表示检查点的持续时间,过长的时间会导致checkpoint失败,
lastCheckpointFullSize表示检查点的大小,这可以帮你检查应用状态大小是否正常
4.基于事件时间的应用的处理延迟:可以对比eventtime和当前时间的延迟,这可以知道是否发生了数据倾斜等问题,导致watermark一直未能前进
5.jvm和容器指标:Jvm使用的内存/cpu大小,容器使用的内存大小(包括jvm+其他组件)
博主介绍:✌全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久,选择我们就是选择放心、选择安心毕业✌感兴趣的可以先收藏起来,点赞、关注不迷路✌
毕业设计:2023-2024年计算机毕业设计1000套(建议收藏)
毕业设计:2023-2024年最新最全计算机专业毕业设计选题汇总
1、项目介绍 技术栈:
Python语言、Flask框架、Vue框架、requests爬虫、Echarts可视化、MySQL数据库、HTML
使用爬虫爬取京东商品信息数据,对数据进行清洗、存储、分析展示
2、项目界面 (1)商品价格可视化分析
(2)商品价格区间分析
(3)商品数据信息
(4)店铺评分排名
(5)平均价格排名
(6)商品评论分析
(7)后台数据管理
3、项目说明 (1)介绍 使用爬虫爬取[京东商品信息]数据,对数据进行清洗、存储、分析展示,应用Python爬虫、Flask框架、Vue、Echarts等技术实现。此系统适用于目标网站任何类型的商品分析。
(2)系统功能 1、数据概览 使用爬虫爬取京东商品数据后,将数据在此模块进行展示。所有爬虫在文章后面进行介绍
搜索:输入商品标题,可对商品进行模糊查询
获取评论:管理员功能,点击此按钮调用获取评论爬虫,开始获取对应商品的评论信息,默认爬5页,可在程序中修改爬取页数
获取店铺信息:管理员功能,点击此按钮调用获取店铺信息爬虫,获取该商品对应店铺的信息,包括店铺星级、店铺评分等
详情:点击详情按钮,跳转到商品详情页面
店铺:点击按钮,跳转到店铺页面
2、商品价格排名 将所有商品的价格进行排序,使用echarts柱状图从高到低展示前20条数据。支持按照店铺查询店内商品排名
搜索:选择店铺(可以输入)后点击搜索,查询该店铺所有商品排名
3、店铺星级排名 对已获取信息的店铺星级进行排序,使用echarts折线图进行展示。
4、店铺评分排名 对已获取信息的店铺评分进行排序,可分别展示商品评分,物流评分和售后评分。
5、店铺均价排名 计算所有店铺的商品均价,使用echarts折线图从高到低展示前20条数据。
6、评论分析 展示评论信息的词云图和评分占比,使用词云和饼状图实现。可根据条件展示不同的结果
店铺空、商品空:展示所有数据的评论信息词云,以及评分占比
店铺不空、商品空:展示该店铺的评论信息词云,以及评分占比
店铺不空、商品不空:展示该商品的评论信息词云,以及评分占比
7、个人信息 用户查看个人信息,输入新的信息点击提交,可更新个人信息
9、修改密码 输入原密码与新密码,可修改密码
10、登录注册 用户登录注册
11、用户管理 该功能是管理员功能,管理用户信息
新增:点击新增按钮,输入用户信息,可添加新用户
1:达梦数据库(DM8)简介 达梦数据库管理系统是武汉达梦公司推出的具有完全自主知识产权的高性能数据库管理系统,简称DM。达梦数据库管理系统目前最新的版本是8.0版本,简称DM8。
DM8是达梦公司在总结DM系列产品研发与应用经验的基础上,坚持开放创新、简洁实用的理念,推出的新一代自研数据库。
DM8吸收借鉴当前先进新技术思想与主流数据库产品的优点,融合了分布式、弹性计算与云计算的优势,对灵活性、易用性、可靠性、高安全性等方面进行了大规模改进,多样化架构充分满足不同场景需求,支持超大规模并发事务处理和事务-分析混合型业务处理,动态分配计算资源,实现更精细化的资源利用、更低成本的投入。一个数据库,满足用户多种需求,让用户能更加专注于业务发展。
2:达梦数据在Linux上的安装 产品下载 | 达梦数据库,选择X86,CentOS7
2.1:操作系统环境准备 本次使用的系统版本是CentOS Linux release 7.6.1810 (Core)
[root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) 2.2:上传所需文件到/opt/soft [root@localhost soft]# ls dm8_20231116_x86_rh6_64.zip 2.3:创建安装用户dmdba和组dinstall,并设置用户密码 [root@localhost ~]# groupadd dinstall [root@localhost ~]# useradd -s /bin/bash -m -d /home/dmdba -g dinstall dmdba [root@blocalhost ~]# passwd dmdba //这里需要设置一个密码,可以设置为 12345678 2.4:关闭SELinux [root@localhost soft]# vi /etc/selinux/config SELINUX=disabled #关闭防火墙 systemctl stop firewalld systemctl disable firewalld 2.5:给dmdba配置系统资源限制 [root@blocalhost ~]# vi /etc/security/limits.conf dmdba soft nofile 65536 dmdba hard nofile 65536 dmdba soft nproc 65536 dmdba hard nproc 65536 dmdba soft stack 16384 dmdba hard stack 32768 用dmdba用户登录系统,查看ulimit参数是否生效: ulimit -a(注意:要切换到dmdba用户进行查看) [root@localhost soft]# su dmdba [dmdba@localhost soft]$ ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31078 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 65536 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 4096 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 2.
什么是Arduino?
Arduino 是一款开源的电子原型平台,它可以让你用简单的硬件和软件来创建各种创意的项目。无论你是初学者还是专家,Arduino 都能为你提供无限的可能性。你可以用 Arduino 来控制传感器、灯光、马达、机器人、物联网设备等等,只要你能想到的,Arduino 都能帮你实现。
如果你想了解更多关于 Arduino 的信息,你可以访问 Arduino 的官方网站,那里有丰富的资源和教程供你参考。你也可以加入 Arduino 的社区,和来自世界各地的爱好者、学生、设计师和工程师交流心得和经验。此外,你还可以使用 Arduino 的在线编程工具,在云端编写代码并上传到你的开发板上。
Arduino 是一个不断发展和创新的平台,它有着广泛的应用领域和潜力。这里希望本手册能激发你对 Arduino 的兴趣和热情,让你享受 Arduino 带来的创造力和乐趣。
维基百科的定义
Arduino 是一个开源嵌入式硬件平台,用来供用户制作可交互式的嵌入式项目。此外 Arduino 作为一个开源硬件和开源软件的公司,同时兼有项目和用户社群。该公司负责设计和制造Arduino电路板及相关附件。这些产品按照GNU宽通用公共许可证(LGPL)或GNU通用公共许可证(GPL)许可的开源硬件和软件分发的,Arduino 允许任何人制造 Arduino 板和软件分发。 Arduino 板可以以预装的形式商业销售,也可以作为 DIY 套件购买。
Arduino 2005 年时面世,作为意大利伊夫雷亚地区伊夫雷亚互动设计研究所的学生设计,目的是为新手和专业人员提供一种低成本且简单的方法,以建立使用传感器与环境相互作用的装置。初学者和爱好者可用Arduino制造传感器、简单机器人、恒温器和运动检测器等装置。
Arduino 这个名字来自意大利伊夫雷亚的一家酒吧,该项目的一些创始人过去常常会去这家酒吧。 酒吧以伊夫雷亚的 Arduin(Arduin of Ivrea)命名,他是伊夫雷亚边疆伯爵,也是 1002 年至 1014 年期间的意大利国王。
十九、Arduino 位操作 bit()
Arduino的bit()是一个函数,用于返回一个数值,该数值只有指定位置的二进制位为1,其他位都为0。这个函数可以用于处理多位的数据,比如byte、int、long等,或者进行位运算。
bit()的适用范围:
1)用于创建一个掩码,用于与其他数值进行位与或位或运算,以设置或清除某些位的状态。例如,如果要设置一个byte类型的变量的最高位为1,可以用bit(7)创建一个掩码,然后与原变量进行位或运算。
2)用于检测一个数值的某一位的状态,用于与其他数值进行位与运算,以判断该位是否为1。例如,如果要检测一个byte类型的变量的最高位是否为1,可以用bit(7)创建一个掩码,然后与原变量进行位与运算,如果结果不为0,则说明该位为1。
3)用于将多个单独的位组合成一个数值,用于与其他数值进行位或运算,以生成一个新的数值。例如,如果要将一个byte类型的变量的第0、2、4、6位都设置为1,可以用bit(0)、bit(2)、bit(4)、bit(6)创建四个掩码,然后依次与原变量进行位或运算。
主要应用场景:
1)读取传感器数据:在许多应用中,传感器的输出通常是一个字节或整数,其中的特定位表示特定的传感器数据。使用bit()函数可以方便地读取特定位的值,从而获取传感器的具体数据。
2)判断标志位:在某些情况下,使用位来表示特定的标志位,例如开关状态、使能标志、错误标志等。bit()函数可以将字节或整数中特定位的值提取出来,以便进行相应的判断或处理。
3)位操作中的辅助操作:bit()函数常常被用作位操作中的辅助函数,与其他位操作函数结合使用,以实现更复杂的位操作逻辑。
bit()的使用注意事项有以下几点:
bit()只能作用于一个常量,不能作用于一个变量或表达式。例如,bit(x)是错误的写法,应该先将x赋值给一个常量,然后再用bit()提取。
bit()返回的是一个无符号长整型(unsigned long)的值,范围是0~4294967295。如果要将其转换为其他类型,需要进行强制类型转换。例如,如果要将其转换为byte类型,需要写成byte(bit(n))。
bit()只能提取0~31位置的二进制位的值。如果要提取其他位置的位的值,需要使用其他方法。例如,如果要提取第32位的值,可以先右移31位,然后再用bit(0)提取。
以下是Arduino的bit()几个实际运用程序案例:
例1:创建一个掩码
//定义一个byte类型的变量 byte x = 0b10101010; //创建一个掩码 byte mask = bit(7); //10000000 //设置最高位为1 x = x | mask; //10101010 | 10000000 = 11101010 //打印修改后的结果 Serial.
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦🍂博主正在努力完成2023计划中:源码溯源,一探究竟📝联系方式:nhs19990716,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬👀 文章目录 Linux 入门概述Linux 和 Windows 区别安装 VI/VIM编辑器简介测试编辑模式指令模式基本语法案例实操模式转换 网络修改hosts映射文件 系统管理Linux 中的进程和服务service 服务管理(CentOS 6 版本-了解)chkconfig 设置后台服务的自启配置(CentOS 6 版本)systemctl (CentOS 7 版本-重点掌握)systemctl 设置后台服务的自启配置关机重启命令 常用基本命令(重要)帮助命令man 获得帮助信息help 获得 shell 内置命令的帮助信息常用快捷键 文件目录类pwd 显示当前工作目录的绝对路径ls 列出目录的内容cd 切换目录mkdir 创建一个新的目录rmdir 删除一个空的目录touch 创建空文件cp 复制文件或目录rm 删除文件或目录mv 移动文件与目录或重命名cat 查看文件内容more 文件内容分屏查看器less 分屏显示文件内容echohead 显示文件头部内容tail 输出文件尾部内容>输出重定向和 >> 追加history 查看已经执行过历史命令 时间日期类date 显示当前时间date 显示非当前时间date 设置系统时间cal 查看日历 搜索查找类find 查找文件或者目录locate 快速定位文件路径grep 过滤查找及“|”管道符 磁盘查看和分区类du 查看文件和目录占用的磁盘空间df 查看磁盘空间使用情况 进程管理类ps 查看当前系统进程状态kill 终止进程pstree 查看进程树top 实时监控系统进程状态netstat 显示网络状态和端口占用信息 经典面试题百度瓜子二手车 Linux 入门 概述 Linux 和 Windows 区别 安装 1.
本文档旨在指导读者在x86_64平台上交叉编译curl和openssl库以支持aarch64架构。在开始之前,请确保您的系统环境已正确配置。
1. 系统环境准备 系统是基于Ubuntu 20.04 LTS,高版本可能会有问题。首页,安装必要的开发工具和库文件。打开终端并执行以下命令:
sudo apt-get update sudo apt-get install build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu autoconf automake libtool 这些软件包将为您提供编译过程中所需的基本工具链。
2. OpenSSL交叉编译 2.1 支持的CPU架构 在开始交叉编译之前,请注意OpenSSL 1.1.1w支持广泛的CPU架构,包括aarch64。确保您的目标平台与此版本兼容。目录支持架构如下:
BS2000-OSD BSD-generic32 BSD-generic64 BSD-ia64 BSD-sparc64 BSD-sparcv8 BSD-x86 BSD-x86-elf BSD-x86_64 Cygwin Cygwin-i386 Cygwin-i486 Cygwin-i586 Cygwin-i686 Cygwin-x86 Cygwin-x86_64 DJGPP MPE/iX-gcc OS390-Unix QNX6 QNX6-i386 UEFI UWIN VC-CE VC-WIN32 VC-WIN64A VC-WIN64A-masm VC-WIN64I aix-cc aix-gcc aix64-cc aix64-gcc android android-armeabi android-mips android-x86 android64 android64-aarch64 bsdi-elf-gcc cc darwin-i386-cc darwin-ppc-cc darwin64-debug-test-64-clang darwin64-ppc-cc darwin64-x86_64-cc dist gcc haiku-x86 haiku-x86_64 hpux-ia64-cc hpux-ia64-gcc hpux-parisc-cc hpux-parisc-gcc hpux-parisc1_1-cc hpux-parisc1_1-gcc hpux64-ia64-cc hpux64-ia64-gcc hpux64-parisc2-cc hpux64-parisc2-gcc hurd-x86 ios-cross ios64-cross iphoneos-cross irix-mips3-cc irix-mips3-gcc irix64-mips4-cc irix64-mips4-gcc linux-aarch64 linux-alpha-gcc linux-aout linux-arm64ilp32 linux-armv4 linux-c64xplus linux-elf linux-generic32 linux-generic64 linux-ia64 linux-mips32 linux-mips64 linux-ppc linux-ppc64 linux-ppc64le linux-sparcv8 linux-sparcv9 linux-x32 linux-x86 linux-x86-clang linux-x86_64 linux-x86_64-clang linux32-s390x linux64-mips64 linux64-s390x linux64-sparcv9 mingw mingw64 nextstep nextstep3.
解决LocalDateTime 时间格式中间带’T’返回的问题 前言:在一次工作开发过程中,LocalDateTime 类型的字段返回给前端带着T,然后被测试无情的提了一个bug,然后只能使用百度大法了,结果发现网上全是一堆相同的答案,且是无效无用的,只能自己实践整理一版有效的使用出来。
PS:要看自己的项目是数据序列化是不是用fastJson序列化(很重要,因为这个导致很多正常有效的都变无效了,我就是踩这个坑)
首先我们先了解Date和LocalDateTime 的源码返回格式 下面是Date的toString方法的源码,里面返回的字符格式就是日常使用的
public String toString() { // "EEE MMM dd HH:mm:ss zzz yyyy"; BaseCalendar.Date date = normalize(); StringBuilder sb = new StringBuilder(28); int index = date.getDayOfWeek(); if (index == BaseCalendar.SUNDAY) { index = 8; } convertToAbbr(sb, wtb[index]).append(' '); // EEE convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH CalendarUtils.sprintf0d(sb, date.
很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403
前言 本文分享vtkCaptionActor2D源码解析,希望对各位小伙伴有所帮助!
感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!
你的点赞就是我的动力(^U^)ノ~YO
目录
前言
1. vtkCaptionActor2D概述
2. 重要参数
2.1 定义标注文本
2.2 设置标注附着点
2.3 设置是否启用边框 2.4 设置是否启用标注到附着点的引导线
2.5 指定2D或3D箭头
2.6 设置文本与包围盒的距离
2.7 设置文本属性
2.8 设置箭头是否在Edge上附着 3. 原理解析
3.1 vtkBorderRepresentation原理解析
结论:
1. vtkCaptionActor2D概述 vtkCaptionActor2D是一个2DActor和3DActor混合的对象,用于将文本与场景中的点(AttachmentPoint)相关联。可以使用矩形边框和将标题连接到附着点的引线来绘制标题。可选地,可以在leader的端点处对其进行符号化,以创建箭头或其他指示符。
使用vtkCaptionActor2D时,必须指定Position和Position2两个点。Position和Position2定义标题的大小,AttachmentPoint定义标题所关联的点。还必须定义标题文本、是否希望在标题周围设置边框,以及是否希望在标题到附件点之间设置一个引线。
文本的属性通过关联的vtkTextProperty进行设置。引线可以设置为2D或3D。(2D绘制在底层几何上,3D三维引线可能被几何遮挡。)
2. 重要参数 2.1 定义标注文本 //@{ /** * Define the text to be placed in the caption. The text can be multiple * lines (separated by "\n"). * 定义标注的文本,文本可以多行(通过"\n"进行分隔) */ virtual void SetCaption(const char* caption); virtual char* GetCaption(); //@} 2.
文章目录 第1关:统计共享单车每天的平均使用时间第2关:统计共享单车在指定地点的每天平均次数第3关:统计共享单车指定车辆每次使用的空闲平均时间第4关:统计指定时间共享单车使用次数第5关:统计共享单车线路流量 第1关:统计共享单车每天的平均使用时间 任务描述
本关任务:使用Hbase的MapReduce对已经存在 Hbase 的共享单车运行数据进行分析,统计共享单车每天的平均使用时间,其中共享单车运行数据在Hbase的t_shared_bicycle表中(表结构可在编程要求中进行查看)。
相关知识
为了完成本关任务,你需要掌握:
如何配置Hbase的MapReduce类;
如何使用Hbase的MapReduce进行数据分析。
如何配置Hbase的MapReduce类
MapReduce是运行在Job上的一个并行计算框架,分为Map节点和Reduce节点。
Hbase提供了org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil的initTableMapperJob和initTableReducerJob两个方法来完成MapReduce的配置。
initTableMapperJob 方法:
/**
*在提交TableMap作业之前使用它。 它会适当地设置
* 工作。
*
* @param table要读取的表名。
* @param scan具有列,时间范围等的扫描实例。
* @param mapper要使用的mapper类。
* @param outputKeyClass输出键的类。
* @param outputValueClass输出值的类。
* @param job当前要调整的工作。 确保传递的作业是
*携带所有必要的HBase配置。
* @throws IOException设置细节失败。
*/
public static void initTableMapperJob(String table, Scan scan,
Class<? extends TableMapper> mapper, Class<?> outputKeyClass,
Class<?> outputValueClass, Job job)
throws IOException
/ **
initTableReducerJob 方法:
我先来说一下我为啥要分包
1.小程序比较庞大,页面比较多
2.需要本地引入的图片静态资源比较多造成小程序超过2MB
3.为了方便
okok 开始分包。其实很简单,做个简单比喻。
其实就像吃火锅,一个锅一次性把食材全部放下去吃跟吃一点放一点没什么区别,最后都是要吃完这顿火锅,这个分包就跟这个类似。
多的不说少的不唠开始。我这里拿我的一个项目来浅浅的演示一下。
首先先查看自己的项目包大小,点右上角的详情可以看到,这里已经可以看到明显超出2MB了
打包上传必定会失败,一般就是下面这种报错。原因就是你的小程序超过2MB上传失败了。
分包我们需要在pages同等级目录下再创建一个目录
比如这样 我在pages同等级目录创建了一个pagesA目录。这个pagesA目录跟咱们的pages类似,可以说一摸一样,不过要注意的是需要在pages.json里面配置一下。配置方法也很简单都有提示。
这里我配置完新建了一个页面,就跟在pages下面建页面是一摸一样。注意在建页面的时候选择在pages.json里面注册。
ok 这样基本就完了,在看一下项目详情。
这里就会显示你有两个包了 一个主包一个咱们新建的pagesA的包。
分包预加载就更简单了,直接在pages.json里面写 上面pages/index/index 代表你要在那个页面进行分包的加载,代码都有提示。
"preloadRule":{ "pages/index/index": { "network": "wifi", "packages": ["pagesA"] } }, 这样就可以把项目中比较复杂的模块或者一些页面单独分离出来建一个包,让小程序的主包不会超出2MB从而不影响项目的真机测试和上线。分包最好在项目初期就确定好,血的教训啊!!!!
AWS S3作为非结构化数据的存储,经常会有内网中的app调用的需求。S3默认是走公网访问的,如果内网app通过公网地址访问S3并获取数据会消耗公网带宽费用。如下图所示:
AWS 提供了一种叫做endpoints的资源,这种资源可以后挂S3服务,使得内网服务可以不出公网访问S3.
VPC endpoints for Amazon S3 simplify access to S3 from within a VPC by providing configurable and highly reliable secure connections to S3 that do not require an internet gateway or Network Address Translation (NAT) device. When you create a S3 VPC endpoint, you can attach an endpoint policy to it that controls access to Amazon S3.
创建endpoints时,如果是S3,需选择gateway类型。
There are three types of VPC endpoints – Interface endpoints, Gateway Load Balancer endpoints, and Gateway endpoints.
Linux系统的升级是确保系统稳定和安全性的重要步骤。本文将介绍Linux系统升级的基本概念,以及具体的操作步骤和注意事项,以帮助用户顺利升级他们的Linux系统。
Linux操作系统以其稳定性和可定制性而闻名,它经常通过升级来提供新的功能、修复漏洞和提高性能。在这篇文章中,我们将讨论Linux系统升级的重要性以及如何进行升级。
为什么要升级Linux系统 Linux系统升级的主要目的是确保系统的稳定性和安全性。通过升级,您可以获得以下优势:
修复漏洞: Linux社区会定期发布安全补丁,以修复已知漏洞。升级系统可以确保您的系统受到最新的安全修复的保护。
新功能: Linux社区不断创新,为用户带来新的功能和改进。通过升级,您可以获得最新的功能和性能提升,以提高您的系统体验。
应用程序兼容性: 通过升级系统,您可以确保您的系统与最新的应用程序和库文件保持兼容,从而避免可能的兼容性问题。 性能优化: 升级Linux系统通常会带来性能的提升,包括更好的内存管理、文件系统优化以及更高效的资源利用。这些改进可以增加系统的响应速度和整体的运行效率。
易用性改进: Linux系统的升级通常会伴随着用户界面的改进和功能的增加,使系统更加易于使用和操作。新的图形界面、工具和命令可以提高您的工作效率和使用体验。
社区支持: 升级到最新的Linux系统版本,您可以获得更完善的社区支持。有更新的文档、教程和解决方案可用于您遇到的问题,您可以更快速地获取技术支持和寻求解决方案。
如何升级Linux系统 升级Linux系统通常有几种方法,取决于您当前使用的发行版和个人偏好。
包管理器: 大多数Linux发行版都提供了包管理器,如apt、yum、dnf等。您可以使用包管理器来更新和升级系统的软件包。只需运行相应的命令,您的系统将会自动下载和安装最新的软件包。
发行版升级: 如果您希望更新整个操作系统,而不仅仅是软件包,您可以考虑进行发行版的升级。每个发行版都有相应的升级指南,您可以按照指南中的步骤来完成系统的升级。
源代码编译: 如果您对Linux系统有深入的了解,并且喜欢自定义您的系统,您可以选择从源代码编译安装最新版本的内核和软件。这需要一些专业知识和技术能力。
请注意,在进行系统升级之前,建议备份您的数据和配置文件,以防发生意外情况。另外,如果您使用的是生产环境的系统,建议先在测试环境中进行升级,以确保升级过程不会影响到关键业务的正常运行。
Linux系统升级是确保系统稳定性和安全性的关键步骤。通过升级,您可以修复漏洞、获得新功能、提升性能、改善易用性并享受社区支持。根据您的需求和技术水平,选择适合的升级方法,并确保做好备份工作,以确保升级过程的顺利进行。
升级Linux系统的步骤 以下是升级Linux系统的一般步骤:
备份数据: 在升级之前,务必备份重要的数据。尽管大多数升级过程是安全的,但备份可以保护您免受任何意外数据丢失的影响。
更新软件源: 在升级之前,确保您的软件源是最新的。您可以使用适用于您的Linux发行版的特定命令或工具来更新软件源。
更新系统: 运行升级命令来更新您的Linux系统。具体的命令可能因您使用的发行版而异。大多数发行版都提供了基于命令行或图形界面的工具来执行升级操作。
重启系统: 在升级完成后,建议重新启动系统以应用所有的更改和更新。重新启动可以确保新的内核和库文件得到正确加载和使用。
注意事项和建议 在升级Linux系统时,以下是一些建议和注意事项:
确保有可靠的互联网连接: 在升级过程中,您需要下载和安装大量的软件包和更新,因此确保您的网络连接稳定和高速。
不要中断升级过程: 在进行升级时,尽量不要中断升级过程。意外的系统中断可能导致操作系统损坏或不稳定。
关注升级提示: 在执行升级过程中,系统可能会要求您进行一些额外的操作。请仔细阅读并按照系统提示进行操作。
验证升级结果: 在升级完成后,建议您验证系统的版本和安装的软件包是否与预期一致。使用适当的命令或工具来检查系统和软件的版本信息。
结论 在这篇文章中,我们讨论了Linux系统升级的重要性以及相关的操作步骤和注意事项。通过定期升级Linux系统,您可以确保系统的稳定性、安全性以及享受最新功能的好处。请记住,在进行任何升级之前,务必备份重要的数据,并遵循官方文档和社区支持以获得最佳的升级体验。
体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构
前言 在学习C语言时,我们通常会遇到两个数交换的问题,为了实现这一功能,我们会编写一个经典的Swap函数,如下所示:
void Swap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } 然而,这个Swap函数看起来可能有些繁琐,需要使用指针和解引用操作符。相比之下,C++引入了引用的概念,使得代码更为简洁:(这两个函数还构成了函数重载哦)
void Swap(int& a, int& b) { int tmp = a; a = b; b = tmp; } 并且引用避免了直接操作指针和解引用的繁琐性,调用时也更加直观,如下所示:
Swap(a, b); 虽然这个例子中看似只是减少了取地址的操作,但引用的使用远不止于此。可能你这里会有点懵圈,但没关系,接下来我们将详细探讨引用。
注意:本篇博客中的代码均基于包含头文件 <iostream> 并在使用命名空间 std 的前提下编写。
概念 引用不是新定义一个变量,而是给已存在的变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如在外面别人以你的名字来称呼你,而在家中亲人以你的小名称呼你。
用法:类型& 名字 = 引用的变量(对象)名字;
举个例子:
int main() { int a = 10; int& b = a; // b 就是 a 的引用,也就是 a 的别名 return 0; } 这样就定义了一个引用。 int main() { int a = 10; int& b = a; cout << &a << endl; // cout 会自动识别数据类型并输出 cout << &b << endl; b++; cout << a << endl; // a 的值变成了 11 return 0; } 程序运行后,可以发现 a 和 b 的地址相同,证实了它们共用同一块内存空间,进一步证明了编译器不会为引用变量单独分配内存。因此我们改变 b 的值其实就是改变 a 的值。
我们知道,redis常用的5种类型底层都是通过redisObject去封装的。看一下redisObject的源码:
typedef struct redisObject { unsigned type:4; unsigned encoding:4; unsigned lru:LRU_BITS; int refcount; void *ptr; } robj; 这几个属性都很重要,下面就看下他们各自代表什么含义以及有什么作用。
1. type 这个比较熟悉,type的值对应的就是我们平时接触最多的5种数据类型,即:string、list、set、sortedset、hash,当然还包括其他一些不常用的类型,在此不再列举。我们通过 type key 这个命令,可以拿到它的值类型。
type在redis中也会对客户端输入的操作命令进行检查,校验合法性。在redis中,有两种类型的命令,一种是针对所有类型都适用的,如 del、ttl、expire等,还一种是针对特定类型的操作,比如 get、hget、lpush等,针对后者,type就可以对命令和参数的类型进行校验,校验通过会继续执行,否则就会向客户端返回错误提示。
2. encoding encoding这个值记录的每种值对象在底层的结构实现编码,什么意思呢?比如 hash 在redis的实现结构有两种类型,数据量比较少的时候使用 ziplist,数据量比较大的时候是 dict,那么encoding的值分别就是上面提到的 “ziplist” 和 “dict”。使用 object encoding key这个命令可以查询。
除了记录编码值之外,redis也会借助于encoding,实现命令的执行函数。还是上面提到的hash,比如我们执行了 hlen 获取hash长度,如果encoding标记的是ziplist,那么redis就会使用ziplist相关len函数去执行,如果encoding标记的值是dict,就会调用dict 相关的len函数去执行。
3. lru lru这个必然是和内存回收相关的了,这里它记录的是当前的值对象最后一次被程序访问的时间,通过这个时间我们可以得到该对象的空转时长,就是当前时间 - lru记录的时间,如果说redis服务器打开了 maxmemory 最大内存管理的选项,并且内存回收使用 volatile-lru 或者 allkeys-lru算法,那么服务器就会优先释放这个空转时长比较长的对象,从而回收内存。
通过object idletime key这个命令就可以得到最近一次被访问的时间,需要注意的是,这个命令本身也访问了该对象,但是却不会引起这个时间值的改变。
4. refcount refcount记录的是当前这个值对象正在被多少数据结构所共享,redis用这个属性实现了引用计算器,这个值在低版本和高版本的设定有所区别。
在低版本中,有如下场景,创建了一个键值对,key和val是 a = 100,那么此时a的值对象refcount值就是1,如果我们再新增一个键值对,key和val是b = 100,那么a和b的refcount的值都是2。但是在高版本中,同样使用object refcount key测试的时候结果截然不同,查看源码得知,在高版本中,redis把一个对象设置为共享状态的时候,就会把refcount的值设置为固定的INT_MAX,所以是2147483647。而且redis把0~9999的数值默认设定为共享的状态,当服务器使用这些值的时候,会使用共享对象而不是新创建。
虽然共享对象可以节约内存,但是如果共享一些结构比较复杂的对象,会导致对象比较的时间复杂度提高,受制于cpu计算时间的限制,redis只会对包含整数值的字符串对象进行共享。同理,如果refcount的值变为0时,表示对象没有被其他结构所共享了,它所占用的内存就会被服务器释放。
很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403
前言 本文分享vtkCoordinate源码解析,并对VTK中的各种坐标变换进行分析,希望对各位小伙伴有所帮助!
感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!
你的点赞就是我的动力(^U^)ノ~YO
1. vtkCoordinate 在VTK的各种坐标系统中,执行坐标变换,并表示位置(Position)。也可以创建一个相互引用的vtkCoordinate对象。
vtkCoordinate对象允许引用,即一个vtkCoordinate对象A可以引用另一个vtkCoordinate对象B,vtkCoordinate对象B也可以引用其他vtkCoordinate对象,依此类推,但是不能形成自循环。这允许你创建像vtkActor2D这样的组合组,它们的位置相对于另一个。注意,在级联序列中,每个vtkCoordinate对象可以在不同的坐标系中指定!。例如在vtkCaptionActor2D的定义中AttachmentPointCoordinate在WORLD坐标系中指定;PositionCoordinate在DISPLAY坐标系中指定。
VTK中的坐标系统有如下几种:
DISPLAY坐标系统:表示在窗口上的x,y的像素值
最小值:(0, 0)表示左下角的第一个像素。
最大值:(Size,Size)表示右上角的最后一个像素
NORMALIZED DISPLAY坐标系统:表示归一化后的窗口像素值。
最小值:(0, 0)表示左下角的第一个像素。
最大值:(1,1)表示右上角的最后一个像素
VIEWPORT坐标系统:表示Viewport上的x,y像素值
最小值:(0, 0)表示左下角的第一个像素。
最大值:(Size,Size)表示右上角的最后一个像素
NORMALIZED VIEWPORT坐标系统:表示归一化后的Viewport的像素值
最小值:(0, 0)表示左下角的第一个像素。
最大值:(1,1)表示右上角的最后一个像素
POSE坐标系统:WORLD坐标系统相对于相机位置和View方向进行的移动和旋转坐标系统。
VIEW坐标系统:相机所看到的坐标系统,取值为【-1,1】。x,y值表示像平面上的位置,Z值表示到相机的距离。相机负责将WORLD坐标系变换到VIEW坐标系。
WORLD坐标系统:世界坐标系
USERDEFINED坐标系统:表示在用户定义的坐标系统下的值。
2. VTK中各坐标系统关系 Model坐标系统:指定义模型时所采用的坐标系统。
World坐标系统:放置Actor的三维空间系统。
vtkActor负责将模型从Model坐标系转化到World坐标系。
VTK中一个窗口可以放置多个Renderer(即ViewPort)。
renderer1->SetViewport(0.,0.,0.5,0.5); renderer1->SetViewport(0.,0.5,0.5,1.0); renderer1->SetViewport(0.5,0.,1.,0.5); renderer1->SetViewport(0.5,0.5,1.0,1.0); 3. vtkCoordinate重要参数 3.1 设置/获取当前的坐标系统 //@{ /** * Set/get the coordinate system which this coordinate * is defined in. The options are Display, Normalized Display, * Viewport, Normalized Viewport, View, and World.
在数字化时代,企业需要借助先进的数字化技术来提高工程管理效率和质量。招投标管理系统作为企业内部业务项目管理的重要应用平台,涵盖了门户管理、立项管理、采购项目管理、采购公告管理、考核管理、报表管理、评审管理、企业管理、采购管理和系统管理等多个方面。该系统以项目为主线,从项目立项到项目归档,实现数据信息的实时共享、规范化管理和有效监控。它通过有效沟通、高效流转与协作,实现工作协同、数据集中化,减少出错率,提高招标工作效率。
功能描述
1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。
2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看所有的立项信息。主要功能包含:招标立项申请、非招标立项申请、采购立项管理。
3、采购项目管理:可对项目采购过程全流程管理,包含功能有:评审人员的选取/抽取、基准价维护、供应商缴费审核、投标过程记录查询、供应商报价维护、项目评审查询、线下项目管理、采购计划制定与维护。
4、采购公告管理:可对项目采购全过程所需发布的公告进行管理。主要功能包含:招标公告管理、变更公告管理、终止公告管理、中标候选人公告管理、中标公告管理、采购公告管理、采购结果公告管理、单一来源采购结果公告管理。
5、考核管理:对已完成招标采购项目的供应商和代理机构进行考核管理,主要功能包含:项目考核分派管理、项目考核查询、项目考核管理。
6、报表管理:以不同维度统计系统的项目信息、供应商信息、评审专家信息。主要功能包含:采购项目分析、评审人员情况分析、供应商情况分析、采购情况分析。
7、评审管理:对采购过程中所有需要评审的项目进行评审管理。
8、企业管理:供应商可维护企业基本信息,对企业发布的招标采购项目进行报名投标工作。主要功能包含:基本信息管理、项目管理、投诉建议管理。
9、采购管理:招标代理机构可查看项目基本信息,并根据业主方需求进行招标工作,发布招标等公告,主要内容包含:项目管理、公告管理。
10、系统管理:管理系统基础信息,包含系统使用的菜单、角色、用户、机构、数据字典信息。
11、基础数据管理:对支持系统使用过程中需要用到的基础数据维护及管理。主要功能包含:公告模板管理、评审人员管理、第三方机构管理、供应商管理、采购类别设置、评审模板管理、考核模板管理。
招投标管理系统-适合于招标代理、政府采购、企业采购、工程交易等业务的企业
招投标管理系统是一个用于内部业务项目管理的应用平台。以项目为主线,从项目立项,资格预审,标书编制审核,招标公告,项目开标,项目评标,项目公示,确定中标人,项目归档, 通过这个平台进行有效沟通、高效流转与协作。实现项目数据信息实时共享,规范化管理及有效监控,实现工作协同,工作网络化、数据集中化,减少出错率,提高招标工作效率。
招投标管理系统是一个适合招标代理、政府采购、企业采购和工程交易等业务的企业使用的应用平台。它通过以项目为主线的管理方式,实现了从项目立项到项目归档的全面管理。该系统不仅提供了多种管理功能,如立项管理、采购项目管理、采购公告管理等,还实现了对项目数据信息的实时共享、规范化管理和有效监控。这有助于企业提高招标工作效率和质量,减少出错率,实现工作协同和数据集中化。
引起该不适的一种可能以及解决方案,网上较多,比如:
但按以上方式操作,并经过查看,发现仍然未能解决问题。
因为两种方式执行,有一种能成功,有一种不能,刚开始未怀疑是文件问题,最后经测试,发现问题原因以及修复方法,记录如下:
注意下图标红两处的差异,差异一个“/”。
至此,Shell脚本-bin/bash: 解释器错误: 没有那个文件或目录-完整路径执行时提示错误问题得到解决。
简单做了个模板,能干这个:
指定sheet中某列数据进行按需拆分,拆分后新建一个test的sheet,将数据分别存入test的不同列中。
import os import xlwings as xw import re #excel路径 path=r'C:\Users\xxx\Desktop\123.xlsx' #设置需要分列的sheet名 sheetname='Sheet1' #设置需要分列的列名 colname='B' #开始单元格 rowb=2 #结束单元格 rowe=25 def excel分列(path): excelapp=xw.App(visible=False, add_book=False) #打开excel excel = excelapp.books.open(path) #获取sheets sheet = excel.sheets #增加一个拆分用sheet,test if sheet[0].name !='test': sheet.add('test', before=sheet[0].name) #print(sheet[0].name) sheet2 = excel.sheets['Sheet1'] #设置拆分条件,这里以复合字串为例,型如:你好123+好的234,拆成:你好,123,+,好的234 num1=re.compile('\w.[0-9]') #print(re.findall(num1,sheet2.range('b2:b25').value[0])[0][:-1]) num2=re.compile('\d++') #print(re.findall(num2,sheet2.range('b2:b25').value[0])[0]) num3=sheet2.range('b2:b25').value[0].split('+') #print(num3[1]) t1=[] t2=[] t3=[] t4=[] #拆分取值 for i in sheet2.range(colname+str(rowb)+':'+colname+str(rowe)).value: t1.append(re.findall(num1,i)[0][:-1]) t2.append(re.findall(num2,i)[0]) t3.append('+') t4.append(i.split('+')[1]) #print(t1,t2,t3,t4) #将拆分数据填入test中 sheet3=excel.sheets['test'] for i in range(len(t1)): sheet3.
一、HTTPS定义 超文本传输安全协议(HyperText Transfer Protocol Secure,缩写:HTTPS)是一种通过计算机网络进行安全通信的传输协议。
HTTPS经由HTTP进行通信,利用SSL/TLS来加密数据包。其主要目的,是提供对网站服务器的身份认证,保护交换资料的隐私与完整性。
二、HTTPS流程 一般而言HTTPS需要基于DNS域名系统(Domain Name System),它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用UDP端口53;
当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。
域名解析过程 操作系统会首先检查自己本地的hosts文件是否有该网址映射关系,如果有就直接调用ip地址映射完成解析;
查找本地dns解析器缓存是否有该网址映射关系,如果有就直接返回完成域名解析;
查询tcp/ip参数中设置的首选dns服务器,此服务器收到查询时,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析;
如果该服务器缓存了此网址映射关系,则调用这个ip地址映射,完成域名解析;
根据本地dns服务器的设置进行查询,当未使用转发模式,本地dns就把请求发至13台根dns服务器,根dns服务器收到请求后会判断这个域名是谁来授权管理,并返回一个负责该顶级域名服务器的一个ip。当本地dns服务器收到这个地址后,就会找到该域名服务器,重复上面的动作进行查询直到找到该域名主机;
如果使用转发模式,此dns服务器就会把请求转发至上一级dns服务器,由上一级服务器进行解析,如此循环。
HTTP组成 协议组成:
起始行(start line),描述请求或响应的基本信息(方法&空格&url&空格&版本号&回车换行);
头部字段(header),使用key-value形式更详细的说明报文;
消息正文(entity),实际传输的数据;
起始行和头部字段合并成为请求头或响应头,即Header;
消息正文即body,Header与body之间有一个空行(CRLF);
请求方法:
GET获取资源,请求访问已被uri识别的资源;
POST传输实体;
PUT传输文件;
HEAD获得响应首部,与GET相同,只是不返回报文主体;
DELETE删除文件;
OPTIONS询问支持的方法,用来查询针对uri指定资源支持的方法;TRACE追踪路径,服务端将之前的请求通信环返还给客户端;CONNECT要求使用隧道协议连接代理,实现用隧道协议进行TCP通信。
TCP/UDP TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层(Transport layer)通信协议,当客户端和服务端彼此传输数据前,必须先在双方之间建立连接,之后才能传输数据;
TCP协议使用超时重传、数据确认等方式来确保数据包被正确的发送;
UDP(User Datagram Protocol)是一种无连接、不可靠、基于数据包的用户数据协议;
UDP传输数据包前不需要在客户端和服务端之间建立连接,只是把包发出去;
容易丢包,效率高;
TCP连接流程:
客户端发送syn包(syn=x)到服务端,并进入SYN_SENT状态,等待服务端确认;
服务端收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
客户端收到服务端的SYN+ACK包,向服务端发送确认包ACK(ack=y+1),客户端和服务端进入ESTABLISHED(TCP连接成功)状态;
TCP断开流程:
客户端向服务端发送的报文中FIN设置为1,请求与服务端断开连接;
服务端收到FIN报文,返回确认应答包(ACK);
服务端发送FIN报文段,请求关闭连接;
客户端想服务端发送ACK报文段,服务端收到后直接断开连接,客户端等待2ms后断开;
一般而言使用UDP时通过广播找到目标地址,然后点对点进行数据传输。
HTTPS加密流程 客户端发起一个HTTPS请求,请求服务器公钥,连接443端口,还包含此时客户端生成的随机数(Client Random);
服务端收到请求后生成一对公私钥和一个随机数(Server Random),把公钥以数字证书的形式加上刚才生成的随机数(Server Random)返回给客户端;证书中有一个公钥(CA)来加密信息,私钥(CA)由服务端持有;
客户端收到数字证书后,先验证证书的合法性;
验证通过后,客户端生成一个随机值(pre-master),并用服务器生成的公钥加密,发给服务端;
服务端收到随机值(pre-master)后,使用私钥进行解密,通过(Client Random、Server Random、pre-master)随机数合成会话密钥(对称加密);
双方使用该密钥对传输信息加密;
客户端和服务端相互发送摘要信息(Encrypted Handshake Message(Finishd)),使用会话密钥加密验证是否被篡改过。
文章目录 1. 系统信息参数说明2. Docker安装3. minikube安装4. kubectl安装5. Helm安装6. 启动Kubernetes集群v1.28.37. 使用helm安装Prometheus8. 使用helm安装Grafana9. Grafana的Dashboard设定10. 设定Prometheus数据源11. 导入Kubernetes Dashboard12. 实验过程中的常见问题13. 参考链接 1. 系统信息参数说明 [root@minikube ~]# uname -a Linux minikube 5.14.0-284.11.1.el9_2.x86_64 #1 SMP PREEMPT_DYNAMIC Tue May 9 17:09:15 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux [root@minikube ~]# hostnamectl Static hostname: minikube Icon name: computer-vm Chassis: vm 🖴 Machine ID: 8f112fe303914f1e8e27c6b68d205117 Boot ID: 75046d09558f47d9a823fff033cb1fe1 Virtualization: vmware Operating System: Rocky Linux 9.2 (Blue Onyx) CPE OS Name: cpe:/o:rocky:rocky:9::baseos Kernel: Linux 5.
文章目录 【 1. 配置 】【 2. 编译 】makefile编写的要点makefile中的全局自变量CMake编译依赖的库g++编译 【 3. 安装 】 一般源代码提供的程序安装需要通过配置、编译、安装三个步骤; 配置。检查当前环境是否满足要安装软件的依赖关系,以及设置程序安装所需要的初始化信息,比如安装路径,需要安装哪些组件;配置完成,会生成 makefile文件 供第二步make使用。编译。是对源文件进行编译链接生成可执行程序。安装。将生成的可执行文件拷贝到配置时设置的初始路径下。 【 1. 配置 】 查询可用的配置选项 ./configure --help 配置路径
–prefix 是配置使用的最常用选项,设置程序安装的路径。 ./configure --prefix=/usr/local/snmp 【 2. 编译 】 编译使用make编译:
通过-f选项显示指定需要编译的makefile;如果待使用makefile文件在当前路径,且文件名为以下几个,则不用显示指定。 make -f myMakefile makefile编写的要点 必须满足第一条规则,满足后停止。除第一条规则,其他无顺序。 makefile中的全局自变量 $@目标文件名@^所有前提名,除副本@+所有前提名,含副本@<一个前提名@?所有新于目标文件的前提名@*目标文件的基名称 CMake CMake 是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。能够输出各种各样的makefile或者project文件。使用CMake,能够使程序员从复杂的编译连接过程中解脱出来。它使用一个名为 CMakeLists.txt 的文件来描述构建过程,可以生成标准的构建文件,如 Unix/Linux 的 Makefile 或Windows Visual C++ 的 projects/workspaces 。
编译依赖的库 链接多库时,多个库之间如果有依赖,需要注意书写的顺序,右边是左边的前提。makefile编译过程中所依赖的非标准库和头文件路径需要显示指明: CPPFLAGS -I标记非标准头文件存放路径 LDFLAGS -L标记非标准库存放路径 如果CPPFLAGS和LDFLAGS已在用户环境变量中设置并且导出(使用export关键字),就不用再显示指定 make -f myMakefile LDFLAGS='-L/var/xxx/lib -L/opt/mysql/lib' CPPFLAGS='-I/usr/local/libcom/include -I/usr/local/libpng/include' g++编译 基本语法 -o:指明生成的目标文件。-g:添加调试信息。-E:查看中间文件。 g++ -o unixApp unixApp.
前言 最近终于有机会从围墙里往外看,了解到外面的世界已经有了天翻地覆的变化,感叹万千,笔者在本地mac,windows,linux,docker部署了不下20遍后,整理出来的linux极简避坑安装方案,供大家参考学习。
注 系统:linux
用户:py
python:3.10
涉及工具:wget、miniconda、git
Stable Diffusion WebUI简称:webui
安装目录:/data/
github地址 https://github.com/AUTOMATIC1111/stable-diffusion-webui
安装 miniconda 由于stable-diffusion-webui的安装需要特定的python版本,所以使用工具管理python库,且由于Anaconda过于臃肿,所以选择miniconda
# 安装wget工具,确保可以使用下载功能 yum install -y wget # 安装miniconda wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh # 执行权限 chmod +x Miniconda3-latest-Linux-x86_64.sh # 新建用户 py ## 由于webui默认不允许root用户执行,且新建用户更好的管理python useradd py # 新建目录 /data # 将安装脚本移动到/data,方便管理 mv Miniconda3-latest-Linux-x86_64.sh /data/ #将data目录授权给py chown -R py:py /data # 安装miniconda # 切换用户 su - py cd /data ./Miniconda3-latest-Linux-x86_64.sh ##遇到输入写yes,其他按回车,安装完成 #安装完成后,默认没有(base)前缀,是环境还未生效,需要手动source source /home/py/.bashrc # 就会发现控制台由 [py@localhost ~]$ #变成了 (base) [py@localhost ~]$ # miniconda 安装完成 python 环境 # 使用conda 安装webui需要使用的环境 conda create --name sd python=3.
前言 本文为笔者个人阅读Apache Impala源码时的笔记,仅代表我个人对代码的理解,个人水平有限,文章可能存在理解错误、遗漏或者过时之处。如果有任何错误或者有更好的见解,欢迎指正。
上一篇文章Impala4.x源码阅读笔记(二)——Impala如何高效读取Iceberg表简单介绍了Iceberg表的基本情况和Impala是如何对其进行扫描的。这一篇则从元数据的角度对Impala如果管理Iceberg元数据进行一些简单的分析,这里的Iceberg元数据不是指Iceberg的那些元数据文件,那些是Iceberg API负责管理的,这里的元数据是指Iceberg表在Impala中的那些内存对象。
为了提升查询性能,Impala本身有一套比较复杂的元数据管理机制,这套机制以Catalogd服务进程为核心,实现了元数据在集群内的集中管理。在一个完整的Impala集群中,Catalogd服务进程主要担任了两个角色,首先是一个自动化的元数据缓存,它会负责缓存并自动同步Hive Metastore中的元数据,并将其广播给集群中其他负责处理查询的Coordinator节点,这使得Coordinator可以省去每次查询时和Hive Metastore(HMS)以及HDFS Namenode(NN)的交互,从而缩短了查询耗时。Catalogd的另一个角色是一个集中式的DDL执行者,其他Coordinator节点接收到的DDL最终都会以RPC的形式交由Catalogd进行执行,这样使得集群内部的元数据统一得到了保证。
Iceberg表作为一种表格式而非文件格式,其核心目标是高效且多功能地管理大量的数据文件,为了达成这一目标,Iceberg表的元数据相较于Hive表也更加复杂,从Impala支持Iceberg表的代码大部分都是元数据相关的也能看出这一点。关于Iceberg元数据管理的代码十分庞大,想要在一篇文章内全面地分析一遍是不太现实的,所以本文首先还是整体地、笼统地描述一下Iceberg表元数据的全貌,然后着重对元数据管理的两个关键环节——Iceberg表的加载和创建进行分析。
Iceberg表的相关接口 由于Impala本身元数据管理的特性和Iceberg表元数据的特殊性,在Impala支持Iceberg表各项功能的过程中定义了很多类型,我们首先看一下Iceberg相关类的整体UML图:
图中画出了Iceberg表在Impala中的主要相关接口和类以及其之间的实现或继承关系,其中绿色背景的就是与Iceberg表直接相关的,每个接口和类中都只列举了个别关键的成员变量和方法。在介绍具体的类之前我们先看一下其中的几个接口。
FeTable 首先是Impala中所有类型的表都要实现的接口FeTable,它定义了Impala Frontend与各类型表交互的一些基本操作,比如获取获取库表名、数据列列表、所有者等,其中还包括了可以获取org.apache.hadoop.hive.metastore.api.Table对象的getMetaStoreTable()方法。因为Impala对HMS是强依赖的,基本上所有元数据都来自HMS,为了与HMS进行元数据交互,Impala中所有类型的表中都包括一个HMS中表对象也就是org.apache.hadoop.hive.metastore.api.Table。它为Impala的表提供了基本的元数据,比如库表名、字段信息和表属性properties等。Iceberg表在Impala也不例外,需要在HMS注册了才能被Impala查询。当然Iceberg表本身并不一定依赖HMS,比如使用HadoopCatalog创建的Iceberg表只依赖一个像HDFS一样的支持原子重命名文件的文件系统而已。对于这种Iceberg表需要先在Impala中通过创建外表的方式在HMS进行注册才能被Impala元数据管理所接受。
FeFsTable FeFsTable是Impala中所有基于文件系统的表类型都要实现的接口,它继承了FeTable接口,作用也是类似的。像存储在HDFS、S3这种常见的文件系统或存储服务上的表都属于FeFsTable,Iceberg表自然也是FeFsTable。在FeTable的基础之上,FeFsTable额外定义了许多和文件系统相关的方法,比如获取文件系统类型、表位置和文件系统对象FileSystem等。
FeIcebergTable FeIcebergTable是Impala中Iceberg表类型都要实现的接口,继承了FeFsTable并额外定义了关于Iceberg的通用方法。其中有几个关键方法需要重点介绍:
getFeFsTable(),它会返回Iceberg对象内置的一个FeFsTable对象,这个对象会被用于将Iceberg表传递给Impala Backend。我们知道在Impala中Frontend负责制定执行计划、Backend负责执行,两者分别由Java和C++开发,之间主要通过Thrift结构体传递数据,这些数据也包括了查询的执行计划。而Iceberg表在执行期间与普通HDFS表实际上并没有显著差别,可以说都只是一系列规划好的数据文件而已。因此,为了复用Backend中现有的HDFS表扫描代码,Iceberg表对象都内置了一张普通HDFS表对象,在序列化为Thrift结构体传递给Backend时就使用这个内置的FeFsTable对象的相关方法将自身“转变”为HDFS表。
getIcebergApiTable(),它会返回Iceberg表对象对应的Iceberg API中的表对象org.apache.iceberg.Table,这是Iceberg API中的表示Iceberg表的接口,它提供了Iceberg表的许多重要API,比如获取快照、Schema和扫描计划。依靠这些接口,Impala可以进行Iceberg表的时间旅行查询、模式演进、谓词下推和获取数据文件列表等操作。
getIcebergCatalog(),它会返回Iceberg表的Catalog类型,目前Impala支持的Iceberg Catalog类型有HadoopTables、HadoopCatalog、HiveCatalog和Catalogs。Iceberg的Catalog是用于追踪Iceberg表的,它主要负责储存Iceberg表最近元数据文件的位置,可以说是Iceberg表元数据的元数据。换句话说如果说Iceberg表是管理一系列数据文件并告诉我们数据文件在哪里,那么Iceberg Catalog的作用就是管理一系列Iceberg表并告诉我们Iceberg表在哪里。如果Iceberg表的最近元数据位置也直接储存在文件系统的一个文件中,则对应HadoopTables。如果文件系统中有一个专门的Catalog目录,Iceberg表的元数据位置由其负责管理,则对应HadoopCatalog。如果使用HMS储存Iceberg表的最近元数据位置,则对应HiveCatalog。而Catalogs接口相当于一种复合的自动Catalog,它依赖配置文件和表属性自动识别Iceberg表的Catalog类型。
接口FeIcebergTable可以说是Iceberg表在Impala中的关键抽象,从图中也可以看到许多Iceberg表的相关类实现了该接口。
Iceberg表的相关类 介绍完了相关接口之后,我们接下来继续看看Iceberg相关的类。从图中可以看到与Iceberg直接相关的表类型就有足足七种,当然其中除了IcebergTable和LocalIcebergTable这两个真正表示实际存在的Iceberg表的“正经”表类型外,其他的都可以算是为了支持各种Iceberg特性而抽象出来的功能性的工具类。接下来我们逐个介绍。
IcebergTable IcebergTable是Iceberg表在Impala元数据管理中的代理类之一,每个对象都是对应了一张实际存在的Iceberg表。IcebergTable实现了FeIcebergTable接口并继承了Table类。Table类是Impala中所有表类的主要父类之一(另一个是LocalTable),它是一个抽象类,实现了FeTable接口,它定义了所有表共有的一些成员变量,如库对象、表名、所有者、表锁和数据列容器等等,它还定义了表对象共有的一些成员方法,其中最重要的就是实现表加载的抽象方法load()以及Coordinator接收到Catalogd服务广播的元数据Thrift结构体后从Thrift结构体加载元数据的loadFromThrift(TTable)方法。IcebergTable作为Table的子类,实现了自己的load()方法来加载Iceberg表,除此之外还包括一些特有的成员,如前文提到的内置的HDFS表对象hdfsTable_、Iceberg API表对象icebergApiTable_和从Iceberg元数据加载Schema的方法loadSchemaFromIceberg()等等。
LocalIcebergTable LocalIcebergTable可以理解为IcebergTable的Local版本,它只在Coordinator的Local Catalog模式下使用,而IcebergTable会在Catalogd和Coordinator的传统Catalog模式下使用,LocalIcebergTable在Coordinator的作用和IcebergTable基本是一致的,可以说是更加轻量化的IcebergTable。Local Catalog模式是为了解决传统Catalog模式的一些缺点而设计的,它支持更细粒度的元数据缓存并能在启动时按需加载元数据,提升了Coordinator的启动速度并减少了内存消耗。LocalIcebergTable同样实现了FeIcebergTable接口,但是继承的是LocalTable类,而不是Table类。LocalTable类也是抽象类,是Table类的Local版本,其成员LocalDb这是Db类的Local版本。如同IcebergTable一样,LocalIcebergTable也内置了一张HDFS表对象,不过不再是HdfsTable类了,而是其Local版本的LocalFsTable,这些Local类都是只在Coordinator的Local Catalog模式下使用的,和非Local版本一一对应。
IcebergPositionDeleteTable IcebergPositionDeleteTable是用于Iceberg MOR的虚拟表,在上一篇文章中其实已经登场过了,它只在制定Iceberg的Position Delete扫描计划中会被使用到,用来将Iceberg表的Delete File组织为一张虚拟表,这样才能使用Impala的ScanNode进行扫描,具体的使用过程可以参考上一篇文章Impala4.x源码阅读笔记(二)——Impala如何高效读取Iceberg表。IcebergPositionDeleteTable同样实现了FeIcebergTable接口,不过它继承的是表示虚拟表的抽象类VirtualTable,虚拟表不是实际存在的表,而是为了实现某些特定功能而虚拟出来的表,它往往会根据需要而添加一些虚拟列,可以将非表形式的数据以表的形式进行处理。
IcebergMetadataTable Iceberg API提供了一系列专门的元数据表来查询Iceberg表的元数据,可通过其MetadataTableUtils类来创建各种类型的Iceberg元数据表,如ManifestEntriesTable、FilesTable和SnapshotsTable等。这些元数据表基于基本的Iceberg表创建,有各自的Schema,用于查询该表的各种元数据。IcebergMetadataTable就是Impala为了对接这些Iceberg元数据表而定义的类,它是另外一个继承了VirtualTable的类,不过它并没有实现FeIcebergTable接口,因为它不是通常的Iceberg表。它可以根据一个FeIcebergTable对象和元数据表类型字符串来创建,利用MetadataTableUtils来对接Iceberg元数据表获取Schema并依此填充自身作为VirtualTable的虚拟列,执行时IcebergMetadataTable由执行引擎这边的专门的IcebergMetadataScanNode负责扫描,当然由于执行引擎是C++编写的,所以实际扫描时还是需要通过JNI调用Iceberg API来完成。
IcebergCtasTarget IcebergCtasTarget是用于CTAS(Create Table As Select)语句的临时目标表类型,它继承了CtasTargetTable类并实现了FeIcebergTable接口,不过它也不是实际存在的表,只是用于CTAS的分析过程。Impala分析CTAS语句时会将其分解为CREATE语句和INSERT语句,然后根据CREATE语句先创建临时目标表,再结合临时目标表来分析INSERT语句。如果分析过程顺利完成才会真正创建目标表。对于Iceberg表来说,临时目标表只是分析使用的,不应该通过Iceberg API实际创建它,所以需要IcebergCtasTarget来充当这一角色。IcebergCtasTarget实现了FeIcebergTable,但是并不会通过Iceberg API实际创建一张Iceberg表。
ForwardingFelcebergTable ForwardingFelcebergTable一个用于FeIcebergTable的转发类,也并非什么实际存在的表,只是一种使用组合代替继承的编程技巧,通过ForwardingFelcebergTable可以在不继承基类的前提下将不需要重写的方法委托给基类FeIcebergTable。这个类会在IcebergTimeTravelTable中使用,避免IcebergTimeTravelTable继承IcebergTable、LocalIcebergTable等类。
IcebergTimeTravelTable IcebergTimeTravelTable表示进行时间旅行的Iceberg表,由于Iceberg表时间旅行和模式演进的特性,在不同的时间点Iceberg表可能有不同的Schema,因此对于进行时间旅行的Iceberg表我们需要根据时间或版本重新加载Schema,为了避免复制或破坏原始的Iceberg元数据,Impala通过IcebergTimeTravelTable来实现时间旅行的Iceberg表。IcebergTimeTravelTable没有继承FeIcebergTable而是继承了ForwardingFelcebergTable,通过ForwardingFelcebergTable嵌入对原始Iceberg表的引用并在此基础之上实现readSchema()加载自己的Schema,而那些未涉及时间旅行的方法都可以通过ForwardingFelcebergTable委托给原始Iceberg表类的同名方法 。
至此Iceberg表在Impala中的相关类就介绍完了,可以发现除了IcebergTable和LocalIcebergTable可以真正称得上是Iceberg表的元数据之外,其他的类都是为了实现Iceberg表的各种功能而定义工具类,这些繁多的类看起来复杂,实际上本身代码量并不多,不如说正是因为定义了这些类才使得Iceberg元数据更好地融入Impala的元数据体系,也使得Impala在支持Iceberg的过程中可以大量复用现有的、可靠的、高性能的代码,反而减少了开发工作量。
Iceberg表的加载 接下来我们分析一下Iceberg表在Impala中是如何加载的,所谓表的加载实际上就是Impala根据HMS的元数据对象创建自己的元数据对象的过程,对于Iceberg也是一样的,不过Iceberg还有很大一部分元数据以文件的形式存在,需要Iceberg API处理。不过在调用IcebergTable的load()方法之前我们需要先知道它是一张Iceberg表,这一判断由其静态方法isIcebergTable()完成:
public static boolean isIcebergTable(org.apache.hadoop.hive.metastore.api.Table msTbl) { // 从HMS元数据获取InputFormat,如果是org.