首页> 标签> Ruby
"Ruby"
共 3909 条结果
全部 问答 文章 公开课 课程 电子书 技术圈 体验
linux进程管理
进程管理进程就是运行中的程序,一个运行着的程序,可能有多个进程。 比如 LinuxSir.Org 所用的 WWW服务器是 apache 服务器,当管理员启动服务后,可能会有好多人来访问,也就是说许多用户来同时请求 httpd 服务,apache 服务器将会创建有多个 httpd 进程来对其进行服务。进程分类进程一般分为交互进程、批处理进程和守护进程三类。值得一提的是守护进程总是活跃的,一般是后台运行,守护进程一般是由系统在开机时通过脚本自动激活启动或超级管理用户 root 来启动。比如在 Fedora 或 Redhat 中,我们可以定义 httpd 服务器的启动脚本的运行级别,此文件位于/etc/init.d 目录下,文件名是 httpd,/etc/init.d/httpd 就是 httpd 服务器的守护程序,当把它的运行级别设置为 3 和 5 时,当系统启动时,它会跟着启动。[root@localhost ~]# chkconfig --level 35 httpd on由于守护进程是一直运行着的,所以它所处的状态是等待请求处理任务。比如,我们是不是访问LinuxSir.Org ,LinuxSir.Org 的 httpd 服务器都在运行,等待着用户来访问,也就是等待着任务处理。进程的属性进程 ID(PID):是唯一的数值,用来区分进程;父进程和父进程的 ID(PPID);启动进程的用户 ID(UID)和所归属的组(GID);进程状态:状态分为运行 R、休眠 S、僵尸 Z;进程执行的优先级;进程所连接的终端名;进程资源占用:比如占用资源大小(内存、CPU 占用量);父进程和子进程他们的关系是管理和被管理的关系,当父进程终止时,子进程也随之而终止。但子进程终止,父进程并不一定终止。比如 httpd 服务器运行时,我们可以杀掉其子进程,父进程并不会因为子进程的终止而终止。在进程管理中,当我们发现占用资源过多,或无法控制的进程时,应该杀死它,以保护系统的稳定安全运行进程管理命令psps 为我们提供了进程的一次性的查看,它所提供的查看结果并不动态连续的;如果想对进程时间监控,应该用 top 工具。ps 的参数说明:ps 提供了很多的选项参数,常用的有以下几个; l 长格式输出; u 按用户名和启动时间的顺序来显示进程; j 用任务格式来显示进程; f 用树形格式来显示进程; a 显示所有用户的所有进程(包括其它用户); x 显示无控制终端的进程; r 显示运行中的进程; ww 避免详细参数被截断; 我们常用的选项是组合是 aux 或 lax,还有参数 f 的应用; ps aux 或 lax 输出的解释;USER 表示启动进程用户。PID 表示进程标志号。%CPU 表示运行该进程占用 CPU 的时间与该进程总的运行时间的比例。%MEM 表示该进程占用内存和总内存的比例。VSZ 表示占用的虚拟内存大小,以 KB 为单位。RSS 为进程占用的物理内存值,以 KB 为单位。TTY 表示该进程建立时所对应的终端,"?"表示该进程不占用终端。STAT 表示进程的运行状态,包括以下几种代码:D,不可中断的睡眠;R,就绪(在可运行队列中);S,睡眠;T,被跟踪或停止;Z,终止(僵死)的进程,Z 不存在,但暂时无法消除;W,没有足够的内存分页可分配;<高优先序的进程;N,低优先序的进程;L,有内存分页分配并锁在内存体内(实时系统或 I/O)。START 为进程开始时间。TIME 为执行的时间。COMMAND 是对应的命令名。 ps 应用举例:实例一:ps aux 最常用[root@localhost ~]# ps -aux |more可以用 | 管道和 more 连接起来分页查看;[root@localhost ~]# ps aux > ps001.txt[root@localhost ~]# more ps001.txt 这里是把所有进程显示出来,并输出到 ps001.txt 文件,然后再通过 more 来分页查看;实例二:和 grep 结合,提取指定程序的进程;[root@localhost ~]# ps aux |grep httpdroot 4187 0.0 1.3 24236 10272 ? Ss 11:55 0:00 /usr/sbin/httpdapache 4189 0.0 0.6 24368 4940 ? S 11:55 0:00 /usr/sbin/httpd实例三:父进和子进程的关系友好判断的例子:这里用到了 f 参数;父与子关系一目了然;[root@192-168-189-131 ~]# ps auxfroot      3609  0.0  0.0   2364    80 ?        Ss   Jun18   0:00      |   \_ runsv grafanaroot      3610  0.0  0.0   2508   288 ?        S    Jun18   0:00      |       \_ svlogd -tt /var/log/gitlab/grafana992       3611  0.0  0.7 1524792 29412 ?       Ssl  Jun18  24:49      |       \_ /opt/gitlab/embedded/bin/grafana-server -config /root      3876  0.0  0.0   5720   272 ?        S    Jun18   0:00      \_ /bin/bash /opt/gitlab/bin/gitlab-ctl tailroot      3877  0.0  0.0  96932  1924 ?        S    Jun18   0:01          \_ /opt/gitlab/embedded/bin/ruby /opt/gitlab/embedded/biroot      3879  0.0  0.0   2600   192 ?        S    Jun18   0:00              \_ sh -c find -L /var/log/gitlab -type f -not -path  root      3882  0.0  0.0   4552    76 ?        S    Jun18   0:00                  \_ xargs tail --follow=name --retryroot      3883  0.0  0.0   4288   196 ?        S    Jun18   4:23                      \_ tail --follow=name --retry /var/log/gitla例四:找出消耗内存最多的前 10 名进程# ps -auxf | sort -nr -k 4 | head -10 例五:找出使用 CPU 最多的前 10 名进程# ps -auxf | sort -nr -k 3 | head -10pstree功能:pstree 命令列出当前的进程,以及它们的树状结构。格式:pstree [选项] [pid|user]主要选项如下:-a:显示执行程序的命令与完整参数。 -c:取消同名程序,合并显示。 -h:对输出结果进行处理,高亮显示正在执行的程序。 -l:长格式显示。 -n:以 PID 大小排序。 -p:显示 PID。 -u:显示 UID 信息。 -G:使用 VT100 终端编码显示。 -U:使用 UTF-8(Unicode)编码显示。 说明:使用 ps 命令得到的数据精确,但数据庞大,这一点对掌握系统整体概况来说是不容易的。pstree 正好可以弥补这个缺憾。它能将当前的执行程序以树状结构显示。pstree 支持指定特定程序(PID) 或使用者(USER)作为显示的起始。应用实例如下:进程启动的时候可能会产生自己的一个子进程。运行 pstree 命令就可以很容易地看到这些信息。以超级用户权限运行 应用实例如下。进程启动的时候可能会产生自己的一个子进程。运行 pstree 命令就可以很容易地看到这些信息。以超级用户权限运行 pstree:如果出现一下问题:-bash: pstree: command not found需要安装一下:[root@192-168-189-131 ~]# yum -y install psmisctoptop 命令用来显示系统当前的进程状况。格式:top [选项]主要选项如下d:指定更新的间隔,以秒计算。 q:没有任何延迟的更新。如果使用者有超级用户,则 top 命令将会以最高的优先序执行。 c:显示进程完整的路径与名称。 S:累积模式,会将已完成或消失的子进程的 CPU 时间累积起来。 s:安全模式。 i:不显示任何闲置(Idle)或无用(Zombie)的进程。 n:显示更新的次数,完成后将会退出 top。 说明:top 命令和 ps 命令的基本作用是相同的,都显示系统当前的进程状况。但是 top 是一个动态显 示过程,即可以通过用户按键来不断刷新当前状态。这里结合下图来说明它给出的信息。第一行表示的项目依次为当前时间、系统启动时间、当前系统登录用户数目、平均负载。第二行显示的是 Tasks: 114 total 进程总数、2 running 正在运行的进程数、110 sleeping 睡眠的进程数、0 stopped 停止的进程数、2 zombie 僵尸进程数第三行显示的是目前 CPU 的使用情况,Cpu(s): 0.3% us 用户空间占用 CPU 百分比、1.0% sy 内核空间占用 CPU 百分比、0.0% ni 用户进程空间内改变过优先级的进程占用 CPU 百分比、98.7% id 空 闲 CPU 百分比、0.0% wa 等待输入输出的 CPU 时间百分比、0.0% hi、0.0% si第四行显示物理内存的使用情况,Mem: 191272k total 物理内存总量、173656k used 使用的物理内存总量、17616k free 空闲内存总量、22052k buffers 用作内核缓存的内存量第五行显示交换分区使用情况,Swap: 192772k total 交换区总量、0k used 使用的交换区总量、192772k free 空闲交换区总量、123988k cached 缓冲的交换区总量、内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖,该数值即为这些内容已存在于内存中的交换区的大小。相应的内存再次被换出时可不必再对交换区写入。第六行显示的项目最多,下面列出了详细解释。PID(Process ID):进程标志号,是非零正整数。USER:进程所有者的用户名。PR:进程的优先级别。NI:进程的优先级别数值。VIRT:进程占用的虚拟内存值。RES:进程占用的物理内存值。SHR:进程使用的共享内存值。STAT:进程的状态,其中 S 表示休眠,R 表示正在运行,Z 表示僵死状态,N 表示该进程优先值是负数。%CPU:该进程占用的 CPU 使用率。%MEM:该进程占用的物理内存和总内存的百分比。TIME:该进程启动后占用的总的 CPU 时间。COMMAND:进程启动的启动命令名称,如果这一行显示不下,进程会有一个完整的命令行。top 命令使用过程中,还可以使用一些交互的命令来完成其他参数的功能。这些命令是通过快捷键启动的。<空格>:立刻刷新。A 分类显示系统不同资源的使用大户。有助于快速识别系统中资源消耗多的任务。f 添加删除所要显示栏位. o 调整所要显示栏位的顺序. r 调整一个正在运行的进程 Nice 值. k 结束一个正在运行的进程. z 彩色/黑白显示开关P:根据 CPU 使用大小进行排序。T:根据时间、累计时间排序。q:退出 top 命令。m:切换显示内存信息。t:切换显示进程和 CPU 状态信息。c:切换显示命令名称和完整命令行。M:根据使用内存大小进行排序。W:将当前设置写入~/.toprc 文件中。这是写 top 配置文件的推荐方法。可以看到,top 命令是一个功能十分强大的监控系统的工具,对于系统管理员而言尤其重要。但是,它的缺点是会消耗很多系统资源
文章
缓存  ·  监控  ·  安全  ·  Linux  ·  Shell  ·  BI  ·  网络安全  ·  Apache  ·  Ruby
2022-08-16
InnoDB表聚集索引层高什么时候发生变化(1)
导读本文略长,主要解决以下几个疑问1、聚集索引里都存储了什么宝贝2、什么时候索引层高会发生变化3、预留的1/16空闲空间做什么用的4、记录被删除后的空间能回收重复利用吗1、背景信息1.1 关于innodb_fill_factor有个选项 innodb_fill_factor 用于定义InnoDB page的填充率,默认值是100,但其实最高只能填充约15KB的数据,因为InnoDB会预留1/16的空闲空间。在InnoDB文档中,有这么一段话An innodb_fill_factor setting of 100 leaves 1/16 of the space in clustered index pages free for future index growth.另外,文档中还有这样一段话When new records are inserted into an InnoDB clustered index, InnoDB tries to leave 1/16 of the page free for future insertions and updates of the index records. If index records are inserted in a sequential order (ascending or descending), the resulting index pages are about 15/16 full. If records are inserted in a random order, the pages are from 1/2 to 15/16 full.上面这两段话,综合起来理解,就是即便 innodb_fill_factor=100,也会预留1/16的空闲空间,用于现存记录长度扩展用在最佳的顺序写入数据模式下,page填充率有可能可以达到15/16在随机写入新数据模式下,page填充率约为 1/2 ~ 15/16预留1/16这个规则,只针对聚集索引的叶子节点有效。对于聚集索引的非叶子节点以及辅助索引(叶子及非叶子)节点都没有这个规则不过 innodb_fill_factor 选项对叶子节点及非叶子节点都有效,但对存储text/blob溢出列的page无效1.2 关于innodb_ruby项目innodb_ruby 项目是由Jeremy Cole 和 Davi Arnaut 两位大神开发的项目,可用于解析InnoDB数据结构,用ruby开发而成。他们还维护了另一个众所周知的项目叫 InnoDB Diagrams,相信稍微资深一点的MySQL DBA都应该知道这个项目。1.3 关于innblock工具由八怪开发,用于扫描和分析InnoDB page,详见 innblock | InnoDB page观察利器1.4 阅读本文背景信息需要假设您对InnoDB的数据结构已经有了一定了解,包括B+树、聚集索引、辅助索引,以及innodb page的一些简单结构。如果不太肯定,请先阅读这些文档内容Clustered and Secondary IndexesThe Physical Structure of an InnoDB IndexInnoDB Row FormatsInnoDB Record StructureInnoDB Page Structure2、测试验证:一层高的InnoDB表聚集索引,最多能存多少条数据从上面我们知道,一个page最大约能存储15/16容量,扣掉用于存储page header、trailer信息,以及index header、File Segment Header、Infimum&Supremum(两条虚拟记录)等必要的固定消耗之后,实际大约只有15212字节可用于存储用户数据。这样一来,我们就可以简单测算出一个page大约能存储多少条记录了。本次用到的测试表,只有一个INT列,同时作为主键(建议横版观看,可左右滑动。或者复制链接到PC端打开观看,效果更佳。下同)# MySQL的版本是Percona Server 5.7.22-22,我自己下载源码编译的 [root@yejr.me#] mysql -Smysql.sock innodb ... Server version: 5.7.22-22-log Source distribution ... [root@yejr.me]> \s ... Server version: 5.7.22-22-log Source distribution # 创建测试表 [root@yejr.me]> CREATE TABLE `t1` ( `i` int(10) unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`i`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;另外,我们知道每条记录都要几个额外存储的数据DB_TRX_ID,6字节DB_ROLL_PTR,7字节Record Header,至少5字节(用上面这个测试表,只需要5字节,不同数据类型需要的header长度也不同,详见 浅析InnoDB Record Header及page overflow因此,一条数据需要消耗 4(INT列) + 6 + 7 + 5 = 22字节此外,大约每4条记录就需要一个directory slot,每个slot需要2字节综上,假设可以存储N条记录,则 N*22 + N/4*2 = 15212,可求得N约等于676接下来我们验证一下,往该表中持续插入 676 条数据[root@yejr.me]> insert into t1 select 0;...# 逐次反复执行676次然后,我们利用 innodb_ruby 工具查看其数据结构2.1 查看聚集索引page结构此时t1表的聚集索引树只有一层高,一个page即pageno=3[root@yejr]# innodb_space -s ibdata1 -T innodb/t1 space-indexesid name root fseg fseg_id used allocated fill_factor128 PRIMARY 3 internal 1 1 1 100.00%128 PRIMARY 3 leaf 2 0 0 0.00%再用innblock工具扫描佐证一下[root@yejr]# innblock innodb/t1.ibd scan 16...level0 total block is (1)block_no: 3,level: 0|*|2.2 查看其directory slot可以看到170个slot,其中Infimum记录的owned=1,Supremum记录的owned=5[root@yejr]# innodb_space -s ibdata1 -T innodb/t1 \-p 3 page-directory-summary|grep -c -v slot1702.3 查看整个page的全览图前面是一堆头信息[root@yejr]# innodb_space -s ibdata1 -T innodb/t1 -p 3 page-illustrate Offset ╭────────────────────────────────────────────────────────────────╮ 0 │█████████████████████████████████████▋██████████████████████████│ 64 │█████████▋███████████████████▋████████████▋████████████▋████▋███│# 大概从这里开始是第一条记录 128 │█████████████▋████▋████████████████▋████▋████████████████▋████▋█│ 192 │███████████████▋████▋████████████████▋████▋████████████████▋████│...# 中间是用户数据...# 这里是预留的1/16空闲空间 15872 │ │ 15936 │ │# 这里是page directory slot,逆序存储# trailer占用8字节,此后每个slot占用2字节# 共170个slot 16000 │ █▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋│... 16320 │█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋███████▋│ ╰────────────────────────────────────────────────────────────────╯# 最后是统计汇总信息Legend (█ = 1 byte): Region Type Bytes Ratio █ FIL Header 38 0.23% █ Index Header 36 0.22% █ File Segment Header 20 0.12% █ Infimum 13 0.08% █ Supremum 13 0.08% █ Record Header 3380 20.63% █ Record Data 11492 70.14% █ Page Directory 340 2.08% █ FIL Trailer 8 0.05% ░ Garbage 0 0.00% Free 1044 6.37%可以得到几点信息Record Data共占用11492字节,共676条记录,每条记录17字节(4+6+7)Page Directory共340字节,170个slot,每个slot占用2字节两条虚拟记录,均占用13字节(含5字节的record header)Record Header共3380字节,共676条记录,每条记录需要5字节头信息(再次提醒,表里字段类型各异,Record Header也会随之不同,仅在本例中只需要5字节。详见 浅析InnoDB Record Header及page overflow)提醒:本次测试是顺序写入,如果是随机写入或批量写入,可能就没办法把15/16的page空间填充的满满当当了 </div>
文章
存储  ·  关系型数据库  ·  MySQL  ·  数据库管理  ·  索引  ·  Ruby
2022-08-16
Ruby on rails 和Java的相似点是什么啊?
Ruby on rails 和Java的相似点是什么啊?
问答
Java  ·  Ruby
2022-08-15
Kubernetes 微服务、容器介绍
Kubernetes 微服务、容器介绍什么是微服务?什么是微服务?你应该使用微服务吗?微服务与容器和 Kubernetes 有什么关系?如果这些事情在您的日常生活中不断出现,并且您需要在 10 分钟内进行概述,那么这篇博文适合您。从根本上讲,微服务只是一个运行在服务器或虚拟计算实例上并响应网络请求的计算机程序。这与典型的 Rails/Django/Node.js 应用程序有何不同?它根本上没有什么不同。事实上,您可能会发现您的组织中已经部署了十几个微服务。没有任何新的神奇技术使您的应用程序有资格称为微服务。微服务不是由它的构建方式来定义的,而是由它如何变成更通用的系统或解决方案来定义的。那么是如何使服务成为微服务呢?一般来说,微服务的范围更窄,专注于做好较小的任务。让我们通过看一个例子来进一步探索。微服务示例:亚马逊产品列表让我们检查在 Amazon 上为您提供此产品页面的系统。它包含几个信息块,可能是从不同的数据库中检索到的:产品描述,包括价格、标题、照片等。推荐项目,即其他人购买的类似书籍。与此项目相关的赞助商列表。关于本书作者的信息。顾客评论。您自己在亚马逊商店中浏览其他商品的历史记录。如果您要快速编写用于此列表的代码,那么简单的方法将如下所示:当用户的请求来自浏览器时,它将由 Web 应用程序(Linux 或 Windows 进程)提供服务。通常,被调用的应用程序代码片段称为请求处理程序。处理程序内部的逻辑将依次多次调用数据库,获取呈现页面所需的信息并将其拼接在一起,然后呈现返回给用户的网页。很简单吧?事实上,许多 Ruby on Rails 书籍都有类似这样的教程和示例。那么,你可能会问,为什么要把事情复杂化?想象一下随着应用程序的增长和越来越多的工程师参与其中会发生什么。上面例子中的推荐引擎是由一小群程序员和数据科学家维护的。有几十个不同的团队负责渲染该页面的某些组件。这些团队中的每一个通常都希望获得以下自由:更改他们的数据库架构。快速且频繁地将他们的代码发布到生产环境中。使用他们选择的编程语言或数据存储等开发工具。在计算资源和开发人员生产力之间做出自己的权衡。偏好维护/监控其功能。可以想象,随着时间的推移,让团队就发布 Web 商店应用程序的新版本的所有内容达成一致将变得更加困难。解决方案是将组件拆分为更小的、独立的服务(也就是微服务)。升级流程变得更小、更笨。它基本上是一个代理,它简单地将传入的页面请求分解为几个专门的请求,并将它们转发给相应的微服务,这些微服务现在是他们自己的进程并在其他地方运行。“应用微服务”基本上是专门服务返回的数据的聚合器。您甚至可以完全摆脱它并将该工作卸载到用户的设备上,让此代码在浏览器中作为单页 JavaScript 应用程序运行。其他微服务现在被分离出来,每个开发微服务的开发团队都可以:随心所欲地部署他们的服务,而不会干扰其他团队。以他们认为合适的方式扩展他们的服务。例如,使用他们选择的 AWS 实例类型,或者可能在专用硬件上运行。拥有自己特定于其服务的监控、备份和灾难恢复。什么是容器?从技术上讲,容器只是一个从可执行文件产生的进程,运行在 Linux 机器上,它有一些限制,例如:容器不允许“看到”所有文件系统,它只能访问其中的指定部分。一个容器不允许使用所有的 CPU 或 RAM。容器在如何使用网络方面受到限制。从历史上看,现代操作系统总是对进程施加限制,例如每个 Linux 进程都以系统用户的权限运行,但是容器化技术引入了更多可能的限制并使其更加灵活。基本上,任何 Linux 可执行文件都可以受到限制,即可以“容器化”。大多数情况下,当人们说“容器”时,他们不仅仅指的是 Linux 进程,还指的是可执行文件的打包和存储方式。类似的工具 Docker 允许开发人员获取他们的可执行文件及其依赖项,以及他们想要的任何其他文件,并将它们全部打包成一个文件。这项技术与 tarball 之类的存档没有太大区别。Docker 还允许包含一些额外的指令和配置来运行这个打包的可执行文件。通常这些文件,通常称为“容器镜像”,也称为容器。但为了简单起见,请记住:一个容器就是一个运行受限制的 linux 进程容器镜像是可执行进程的依赖和配置打包容器镜像是自给自足的。它们将在任何 Linux 机器上运行,因此容器化使得将代码从开发人员的机器复制(部署)到任何环境变得更加容易。微服务和容器有什么区别?我们刚刚了解到,容器只是一种打包、部署和运行 Linux 程序/进程的方法。您可以将一个巨大的单体应用程序作为容器,也可以拥有一群完全不使用容器的微服务。容器是一种有用的资源分配和共享技术。这是 DevOps 人们感到兴奋的事情。微服务是一种软件设计架构。这是开发人员感到兴奋的事情。它们是相关的,但不需要彼此。您可以将单体应用部署为容器,也可以拥有不受限制的、非容器化的微服务。什么时候使用微服务?微服务背后的想法并不新鲜。几十年来,软件架构师一直致力于将单体应用程序分解为可重用的组件。微服务的好处微服务的好处很多,包括:更简单的自动化测试;快速灵活的部署模式;更强弹性扩缩容。采用微服务的另一个好处是能够为工作选择最佳工具。应用程序的某些部分可以从 C++ 的速度中受益,而其他部分可以从更高级别语言(例如 Python 或 JavaScript)的生产力提高中受益。微服务的缺点微服务的缺点包括:需要更仔细的规划;更高的研发投入;过度设计的诱惑。如果应用程序和开发团队足够小并且工作量不具有挑战性,则通常无需投入额外的工程资源来解决您尚未解决的问题并使用微服务。但是,如果您开始看到微服务的利大于弊,这里有一些具体的设计注意事项:计算和存储分离。随着您对 CPU 能力和存储需求的增长,这些资源具有非常不同的扩展成本和特性。从一开始就不必依赖本地存储,这将使您能够相对轻松地适应未来的工作负载。这既适用于文件系统等简单的存储形式,也适用于数据库等更复杂的解决方案。异步处理。通过添加越来越多的相互调用的子进程或对象来逐步构建应用程序的传统方法随着工作负载的增长而停止工作,并且应用程序本身必须跨多台机器甚至数据中心扩展。将需要围绕事件驱动模型重新构建应用程序。这意味着发送事件(而不是等待结果)而不是调用函数并同步等待结果。拥抱消息总线。这是必须实现异步处理模型的直接后果。随着您的单体应用程序被分解为事件处理程序和事件发射器,就需要一个健壮、高性能和灵活的消息总线。有多种选择,选择取决于应用程序规模和复杂性。对于一个简单的用例,像 Redis 这样的东西就可以做到。如果您需要您的应用程序真正是云原生的并自行扩展和缩减,您可能需要能够处理来自多个事件源的事件:从 Kafka 等流管道到基础设施,甚至监控事件。API 版本控制。由于您的微服务将使用彼此的 API 通过总线相互通信,因此设计用于保持向后兼容性的架构将是至关重要的。只需部署一个微服务的最新版本,开发人员就不应该要求其他人升级他们的代码。这将是向整体方法向后兼容的一步,开发团队必须在永远支持旧 API 和保持更高的开发速度之间达成合理的妥协。这也意味着 API 设计成为一项重要的技能。频繁的破坏性 API 更改是团队无法高效开发复杂微服务的原因之一。重新考虑您的安全性。许多开发人员没有意识到这一点,但迁移到微服务为更好的安全模型创造了机会。由于每个微服务都是一个专门的进程,因此最好只允许它访问所需的资源。这样,仅一个微服务中的漏洞就不会将系统的其余部分暴露给攻击者。这与大型单体形成对比,后者倾向于以更高的特权(每个人都需要的超集)运行,并且可能导致更多的违规行为。Kubernetes 与微服务有什么关系?Kubernetes 太复杂了,无法在此详细描述,但值得对其进行概述,因为很多人在有关微服务的对话中都会提到它。严格来说,Kubernetes(又名 K8s)的主要好处是通过跨多个进程高效共享计算资源来提高基础设施利用率。Kubernetes 是动态分配计算资源以满足需求的大师。这允许组织避免为他们不使用的计算资源付费。但是,K8s 的一些附带好处使向微服务的过渡变得更加容易。当您将单体应用程序分解为单独的、松散耦合的微服务时,您的团队将获得更多的自主权和自由度。但是,在与微服务必须运行的基础设施进行交互时,它们仍然必须密切合作。您必须解决以下问题:预测每个服务需要多少计算资源;这些要求在负载下如何变化;如何划分基础设施分区并将它们划分到微服务之间;实施资源限制。Kubernetes 非常优雅地解决了这些问题,并提供了一个通用框架来描述、检查和推理基础设施资源的共享和利用。这就是为什么采用 Kubernetes 作为微服务重新架构的一部分是一个好主意。然而,Kubernetes 是一项需要学习的复杂技术,而且更难管理。如果可以,您应该利用云提供商提供的托管 Kubernetes 服务。但是,对于需要跨多个云提供商和企业数据中心运行自己的 Kubernetes 集群的公司来说,这并不总是可行的。结论总结一下:容器只是具有应用受限制的 Linux 进程。限制的示例包括允许进程使用多少 CPU 或内存。Docker 之类的工具允许开发人员将他们的可执行文件与依赖项和附加配置打包在一起。这些包被称为 镜像,并且经常且容易混淆地也被称为容器。微服务并不新鲜。这是一种旧的软件设计模式,由于互联网公司的规模不断扩大,它越来越受欢迎。微服务不一定要容器化。同样,单体应用程序可以是微服务。小项目不应该回避整体设计。它为较小的团队提供更高的生产力。Kubernetes 是由多个微服务组成的复杂应用程序的绝佳平台。Kubernetes 也是一个复杂的系统,学习曲线陡峭,管理成本非常高。
文章
存储  ·  Kubernetes  ·  监控  ·  Linux  ·  API  ·  数据库  ·  Docker  ·  Ruby  ·  微服务  ·  容器
2022-08-11
Git入门Git简介
Git 技能树(1):Git 简介什么是“版本控制”?我为什么要关心它呢? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。在 GIT CODE 中,我们对保存着软件源代码的文件作版本控制,但实际上,你可以对任何类型的文件进行版本控制。如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能),采用版本控制系统(VCS)是个明智的选择。 有了它你就可以将选定的文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。 使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。 但额外增加的工作量却微乎其微。接下来,我们将要回顾版本控制系统的发展历史。版本控制系统发展可以分为三个阶段:本地版本控制系统集中式版本控制系统分布式版本控制系统本地版本控制系统许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。其中最流行的一种叫做 RCS ,现今许多计算机系统上都还看得到它的踪影。 RCS 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。集中化的版本控制系统接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作? 于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。 这类系统,诸如 CVS、Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。但这么做也有一个显而易见的缺点,那就是是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。分布式版本控制系统于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。不仅如此,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。这样一来,你就可以在同一个项目中,分别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。Git 的诞生接下来,让我们来看一看 Git 诞生的故事。Git 诞生的背景同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。Linus 在1991年创建了开源的 Linux,从此,Linux 系统不断发展,已经成为最大的服务器系统软件了。在1991-2002年期间,世界各地的志愿者把源代码文件通过 diff 的方式发给 Linus,然后由 Linus 本人通过手工方式合并代码。你也许会想,为什么 Linus 不把 Linux 代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?因为Linus 坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和 Linux 的开源精神不符。Linus 两周完成 Git到 2002 年,Linux 系统已经发展了十年了,代码库之大让 Linus 很难继续通过手工方式管理了,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码,BitKeeper 的东家 BitMover 公司也免费授权 Linux 社区使用这个版本控制系统。后来 BitMover 公司发现社区有人试图破解 BitKeeper 的协议,于是 BitMover 公司收了回 Linux 社区的免费使用权。这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:速度简单的设计对非线性开发模式的强力支持(允许成千上万个并行开发的分支)完全分布式有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)于是,Linus 花了两周时间自己用 C 写了一个分布式版本控制系统,这就是 Git!一个月之内,Linux 系统的源码已经由 Git 管理了!Git 的发展壮大自 2005 年诞生以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。Git 迅速成为最流行的分布式版本控制系统,尤其是 2008 年,GitHub 网站上线了,它为开源项目免费提供 Git 存储,无数开源项目开始迁移至 GitHub ,包括jQuery,PHP,Ruby等等。
文章
存储  ·  JavaScript  ·  Linux  ·  PHP  ·  开发工具  ·  数据库  ·  git  ·  开发者  ·  Ruby
2022-08-09
Redis管道技术/分区
Redis管道技术Redis是一种基于客户机-服务器模型和请求/响应协议的TCP服务。这意味着请求通常将遵循以下步骤:客户端向服务器发送查询请求,并侦听套接字返回,通常处于阻塞模式,等待服务器响应。服务器处理该命令并将结果返回给客户端。Redis管道技术允许客户端在服务器没有响应时继续向服务器发送请求,最后一次读取所有服务器的响应。实例要查看redis管道,只需启动redis实例并输入以下命令:$(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379 +PONG +OK redis :1 :2 :3在上面的示例中,我们使用ping命令检查redis服务是否可用。然后我们将runoobkey的值设置为redis,然后我们得到runoobkey的值,并使访问者自动增加三倍。在返回的结果中,我们可以看到这些命令一次提交到redis服务,最后一次读取所有服务器的响应管道技术最显著的优势是提高redis服务的性能。一些测试数据require 'rubygems' require 'redis' def bench(descr) start = Time.now yield puts "#{descr} #{Time.now-start} seconds" end def without_pipelining r = Redis.new 10000.times { r.ping } end def with_pipelining r = Redis.new r.pipelined { 10000.times { r.ping } } end bench("without pipelining") { without_pipelining } bench("with pipelining") { with_pipelining }在接下来的测试中,我们将使用redis的Ruby客户端来支持流水线技术的特性,并测试流水线技术的提速效果。在局域网中的Mac OS X系统上执行的上述简单脚本的数据表明,在开启管道操作后,往返延迟已显著改善。Redis分区是将数据划分为多个redis实例的过程,因此每个实例只保存密钥的子集。分区的优势通过使用多台计算机的内存总和,我们可以构建一个更大的数据库。通过多核和多台计算机,我们可以扩展我们的计算能力;通过多台计算机和网络适配器,我们可以扩展网络带宽。分区不足redis的一些功能在分区方面表现不佳:通常不支持涉及多个键的操作。例如,当两个集合映射到不同的redis实例时,您无法对这两个集合执行交集操作。不能使用涉及多个密钥的Redis事务。使用分区时,数据处理更加复杂。例如,您需要处理多个rdb/aof文件,并备份来自多个实例和主机的持久文件。添加或删除容量也很复杂。大多数redis集群支持在运行时添加和删除节点的透明数据平衡,但其他系统(如客户端分区和代理)不支持此功能。然而,一种叫做预硬化的技术是有帮助的。分区类型Redis有两种类型的分区。假设有四个redis实例R0、R1、R2、R3和多个键代表用户,例如user:1和user:2。对于给定的键,有许多不同的方法来选择该键存储在哪个实例中。换句话说,有不同的系统将密钥映射到redis服务。范围分区最简单的分区方法是按范围,即将特定范围内的对象映射到特定的redis实例。例如,ID为0到10000的用户将保存到实例R0,ID为10001到20000的用户将保存到R1,依此类推。该方法是可行的,可以在实践中使用。缺点是有一个从区间范围到实例的映射表。此表需要管理。同时,它还需要各种对象的映射表,这通常不是redis的好方法。哈希分区另一种分区方法是哈希分区。这适用于任何键,并且不需要是对象名称:该形式与以下描述一样简单:使用哈希函数将密钥转换为数字,例如,使用CRC32哈希函数。在键foobar上执行CRC32(foobar)将输出一个类似于93024922的整数。取这个整数的模并将其转换为0到3之间的数字,然后这个整数可以映射到四个redis实例之一。93024922%4=2,这意味着键foobar应该保存在R2实例中。注:模运算是除法的余数,在许多编程语言中通常由%运算符实现。
文章
存储  ·  NoSQL  ·  网络协议  ·  数据处理  ·  Redis  ·  数据库  ·  iOS开发  ·  MacOS  ·  Ruby
2022-08-08
Webpack(4): 处理 less 和 scss
前言上文介绍了如何在webpack 中处理 css 文件,主要依靠 css-loader 和 style-loader,作用分别是 解析 css 模块为 webpack 识别的模块,使用 本文会介绍在 webpack 中处理 less 和 scss 文件的方法。准备文件示例代码该系列的代码示例已经上传到 Github,点此访问。准备 less 和 scss 文件:// src/index.less @bgColor: red; body { background: @bgColor; }// src/index.scss $color: white; body { color: $color; }将它们在入口文件中导入:import './index.css' import './index.less' import './index.scss' document.querySelector('body').innerHTML = 'Hello'安装 loader pnpm add -D less less-loader sass sass-loaderless-loader 的主要作用是帮助 webpack 识别 .less 文件,同时底层会调用 less 模块将 .less 文件编译为 css,供后续的 loader 调用处理。sass-loader 的作用也是如此,加载 .sass 或者 .scss 文件并将他们编译为 CSS。配置 loadermodule.exports = { // ...... module: { rules: [ { test: /\.less$/, // loader 从右到左执行,经过 less-loader 转为 css,再经 css-loader 转为 webpack 识别的模块,最后插入到页面中 use: ['style-loader', 'css-loader', 'less-loader'], }, { test: /\.s[ac]ss$/, use: ['style-loader', 'css-loader', 'sass-loader'], } ] } }打开命令行窗口,执行打包命令: pnpm webpack现在 webpack 完成了对 less 和 scss 模块的打包工作,并将编译后的 CSS 插入到了 html 文件中。浏览器打开 index.html:dart-sass 和 node-sass先来看下 less-loader 和 sass-loader 它们两个的依赖情况。less-loader 依赖了 less 来编译 less 文件,这个没啥可说的:sass-loader 依赖 sass 和 node-sass 模块来编译 scss 文件:竟然依赖了两个模块来编译 scss 文件?其实 sass 的发展经历了三个时期:ruby sass:采用 ruby 实现 sass 编译器,时代的开创者,不能用在 node 环境中node-sass:采用 c++ 实现 sass 编译器,可以在 node 中编译 sass 文件。不再推荐使用dart-sass:采用 dart 实现的编译器,性能更好。推荐使用虽然 sass-loader 默认依赖了 node-sass 和 sass(就是 dart-sass)模块,但是默认情况下它会使用 sass 模块来进行编译。loader 的其他配置目前在配置 module.rules 时,主要用到了两个配置项:test : 匹配要处理的模块类型use:使用哪些 loader 来处理模块除了这两个配置项外,这里再介绍一些常用的其他的选项。更多的可以去阅读官方文档。loader值是一个 loader 的名字,是 use 的简写,已废弃。 { test: /\.css$/, loader: 'css-loader' }options传给 loader 的配置项:{ test: /\.s[ac]ss$/i, use: [ 'style-loader', 'css-loader', { loader: 'sass-loader', options: { // 使用哪个模块来编译 scss 文件,默认就是 sass implementation: require('sass'), }, }, ], }exclude排除掉匹配的资源,不使用 loader 处理{ test: /\.css$/, use: ['css-loader'], exclude: /node_modules/ }include设定模块匹配的范围,交给 loader 处理{ test: /\.css$/, user: ['css-loader'], include: path.resolve(__dirname, './node_modules/normalize.css') }useuse 用来执行使用哪些 loader 来加载模块,是一个应用于模块的 UseEntries 数组。有多种使用形式:{ use: [ 'style-loader' ] // 使用一个 loader use: [ 'style-loader', 'style-loader' ] // 使用多个 loader use: [ { loader: 'style-loader', options:{}} ] // 给 loader传递的选项,需要写成对象的形式 }小结本文介绍了如何在 webpack 处理 less 和 scss 模块,主要使用两个 loader——less-loader 和 sass-loader。它们底层分别使用了 less 和 sass 来将各自的文件编译为普通的 css 文件 ,最后才能被浏览器识别和解析。同时也介绍了 module.rules 的其他的一些配置项,尤其是 use 属性的多种用法。下篇文章,会介绍如何在 webpack 处理 css 的兼容性。
文章
Dart  ·  前端开发  ·  编译器  ·  C++  ·  Ruby
2022-08-08
从零开始搭建Vue2.0项目(一)之项目快速开始
前言该样板适用于大型,严肃的项目,并假定您对Webpack和有所了解vue-loader。确保还阅读vue-loader的文档,了解常见的工作流程配方。如果您只想尝试vue-loader或快速制作出原型,请改用webpack-simple模板。快速开始要使用此模板,请使用vue-cli搭建项目。建议使用npm 3+以获得更有效的依赖关系树。$ npm install -g vue-cli $ vue init webpack my-project $ cd my-project $ npm install $ npm run dev安装完成后,成功运行:项目结构. ├── build/ # webpack配置文件 │ └── ... ├── config/ │ ├── index.js # 主要项目配置 │ └── ... ├── src/ │ ├── main.js # 应用入口文件 │ ├── App.vue # 主应用程序组件 │ ├── components/ # ui组件 │ │ └── ... │ └── assets/ # 模块资源(由webpack处理) │ └── ... ├── static/ # 纯静态资源(直接复制) ├── test/ │ └── unit/ # 单元测试 │ │ ├── specs/ # 测试spec文件 │ │ ├── index.js # 测试构建条目文件 │ │ └── karma.conf.js # 测试跑步者配置文件 │ └── e2e/ # e2e测试 │ │ ├── specs/ # 测试spec文件 │ │ ├── custom-assertions/ # e2e测试的自定义断言 │ │ ├── runner.js # 测试跑步脚本 │ │ └── nightwatch.conf.js # 测试跑步者配置文件 ├── .babelrc # babel 配置 ├── .postcssrc.js # postcss 配置 ├── .eslintrc.js # eslint 配置 ├── .editorconfig # editor 配置 ├── index.html # index.html模板 └── package.json # 构建脚本和依赖关系下面的内容建议根据需要自行了解哈,这里就不再细讲了!想直接上手下一步配置的可以直接跳转到下一篇了 项目完整配置详细配置参考webpack官网:http://vuejs-templates.github.io/webpack/Babel配置该样板babel-preset-env用于配置Babel。您可以在此处了解更多信息-http://2ality.com/2017/02/babel-preset-env.html。因此,通过配置Babel可以使程序运行在不同版本的浏览器中(比如:IE 11+)一个Babel预设,可根据目标浏览器或运行时环境自动确定所需的Babel插件和polyfill,从而将ES2015 +向下编译为ES5。它用于browserslist解析此信息,因此我们可以使用所支持的browserslist任何有效查询格式。但是有一个警告。browserslist建议在定义像一个共同的地方目标package.json或在.browserslistrc配置文件中。这允许像autoprefixer和eslint-plugin-compat共享配置的工具。对于此模板,browserslist在中配置package.json:{ "...": "...", "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }但最新的稳定版本babel-preset-env,v1.6.1不支持从中加载配置package.json。因此,在中重复了目标环境.babelrc。如果要更改目标环境,请确保同时更新package.json和.babelrc。请注意,此问题已在beta版本(@babel/preset-env@7.0.0-beta.34)中修复,一旦模板超出beta版本,模板就会进行更新。Linter配置该样板使用ESLint作为临时对象,并使用带有一些小的定制的Standard预设。如果您对默认的掉毛规则不满意,则可以选择以下几种方法:覆盖中的单个规则.eslintrc.js。例如,您可以添加以下规则来强制使用分号而不是省略分号:// .eslintrc.js "semi": [2, "always"]生成项目时,请选择其他ESLint预设,例如eslint-config-airbnb。生成项目并定义自己的规则时,为ESLint预设选择“无”。有关更多详细信息,请参见ESLint文档。修复棉绒错误您可以运行以下命令让eslint修复发现的任何错误(如果可以的话-并非所有错误都可以像这样修复):npm run lint -- --fix(--中间的,以确保将--fix选项传递给eslint,而不是npm)是必要的预处理器此样板为大多数流行的CSS预处理器(包括LESS,SASS,Stylus和PostCSS)预先配置了CSS提取。 要使用预处理器,您需要做的就是为其安装适当的webpack加载器。 例如,要使用SASS:npm install sass-loader node-sass --save-dev请注意,您还需要安装node-sass,因为sass-loader将其视为对等依赖关系。在组件内部使用预处理器:安装完成后,您可以使用* .vue组件中的预处理器,使用 <style> 标签上的lang属性:<style lang="scss"> /* write SASS! */ </style>关于SASS语法的注释:lang =“scss”对应于CSS-superset语法(带大括号和分号)。lang =“sass”对应于基于缩进的语法。PostCSS默认情况下,* .vue文件中的样式通过PostCSS管道传输,因此您不需要使用特定的加载器。 您可以在vue块下简单添加要在build / webpack.base.conf.js中使用的PostCSS插件:// build/webpack.base.conf.js module.exports = { // ... vue: { postcss: [/* your plugins */] } }有关详细信息,请参阅vue-loader's的相关文档。Standalone CSS Files:为了确保一致的提取和处理,建议从您的根App.vue组件导入全局独立样式文件,例如:<!-- App.vue --> <style src="./styles/global.less" lang="less"></style>请注意,您应该仅为自己为您的应用程序编写的样式。 对于现有的图书馆 引导或语义UI,您可以将它们放在/静态中,并直接在index.html中引用它们。 这避免了额外的构建时间,也更适合浏览器缓存。 (见 Static Asset Handling)处理静态资产(Static Assets):您将在项目结构中注意到,静态资产有两个目录:src / assets和static /。 他们有什么区别?Webpacked资产:为了回答这个问题,我们首先需要了解Webpack如何处理静态资产。 在* .vue组件中,所有的模板和CSS都由vue-html-loader和css-loader解析来查找资源URL。 例如,在和background:url(./ logo.png)中,“./logo.png”是相对的资产路径,将由Webpack解析为模块依赖关系。因为logo.png不是JavaScript,当被视为模块依赖关系时,我们需要使用url-loader和file-loader来处理它。 此样板已经为您配置了这些加载程序,因此您可以免费获得文件名指纹和条件base64内联等功能,同时可以使用相对/模块路径,而不必担心部署。由于这些资源可能在构建过程中被内联/复制/重命名,所以它们基本上是您的源代码的一部分。 这就是为什么建议将Webpack处理的静态资产放在/ src中,沿着其他源文件。 实际上,您甚至不必将它们全部放在/ src / assets中:您可以根据使用它们的模块/组件进行组织。 例如,您可以将每个组件放在自己的目录中,其静态资产就在它的旁边。资产解决规则:.相对网址,例如 ./assets/logo.png将被解释为模块依赖关系。 它们将被基于Webpack输出配置的自动生成的URL替换。.非前缀网址,例如 assets / logo.png将被视为与相对URL相同,并被翻译成./assets/logo.png。.前缀为〜的URL被视为模块请求,类似于require('some-module / image.png')。 如果要使用Webpack的模块解析配置,则需要使用此前缀。 例如,如果您有资产的解决别名,则需要使用来确保别名符合要求。.根相对URL,例如 /assets/logo.png根本没有被处理。在JavaScript中获取资源路径: 为了使Webpack返回正确的资源路径,您需要使用require('./ relative / path / to / file.jpg'),这将由文件加载程序处理,并返回已解析的URL。 例如:*computed: { background () { return require('./bgs/' + this.id + '.jpg') } }注意上面的例子将包括最终构建中的./bgs/下的每个图像。 这是因为Webpack无法猜测它们在运行时将被使用,所以它包括它们。“真实”静态资产: 相比之下,静态的文件根本不被Webpack处理:它们直接以相同的文件名复制到最终目的地。 您必须使用绝对路径引用这些文件,这是通过在config.js中加入build.assetsPublicPath和build.assetsSubDirectory来确定的。例如,使用以下默认值:// config/index.js module.exports = { // ... build: { assetsPublicPath: '/', assetsSubDirectory: 'static' } }使用绝对URL / static / [filename]引用静态/中的任何文件。 如果将assetSubDirectory更改为资产,则这些URL将需要更改为/ assets / [filename]。我们将在后端集成部分中详细了解配置文件。环境变量有时,根据应用程序运行的环境,使用不同的配置值是可行的。举个例子:// config/prod.env.js module.exports = { NODE_ENV: '"production"', DEBUG_MODE: false, API_KEY: '"..."' // this is shared between all environments } // config/dev.env.js module.exports = merge(prodEnv, { NODE_ENV: '"development"', DEBUG_MODE: true // this overrides the DEBUG_MODE value of prod.env }) // config/test.env.js module.exports = merge(devEnv, { NODE_ENV: '"testing"' })注意:字符串变量需要用单引号和双引号引起来'"..."'因此,环境变量为:生产NODE_ENV ='生产',DEBUG_MODE = false,API_KEY ='...'发展历程NODE_ENV ='发展',DEBUG_MODE = true,API_KEY ='...'测验NODE_ENV ='正在测试',DEBUG_MODE = true,API_KEY ='...'如我们所见,test.env继承了dev.env和dev.env继承了prod.env。用法在代码中使用环境变量很简单。例如:Vue.config.productionTip = process.env.NODE_ENV === 'production'与后端框架集成如果您要构建一个纯静态的应用程序(一个与后端API分开部署的应用程序),那么您甚至可能不需要进行编辑config/index.js。但是,如果您想将此模板与现有的后端框架(例如Rails / Django / Laravel)集成在一起,它们都具有自己的项目结构,则可以进行编辑config/index.js以将前端资产直接生成到您的后端项目中。让我们看一下默认值config/index.js:// config/index.js var path = require('path') module.exports = { build: { index: path.resolve(__dirname, 'dist/index.html'), assetsRoot: path.resolve(__dirname, 'dist'), assetsSubDirectory: 'static', assetsPublicPath: '/', productionSourceMap: true }, dev: { port: 8080, proxyTable: {} } }在此build部分中,我们有以下选项:build.index必须是本地文件系统上的绝对路径。这是生成index.html(带有注入的资产URL)的地方。如果您将此模板与后端框架一起使用,则可以进行相应的编辑index.html,并将此路径指向后端应用程序渲染的视图文件,例如,app/views/layouts/application.html.erb用于Rails应用程序或resources/views/index.blade.phpLaravel应用程序。build.assetsRoot必须是本地文件系统上的绝对路径。这应该指向包含应用程序所有静态资产的根目录。例如,public/对于两个Rails / Laravel。build.assetsSubDirectory将webpack生成的资产嵌套在此目录下build.assetsRoot,以使它们不会与中可能包含的其他文件混合build.assetsRoot。例如,如果build.assetsRootis/path/to/dist和build.assetsSubDirectoryis static,则所有Webpack资产都将在中生成path/to/dist/static。该目录将在每次构建之前清除,因此它应仅包含由构建生成的资产。内部文件static/将在构建过程中原样复制到此目录中。这意味着,如果您更改此前缀,则所有引用文件的绝对URLstatic/也将需要更改。有关更多详细信息,请参见处理静态资产。build.assetsPublicPath这应该是build.assetsRoot将通过HTTP为您提供服务的URL路径。在大多数情况下,这将是根(/)。仅当您的后端框架提供带有路径前缀的静态资产时才更改此设置。在内部,这作为传递给Webpack output.publicPath。build.productionSourceMap是否生成用于生产构建的源地图。dev.port指定开发服务器要监听的端口。dev.proxyTable定义开发服务器的代理规则。有关更多详细信息,请参见开发期间的API代理。跨域代理当将此样板与现有后端集成时,通常需要在使用dev服务器时访问后端API。 为了实现这一点,我们可以并行(或远程)运行dev服务器和API后端,并让dev服务器将所有API请求代理到实际的后端。要配置代理规则,请在config / index.js中编辑dev.proxyTable选项。 dev服务器正在使用http代理中间件进行代理,因此您应参考其文档以获取详细的用法。 但这是一个简单的例子:// config/index.js module.exports = { // ... dev: { proxyTable: { // proxy all requests starting with /api to jsonplaceholder '/api': { target: 'http://jsonplaceholder.typicode.com', changeOrigin: true, pathRewrite: { '^/api': '' } } } } }以上示例将代理请求/ api / posts / 1 到 http://jsonplaceholder.typicode.com/posts/1.网址匹配:除了静态网址之外,您还可以使用glob模式来匹配网址,例如/ API/ **。 有关详细信息,请参阅上下文匹配。 此外,您可以提供一个过滤器选项,该选项可以是自定义函数,用于确定请求是否应被代理:proxyTable: { '**': { target: 'http://jsonplaceholder.typicode.com', filter: function (pathname, req) { return pathname.match('^/api') && req.method === 'GET' } } }单元测试该项目为单元测试提供了两种选择:Karma:启动浏览器,运行测试并将结果报告给我们的测试运行程序。karma-webpack:Karma插件,使用Webpack捆绑了我们的测试。Mocha:我们用来编写测试规范的测试框架。Chai:测试断言库,提供更好的断言语法。Sinon:提供间谍,存根和模拟的测试实用程序库。Chai 和 Sinon是使用karma-sinon-chai进行集成的,因此所有的柴接口(should,expect,assert),并sinon在测试文件全局可用。端到端测试该样板使用Nightwatch.js进行e2e测试。Nightwatch.js是建立在Selenium之上的高度集成的e2e测试运行程序。该样板随附为您预先配置的Selenium服务器和chromedriver二进制文件,因此您不必自己弄乱这些文件。让我们看一下目录中的test/e2e文件:runner.js一个Node.js脚本,该脚本启动开发服务器,然后启动Nightwatch对它运行测试。这是运行时将运行的脚本npm run e2e。nightwatch.conf.jsNightwatch配置文件。有关更多详细信息,请参见Nightwatch的有关配置的文档。custom-assertions/可在Nightwatch测试中使用的自定义断言。有关更多详细信息,请参见Nightwatch的有关编写自定义断言的文档。specs/您的实际测试!有关更多详细信息,请参见Nightwatch的有关编写测试的文档和API参考。在更多浏览器中运行测试要配置在其中运行测试的浏览器,请在中的“ test_settings”下添加一个条目test/e2e/nightwatch.conf.js,并在中添加--env标记test/e2e/runner.js。如果希望在SauceLabs等服务上配置远程测试,则可以根据环境变量使Nightwatch配置为条件,或者完全使用单独的配置文件。有关更多详细信息,请查阅Nightwatch关于Selenium的文档。预渲染SEO​ 如果您希望预先投放一旦推送到生产时不会显着更改的路线,请使用此Webpack插件:prerender-spa-plugin,它已经过Vue测试。 对于频繁更改的页面,Prerender.io和Netlify都提供定期重新预览您的搜索引擎内容的计划。​ 使用prerender-spa-plugin 将其安装为开发人员依赖关系:npm install --save-dev prerender-spa-plugin需要在build / webpack.prod.conf.js中:// 该行应该位于其他“进口”生活的文件的顶部 var PrerenderSpaPlugin = require('prerender-spa-plugin')在plugins数组中(也在build / webpack.prod.conf.js中)进行配置:new PrerenderSpaPlugin( // Path to compiled app path.join(__dirname, '../dist'), // List of endpoints you wish to prerender [ '/' ] )如果您还想预先投射/关于和/接触,那么该数组将是['/','/ about','/ contact']。启用vue-router的历史记录模式const router = new VueRouter({ mode: 'history', routes: [...] })【学无止境❤️谦卑而行】欢迎关注白羊,感谢观看ヾ(◍°∇°◍)ノ゙
文章
缓存  ·  JavaScript  ·  前端开发  ·  中间件  ·  测试技术  ·  API  ·  定位技术  ·  PHP  ·  Ruby  ·  Python
2022-08-07
InnoDB表聚集索引层高什么时候发生变化(1)
导读本文略长,主要解决以下几个疑问1、聚集索引里都存储了什么宝贝2、什么时候索引层高会发生变化3、预留的1/16空闲空间做什么用的4、记录被删除后的空间能回收重复利用吗1、背景信息1.1 关于innodb_fill_factor有个选项 innodb_fill_factor 用于定义InnoDB page的填充率,默认值是100,但其实最高只能填充约15KB的数据,因为InnoDB会预留1/16的空闲空间。在InnoDB文档中,有这么一段话An innodb_fill_factor setting of 100 leaves 1/16 of the space in clustered index pages free for future index growth.另外,文档中还有这样一段话When new records are inserted into an InnoDB clustered index, InnoDB tries to leave 1/16 of the page free for future insertions and updates of the index records. If index records are inserted in a sequential order (ascending or descending), the resulting index pages are about 15/16 full. If records are inserted in a random order, the pages are from 1/2 to 15/16 full.上面这两段话,综合起来理解,就是即便 innodb_fill_factor=100,也会预留1/16的空闲空间,用于现存记录长度扩展用在最佳的顺序写入数据模式下,page填充率有可能可以达到15/16在随机写入新数据模式下,page填充率约为 1/2 ~ 15/16预留1/16这个规则,只针对聚集索引的叶子节点有效。对于聚集索引的非叶子节点以及辅助索引(叶子及非叶子)节点都没有这个规则不过 innodb_fill_factor 选项对叶子节点及非叶子节点都有效,但对存储text/blob溢出列的page无效1.2 关于innodb_ruby项目innodb_ruby 项目是由Jeremy Cole 和 Davi Arnaut 两位大神开发的项目,可用于解析InnoDB数据结构,用ruby开发而成。他们还维护了另一个众所周知的项目叫 InnoDB Diagrams,相信稍微资深一点的MySQL DBA都应该知道这个项目。1.3 关于innblock工具由八怪开发,用于扫描和分析InnoDB page,详见 innblock | InnoDB page观察利器1.4 阅读本文背景信息需要假设您对InnoDB的数据结构已经有了一定了解,包括B+树、聚集索引、辅助索引,以及innodb page的一些简单结构。如果不太肯定,请先阅读这些文档内容Clustered and Secondary IndexesThe Physical Structure of an InnoDB IndexInnoDB Row FormatsInnoDB Record StructureInnoDB Page Structure2、测试验证:一层高的InnoDB表聚集索引,最多能存多少条数据从上面我们知道,一个page最大约能存储15/16容量,扣掉用于存储page header、trailer信息,以及index header、File Segment Header、Infimum&Supremum(两条虚拟记录)等必要的固定消耗之后,实际大约只有15212字节可用于存储用户数据。这样一来,我们就可以简单测算出一个page大约能存储多少条记录了。本次用到的测试表,只有一个INT列,同时作为主键(建议横版观看,可左右滑动。或者复制链接到PC端打开观看,效果更佳。下同)# MySQL的版本是Percona Server 5.7.22-22,我自己下载源码编译的 [root@yejr.me#] mysql -Smysql.sock innodb ... Server version: 5.7.22-22-log Source distribution ... [root@yejr.me]> \s ... Server version: 5.7.22-22-log Source distribution # 创建测试表 [root@yejr.me]> CREATE TABLE `t1` ( `i` int(10) unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`i`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;另外,我们知道每条记录都要几个额外存储的数据DB_TRX_ID,6字节DB_ROLL_PTR,7字节Record Header,至少5字节(用上面这个测试表,只需要5字节,不同数据类型需要的header长度也不同,详见 浅析InnoDB Record Header及page overflow因此,一条数据需要消耗 4(INT列) + 6 + 7 + 5 = 22字节此外,大约每4条记录就需要一个directory slot,每个slot需要2字节综上,假设可以存储N条记录,则 N*22 + N/4*2 = 15212,可求得N约等于676接下来我们验证一下,往该表中持续插入 676 条数据[root@yejr.me]> insert into t1 select 0;...# 逐次反复执行676次然后,我们利用 innodb_ruby 工具查看其数据结构2.1 查看聚集索引page结构此时t1表的聚集索引树只有一层高,一个page即pageno=3[root@yejr]# innodb_space -s ibdata1 -T innodb/t1 space-indexesid name root fseg fseg_id used allocated fill_factor128 PRIMARY 3 internal 1 1 1 100.00%128 PRIMARY 3 leaf 2 0 0 0.00%再用innblock工具扫描佐证一下[root@yejr]# innblock innodb/t1.ibd scan 16...level0 total block is (1)block_no: 3,level: 0|*|2.2 查看其directory slot可以看到170个slot,其中Infimum记录的owned=1,Supremum记录的owned=5[root@yejr]# innodb_space -s ibdata1 -T innodb/t1 \-p 3 page-directory-summary|grep -c -v slot1702.3 查看整个page的全览图前面是一堆头信息[root@yejr]# innodb_space -s ibdata1 -T innodb/t1 -p 3 page-illustrate Offset ╭────────────────────────────────────────────────────────────────╮ 0 │█████████████████████████████████████▋██████████████████████████│ 64 │█████████▋███████████████████▋████████████▋████████████▋████▋███│# 大概从这里开始是第一条记录 128 │█████████████▋████▋████████████████▋████▋████████████████▋████▋█│ 192 │███████████████▋████▋████████████████▋████▋████████████████▋████│...# 中间是用户数据...# 这里是预留的1/16空闲空间 15872 │ │ 15936 │ │# 这里是page directory slot,逆序存储# trailer占用8字节,此后每个slot占用2字节# 共170个slot 16000 │ █▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋│... 16320 │█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋█▋███████▋│ ╰────────────────────────────────────────────────────────────────╯# 最后是统计汇总信息Legend (█ = 1 byte): Region Type Bytes Ratio █ FIL Header 38 0.23% █ Index Header 36 0.22% █ File Segment Header 20 0.12% █ Infimum 13 0.08% █ Supremum 13 0.08% █ Record Header 3380 20.63% █ Record Data 11492 70.14% █ Page Directory 340 2.08% █ FIL Trailer 8 0.05% ░ Garbage 0 0.00% Free 1044 6.37%可以得到几点信息Record Data共占用11492字节,共676条记录,每条记录17字节(4+6+7)Page Directory共340字节,170个slot,每个slot占用2字节两条虚拟记录,均占用13字节(含5字节的record header)Record Header共3380字节,共676条记录,每条记录需要5字节头信息(再次提醒,表里字段类型各异,Record Header也会随之不同,仅在本例中只需要5字节。详见 浅析InnoDB Record Header及page overflow)提醒:本次测试是顺序写入,如果是随机写入或批量写入,可能就没办法把15/16的page空间填充的满满当当了 </div>
文章
存储  ·  关系型数据库  ·  MySQL  ·  数据库管理  ·  索引  ·  Ruby
2022-08-06
浅析InnoDB Record Header及page overflow(1)
前言土人有土办法,利用innodb_ruby观测验证innodb page header及overflow临界点。这是一篇封存了两年的文章,最近拿出来重新整理发布。1、背景信息1.1 InnoDB Diagrams项目首先看一下Jeremy Cole、Davi Arnaut两位大神联合维护的牛逼项目:InnoDB Diagrams。在这个项目中,详细介绍了InnoDB引擎数据结构、日志结构,以及InnoDB内部的运行机制。为了配合这个项目,二位大神还开发了一个InnoDB数据文件解析工具 innodb_ruby1.2 InnoDB Record HeaderInnoDB Diagrams项目中有一张图介绍了InnoDB record header是如何构成的关于这些头信息的解释可见文章 The physical structure of records in InnoDB,本文不赘述。简言之,记住几条关键规则一条记录的record header,至少是5字节对record header影响最大的是变长列数量,及其是否允许为NULL的属性关于变长列每个变长列,如果列长度 <128 字节,则需要额外1字节每个变长列,如果列长度 >=128 字节,则需要额外2字节如果没有任何变长列,则无需这额外的1-2字节变长类型为char/varchar/text/blob等同学们可能会诧异,char为什么也当做变长类型了?这是因为,当字符集非latin1时,最大存储长度可能会超过255字节,例如 char(65) utf8mb4 最长就可以存储260字节,此时在record header中需要用2字节来表示其长度,因此也被当做变长类型了关于列允许为NULL每个列如果允许为NULL,则增加 1bit,不足8bit也需要额外1字节例如只有2个列允许为NULL,只需要2bit来表示,但也需要占用1字节P.S,在InnoDB的存储结构里,从tablespace到segment,再到extent、page,还是file层面,总有各种必要的header或trailer信息需要消耗额外的字节数,不像MyISAM那么简单。1.3 innodb_ruby项目上面提过,innodb_ruby工具可以帮助我们进一步理解InnoDB引擎数据结构、日志结构。该项目用ruby语言开发(大神真是任性,选了这个比较冷门的开发语言)。特别提醒,该项目已经多年未更新,有些数据类型发生了变化(例如最经典的5.6之后时间日期类型),它解析的可能就不准确了,在我下面的实测案例中也证实了这点。因此,我还用到另外一个辅助工具 innblock。1.4 innblock工具由八怪开发,用于扫描和分析InnoDB page,详见 innblock | InnoDB page观察利器2、定义不同数据类型时的record header消耗根据上面的理论,我们接下来计算并验证当表里有各种不同的数据类型时,分别需要多少额外字节。关于测试环境MySQL版本:Percona Server 5.7.22-22测试配套工具:innodb_ruby & innblock特别提醒,测试表的字符集为utf8mb4。经过计算和验证,最终可以得到以下几条结论:每条记录的record header(下面简称RH)基础是5字节(简写成 RH=5)每当表中多一个列允许为NULL,则额外增加1bit,且不足8bit时也需要消耗1字节(同理,不足16bit时需要消耗2字节)每当表中多一个最大定义存储长度不超过255字节的变长列(char/varchar)时,额外增加1字节每当表中多一个最大定义存储长度超过255字节的变长列(char/varchar/text/blob)时,额外增加2字节由此我们可以推断出以下几种场景所需的record header大小(横屏观看,下同)场景表定义行长度(字节)record header(字节)备注说明1id int not null提醒:无显式主键2855(RH)+6(TRX_ID)+7(ROLL_PTR)+6(ROW_ID)+4(INT) = 282id int提醒:无显式主键,且未指定not null2966(允许null) + 6 +7 +6+4= 283id int not nullprimary key(id)提醒:id列是显式主键2255 + 6 + 7+4= 224id int not null,c1 char(10),primary key(id)c1列只存储一个字符'a'3477(char+null)+6 + 7+ 4 + 10(c1)= 345id int not null,c1 varchar(10),primary key(id)c1列只存储一个字符'a'2577(varchar+null) + 6 + 7+ 4 + 1(c1)= 25更多的场景,详见下面这个汇总表格 </div>
文章
存储  ·  关系型数据库  ·  MySQL  ·  测试技术  ·  Ruby
2022-08-06
1 2 3 4 5 6 7 8 9
...
20
跳转至:
阿里云开发者学堂
124023 人关注 | 4987 讨论 | 2557 内容
+ 订阅
  • 全链路数据治理实操演练营,互联网、金融、制造等行业都适用!
  • 【Vue.js 入门与实战】--组件传值-父组件向子组件传值和data与props的区别
  • 【Vue.js 入门与实战】--动画-小球动画flag标识符的作用分析
查看更多 >
开发与运维
5322 人关注 | 128015 讨论 | 213560 内容
+ 订阅
  • 西安邮电陈莉君教授领衔,业界首个产学研 eBPF技术探索SIG成立!
  • 云数据库RDS MySQL Serverless已来
  • 阿里云 X Elastic 联合Meetup -北京站
查看更多 >
数据库
250023 人关注 | 46006 讨论 | 67833 内容
+ 订阅
  • 云数据库RDS MySQL Serverless已来
  • 从函数计算到 Serverless 架构
  • 合作再升级!云原生加速器成员企业云霁科技获得阿里云产品生态集成认证
查看更多 >
大数据
185224 人关注 | 24752 讨论 | 59990 内容
+ 订阅
  • 西安邮电陈莉君教授领衔,业界首个产学研 eBPF技术探索SIG成立!
  • 阿里云 X Elastic 联合Meetup -北京站
  • 浅谈点量云实时渲染和像素流的六点区别
查看更多 >
安全
1097 人关注 | 23397 讨论 | 59807 内容
+ 订阅
  • 西安邮电陈莉君教授领衔,业界首个产学研 eBPF技术探索SIG成立!
  • 阿里云无影发布生态共荣计划,携手伙伴推动终端算力上云
  • 浅谈点量云实时渲染和像素流的六点区别
查看更多 >