首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

MySQL性能优化(七):MySQL执行计划,真的很重要,来一起学习

一条SQL被一个懵懂的少年,扔向了MySQL服务器的尽头,少年苦苦等待,却迟迟等不来那满载而归的硕果。于是少年气愤,费尽苦心想从度娘那边寻求帮助,面对执行计划EXPLAIN,却等来的是无尽的折磨与抓狂。 通过explain命令,根据执行计划找到存在性能问题的SQL语句,以帮助我们优化SQL提供方向和依据。 如果面对执行计划,你也是一脸疑惑,甚至抓狂,那么你真的需要认真的来了解它了。在数据库性能优化中,执行计划,真的很重要,通过执行计划能够帮助我们更加明确的来进行SQL优化。本文将从执行计划开始说起,讲解执行计划该如何用,其中各个列的含义究竟是什么。 一、执行计划? 执行计划,就是一条SQL语句,在数据库中实际执行的时候,一步步的分别都做了什么。也就是我们用EXPLAIN分析一条SQL语句时展示出来的那些信息。 EXPLAIN命令是查看查询优化器是如何决定执行查询的主要方法,从它的查询结果中可以知道一个SQL语句每一步是如何执行的,都经历了些什么,分为哪几步,有没有用到索引,哪些字段用到了什么样的索引,是否有一些可优化的地方等,这些信息都是我们SQL优化的依据。 要使用·EXPLAIN,只需在查询中的SELECT关键字之前增加EXPLAIN。语法如下: EXPLAIN + SELECT查询语句; 当执行执行计划时,只会返回执行计划中每一步的信息,它会返回一行或多行信息,显示出执行计划中的每一部分和执行的次序。 如: 如果查询的是多个关联表,执行计划结果可能是多行。 在接下来涉及到的示例表,均来自于MySQL官方的示例数据库sakila,脚本下载:https://downloads.mysql.com/docs/sakila-db.zip 二、执行计划中的列 EXPLAIN的结果总是有相同的列,每一列代表着不同的含义,可变的只是行数和内容。从上面的例子中,我们看到返回的有很多列,为了更加清楚的了解每一列的含义,便于我们更好的完成优化SQL。 涉及到的列有: 列名 含义 id id列,表示查询中执行select子句或操作表的顺序。 select_type 查询类型,主要是用于区分普通查询、联合查询、子查询等复杂的查询。 table 表明对应行正在访问的是哪个表。 partitions 查询涉及到的分区。 type 访问类型,决定如何查找表中的行。 possible_keys 查询可以使用哪些索引。 key 实际使用的索引,如果为NULL,则没有使用索引。 key_len 索引中使用的字节数,查询中使用的索引的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。 ref 显示索引的那一列被使用。 rows 估算出找到所需行而要读取的行数。 filtered 返回结果的行数占读取行数的百分比,值越大越好。 Extra 额外信息,但又十分重要。 1. id列 id列是一个编号,用于标识SELECT查询的序列号,表示执行SQL查询过程中SELECT子句或操作表的顺序。 如果在SQL中没有子查询或关联查询,那么id列都将显示一个1。否则,内层的SELECT语句一般会顺序编号。 id列分为三种情况: 1)id相同 如下普通查询,没有子查询。 explain select f.* from film f,film_actor fa,actor a where f.film_id = fa.film_id and fa.actor_id = a.actor_id and a.first_name = 'NICK'; 2)id不同 如果存在子查询,id的序号会递增,id值越大优先级越高,越先被执行。 explain select * from film where film_id = (select film_id from film_actor where actor_id = 2 limit 1); 3)id相同又不同 1)、2)两种情况同时存在。id如果相同,认为是一组,从从上往下执行。在所有组中,id值越大,优先级越高,越先执行。 2. select_type列 select_type列表示对应行的查询类型,是简单查询还是复杂查询,主要用于区分普通查询、联合查询、子查询等复杂的查询。 select_type列有如下值: select_type值 说明 SIMPLE 简单查询,意味着不包括子查询或UNION。 PRIMARY 查询中包含任何复杂的子部分,最外层查询则被标记为PRIMARY SUBQUERY 在select 或 where列表中包含了子查询 DERIVED 表示包含在from子句的子查询中的select,MySQL会递归执行并将结果放到一个临时表中,称其为“派生表”,因为该临时表是从子查询中派生而来的。 UNION 第二个select出现在UNION之后,则被标记为UNION。 UNION RESULT 从UNION表获取结果的select。 3. table列 table列表示对应行正在执行的哪张表,指代对应表名,或者该表的别名(如果SQL中定义了别名)。 4. partitions列 查询涉及到的分区。 5. type列 type列指代访问类型,是MySQL决定如何查找表中的行。 是SQL查询优化中一个很重要的指标,拥有很多值,依次从最差到最优: ALL < index < range < index_subquery < unique_subquery < index_merge < ref_or_null < fulltext < ref < eq_ref < const < system 1)ALL 众所周知的全表扫描,表示通过扫描整张表来找到匹配的行,很显然这样的方式查询速度很慢。 这种情况,性能最差,在写SQL时尽量避免此种情况的出现。 举例如下: explain select * from film; 在平时写SQL时,避免使用select *,就不难理解了。换言之,是为了避免全表扫描,因为全面扫描是性能最差的。 2)index 全索引扫描,和全表扫描ALL类似,扫描表时按索引次序进行,而不是按行扫描,即:只遍历索引树。 index与ALL虽然都是读全表,但index是从索引中读取,而ALL是从硬盘读取。显然,index性能上优于ALL,合理的添加索引将有助于性能的提升。 举例如下: explain select title from film; explain select description from film; 通过explain结果来看,只查询表film中字段title时,是按照索引扫描的(type列为index),倘若查询字段description,却是按照全表扫描的(type列为ALL)。这是为何呢? 接下来,我们不妨看看表film的结构: 从desc film结果来看,字段title创建的有索引,而字段description没有,所以select title from film是按索引扫描,而select description from film按全表扫描。 从上面的举例对比中,也充分印证了索引的重要性。 3)range 只检索给定范围的行,使用一个索引来选择行。key列显示使用了那个索引。一般就是在where语句中出现了bettween、<、>、in等的查询。这种索引列上的范围扫描比全索引扫描index要好。 举例如下: explain select * from film where film_id between 1 and 10; 4)ref 非唯一性索引扫描,返回匹配某个单独值的所有行。本质是也是一种索引访问,它返回所有匹配某个单独值的行,然而它可能会找到多个符合条件的行,所以它属于查找和扫描的混合体。 此类型只有当使用非唯一索引或者唯一索引的非唯一性前缀时,才会发生。 举例如下: show index from film; explain select * from film where title = 'ACADEMY DINOSAUR'; 5)eq_ref **唯一索引扫描。**常见于主键或唯一索引扫描。 6)const 通过索引一次就能找到,const用于比较primary key 或者 unique索引。因为只需匹配一行数据,所有很快。如果将主键置于where列表中,mysql就能将该查询转换为一个const。 举例如下: show index from film; explain select * from film where film_id = 1; 7)system 表只有一行记录,这是const类型的特例,比较少见,如:系统表。 6. possible_keys列 显示在查询中使用了哪些索引。 7. key列 实际使用的索引,如果为NULL,则没有使用索引。查询中如果使用了覆盖索引,则该索引仅出现在key列中。 possible_keys列表明哪一个索引有助于更高效的查询,而key列表明实际优化采用了哪一个索引可以更加高效。 举例如下: show index from film_actor; explain select actor_id,film_id from film_actor; 8. key_len列 表示索引中使用的字节数,查询中使用的索的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。key_len是根据表定义计算而得的,不是通过表内检索出的。 9. ref列 表示在key列记录的索引中查找值,所用的列或常量const。 10. rows列 估算出找到所需行而要读取的行数。 这个数字是内嵌循环关联计划里的循环数,它并不是最终从表中读取出来的行数,而是MySQL为了找到符合查询的那些行而必须读取行的平均数,只能作为一个相对数来进行衡量。 11. filtered列 返回结果的行数占读取行数的百分比,值越大越好。 举例如下: 表film_actor中actor_id为1的记录有19条,而SQL查询时扫描了19行(rows:19),19条符合条件(filtered: 100 19/19) 12. Extra列 额外信息,但又十分重要。 常见的值如下: 1)Using index 表示SQL中使用了覆盖索引。 举例如下: 2)Using where 许多where条件里是涉及索引中的列,当它读取索引时,就能被存储引擎检验,因此不是所有带·where子句的查询都会显示“Using where”。 3)Using temporary 对查询结果排序时,使用了一个临时表,常见于order by 和group by。 4)Using filesort 对数据使用了一个外部的索引排序,而不是按照表内的索引进行排序读取。也就是说MySQL无法利用索引完成的排序操作成为“文件排序”。 三、总结 通过上述对执行计划的了解,我们能够从中得到什么? SQL如何使用索引 复杂SQL的执行顺序 查询扫描的数据函数 …… 当面临不够优的SQL时,我们首先要查看其执行计划,根据执行计划结果来分析可能存在哪些问题,从而帮助、指导我们是否添加索引、是否调整SQL顺序、是否避免不应该的书写方式等等。 以上就是这篇文章的全部内容,希望本文的内容对大家在SQL性能优化、SQL书写时,有一定的帮助。 执行计划,真的很重要,尤其是SQL调优时,很香!

优秀的个人博客,低调大师

Waifu2x-Extension-GUI v2.71.21-beta 发布,机器学习多媒体处理应用

Waifu2x-Extension-GUI v2.71.21-beta 已经发布。 ⚠ 这是一个测试版本, 点击这里下载稳定版本⚠ 此版本更新内容包括: 最大线程数量将不再受到CPU逻辑核心数量的限制. 加快组装GIF的速度. 修复bug: 暂停后修改视频片段时长然后继续处理会造成视频顺序错乱. Download: ➡Github.com ➡Sourceforge.net 下载: ➡超星云盘(不限速, 直链) ➡百度网盘 提取码: 4nwr Waifu2x-Extension-GUI是什么? 借助深度卷积神经网络对图片&GIF&视频进行超分辨率放大(即放大与降噪). 主要特性: 自动化处理多种媒体: 支持处理 图片 的同时,实现了自动化处理 GIF 和 视频. 全图像风格支持: 内置多种算法, 无论是 二次元动漫 还是 您日常拍摄的照片&录像 ,都可以进行清晰化处理. 强大的兼容性: 内置多个引擎, 几乎与所有现代 Windows PC 兼容. 灵活的多线程设定: 在为每个引擎提供完备的设置项的同时,您也可以自由调整线程数量,充分利用PC的一切性能. 多GPU支持: 内置的所有引擎均可支持多显卡,充分利用您的PC的所有性能. 众多自定义设置: 您可以通过调整软件内的众多自定义设置实现自动化的工作流. 智能设定: 本软件可根据您的PC硬件信息和您要处理文件的信息自动调整部分软件设定. 易于使用的图形用户界面. 持续的维护与更新. 内置图像处理算法: Waifu2x / SRMD / RealSR / Anime4K / ACNet 内置图像处理引擎: Waifu2x-caffe / Waifu2x-converter / Waifu2x-ncnn-vulkan / SRMD-ncnn-vulkan / RealSR-ncnn-vulkan / Anime4KCPP 已经在AMDRX 550,NVIDIAGeForce GTX 1070 和IntelUHD 620 上通过测试. 详情查看:https://gitee.com/aaronfeng0711/Waifu2x-Extension-GUI/

优秀的个人博客,低调大师

Waifu2x-Extension-GUI v2.58.14-beta 发布,机器学习多媒体处理应用

Waifu2x-Extension-GUI v2.58.14-beta 已经发布。 ⚠ 这是一个测试版本, 点击这里下载稳定版本⚠ 此版本更新内容包括: v2.58.14-beta: NEW Feature: Now you can adjust the horizontal width of the file list. Move [Move to Recycle Bin] option to Right-click menu of [Delete original files] Other improvements to the GUI. Notify users GPU ID list is empty when they try to enable Multi-GPU. Optimize performance. Download: ➡github.com ➡sourceforge.net ➡超星云盘直链 (Only for users in People's Republic of China) Waifu2x-Extension-GUI是什么? 借助深度卷积神经网络对图片&GIF&视频进行超分辨率放大(即放大与降噪). 主要特性: 自动化处理多种媒体: 支持处理 图片 的同时,实现了自动化处理 GIF 和 视频. 全图像风格支持: 内置多种算法, 无论是 二次元动漫 还是 您日常拍摄的照片&录像 ,都可以进行清晰化处理. 强大的兼容性: 内置多个引擎, 几乎与所有现代 Windows PC 兼容. 灵活的多线程设定: 在为每个引擎提供完备的设置项的同时,您也可以自由调整线程数量,充分利用PC的一切性能. 多GPU支持: 内置的所有引擎均可支持多显卡,充分利用您的PC的所有性能. 众多自定义设置: 您可以通过调整软件内的众多自定义设置实现自动化的工作流. 智能设定: 本软件可根据您的PC硬件信息和您要处理文件的信息自动调整部分软件设定. 易于使用的图形用户界面. 持续的维护与更新. 内置图像处理算法: Waifu2x / SRMD / RealSR / Anime4K / ACNet 内置图像处理引擎: Waifu2x-caffe / Waifu2x-converter / Waifu2x-ncnn-vulkan / SRMD-ncnn-vulkan / RealSR-ncnn-vulkan / Anime4KCPP 已经在AMDRX 550,NVIDIAGeForce GTX 1070 和IntelUHD 620 上通过测试. 详情查看:https://gitee.com/aaronfeng0711/Waifu2x-Extension-GUI/releases/v2.58.14-beta

优秀的个人博客,低调大师

Waifu2x-Extension-GUI v2.58.02-beta 发布,使用机器学习放大 图片/视频/GIF

Waifu2x-Extension-GUI v2.58.02-beta 已经发布。 ⚠ 这是一个测试版本, 点击这里下载稳定版本⚠ v2.58.02-beta: Notify user when all files in Files list are Finished or Deleted. Compatible with future version of NCNN-Vulkan engines. More detailed tooltips. Download: ➡github.com ➡sourceforge.net ➡超星云盘直链 (Only for users in People's Republic of China) Waifu2x-Extension-GUI是什么? 借助深度卷积神经网络对图片&GIF&视频进行超分辨率放大(即放大与降噪). 主要特性: 自动化处理多种媒体: 支持处理 图片 的同时,实现了自动化处理 GIF 和 视频. 全图像风格支持: 内置多种算法, 无论是 二次元动漫 还是 您日常拍摄的照片&录像 ,都可以进行清晰化处理. 强大的兼容性: 内置多个引擎, 几乎与所有现代 Windows PC 兼容. 灵活的多线程设定: 在为每个引擎提供完备的设置项的同时,您也可以自由调整线程数量,充分利用PC的一切性能. 多GPU支持: 内置的所有引擎均可支持多显卡,充分利用您的PC的所有性能. 众多自定义设置: 您可以通过调整软件内的众多自定义设置实现自动化的工作流. 智能设定: 本软件可根据您的PC硬件信息和您要处理文件的信息自动调整部分软件设定. 易于使用的图形用户界面. 持续的维护与更新. 内置图像处理算法: Waifu2x / SRMD / RealSR / Anime4K / ACNet 内置图像处理引擎: Waifu2x-caffe / Waifu2x-converter / Waifu2x-ncnn-vulkan / SRMD-ncnn-vulkan / RealSR-ncnn-vulkan / Anime4KCPP 已经在AMDRX 550,NVIDIAGeForce GTX 1070 和IntelUHD 620 上通过测试. 详情查看:https://gitee.com/aaronfeng0711/Waifu2x-Extension-GUI/releases/v2.58.02-beta

优秀的个人博客,低调大师

Waifu2x-Extension-GUI v2.58.01-beta 发布,使用机器学习放大 图片/视频/GIF

Waifu2x-Extension-GUI v2.58.01-beta 已经发布。 这是一个测试版本, 点击这里下载稳定版本⚠ 此版本更新内容包括: NEW Feature: CPU support for waifu2x-ncnn-vulkan. Update waifu2x-ncnn-vulkan(20210102). Waifu2x-Extension-GUI是什么? 借助深度卷积神经网络对图片&GIF&视频进行超分辨率放大(即放大与降噪). 主要特性: 自动化处理多种媒体: 支持处理 图片 的同时,实现了自动化处理 GIF 和 视频. 全图像风格支持: 内置多种算法, 无论是 二次元动漫 还是 您日常拍摄的照片&录像 ,都可以进行清晰化处理. 强大的兼容性: 内置多个引擎, 几乎与所有现代 Windows PC 兼容. 灵活的多线程设定: 在为每个引擎提供完备的设置项的同时,您也可以自由调整线程数量,充分利用PC的一切性能. 多GPU支持: 内置的所有引擎均可支持多显卡,充分利用您的PC的所有性能. 众多自定义设置: 您可以通过调整软件内的众多自定义设置实现自动化的工作流. 智能设定: 本软件可根据您的PC硬件信息和您要处理文件的信息自动调整部分软件设定. 易于使用的图形用户界面. 持续的维护与更新. 内置图像处理算法: Waifu2x / SRMD / RealSR / Anime4K / ACNet 内置图像处理引擎: Waifu2x-caffe / Waifu2x-converter / Waifu2x-ncnn-vulkan / SRMD-ncnn-vulkan / RealSR-ncnn-vulkan / Anime4KCPP 已经在AMDRX 550,NVIDIAGeForce GTX 1070 和IntelUHD 620 上通过测试. 详情查看:https://gitee.com/aaronfeng0711/Waifu2x-Extension-GUI/releases/v2.58.01-beta

优秀的个人博客,低调大师

k8s | 搞不明白为什么大家都在学习 k8s

Hi! 我是小小,今天是本周的第二篇,本篇主要内容是讲解k8s 前言 都9102年了,你还不知道kubernetes就真的真的真的out啦。(贩卖焦虑体) 什么是k8s,k8s这个词来自于希腊语,有主管,舵手,船长的意思,我们从图标中能看出来。在k8s的网站上,描述是这样的 生产级别的容器编排系统 从定义中可以提炼出三个关键字,分别是 生产级别 容器 编排系统 1. 生产级别 说k8s是生产级别的有如下的几个原因: k8s 是谷歌的开源系统,基于谷歌的系统设计,并且已经在谷歌系统上平稳运行的很久。 k8s 是CNCF的首个毕业项目。 2. 容器 容器有以下几个特点 可移植性,容器可以被任何类型的操作系统安装使用。 包容性:支持多种类型的软件,这些软件都可以打包在容器内。 标准格式。 共存,多个容器可以运行在同一个物理机上。 隔离,不同的容器的软件彼此隔离。 最重要的一句话:没有容器就没有微服务。 容器和微服务化后,带来了一些好处,比如: 模块间更加独立,可以独立的部署和发布,加快了发布和更新的速度 隔离的运行环境,可以为不同模块定制不同的运行环境 3. 编排系统 容器的编排系统可以有效的管理在宿主机上的容器。 管理网络和访问 跟踪容器的状态 增大或缩小服务的规模 实现负载平衡 宿主机无响应后实现容器的重新分配 服务发现 管理容器的存储 等等… 主要功能 数据卷 pod中容器之间共享数据,可以使用数据卷。 应用程序健康检查 容器内服务可能进程阻塞无法处理请求,可以设置监控检查的策略, 复制应用程序实例 控制器维护者pod副本数量,保证一个pod或一组同类prod数量始终可用 弹性伸缩 根据设定的指标,自动缩放pod副本数 服务发现 使用环境变量或DNS插件保证容器中程序发现pod入口访问地址。 负载均衡 一组pod副本分配一个私有的集群ip地址,负载均衡转发请求到后端容器,在集群类其他pod可以通过clusterIP访问应用。 滚动更新 更新服务不中断,一次更新一个pod,而不是同时删除整个服务。 服务编排 通过文件描述部署服务,使得应用程序部署变得高效。 资源监控 Node节点组件集成cAdvisor资源收集工具,通过Heapster汇总,并保存到influxDB时序数据库,最后由Grafana展示。 提供认证授权 支持RBAC认证授权机制。 设计架构 功能组件 k8s 集群中有管理节点,Master与工作节点,Node两种类型。 管理节点Master主要负责k8s集群管理,集群中各个节点之间信息交互,任务调度,还负责容器,pod, namespaces , pv 等生命周期的管理。 工作节点node主要为容器和pod提供计算资源,pod及其容器全部运行在工作节点上,工作节点通过kubelet服务与管理节点通信以管理容器的生命周期,并与集群其他节点进行通信。 master组件 kube-apiserver kubernetes api 资源操作的唯一入口,各种组件的协调者,以HTTP API 提供接口服务,并提供相关的认证,授权等机制, kube-controller-manager 处理集群中常规的后台任务,一个资源对应一个控制器,而ControllerManager负责管理这些控制器,并维护集群的状态。 kube-scheduler 负责资源的调度,按照预定的策略把pod调度到对应的Node节点上。 Node组件 kubelet kubelet是Master在Node节点上的agent,管理本机运行容器的生命周期,同时也负责Volume和网络的管理。例如创建容器,挂载数据卷,下载secret,获取容器和节点的状态等工作。 kube-proxy 在Node节点上实现Pod/serviced网络代理,提供cluster内部的服务发现和四层负载均衡。 docker 真正运行容器的地方 etcd集群 分布式键值对储存系统,用于保存集群状态,比如pod,service等对象信息。 分层架构 核心层:最核心的功能,对外提供api 应用层,部署无状态应用,等,和路由。管理层:系统度量,自动化,以及RBAC等 接口层:kubectl命令行工具,以及客户端sdk 生态系统:分为外部的日志,监控等,内部的镜像仓库等。 安装 创建集群 首先,查看所使用的 minikube 版本: $ minikube versionminikube version: v0.25.0 启动 minikube: $ minikube startStarting local Kubernetes v1.9.0 cluster...Starting VM...Getting VM IP address...Moving files into cluster...Setting up certs...Connecting to cluster...Setting up kubeconfig...Starting cluster components...Kubectl is now configured to use the cluster.Loading cached images from config file. minikube 启动之后,会创建一个单节点 Kubernetes 集群。 查看集群版本: $ kubectl versionClient Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2017-12-15T21:07:38Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}Server Version: version.Info{Major:"", Minor:"", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2018-01-26T19:04:38Z", GoVersion:"go1.9.1", Compiler:"gc", Platform:"linux/amd64"} 这里有两个版本,client version 指的是 kubectl 命令行工具的版本,而 server version 才是 Kubernetes 的版本。 查看更详细的版本信息: $ kubectl cluster-infoKubernetes master is running at https://172.17.0.77:8443To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. 集群所在主机的 ip 为 172.17.0.77。 注意:这里的 master 指的是 Kubernetes 集群的 master 节点(在 Kubernetes 集群中,节点分为两类,一类是 master 节点,一类是 node 节点)。那怎么看到 node 节点呢? $ kubectl get nodeNAME STATUS ROLES AGE VERSIONhost01 Ready <none> 20m v1.9.0 host01 就是 node 节点,在当前环境中,实际上只有一台主机。这台主机既作为 master 节点,也作为 node 节点。 部署应用 下面以部署一个 nginx 为例来演示部署应用的过程: $ kubectl run first-app --image=nginx --port=80deployment "first-app" created 通过 run 命令创建一个名为 first-app 的 deployment,使用的是 docker hub 上最新的 nginx 镜像,并指定了应用端口为 80。deployment 是干嘛的呢?别急,往下看: 查看当前的 deployment: $ kubectl get deploymentNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEfirst-app 1 1 1 1 1m 查看当前的 pod: $ kubectl get podNAME READY STATUS RESTARTS AGEfirst-app-6db44b474-dbbtp 1/1 Running 0 4m 查看更详细的 pod 内容: $ kubectl describe pod first-app-6db44b474-dbbtpName: first-app-6db44b474-dbbtpNamespace: defaultNode: host01/172.17.0.77Start Time: Fri, 02 Mar 2018 06:48:02 +0000Labels: pod-template-hash=286006030 run=first-appAnnotations: <none>Status: RunningIP: 172.18.0.4Controlled By: ReplicaSet/first-app-6db44b474Containers: first-app: Container ID: docker://54eacc7ff536d7181fa366883f7ed4cf632492ad6ed391207fea436d22d219a9 Image: nginx Image ID: docker-pullable://nginx@sha256:4771d09578c7c6a65299e110b3ee1c0a2592f5ea2618d23e4ffe7a4cab1ce5de Port: 80/TCP State: Running Started: Fri, 02 Mar 2018 06:48:14 +0000 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-zkqw6 (ro)Conditions: Type Status Initialized True Ready True PodScheduled TrueVolumes: default-token-zkqw6: Type: Secret (a volume populated by a Secret) SecretName: default-token-zkqw6 Optional: falseQoS Class: BestEffortNode-Selectors: <none>Tolerations: <none>Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 7m default-scheduler Successfully assigned first-app-6db44b474-dbbtp to host01 Normal SuccessfulMountVolume 7m kubelet, host01 MountVolume.SetUp succeeded for volume "default-token-zkqw6" Normal Pulling 7m kubelet, host01 pulling image "nginx" Normal Pulled 7m kubelet, host01 Successfully pulled image "nginx" Normal Created 7m kubelet, host01 Created container Normal Started 7m kubelet, host01 Started container 对外发布服务 已经部署好了一个 nginx 应用,那么要怎么去访问呢?这时候就需要用到 service。创建一个 service: $ kubectl expose deployment/first-app --type="NodePort" --port=80service "first-app" exposed 查看创建好的名为 first-app 的 service : $ kubectl get svc first-appNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEfirst-app NodePort 10.102.0.12 <none> 80:30491/TCP 1m 在 PORT(S) 一栏中,除了 80 端口,后面还有一个 30491 端口。这是使用了“NodePort”类型创建 service 分配的端口,通过主机 ip 和这个端口,就可以访问到这个 service 了。可以使用 curl 工具进行访问: $ curl 172.17.0.77:30491<!DOCTYPE html><html><head><title>Welcome to nginx!</title><style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }</style></head><body><h1>Welcome to nginx!</h1><p>If you see this page, the nginx web server is successfully installed andworking. Further configuration is required.</p><p>For online documentation and support please refer to<a href="http://nginx.org/">nginx.org</a>.<br/>Commercial support is available at<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p></body></html> 扩缩应用 刚刚已经成功访问到 nginx 应用,但有些时候,可能需要多个 nginx 来横向扩展,那么在 Kubernetes 中怎么实现呢? $ kubectl scale deployment/first-app --replicas=3deployment "first-app" scaled 再查看当前的 pod,可以看到当前已经有了 3 个 first-app 了。 $ kubectl get podNAME READY STATUS RESTARTS AGEfirst-app-6db44b474-6vlrj 1/1 Running 0 39sfirst-app-6db44b474-dbbtp 1/1 Running 0 19mfirst-app-6db44b474-gjzgg 1/1 Running 0 39s 如果觉得 3 个太浪费资源了,想减少 pod 的数量,那么可以使用同样的命令,把 replicas 参数的值改为需要的值就可以了。 更新应用 最常用的就是更新镜像。之前使用的是 docker hub 上最新的 nginx,现在用 1.10.3 这个比较老的版本来替代最新版本。先查看当前使用的 nginx 版本。这里有一个很简单的方法,访问一个不存在的页面,如下: $ curl 172.17.0.77:30491/abc<html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>404 Not Found</h1></center><hr><center>nginx/1.13.9</center></body></html> 当前使用的 nginx 版本是 1.13.9,接下来进行更新操作: $ kubectl set image deployment/first-app first-app=nginx:1.10deployment "first-app" image updated 再查看当前 nginx 的版本: $ curl 172.17.0.77:30491/abc<html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>404 Not Found</h1></center><hr><center>nginx/1.10.3</center></body></html> nginx 版本已经成功更新为 1.10.3。 删除应用 最后来讲讲删除应用,之前是通过 deployment 来创建应用,所以只需要删除 deployment 就可以删除对应的应用了。 $ kubectl delete deployment/first-appdeployment "first-app" deleted 再查看一下当前的 pod: $ kubectl get podNo resources found. 所有的 pod 都已经删除了。 关于作者 一个生于二线,活在一线城市的程序猿,我是小小,我们下期再见。 小明菜市场 往期推荐 对战 | RabbitMq 大战 kafka 执行流程 | 你真的了解Spring AOP的执行顺序吗? 吊打面试官 | Java到底是值传递还是引用传递 容器 | Docker 如此之好,你为什么还要用k8s 分布式ID | 这六种分布式ID生成方法,总有一款适合你 本文分享自微信公众号 - 小明菜市场(fileGeek)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

撸了个多线程断点续传下载器,我从中学习到了这些知识

> 文章已经收录在 Github.com/niumoo/JavaNotes ,更有 Java 程序员所需要掌握的核心知识,欢迎Star和指教。 > 欢迎关注我的公众号,文章每周更新。 感谢看客老爷点进来了,周末闲来无事,想起同事强哥的那句话:“你有没有玩过断点续传?” 当时转念一想,断点续传下载用的确实不少,具体细节嘛,真的没有去思考过啊。这不,思考过后有了这篇文章。感谢强哥,让我有了一篇可以水的文章,下面会用纯 Java 无依赖实现一个简单的多线程断点续传下载器。 这篇水文章到底有什么内容呢?先简单列举一下,顺便思考几个问题。 断点续传的原理。 重启续传文件时,怎么保证文件的一致性? 同一个文件多线程下载如何实现? 网速带宽固定,为什么多线程下载可以提速? 多线程断点续传会用到哪些知识呢?上面已经抛出了几个问题,不放思考一下。下面会针对上面的四个问题一一进行解释,现在大多数的服务都可以在线提供,下载使用的场景越来越少,不过这不妨碍我们对原理的探求。 断点续传的原理 想要了解断点续传是如何实现的,那么肯定是要了解一下 HTTP 协议了。HTTP 协议是互联网上应用最广泛网络传输协议之一,它基于 TCP/IP 通信协议来传递数据。所以断点续传的奥秘也就隐藏在这 HTTP 协议中了。 我们都知道 HTTP 请求会有一个 Request header 和 Response header ,就在这请求头和响应头里,有一个和 Range 相关的参数。下面通过百度网盘的 pc 客户端下载链接进行测试。 使用 cURL 查看 response header. 如果你想知道更多关于 cURL 的用法,可以看我之前的一篇文章 :进来领略下cURL的独门绝技。 $ curl -I http://wppkg.baidupcs.com/issue/netdisk/yunguanjia/BaiduYunGuanjia_7.0.1.1.exe HTTP/1.1 200 OK Server: JSP3/2.0.14 Date: Sat, 25 Jul 2020 13:41:55 GMT Content-Type: application/x-msdownload Content-Length: 65804256 Connection: keep-alive ETag: dcd0bfef7d90dbb3de50a26b875143fc Last-Modified: Tue, 07 Jul 2020 13:19:46 GMT Expires: Sat, 25 Jul 2020 14:05:19 GMT Age: 257796 Accept-Ranges: bytes Cache-Control: max-age=259200 Content-Disposition: attachment;filename="BaiduYunGuanjia_7.0.1.1.exe" x-bs-client-ip: MTgwLjc2LjIyLjU0 x-bs-file-size: 65804256 x-bs-request-id: MTAuMTM0LjM0LjU2Ojg2NDM6NDM4MTUzMTE4NTU3ODc5MTIxNzoyMDIwLTA3LTA3IDIyOjAxOjE1 x-bs-meta-crc32: 3545941535 Content-MD5: dcd0bfef7d90dbb3de50a26b875143fc superfile: 2 Ohc-Response-Time: 1 0 0 0 0 0 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS, HEAD Ohc-Cache-HIT: bj2pbs54 [2], bjbgpcache54 [4] 可以看到百度 pc 客户端的 response header 信息有很多,我们只需要重点关注几个。 Content-Length: 65804256 // 请求的文件的大小,单位 byte Accept-Ranges: bytes // 是否允许指定传输范围,bytes:范围请求的单位是 bytes (字节),none:不支持任何范围请求单位, Last-Modified: Tue, 07 Jul 2020 13:19:46 GMT // 服务端文件最后修改时间,可以用于校验文件是否更改过 x-bs-meta-crc32: 3545941535 // crc32,可以用于校验文件是否更改过 ETag: dcd0bfef7d90dbb3de50a26b875143fc //Etag 标签,可以用于校验文件是否更改过 可见并不见得所有下载都支持断点续传,只有在 response header 中有 Accept-Ranges: bytes 字段时才可以断点续传。如果有这个信息,该怎么断点续传呢?其实只需要在 response header 中指定 Content-Range 值就可以了。 Content-Range 使用格式有下面几种。 Content-Range: <unit>=<range-start>-<range-end>/<size> // size 为文件总大小,如果不知道可以用 * Content-Range: <unit>=<range-start>-<range-end>/* Content-Range: <unit>=<range-start>- Content-Range: <unit>=*/<size> 举例: 单位 bytes,从第 10 个 bytes 开始下载:Content-Range: bytes=10-. 单位 bytes,从第 10 个 bytes 开始下载,下载到第100个 bytes:Content-Range: bytes=10-100. 这就是断点续传实现的原理了,你可以能已经发现了,Content-Range 的 start 和 end 已经让分段下载有了可能。 怎么保证文件的一致性? 这里要说的文件完整性有两个方面,一个是下载阶段的,一个是写入阶段的。 因为我们要写的下载器是支持断点续传的,那么在进行续传时,怎么确定文件自从我们上次下载时没有进行过更新呢?其实可以通过 response header 中的几个属性值进行判断。 Last-Modified: Tue, 07 Jul 2020 13:19:46 GMT // 服务端文件最后修改时间,可以用于校验文件是否更改过 ETag: dcd0bfef7d90dbb3de50a26b875143fc //Etag 标签,可以用于校验文件是否更改过 x-bs-meta-crc32: 3545941535 // crc32,可以用于校验文件是否更改过 Last-Modified 和 ETag 都可以用来检验文件是否更新过,根据 HTTP 协议的规定,当文件更新时,是会生成新的 ETag 值的,它类似于文件的指纹信息,而 Last-Modified 只是上次修改时间,有时可能并不能够证明文件内容被修改过。 上面是下载阶段的文件一致性校验,那么在写入阶段呢?不管单线程还是多线程,由于要断点续传,在写入时都要在指定位置进行字符追加。在 Java 中有没有好的实现方式? 答案是一定的,使用 RandomAccessFile 类即可,RandomAccessFile 不同于其他的流操作。它可以在使用时指定读写模式,使用 seek 方法随意的移动要操作的文件指针位置。很适合断点续传的写入场景。 比如在 test.txt 的位置 0 开始写入字符 abc,在位置 100 开始写入字符 ddd. try (RandomAccessFile rw = new RandomAccessFile("test.txt", "rw")){ // rw 为读写模式 rw.seek(0); // 移动文件内容指针位置 rw.writeChars("abc"); rw.seek(100); rw.writeChars("ddd"); } 断点续传的写入就靠它了,在续传时只需要移动文件内容指针到要续传的位置即可。 seek 方法还有很多妙用,比如使用它你可以快速定位到已知的位置,进行快速检索;也可以在同一个文件的不同位置进行并发读写。 多线程下载如何实现? 多线程下载必然要每个线程下载文件中的一部分,然后把每个线程下载到的文件内容组装成一个完整的文件,在这个过程中肯定是一个 byte 都不能出错的,不然你组装起来的文件是肯定运行不起来的。那么怎么实现下载文件的一部分呢?其实在断点续传的部分已经介绍过了,还是 Content-Range 参数,只要计算好每个部分要下载的 bytes 范围就可以了。 比如:单位 bytes,第二部分从第 10 个 bytes 开始下载,下载到第100个 bytes:Content-Range: bytes=10-100. 网速带宽固定,为什么多线程下载可以提速? 这是一个比较有意思的问题了,最大网速是固定的,运营商给你 100Mbs 的网速,不管你怎么使用,速度最大也就是 100/8=12.5MB/S. 既然瓶颈在这里,为什么多线程下载可以提速呢?其实理论上来说,单线程下载就可以达到最大网速。但是往往事实是网络不是那么通畅,十分拥堵,很难达到理想的最大速度。也就是说只有在网络不那么通畅的时候,多线程下载才能提速。否则,单线程即可。不过最大速度永远都是网络带宽。 那为什么多线程下载可以提速呢?HTTP 协议在传输时候是基于 TCP 协议传输数据的,为了弄明白这个问题需要了解一下 TCP 协议的拥塞控制机制。拥塞控制 是TCP 的一个避免网络拥塞的算法,它是基于和性增长/乘性降低这样的控制方法来控制拥塞的。 简单来说就是在 TCP 开始传输数据时,服务端会不断的探测可用带宽。在一个传输内容段被成功接收后,会加倍传输两倍段内容,如果再次被成功接收,就继续加倍,直到发生了丢包,这是这也被叫做慢启动。当达到**慢启动阀值(ssthresh)**时,满启动算法就会转换为线性增长的阶段,每次只增加一个分段,放缓增加速度。我觉得其实慢启动的加倍增速过程并不慢,只是一种叫法。 但是当发生了丢包,也就是检测到拥塞时,发送方就会将发送段大小降低一个乘数,比如二分之一,慢启动阈值降为超时前拥塞窗口的一半大小、拥塞窗口会降为1个MSS,并且重新回到慢启动阶段。这时多线程的优势就体现出来了,因为你的多线程会让这个速度减速没有那么猛烈,毕竟这时可能有另一个线程正处在慢启动的在最终加速阶段,这样总体的下载速度就优于单线程了。 多线程断点续传代码实现 基于上面的原理介绍,心里应该有了具体的实现思路了。我们只需要使用多线程,结合 Content-Range 参数分段请求文件内容保存到临时文件,下载完毕后使用 RandomAccessFile 把下载的文件合并成一个文件即可。而在需要断点续传时,只需要读取一下当前临时文件大小,然后调整 Content-Range ,就可以进行续传下载。 代码不多,下面是部分核心代码,完整代码可以直接点开文章最后的 Github 仓库。 Content-Range 请求指定文件的区间内容。 URL httpUrl = new URL(url); HttpURLConnection httpConnection = (HttpURLConnection)httpUrl.openConnection(); httpConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"); httpConnection.setRequestProperty("RANGE", "bytes=" + start + "-" + end + "/*"); InputStream inputStream = httpConnection.getInputStream(); 获取文件的 ETag. Map<string, list<string>&gt; headerFields = httpConnection.getHeaderFields(); List<string> eTagList = headerFields.get("ETag"); System.out.println(eTagList.get(0)); 使用 RandomAccessFile 续传写入文件。 RandomAccessFile oSavedFile = new RandomAccessFile(httpFileName, "rw"); oSavedFile.seek(localFileContentLength); // 文件写入开始位置指针移动到已经下载位置 byte[] buffer = new byte[1024 * 10]; int len = -1; while ((len = inputStream.read(buffer)) != -1) { oSavedFile.write(buffer, 0, len); } 断点续传测试,下载一部分之后关闭程序再次启动。 完整代码已经上传到 github.com/niumoo/down-bit. 参考: [1] HTTP headers [2] Class RandomAccessFile [3] RandomAccessFile简介与使用 [4] 维基百科 - TCP拥塞控制 [5] 维基百科 - 和性增长/乘性降低 最后的话 >文章已经收录在 Github.com/niumoo/JavaNotes ,欢迎Star和指教。更有一线大厂面试点,Java程序员需要掌握的核心知识等文章,也整理了很多我的文字,欢迎 Star 和完善,希望我们一起变得优秀。 文章有帮助可以点个「赞」或「分享」,都是支持,我都喜欢! 文章每周持续更新,要实时关注我更新的文章以及分享的干货,可以关注「 未读代码 」公众号或者我的博客。 </string></string,></size></unit></range-start></unit></range-end></range-start></unit></size></range-end></range-start></unit>

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册