Linux优化之IO子系统监控与调优

Linux优化之IO子系统

作为服务器主机来讲,最大的两个IO类型 :

1.磁盘IO 

2.网络IO

这是我们调整最多的两个部分所在

 

磁盘IO是如何实现的

在内存调优中,一直在讲到为了加速性能,linux内核一般情况下都会尝试将磁盘上的慢速设备上的文件缓存至内存中,从而达到加速效果;

虚拟内存的概念:

读写都在内存中完成,当某一进程在cpu运行的时候,进程要访问自己地址空间中的某一内存页,当进程需要访问页面中的数据,而这个页面最终是要对应在物理内存中的某个物理页面,而进程只能看到自己的线性地址空间,而这个地址并不存在,一旦访问这个地址,那么会通过MMU(内存管理单元)机制中的存储当前进程的线性地址到物理地址的映射表

由此通过MMU实现对应的地址查询于是得到了其映射的地址,最终进程虽然访问的数据是来自于映射过的地址,这种访问访问我们被称为虚拟地址或虚拟内存

 

如果由于我们使用交换内存或其他方式有可能这个进程所打开的文件长时间没有被访问,这个文件所对应的内存已经被清出去了,所以使用mmu地址转换后的地址对应的数据在内存中不存在了,这时候会产生页错误,我们也被称为缺页异常

 

缺页异常

缺页异常分为大异常和小异常:

    如果数据不存在使得不得不在磁盘中载入页面文件,这时CPU就会进入内核模式,访问磁盘,每次CPU访问内存就要3个周期,访问磁盘需要N个周期,首先需要定位数据的准确位置,而后定位物理内存中开辟数据空间,最后将数据总线贯通,从而将数据从磁盘转入到内存--blockin

 

    当我们找一个空闲空间,而事实上当进程访问这段数据就需要访问新位置的数据,所以我们要更新这个映射表,明确说明所要访问的逻辑地址所要对应的空间的转换的位置,并且让进程重新发起一次访问,这时需要先查找TLB(缓存缓冲器),再次进行查表

    而将磁盘装入内存的过程就会发生IO,如果进程修改了数据,最终数据还需要写到磁盘中去,而写到磁盘中去,过程使得数据比原来的文件更大了

具体是由文件系统模块根据进程发起的请求,内核指挥文件系统模块开辟更多的存储块而后将数据存储,这种过程被称为 block out

 

#缓冲器负责将之前缓冲过的缓存下来,那么如果N个条目,而缓冲器只能缓存有限的几个,那么命中率可能会很低,如果我们使用大页面的话,那么命中率可以大大提高。

 

 

机械硬盘的特性

同一方向的操作是合并起来完成的,而后在这个方向结束之后则是另外一方向的

对硬盘来讲,读写是不同类型的操作,读写是不能同时进行的

 

磁盘是如何操作的

将一个或多个进程的读操作合并到一起读

将一个或多个进程的写操作合并到一起写

 

所以读写操作是两类不同的操作而且是同一方向合并的

如果是读文件,这个文件一定是来自于磁盘的

如果是写文件,那么写入到内存中,对于进程来讲是已经完成的,那么用户对计算机性能感知是来自于读,因为读一定是与IO相交互

 

1.读是在同方向合并的

2.写也是需要合并的,而且两者是不同方向的操作

因为在同一方向可以节省很多资源

读必须优先满足,而写也不能等太久,因此必须有一种良好的算法让其尽可能都得到满足,而又不能让用户感到性能下降  

因此在IO系统上有个非常重要的模块---IO调度器

 

IO调度器

用来实现合并同一方向的读写操作并且将读写操作尽可能理想的这种状况

IO调度器本身的完成,最终用户实现写的时候进程级别所看到的数据是文件接口

那么文件接口输出的时候就意味着将磁盘空间以文件接口的方式输出,其需要文件系统

也就意味着进程与磁盘上的数据打交道是依赖文件系统的

 

所以用户的请求先到文件系统,而文件系统通过内核输出是虚拟文件接口(VFS) 通过VFS找到各特定文件系统相关模块,当然对应的文件是哪个那么则通过vfs转换成什么即可

文件系统将数据接下来之后,最终存储为磁盘块的方式保存在磁盘上,因此这些文件系统最终还要转换数据为磁盘块,所以接下来还要有块层

块层主要是将数据转换为磁盘块格式,而后再由磁盘块格式转换成调度以后存储在磁盘上

如下图所示:

wKiom1QdhnPy6EQQAAH_P6Mmz0A257.jpg

(1)用户进程实现写操作 实现系统调用

(2)用户的写操作一定是跟VFS进行交互的

(3)VFS需要将其换换为特定的文件系统

(4)单个文件在虚拟文件系统存放都会转换成页面方式(page cache)

(5)写完之后通过block buffer快缓冲(知所以进行缓冲是因为磁盘太慢了,所以写的时候需要缓冲下来

(6)然后由bio将每个page cache转换成块,并且在块缓冲这个层次上缓存下来

这就是缓冲队列,而在块层实现缓冲之后每个块最终都要交给块层来处理,块层中最重要的一个组件就是IO调度器,IO调度器接收blockbuffer中所发送过来的多个请求块,这多个请求块需要排序的:同方向合并,图中都是写操作的 

至于如何排序,一定是最靠近写请求的最优先满足

 

而IO调度器主要功能就是将随机IO尽可能合并为顺序IO  本文来自http://yijiu.blog.51cto.com 转载请说明,翻版可耻

但是我们有说过,尽可能同一方向合并尽可能会随机变为顺序,但是我们又不得不读饥饿也不能写饥饿,所以要交替进行的

所以:

(10)由IO调度器调度完成之后,提交给Device Driver ,由Device Driver控制磁盘控制器,由控制器将电器信号转换为磁信号写入到磁盘中去

 

为何随机读写比顺序读写要慢:

·随机读写:

我们可能写任意一个磁道的任意一个扇区,那么硬盘磁头可能来回晃动才能完成一次写

·顺序读写:

在一个方向转动即可完成,不用再去移动磁臂的

磁头操作是电磁运动,而磁臂操作是机械运动,所以任何时候随机读写性能都比顺序读写都要差的很多

 

 

调度算法

IO调度器事实上是用程序完成的调度算法,对linux来讲,2.6的内核一共有4个

1、CFQ

  完全公平队列,比较适合于交互式场景      

2、Deadline

   最后期限,任何一个读写请求,都有自己的满足期限,当期限到来时之前,必须达到需求的满足(一般建议在数据库服务器上使用此调度算法)

3、anticpatory

   预期的,任何一个数据读完之后,有可能与其相邻的数据也可能被读到,所以它大致所实现的方法就是,读完之后先不满足,则不处理,需等一段时间后查看是否有相近数据访问过,如果有马上先满足,所以这只能在行为预估的场景下可用

4、Noop

    不排队不合并,先到先得

    #像固态硬盘,因为它不是机械硬盘,它的读写就算是随机IO那么它的性能跟顺序IO差别也不是很大,反而如果想让调度器去调取它的算法,那么调度器本身运行会占用很高的CPU的时钟周期,有可能会得不偿失,所以noop在这种场景下是最好的算法

    #有些RAID设备控制器在硬件设备上自己就有读写操作排序的,也就意味着在硬件级别排好序之后在操作系统级别会将其打散重新排序,得不偿失,所以RAID设备有自己的调度器的话,最好也使用noop

一般来讲,默认是CFQ的

 本文来自http://yijiu.blog.51cto.com 转载请说明,翻版可耻

有时候在不同场景下,他们所最佳所适用的算法可能不一样,比如:

如果是web服务器,这里只是访问放web上的分区的页面数据

如果是db数据库,访问的是db数据库的文件,他们最适用的算法未必会一样,因为他们的访问风格不同,所以这时候我们就需要修改他们的调度器算法

CFQ比较适合于交互式场景,于是在很多时候会将服务器设置为Deadline,当然只是一种假定,具体需要自己测试然后做决定

 

观测当前磁盘IO活动

一般 ethstatus iotio pt-ioprofile sar等查工具看哪些进程引起的io比较高等

这里我们使用sar来观察其状态信息  本文 来自http://yijiu.blog.51cto.com 转载 请说明,翻版 可耻

例:

[root@node3 ~]# sar  -d 1 5

Linux2.6.32-431.20.3.el6.x86_64 (node3.test.com) 09/20/2014   _x86_64_(4 CPU)

 

09:16:00 PM       DEV      tps  rd_sec/s  wr_sec/s avgrq-sz  avgqu-sz     await    svctm     %util

09:16:01 PM  dev252-0    46.46      0.00  46795.96  1007.13      2.65    580.00     2.26     10.51

 

09:16:01 PM       DEV      tps  rd_sec/s  wr_sec/s avgrq-sz  avgqu-sz     await    svctm     %util

09:16:02 PM  dev252-0     3.00      0.00    144.00    48.00      0.00      1.33     1.00      0.30

 

09:16:02 PM       DEV      tps  rd_sec/s  wr_sec/s avgrq-sz  avgqu-sz     await    svctm     %util

09:16:03 PM  dev252-0     0.00      0.00      0.00     0.00      0.00      0.00     0.00      0.00

 

09:16:03 PM       DEV      tps  rd_sec/s  wr_sec/s avgrq-sz  avgqu-sz     await    svctm     %util

09:16:04 PM  dev252-0     0.00      0.00      0.00     0.00      0.00      0.00     0.00      0.00

 

09:16:04 PM       DEV      tps  rd_sec/s  wr_sec/s avgrq-sz  avgqu-sz     await    svctm     %util

09:16:05 PM  dev252-0    72.73      0.00  59967.68   824.56      2.61     35.88     1.21      8.79

用参数-p可以打印出sda,hdc等磁盘设备名称,如果不用参数-p,设备节点则有可能是dev8-0,dev22-0

参数解释:

tps:每秒从物理磁盘I/O的次数.多个逻辑请求会被合并为一个I/O磁盘请求,一次传输的大小是不确定的

rd_sec/s:每秒读扇区的次数. 

avgrq-sz:平均每次设备I/O操作的数据大小(扇区). 

avgqu-sz:磁盘请求队列的平均长度.

await:从请求磁盘操作到系统完成处理,每次请求的平均消耗时间,包括请求队列等待时间,单位是毫秒(1秒=1000毫秒).(一次完成的任务,它的IO完成的平均耗时)

svctm:系统处理每次请求的平均时间,不包括在请求队列中消耗的时间,

%util:I/O请求占CPU的百分比,比率越大,说明越饱,一般到95左右可能要引起关注

我们通常经验值是:

svctm不超过0.5;

await不超过5;

主要看当前设备


核心要点:
1、tps(iops)越高,但%util越低,说明io能力容量越大
2、await、svctm越低越好,说明io响应延迟很低,iops能力很高

 

调整buffer,提高性能

无非就是调整队列数,以及增加预读数,下面我们来手动做一下

·增加队列长度

格式:

/sys/block/vda(特定某设备)/queue/nr_requests

由于我这里跑的是kvm虚机,所以设备号默认都以vdx开头

默认队列为128个长度

[root@node3 ~]#  cat /sys/block/vda/queue/nr_requests

128

这个值是可以调大一点的

 

2.增加预读数

  /sys/block/vda(特定某设备)/queue/read_ahead_kb

表示事先预读数据的kb数,默认也是128

[root@node3 ~]# cat /sys/block/vda/queue/read_ahead_kb
128

这个值也是可以调大的,具体多少自行而定

 本文 来自http://yijiu.blog.51cto.com 转载 请说明,翻版 可耻

 

CFQ完全公平队列

IO调度是在各进程之间平均分配的,主要是根据进程的IO需求来讲IO能力平均分配调度

所以在交互式环境中,这种方式是比较实用的

 

但是在RHEL6.4上 它又提供了三个不同的调度等级:

1.实时 RT

2.最佳效果 BE

3.闲置

 

我们可以使用ionice命令手动分配调度等级,或者使用iopro_set系统调用编程分配,当然涉及到开发层面了

在实时调度等级和最佳效果两个级别都有8个IO等级,

数字越小优先级越高,最佳效果是默认调度等级 也就是4,不用更改

 

修改CFQ,以调节其性能

涉及参数文件:/sys/block/vda/queue/iosched/

修改默认调度器算法:

[root@node3 ~]# cd /sys/block/vda/queue/

[root@node3 queue]# ls

add_random           hw_sector_size      max_hw_sectors_kb  minimum_io_size  physical_block_size  scheduler

discard_granularity  iosched             max_sectors_kb     nomerges         read_ahead_kb        unpriv_sgio

discard_max_bytes    iostats             max_segments       nr_requests      rotational

discard_zeroes_data  logical_block_size  max_segment_size   optimal_io_size  rq_affinity

而在其上层目录里,有一scheduler文件

查看scheduler文件

[root@node3 queue]# cat scheduler

noop anticipatory deadline [cfq]

因此更改磁盘IO调度器则去找这个目录下所对应的scheduler,注意的是,它只是针对每个磁盘进行调整的,如果有多块磁盘的话则需要对应每个磁盘进行修改

它没有办法使用sysctl进行控制,如果想开机生效,只能写到rc.local 或init脚本中

 

一旦更改调度算法之后,再来查看目录中的文件

[root@node3 queue]# ls /sys/block/vda/queue/iosched/

back_seek_max      fifo_expire_async  group_idle       low_latency  slice_async     slice_idle

back_seek_penalty  fifo_expire_sync   group_isolation  quantum     slice_async_rq  slice_sync

修改算法

[root@node3 queue]# echo deadline > scheduler

[root@node3 queue]# cat scheduler

noop anticipatory [deadline] cfq

再次观察iosched目录,并查看其是否有变化

[root@node3 queue]# ls/sys/block/vda/queue/iosched/

fifo_batch  front_merges read_expire  write_expire  writes_starved

所以我们更改调度算法后,每个调度算法在此目录都有很多可调整参数,每个参数都有值,只不过都表现为其文件内容而已,而每个调度器的值通过修改是可以优化调度器的工作特性的

 

比如对CFQ来讲,有以下几个值可以调整:

back_seek_max

    反向寻道可能有负面影响,负载小的时候可以启用,否则不要使用反向寻道太多值

 

back_seek_penal

    反向寻道做惩罚,如果不得不使用反向寻道的话,那么必须对其做出一定惩罚,一旦做完惩罚之后,必须要正向寻道更多次数

 

fifo_expire_async

    用来控制异步请求等待时间长度,默认是250毫秒,过期之后无法满足的异步请求将会被移动到调度队列中,也就意味着要重新调度。通常这些值不需要调整

 

fifo_expire_sync

    用于同步请求的,

严格来讲写操作都是在内存中完成 过周期之后才会同步至硬盘中,站在计算机角度来说这种操作都被称为异步,而同步则是为了尽可能保证数据会被第一时间写到磁盘上来,数据不会在内存上逗留,直接写入磁盘

 

low_latecy

    低延迟,简单来讲,每个进程都有可能发起读写请求,也就意味着最终满足用户读写请求是按进程为单位划分,在满足这个前提下,需要考虑每个进程都需要得到满足,所以必须关注每个进程发起IO请求之后最多等待多长时间,如果启动此值就意味着每个进程只要发起读写请求都要尽可能快速得到满足,默认就启用了低延迟

    在桌面系统环境,低延迟是非常有必要的

 

quantum

    CFQ一次可以发出的IO请求数,一批最大可以调度的IO数,限制IO队列深度的,简单来说就是定义设备一次可以接收的IO请求的队列长度,默认为8

    增加反而会有负面影响,因此谨慎调整

    如果随机IO请求数非常的多,这个值可以适当调大,如果顺序写非常多,那么不建议调整

 

设置IO允许消耗的时间

一次IO请求的操作,一次执行多久,应该执行多久,按理说硬盘只要是没有损坏,能正常运作,在正常范围内,那么它就应该写完、读完所以我们要定义好每次读写请求所最大允许消耗的时间,那么就是以下几个参数的意义了:

slice_async

    定义异步写入的超时值,每次异步写操作最长时长是多少,默认值为40秒

slice_idle

    等待IO请求的闲置时长

slice_sync

    定义同步写入操作超时值,因为同步比较慢,所以其默认值是100秒,因为是从进程直接到磁盘的,所以超时时间会长一点

在桌面环境和在服务环境下,他们如果都使用CFQ调度器,他们工作特性不一定,也就意味着我们关注其背后工作机制参数也不一样,所以要调整某些值做一些测试的评判

 

 

Deadline最后期限调度

最后期限

wKiom1Qdhp2A5fkHAACT0L3TiWU207.jpg

如图所示,其分为了3个队列,分别是:

·读队列

·写对列

·排序队列

而后这些队列都被整合到派发队列中去而后由磁盘得到满足,我们从中任何一队列中选出一个操作得到满足之前必须要保证这类操作不能超期

简单来讲deadline就是将每个读写操作放到队列的时候都给他一个倒计时的计时器,将倒计时的计时器消耗完之前需要赶紧放到派发队列中,而后再同步至硬盘

而对服务器来讲,这种方式是比较理想的

 

常用可调参数

fifo_batch

    单批发出的读写数,在其最后期限满足之前将队列中的数据拿出并满足,但有写操作是需要排序的;默认为16,设置更多的值会获得更好的流量,但是会增加延迟

    比如一批读为16个,那么我们讲其改为32个,那意味着写的时间会更高

    当然所有都取决于测试数据,无论怎么调都不如换一块SSD硬盘

 

front_merges

    可以将多个请求合并在一起,但是有些请求压根不连续,不可能被合并在一起,那么我们可以禁止在满足IO之前进行合并的,禁止合并有可能会带来随机读写的特性的

    但允许合并也有一定的副作用,就是必须花时间去排序

 

read_expire

    每个读操作必须在多少期限内得到满足,默认为半秒钟

 

write_expire

    每个写操作必须在多久内得到满足,默认为5秒钟

 

#写操作是可以延迟满足的

 

writes_starved

    定义一批可以处理多少个读取批,这个值越高,读的效果就越好。默认为2,意味着2批读,一批写。如果服务器读多写少,内存缓冲足够大,那么可以将其调大

 

Noop

如果系统与cpu绑定,且使用高速存储(SSD),这就是最佳的IO调度程序

只要使用固态硬盘就要将其改为noop

 

如果调参数的话则需要直接去挑战/sys/block/vda/queue下的参数,而不是调度器的参数

 

add_random

    其作用是否使用商池

 

max_sectors_kb

    默认发送到磁盘的最大请求是多少,默认为512kb。我们知道每个扇区是512字节,那么每次发送512kb 意味着发送N个扇区,我们可以调整或增大减小该值,对于固态硬盘来讲不是所谓的扇区概念,由此可调。

    在此类情况下建议将max_hw_sectors_kb降低删除块大小

我们可以使用压力测试工具对其做测试,记录大小从512kb到1MB不等,哪个值的效果好就设置为哪个值,当然压力测试跟实际场景有出入的,所以要充分考虑环境尽可能模拟真实场景,尽可能要模拟随机读写

 

nr_request

    请求的队列的值,可以降低其值

rotational

    如果是SSD硬盘要将此值设置为0,禁用轮转模式

 

rq_affinity

    在触发IO不同的CPU中处理IO,一般来讲在同CPU上处理同IO是最好的

    因为CPU处理的仅仅是中断而已

 

因此对于SSD环境中常用的调整参数有:

max_sectors_kb

nr_requests

optimal_io_size

rotational

 

调整后如何测试性能是否提高

比较常用的硬盘压力测试工具

·aio-stress

·iozone

·fio

 

了解磁盘IO活动状况分析工具

blktrace

 

磁盘IO瓶颈分析工具

blkparse

gnuplot

 本文 来自http://yijiu.blog.51cto.com 转载 请说明,翻版 可耻

 

总结:IO优化大致思路

·最好换SSD

·调整raid级别

·选择IO调度器

·根据场景选择合适的文件系统

·配置选定调度器的参数

·优化结果是否理想,则使用工具进行分析

·写在开机启动项里


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/299132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用3年时间破解学界200多年难题,年仅21岁的天才竟因谈了一场恋爱挂掉了.........

全世界只有3.14 % 的人关注了爆炸吧知识俗话说,英雄难过美人关,即便是智商超群的数学天才也毫不例外。破得了百年的世界难题,却解不开一个小小的爱情谜团......没错,这位为情所困的数学天才,便是今天的主人公——伽罗瓦…

投影变换与视口变换

一些说明: 0. 投影变换:描述如何指定视景体(viewing volume)的形状和方向。视口变换:解释如何控制三维模型坐标到屏幕坐标的变换。 1. 无论是透视投影还是平行投影(正交投影),只有在视景体中的物体才可见。…

java 按钮设置图片_Java中如何设置带图片按钮的大小

在java部分需要用到图形界面编程的项目中,经常会使用图片设置对按钮进行美化,但是使用时会出现一个很麻烦的问题, 按照方法:JButton jb1 new JButton();jb1.setBounds(0, 0, 25, 20);ImageIcon ii new ImageIcon("images/x…

JAVA 异常库

为什么80%的码农都做不了架构师?>>> 1.java.lang.NumberFormatException: multiple points已解决 多线程方法中使用了共享变量SimpleDateFormat,报如下错误: java.lang.NumberFormatException: multiple points at sun.misc.Floa…

WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换

WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换独立观察员 2021 年 8 月 23 日我们平常在 WPF 中进行资源绑定操作,一般就是用 StaticResource 或者 DynamicResource 后面跟上资源的 key 这种形式,能满足大部分需求。但是有的时候&am…

你一直憋着的那个屁,放出来时真的有人知道吗?我先告诉你憋着不放的屁会到哪去……...

全世界只有3.14 % 的人关注了爆炸吧知识制作团队制作人 超模君编剧 恐恐恐插画 杨羊羊友情出演 超模君 想增加更多的奇怪知识?带你入学↓↓↓关注“爆炸吧知识”日增怪知识!

Android中View绘制流程

2019独角兽企业重金招聘Python工程师标准>>> 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(measure)、是否重新需要安置视图的…

从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式

本系列文章导航 从零开始学习jQuery (一) 开天辟地入门篇 从零开始学习jQuery (二) 万能的选择器 从零开始学习jQuery (三) 管理jQuery包装集 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式 从零开始学习jQuery (五) 事件与事件对象 从零开始学习jQuery (六) jQuery…

java克鲁斯卡尔算法_Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

所谓有权图,就是图中的每一条边上都会有相应的一个或一组值。通常情况下,这个值只是一个数字如:在交通运输网中,边上的权值可能表示的是路程,也可能表示的是运输费用(显然二者都是数字)。不过,边上的权值也…

[原]一步一步自己制作弹出框

说到javascript弹出框的制作,将其实现步骤分开,其实很容易。下面,将拆分页面弹出框的制作步骤。首先,准备编辑工具(废话),其实,您可以使用notepad..嘿嘿。弹出框的组成结构: 1.一个页面遮罩层。 2.一个di…

那些你从未见过的神奇物理化学实验,今天全给你整理了!

全世界只有3.14 % 的人关注了爆炸吧知识1.电荷吸引水流2.比空气重的六氟化硫六氟化硫(SF6),法国两位化学家Moissan和Lebeau于1900年合成的人造惰性气体,具有良好的电气绝缘性能及优异的灭弧性能,是一种优于空气和油之间…

ASP.NET Core使用Middleware有条件地允许访问路由

问题有时,我们可能在Web API中包含一些具有调试功能的请求。比如我们上次的文章中“晕了!这个配置值从哪来的?”使用的获取配置值的功能:endpoints.MapGet("/test2/{key:alpha}", async context > {var key context…

如何用最低的成本教育出最棒的孩子?看完这些公众号你就知道了

全世界只有3.14 % 的人关注了爆炸吧知识真正决定人与人之间的差距的,其实是我们对事物的见识与内心的格局,见识的深浅决定人生的深浅,格局的大小决定了人生之路是宽是窄。今天给大家推荐几个有深度、有想法的公众号,希望能够给你带…

Virtualbox 无缝整合linux和windows双系统

一直以来,为了使用公司规定的内部通信工具RTX, 而不得不在ubuntu上安装一个virtualbox以运行RTX, 但是由于是运行在虚拟机里面,所以经常不能及时的回复同时的消息,而造成沟通的延迟。 所以就想着,能不能及时的在ubuntu上面看到…

聊一聊对外API接口的存活检查可以怎么做

背景 公司内部的API接口一般会分为两大类,一类是直接暴露在公网可以访问的,一类是只能在局域网内访问的。暴露在公网的一般就是业务网关以及一些和第三方公司有着某些合作,从而进行数据交互的接口。检查API接口是否存活,第一反应应…

各种机械原理动态图,看完脑洞大开,绝对涨姿势!

全世界只有3.14 % 的人关注了爆炸吧知识1.钥匙开锁2.撬锁3.汽车换挡4.手枪上膛发射5.炮弹发射原理6.手雷爆炸7.洗衣机8.缝纫机9.心脏10. 近视眼手术:原理其实很简单,就是把角膜削成一个“隐形眼镜”。11.零钱分类12.吹号转载来源:物理好教师部…

CSharp设计模式读书笔记(10):装饰模式(学习难度:★★★☆☆,使用频率:★★★☆☆)...

装饰模式(Decorator Pattern): 动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。 模式角色与结构: 示例代码: using System; using System.Collections.Generic; using Syste…

ShardingCore 如何呈现“完美”分表

这篇文章是我针对efcore的分表的简单介绍,如果您有以下需求那么可以自己选择是否使用本框架,本框架将一直持续更新下去,并且免费开源为.net生态做贡献,如果您觉得不错那么请帮忙点个star谢谢,框架地址[sharding-core](https://github.com/xuejmnet/shard…

使用javascript oop开发滑动(slide) 菜单控件

这里使用原生的javascript,用面向对象的方式创建一个容易维护使用方便的滑动菜单,调用方式如下:var$sliding document.getElementById("silding");vars1 newSliding();s1.commands $sliding.getElementsByTagName("dt");…

他毕业于北师大,编写了我国首套数学教材,陈景润华罗庚都崇拜他

全世界只有3.14 % 的人关注了爆炸吧知识要说起我国著名的数学家,很多人会想到陈景润、华罗庚等人,这些大数学家为我国数学研究做出了卓越贡献,也深深影响了很多人。那么,像陈景润、华罗庚这些大数学家,他们学习数学有受…