-
1 前言回顾第一次参加性能挑战赛—第四届阿里中间件性能挑战赛,那时候真的是什么都不会,只有一腔热情,借着比赛学会了 Netty、学会了文件 IO 的最佳实践,到了这次华为云举办的 TaurusDB 性能挑战赛,已经是第三次参加比赛了,同时也是最“坎坷”的一次比赛。经过我和某位不愿意透露姓名的 96 年小迷妹的不懈努力,最终跑分排名为第 3 名。如果要挑选一个词来概括这次比赛的核心内容,那非”计算存储分离“莫属了,通过这次比赛,自己也对计算存储分离架构有了比较直观的感受。为了比较直观的体现计算存储分离的优势,以看电影来举个例子:若干年前,我总是常备一块大容量的硬盘存储小电影,但自从家里带宽升级到 100mpbs 之后,我从来不保存电影了,要看直接下载/缓冲,基本几分钟就好了。这在几年前还不可想象,如今是触手可及的事实,归根到底是随着互联网的发展,网络 IO 已经不再是瓶颈了。计算存储分离架构相比传统本地存储架构而言,具有更加灵活、成本更低等特性,但架构的复杂性也会更高,也会更加考验选手的综合能力。计算存储分离架构的含义:存储端有状态,只存储数据,不处理业务逻辑。计算端无状态,只处理逻辑,不持久化存储数据。2 赛题概览比赛整体分成了初赛和复赛两个部分,初赛要求实现一个简化、高效的本地 kv 存储引擎,复赛在初赛的基础上增加了计算存储分离的架构,计算节点需要通过网络传输将数据递交给存储节点存储。计算节点和存储节点共用上述的接口,评测程序分为 2 个阶段:正确性评测此阶段评测程序会并发写入随机数据(key 8B、value 4KB),写入数据过程中进行任意次进程意外退出测试,引擎需要保证异常中止不影响已经写入的数据正确性。异常中止后,重启引擎,验证已经写入数据正确性和完整性,并继续写入数据,重复此过程直至数据写入完毕。只有通过此阶段测试才会进入下一阶段测试。性能评测随机写入:16 个线程并发随机写入,每个线程使用 Set 各写 400 万次随机数据(key 8B、value 4KB)顺序读取:16 个线程并发按照写入顺序逐一读取,每个线程各使用 Get 读取 400 万次随机数据 热点读取:16 个线程并发读取,每个线程按照写入顺序热点分区,随机读取 400 万次数据,读取范围覆盖全部写入数据。热点的逻辑为:按照数据的写入顺序按 10MB 数据粒度分区,分区逆序推进,在每个 10MB 数据分区内随机读取。随机读取次数会增加约 10%。语言限定CPP & Java,一起排名3 赛题剖析初赛主要是文件 IO 和存储架构的设计,实现一个简单的本地KV存储引擎,如果对文件 IO 常识不太了解,可以先行阅读 《文件IO操作的一些最佳实践》。大赛的重头戏基本是在复赛网络通信的比拼上,在引入计算/存储分离架构后,计算节点无状态,计算节点和存储节点需要通过网络交互,网络将引入大于服务器内部的时延,因此,结合应用场景的良好架构和缓存设计,将是此类引擎设计的一个重点。 3.1 架构设计计算节点只负责生成数据,在实际生产中计算节点还承担额外的计算开销,由于计算节点是无状态的,所以不能够聚合数据写入、落盘等操作,但可以在 Get 触发网络 IO 时一次读取大块数据用作缓存,减少网络 IO 次数。存储节点负责存储数据,考验了选手对磁盘 IO 和缓存的设计,可以一次使用缓存写入/读取大块数据,减少磁盘 IO 次数。所以选手们将会围绕网络 IO、磁盘 IO 和缓存设计来设计整体架构。3.2 正确性检测赛题明确表示会进行 kill -9 并验证数据的一致性,正确性检测主要影响的是写入阶段。存储节点负责存储数据,需要保证 kill -9 不丢失数据,但并不要求断电不丢失,这间接地阐释了一点:我们可以使用 PageCache 来做写入缓存;正确性检测对于计算节点与存储节点之间通信影响便是:每次写入操作都必须 ack,所以选手必须保证同步通信,类似于 ping/pong 模型。3.3 性能评测性能评测由随机写、顺序读、热点读(随机读取热点数据)三部分构成。随机写阶段与 PolarDB 的评测不同,TaurusDB 随机写入 key 的 16 个线程是隔离的,即 A 线程写入的数据只会由 A 线程读出,可以认为是彼此独立的 16 个实例在执行评测,这大大简化了我们的架构。顺序读阶段的描述也很容易理解,需要注意的是这里的顺序是按照写入顺序,而不是 Key 的字典序,所以随机写可以转化为顺序写,也方便了选手去设计顺序读的架构。热点读阶段有点故弄玄虚了,其实就是按照 10M 数据为一个分区进行逆序读,同时在 10M 数据范围内掺杂一些随机读,由于操作系统的预读机制只会顺序预读,无法逆序预读,PageCache 将会在这个环节会失效,考验了选手自己设计磁盘 IO 缓存的能力。4 架构详解4.1 全局架构计算存储分离架构自然会分成计算节点和存储节点两部分来介绍。计算节点会在内存维护数据的索引表;存储节点负责存储持久化数据,包括索引文件和数据文件;计算节点与存储节点之间的读写都会经过网络 IO。4.2 随机写架构随机写阶段,评测程序调用计算节点的 set 接口,发起网络 IO,存储节点接收到数据后不会立刻落盘,针对 data 和 index 的处理也会不同。针对 data 部分,会使用一块缓冲区(如图:Mmap Merge IO)承接数据,由于 Mmap 的特性,会形成 Merge File 文件,一个数据缓冲区可以聚合 16 个数据,当缓冲区满后,将缓冲区的数据追加到数据文件后,并清空 Merge File;针对 index 部分,使用 Mmap 直接追加到索引文件中。F: 1. data 部分为什么搞这么复杂,需要聚合 16 个数据再刷盘?Q: 针对此次比赛的数据盘,实测下来 16 个数据刷盘可以打满 IO。F: 2. 为什么使用 Mmap Merge IO 而不直接使用内存 Merge IO?Q: 正确性检测阶段,存储节点可能会被随机 kill,Mmap 做缓存的好处是操作系统会帮我们落盘,不会丢失数据F: 3. 为什么 index 部分直接使用 Mmap,而不和 data 部分一样处理?Q: 这需要追溯到 Mmap 的特点,Mmap 适合直接写索引这种小数据,所以不需要聚合。4.3 热点读&顺序读架构热点读取阶段 & 顺序读取阶段 ,这两个阶段其实可以认为是一种策略,只不过一个正序,一个逆序,这里以热点读为例介绍。我们采取了贪心的思想,一次读取操作本应该只会返回 4kb 的数据,但为了做预读缓存,我们决定会存储节点返回 10M 的数据,并缓存在计算节点中,模拟了一个操作系统预读的机制,同时为了能够让计算节点精确知道缓存是否命中,会同时返回索引数据,并在计算节点的内存中维护索引表,这样便减少了成吨的网络 IO 次数。4.4 存储设计站在每个线程的视角,可以发现在我们的架构中,每个线程都是独立的。评测程序会对每个线程写入 400w 数据,最终形成 16 * 16G 的数据文件和 16 * 32M 左右的索引文件。数据文件不停追加 MergeFile,相当于一次落盘单位是 64K(16 个数据),由于自行聚合了数据,所以可以采用 Direct IO,减少操作系统的 overhead。索引文件由小数据构成,所以采用 Mmap 方式直接追加写计算节点由于无状态的特性,只能在内存中维护索引结构。4.5 网络通信设我们都知道 Java 中有 BIO(阻塞 IO)和 NIO(非阻塞 IO)之分,并且大多数人可能会下意识觉得:NIO 就是比 BIO 快。而这次比赛恰恰是要告诉大家,这两种 IO 方式没有绝对的快慢之分,只有在合适的场景中选择合适的 IO 方式才能发挥出最佳性能。稍微分析下这次比赛的通信模型,写入阶段由于需要保证每次 set 不受 kill 的影响,所以需要等到同步返回后才能进行下一次 set,而 get 本身依赖于返回值进行数据校验,所以从通信模型上看只能是同步 ping/pong 模型;从线程数上来看,只有固定的 16 个线程进行收发消息。以上两个因素暗示了 BIO 将会非常契合这次比赛。在很多人的刻板印象中,阻塞就意味着慢,非阻塞就意味着快,这种理解是完全错误的,快慢取决于通信模型、系统架构、带宽、网卡等因素。我测试了 NIO + CountDownLatch 和 BIO 的差距,前者会比后者整体慢 100s ~ 130s。5 细节优化点5.1 最大化磁盘吞吐量但凡是涉及到磁盘 IO 的比赛,首先需要测试便是在 Direct IO 下,一次读写多大的块能够打满 IO,在此基础上,才能进行写入缓冲设计和读取缓存设计,否则在这种争分夺秒的性能挑战赛中不可能取得较好的名次。测试方法也很简单,如果能够买到对应的机器,直接使用 iostat 观察不同刷盘大小下的 iops 即可,如果比赛没有机器,只能祭出调参法,不停提交了,这次 TaurusDB 的盘实测下来 64k、128K 都可以获得最大的吞吐量。5.2 批量回传数据计算节点设计缓存是一个比较容易想到的优化点,按照常规的思路,索引应该是维护在存储节点,但这样做的话,计算节点在 get 数据时就无法判断是否命中缓存,所以在前文的架构介绍中,我们将索引维护在了计算节点之上,在第一次 get 时,顺便恢复索引。批量返回数据的优势在于增加了缓存命中率、降低总网络 IO 次数、减少上行网络 IO 数据量,是整个比赛中分量较重的一个优化点。5.3 流控在比赛中容易出现的一个问题,在批量返回 10M 数据时经常会出现网络卡死的情况,一时间无法定位到问题,以为是代码 BUG,但有时候又能跑出分数,不得以尝试过一次返回较少的数据量,就不会报错。最后还是机智的小迷妹定位到问题是 CPU 和 IO 速率不均等导致的,解决方案便是在一次 pong 共计返回 10M 的基础上,将报文拆分成 64k 的小块,中间代入额外的 CPU 操作,最终保证了程序稳定性的同时,也保障了最佳性能。额外的 CPU 操作例如:for(int i=0;i<700;i++),不要小看这个微不足道的一个 for 循环哦。流控其实也是计算存储分离架构一个常见设计点,存储节点与计算节点的写入速度需要做一个平衡,避免直接打垮存储节点,也有一种”滑动窗口“机制专门应对这种问题,不在此赘述了。5.4 预分配文件在 Cpp 中可以使用 fallocate 预先分配好文件大小,会使得写入速度提升 2s。在 Java 中没有 fallocate 机制,但是可以利用评测程序的漏洞,在 static 块中事先写好 16 * 16G 的文件,同样可以获得 fallocate 的效果。5.5 合理设计索引结构get 时需要根据 key 查询到文件偏移量,这显示是一个 Map 结构,在这个 Map 上也有几个点需要注意。以 Java 为例,使用 HashMap 是否可行呢?当然可以,但是缺点也很明显,其会占用比较大的内存,而且存取性能不好,可以使用 LongIntHashMap 来代替,看过我之前文章的朋友应该不会对这个数据结构感到陌生,它是专门为基础数据类型设计的 Map 容器。每个线程 400w 数据,每个线程独享一个索引 Map,为了避免出现扩容,需要合理的设置扩容引子和初始化容量:new LongIntHashMap(410_0000, 0.99)。5.6 Direct IO最终进入决赛的,有三支 Java 队伍,相比较 Cpp 得天独厚的对操作系统的灵活控制性,Java 选手更像是带着镣铐在舞蹈,因为有过参赛经验,我提前封装好了 Java 的 Direct IO 类库:https://github.com/lexburner/kdio,相比 FileChannel,它能够使得磁盘 IO 效率更高。得知有 Java 选手真的在比赛中使用了我的 Direct IO 类库,也是比赛中实实切切的乐趣之一。6 失败的优化点6.1 预读线程先行考虑到网络 IO 还是比本地磁盘 IO 要慢的,一个本以为可行的方案是单独使用预读线程进行存储节点的磁盘 IO,设计一个 RingBuffer,不断往前预读,直到环满,计算阶段 get 时会消费 RingBuffer 的一格缓存,从而使得网络 IO 和磁盘 IO 不会相互等待。实际测试下来,发现瓶颈主要还是在于网络 IO,这样的优化徒增了不少代码,不利于进行其他的优化尝试,最终放弃。6.2 计算节点聚合写入缓冲既然在 get 阶段时存储节点批量返回数据给计算节点可以提升性能,那 set 阶段聚合批量的数据再发送给存储节点按理来说也能提升性能吧?的确如此,如果不考虑正确性检测,这的确是一个不错的优化点,但由于 kill 的特性使得我们不得不每一次 set 都进行 ACK。但是可以将 4/8/16 个线程编为一组进行聚合,通过调整参数来确定该方案是否可行。然而事与愿违,该方案并没有取得成效。7 聊聊比赛吧之前此类工程性质的性能挑战赛只有阿里一家互联网公司承办过,作为热衷于中间件性能优化的参赛选手而言,非常高兴华为也能够举办这样性质的比赛。
-
赛题分析赛题要求一个无状态的计算节点和一个存储节点,并要求保证程序崩溃时的数据完整性,所以当计算节点写入时必须等待存储节点的 ack,而存储节点需快快确保数据写入到 page cache。赛题说明 16 个线程,每个线程写入 4 百万条记录,按写入顺序读取及热点区间读取,所以数据按写入线程分离存储。此外 Key 大小固定 8B,value 大小固定 4KB,所以需要批量写入才能打满带宽,并且索引只需要保存位置序号就可以,减小了索引的大小。整体架构针对赛题的要求,可以把问题分解成三个模块来看,分别是计算节点,存储节点和网络通信,因此我们设计了如下图所示的总体结构。在存储节点上,数据分为 16 组存储,按照写入线程分组,保证同一线程的数据写入到同一分组,这样在读取阶段不论是按写入顺序读取还是热点区间读取都可以一次从一个分组中读取一整块 cache,降低网络开销,另外这样并发管理也比较简单,因为一个线程只会对应到一个文件,所以读写的时候是不需要对分组加锁的。具体到到每个分组内部,key 和 value 是分离存储的,因为 key 和 value都是定长的,kv 分离以后恢复索引时只需要读取 key 文件就够了。最后存储节点会保证一旦写入成功数据就不会再丢失,也就是可以容忍 kill -9 退出。我们把索引放在计算节点,并且使用 TCP 进行节点间通信。由于并发数目不高,所以计算节点初始化时创建 16 条 tcp 连接,每个前台线程对应一条连接,在存储节点为每个 tcp 连接创建一个新线程。数据在写入时首先由计算节点发送写请求到存储节点,存储节点收到请求并确认数据成功写入不会丢失后,会把存储的位置回复给计算节点,然后计算节点把位置代入内存索引后返回。读取时计算节点首先根据内存索引判断数据在不在 cache pool 里,如果不在就去向存储节点读取一块新的 cache,然后从 cache 中读数据。存储节点之前我们也提到存储节点按写入线程分组,每个分组里包含四类文件,value data 文件保存 value,key data文件保存 key,两者各有一个 mmap buffer 文件,用来将写入 batch 到一起再刷盘。然后有一个全局的 mmap meta file,记录各个分组当前的数据长度,也就是各分组分别有多少个 kv 对,主要用于数据恢复和重建索引。数据写入时直接将key和value写入对应分组的mmap buffer,两者都写入成功后更新 meta file。只有当 mmap buffer 写满了以后才会 flush 到磁盘中,并且 flush 操作都是用 directIO 进行的。采用这种设计使得写入均是内存操作,将数据写入到 mmap 管理的 page cache 中即可返回,并且我们对mmap使用了mmap_lock标记使其一直锁定在内存中,只有当程序退出时才会刷盘。每次向data文件刷盘都是以一个 buffer 为单位,这样可以最大化利用 nvme 磁盘带宽,采用 directIO 的方式刷盘可以跳过 page cache,一方面减少了一次内存复制,另一方面降低了阶段切换时清空 page cache 的时间。而 mmap 的机制保障了即使进程意外退出,操作系统也会让 mmap buffer 中的数据安全落盘,不会引起数据丢失。我们实际为每个 key 和 data 文件维护了多个 mmap buffer,当一个 buffer 写满时转入后台 flush,接下来的写入会写进另一个 buffer。这是因为写入操作的开销是由网络传输开销和磁盘 IO 开销两部分组成的,单个buffer的情况下两者完全串行执行,在发生刷盘时写入操作需要消耗网络传输加上磁盘IO的时间。采用多个 buffer 以后相当于将磁盘 IO 与网络开销并行化了,产生的阻塞会减少很多。对于数据读取操作,读请求会将 offset 对齐到 cache 长度,也就是 10MB,然后存储节点直接以 directIO 方式从对齐后的 offset 处读出这一块数据返回即可。当存储节点意外关闭时,因为我们已经确保了所有数据都能安全落盘,唯一需要恢复的就是 mmap buffer 文件当前的写入位置,所以只需要从 meta file 中读取个分组的长度,对 buffer 长度取余便可以计算出各 buffer 的当前写入位置了。计算节点计算节点中主要包含了索引和 cache 两部分。索引部分,索引存储在 hash 表中,每个 entry 的格式为 (key, 分组编号+分组内偏移量)。因为 key 和 value 都是大小固定的,因此偏移量只需要保存它是分组内的第几个 kv 对,所以只需要 4 字节。因此每个 entry 的空间占用为 key 8字节加分组编号 4 字节加偏移量 4 字节,总共 16 字节,那么 6400 万个 entry 一共需要大约 1G 左右空间,因此可以完全保存在内存里。我们实现了一个原子的 hash 表。hash 表底层是一个大小为 8000 万左右的数组,以线性探测法处理 hash 冲突。说hash表的每一个 entry 由两个 64 位无符号整数组成,分别代表 key 与索引,并初始化为0。因为 key 本身可能是0,所以我们让分组编号从1开始,然后对索引部分的原子变量做 cas 操作来实现原子代入。代码如下:因为计算节点本身是无状态的,所以重启时需要恢复索引。我们把索引恢复的时机放在第一次 get 操作的时候,这样可以避免写入阶段计算节点请求恢复索引。索引恢复由 16 个线程并行执行,每一个线程向存储节点请求一整个 key 文件,因为 key 在 key 文件中的位置与 value 在 value 文件中的位置是一样的,所以遍历 key 文件就可以重建索引了。如果每次 get 都去存储节点读取,那么网络延迟开销太大,无法打满带宽。所以我们每次向存储节点请求数据时都读取一整块数据保存在内存 cache 里,大小为 10MB。由于我们不确定是不是完全按照 10MB 对齐的,因此我们为每个分组准备了两个 cache,这样当 cache miss 时,可以保证前一块 cache 的数据一定已经被读完了,可以被新的 cache 置换掉。此外我们还实现了 cache 预取机制。由于赛题要求顺序读取及热点区间读取,热点区间读取是按照数据的写入顺序以 10MB 数据粒度分区,分区逆序推进,在每个 10MB 数据分区内随机读取,所以当向存储节点请求一个新 cache 完成时,另一个线程会根据当前两个 cache 的 offset 之差向存储节点预取下一块 cache。在顺序读取阶段差为整数,因此会顺序预取,在热点区间读取阶段差为负数,因此会逆序预取。总结我们的最好成绩是 786 秒,其中写用了 505 秒,顺序读取用了 134 秒,热点读取用了 147 秒,最终排名第 5 名。此外各阶段分别跑出的最佳成绩为505/132/142秒,可惜我们对读操作的优化是最后一天完成的,但是最后一天的评测环境不太好,写性能一直上不去(我们的写入时间基本稳定在520秒以内,但是最后一天一直在560秒+)。在热点读阶段实际消耗在读取上的时间为133秒,但是恢复索引使用了9 秒,这里还有很大的改进空间。考虑到评测系统的带宽大约15Gbps,我们的读取性能已经基本跑满网络带宽了。第一次参加这种类型的比赛,我们学习和积累了很多经验,希望来年还有机会参加,取得更好的成绩。 作者:ADSL
-
#化鲲为鹏,我有话说#是程序就会有bug,有bug程序就可能崩溃,导致鲲卡住不动。所以想让鲲尽可能不卡,程序就应足够简单,简单到一眼就能看出没有明显的bug。但如果想要赢比赛,算法就得复杂。这两种的冲突如何解决?一种简单的方法是:将与服务器交互的程序,以及算法的程序,放在2个不同的进程里。交互程序仅负责接收服务器消息,转发给算法,然后等待750ms,读取算法结果,如果读取不到,则自己生成一个随机动作,返回给服务器。算法程序则接收消息,计算最优的动作,并将结果返回给交互程序。这样,哪怕算法崩了,但交互还在继续。至少鲲不会卡住不动。(随机能赢比赛的可能性很小,但比起静止不动,总归是多了点希望不是?)这种方法的第一个好处,是算法可以在后台专心做耗时的计算,分析对手、模拟对战什么的。这种方法的第二个好处,是交互程序可以充当monitor,在发现异常的时候,把算法程序的进程kill掉重启,瞬间满血复活江湖再战!!!(怎么样?惊不惊喜,意不意外,佩不佩服?)当然代价也是有的,进程间通信与同步带来的复杂度会是一个麻烦。
-
一、Nmon介绍(这句不用看——Nmon得名于 Nigel 的监控器,是IBM的员工 Nigel Griffiths 为 AIX 和 Linux 系统开发的,使用 Nmon 可以很轻松的监控系统的 CPU、内存、网络、硬盘、文件系统、NFS、高耗进程、资源和 IBM Power 系统的微分区的信息)。Nmon是一款计算机性能系统监控工具,因为它免费,体积小,安装简单,耗费资源低,广泛应用于AIX和Linux系统。二,Nmon下载首先查看Linux系统内核版本(两种方式):1,cat /proc/version [qgc@localhost nmon16d]$ cat /proc/versionLinux version 2.6.32-431.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Nov 22 03:15:09 UTC 20132,uname -a[qgc@localhost nmon16d]$ uname -aLinux localhost.localdomain 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux对照上图,我是VMware虚拟机安装的64位centos6.5。接着下载nmon软件包:1,wget方式下载,地址: https://nchc.dl.sourceforge.net/project/nmon/nmon16d_x86.tar.gz[qgc@localhost nmon16d]$ wget https://nchc.dl.sourceforge.net/project/nmon/nmon16d_x86.tar.gz--2018-08-27 11:26:11-- https://nchc.dl.sourceforge.net/project/nmon/nmon16d_x86.tar.gzResolving nchc.dl.sourceforge.net... 211.79.60.17, 2001:e10:ffff:1f02::17Connecting to nchc.dl.sourceforge.net|211.79.60.17|:443... connected.HTTP request sent, awaiting response... 200 OKLength: 9252938 (8.8M) [application/x-gzip]Saving to: “nmon16d_x86.tar.gz” 100%[===========================================================>] 9,252,938 1.77M/s in 5.0s 2018-08-27 11:26:17 (1.77 MB/s) - “nmon16d_x86.tar.gz” saved [9252938/9252938] [qgc@localhost nmon16d]$ lsnmon16d_x86.tar.gz 2,官网手动下载,地址:http://nmon.sourceforge.net/pmwiki.php?n=Site.Downlo ,翻译了下,如下图因为CentOS就是 RedHat 的免费版本(上面内核版本 2.6.32-431.el6.x86_64),所以对应系统是RHEL 6.5,选择右边包含RedHat 6.5的下载。 三,解压安装下载完成后,可以新建一个目录,作为解压后存放的目录,这里为nmon16d,如果是手工下载的,需要拷贝到虚拟机。[qgc@localhost Desktop]$ mkdir nmon16d输入解压命令:tar -zxvf nmon16d_x86.tar.gz -C nmon16d ,-C 是指定解压目录[qgc@localhost Desktop]$ tar -zxvf nmon16d_x86.tar.gz -C nmon16dnmon_power_32_linuxnmon_power_32_rhel6nmon_power_32_sles11nmon_power_64_kvm2nmon_power_64_linux...在nmon6d目录中,可以找到nmon_x86_64_centos6这个文件,并对它添加执行权限[qgc@localhost nmon16d]$ chmod +x nmon_x86_64_centos6再把该程序文件加入环境变量运行目录,如果不是管理员,需要加上sudo命令[qgc@localhost nmon16d]$ mv nmon_x86_64_centos6 /usr/local/bin/nmonmv: cannot move `nmon_x86_64_centos6' to `/usr/local/bin/nmon': Permission denied[qgc@localhost nmon16d]$ sudo mv nmon_x86_64_centos6 /usr/local/bin/nmon[sudo] password for qgc: [qgc@localhost nmon16d]$ 四,运行Nmon输入nmon命令启动Nmon,如下图在上面的交互式窗口中,可以使用nmon 快捷键来显示不同的系统资源统计数据:· q : 停止并退出 Nmon· h : 查看帮助· c : 查看 CPU 统计数据· m : 查看内存统计数据· d : 查看硬盘统计数据· k : 查看内核统计数据· n : 查看网络统计数据· N : 查看 NFS 统计数据· j : 查看文件系统统计数据· t : 查看高耗进程· V : 查看虚拟内存统计数据· v : 详细模式按下c,m,d后如下图,CPU、内存、磁盘的消耗情况都直观的展现出来了,按q键可以退出。五,数据采集性能测试时,需要根据测试场景的执行情况,分析一段时间内系统资源的变化,这时需要nmon采集数据并保存下来,以下是常用的参数: -f 参数:生成文件,文件名=主机名+当前时间.nmon -T 参数:显示资源占有率较高的进程 -s 参数:-s 10表示每隔10秒采集一次数据 -c 参数:-s 10表示总共采集十次数据 -m 参数:指定文件保存目录具体的参数学习可参考博客:https://www.cnblogs.com/iclk/p/4456311.html如每隔5秒采集一次,一共采集12次,就是1分钟的数据(生成的文件已标红):[qgc@localhost nmon16d]$ nmon -f -s 5 -c 12 -m /home/qgc/Desktop/[qgc@localhost nmon16d]$ nmon -f -T -s 5 -c 12 -m /home/qgc/Desktop/[qgc@localhost Desktop]$ lslmon16g.c localhost_180827_2318.nmon nmon16d_x86.tar.gzlocalhost_180827_2317.nmon nmon16d Test数据采集完毕后,如需关闭nmon进程,需要获取nmon的pid(已标红)[qgc@localhost Desktop]$ ps -ef | grep nmonqgc 4455(pid) 4349(ppid) 0 23:40 pts/0 00:00:00 nmonqgc 4491 4429 0 23:40 pts/1 00:00:00 grep nmon再安全杀掉该进程:kill -9 pid[qgc@localhost Desktop]$ kill -9 4455[qgc@localhost Desktop]$ ps -ef | grep nmonqgc 4493 4429 0 23:40 pts/1 00:00:00 grep nmon六,数据分析1,下载nmon analyser借助nmon analyser可以把nmon采集的数据生成直观的Excel表,nmon analyser可以在IBM的官网下载,https://www.ibm.com/developerworks/community/wikis/home?lang=en#!/wiki/Power+Systems/page/nmon_analyser 在windows上下载后解压,有word和exce两个文档,Word是说明文档,包括更新日志,详细参数等,其中的Excel就是nmon analyser工具了。2,打开nmon analyser双击打开nmon analyser v54.xlsm,点击Analyze nmon data按钮: 注:因为我用的个人免费版WPS(10.1),没有包含宏,需要安装宏插件(VBA for WPS),Excel是自带宏插件的,如果宏不能运行,需要做以下操作:工具 -> 宏 -> 安全性 -> 中,然后再打开文件并允许运行宏。 3,下载VBA for WPS地址:https://pan.baidu.com/s/1QzW4ebQxYQtxgVfkTmxVJw,下载VBA7.0.1590_For WPS(中文).exe后,先退出WPS,再直接安装就行,再次打开nmon analyser,启用宏4,使用nmon analyser生成图表成功打开nmon analyser后,点击Analyze nmon data按钮,选择nmon数据文件,会再次提示另存为,选择地址保存即可。 下图就是nmon生成的数据报告截图,底部可以切换其他资源信息。 References:1. https://www.cnblogs.com/qgc1995/p/7523786.html2. http://nmon.sourceforge.net/pmwiki.php
-
A服务向B服务发消息,采用CSE同步restTemplate方式,使用jmeter压测,一分钟500次,故意让B服务延时几秒后返回响应,A服务会报大量的超时错误(设置了30秒超时),看默认的发送线程貌似只有几个。如何定制发送的线程池大小呢?MediaCloud01 发表于2019-08-15 22:25:14 2019-08-15 22:25:14 最后回复 MediaCloud01 2019-08-16 16:32:292891 5
-
Jul 30 14:54:31 huawei kernel: Pid 21310(fcst_cal) over core_pipe_limit Jul 30 14:54:31 huawei kernel: Skipping core dump Jul 30 14:54:31 huawei kernel: Pid 21311(clean_db) over core_pipe_limit Jul 30 14:54:31 huawei kernel: Skipping core dump,容器在运行过程中发生如上问题,请问如何引起?如何处理?
-
provider侧microservice.yaml中有线程配置,容器(tomcat)自身也有线程配置,最终线程数的上限是由什么决定的?
-
本帖对参加华为云TaurusDB性能挑战赛初赛选手的问题进行解答 Q1: 是否可以使用aio 可以使用 Q2:class KVIntf {public: virtual ~KVIntf() {}; virtual bool Init(const char * dir, int id) = 0; virtual void Close() = 0; virtual int Set(KVString &key, KVString & val) = 0; virtual int Get(KVString &key, KVString & val) = 0;}; 1. 接口Init的参数id是什么含义,怎样约定的? 测试程序运行时,每个线程会调用Init,init中的dir相同,id不同。参赛者可以使用,也可以不使用这个id来识别不同的线程。这个id仅体现线程的不同,没有其他含义。另外每个线程都会调用 GetKVIntf, Init, Close; 只有init会传线程标记。 2. 接口Get和Set的返回值是怎样约定的? 在一个实际的使用场景中,返回值可以表征错误码/或者分区信息等,第一阶段的比赛中,没有检验这个返回值; 3. kv_string.h是否可以修改?如果不能修改,主办方如何保证判题的时候、所有人的kv_string.h是原始没有被修改? 判题为自动化程序,判题时不会检查kv_string文件本身是否被修改,但会判题程序会使用原始kv_string的定义来检验返回的k/v是否和原始值相同。 4. 性能评测性能评测随机写入:16个线程并发随机写入,每个线程使用Set各写400万次随机数据(key 8B、value 4KB)顺序读取:16个线程并发按照写入顺序读取,每个线程各使用Get读取400万次随机数据随机读取:16个线程并发读取,每个线程随机读取400万次数据,读取范围覆盖全部写入数据 注:1. 共2个维度测试性能,每一个维度测试结束后会保留DB数据,关闭实例,重启进程,清空PageCache,下一个维度开始后重新打开新的实例 这里是2个维度还是3个维度?如果是2个维度,哪两个阶段是在一起的? 随机写入和顺序读取是一个阶段(即写入完成后立即读取),随机读取是另一个阶段(经过Close和Init后再读取)Q3:关于 Key的问题1)不同线程的key不会重复Q4: GCC 版本gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)Copyright (C) 2015 Free Software Foundation, Inc.
-
官方资料中讲到为了降低功耗,liteos 采用集中式任务调度方式,这个集中式怎么理解呢?假如有两个任务,每个任务执行时间和阻塞时间都不同,而liteos也是个实时内核,要怎么个集中调度法 ,同时还保证实时性呢?
-
【问题简要】动态库coredump 的问题【问题类别】vxml2.0 【IPCC解决方案版本】IPCC V200R001C80【问题现象描述】您好!我们的测试流程大概如下:语音识别获取结果 id 后,使用结果 id 去调用动态库,测试现象为 ivr trace 日志卡死崩溃,我们参考文档初步排查为动态库coredump 的问题。关键日志如下:附件 mds.log 的 137 行「进程未启动或者进程意外退出」。附件 ivr301.log 的 12 行「callinginstance[100] accesscode:777 flow:/home/icd/icddir/bin/Y:/flow/vxml/temp.jsp get sig[11] in dlg:use_dll 」。ivr 服务器的「/home/icd/icddir/corebak」目录下有 core 文件生成。在 gdb 提示符环境下,输入 where 回车看到Core was generated by `/home/icd/icddir/bin/ivr -p 301'.Program terminated with signal 6, Aborted.#0 0xffffe430 in __kernel_vsyscall ()(gdb) where#0 0xffffe430 in __kernel_vsyscall ()#1 0xf6347e30 in raise () from /lib/libc.so.6#2 0xf6349765 in abort () from /lib/libc.so.6#3 0x082c3efa in ProgramExitSIGDeal (sig=11) at ../scp/ntscp.cpp:285#4 #5 0x00000000 in ?? ()#6 0xf71f1dba in CObj::Obj_UseDll (this=0xd813ed8) at ../vxml/Obj.cpp:9982#7 0xf7214137 in CObj::Visit (this=0xd813ed8) at ../vxml/Obj.cpp:1883#8 0xf70ce634 in CForm::Collect (this=0xd82c9a8, pItem=0xd813edc) at ../vxml/Form.cpp:700#9 0xf70f486f in CInterpreter::Collect (this=0xa0b1e70) at ../vxml/Interpreter.cpp:474#10 0xf70ff1a6 in CInterpreter::Go (this=0xa0b1e70) at ../vxml/Interpreter.cpp:1136#11 0xf71040d4 in CInterpreter::Run (this=0xa0b1e70, sUrl=0xd58fc11 "/home/icd/icddir/bin/Y:/flow/vxml/temp.jsp", usRetCode=@0xdc0db302: 65535) at ../vxml/Interpreter.cpp:2541#12 0xf71042c7 in CInterpreter::VXMLRun (this=0xa0b1e70, pUrl=0xd58fc11 "/home/icd/icddir/bin/Y:/flow/vxml/temp.jsp", usRetCode=@0xdc0db302: 65535, dwGetFileTime=@0xdc0db2dc: 0, bGetFileSuccessFalg=@0xdc0db2d8: 0) at ../vxml/Interpreter.cpp:2389#13 0x0812988d in CCallingInstance::ThreadProc (lpParam=0xa0c01e8) at ../icd_files/icd_callapp.cpp:1478#14 0xf6491809 in start_thread () from /lib/libpthread.so.0#15 0xf63f63be in clone () from /lib/libc.so.6问题:如何继续排查和解决这个问题?源码和日志已发附件。
-
1. 简介ELK是集中日志解决方案的一种,具有收集、传输、存储、分析日志的功能。ELK分别是Elasticsearch、Logstash和Kibana三个开源软件的首字母缩写。Elasticsearch 是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。Logstash 的作用就是一个数据收集器,将各种格式各种渠道的数据通过它收集解析之后格式化输出到 Elasticsearch。Kibana 是一款基于 Apache 开源协议,使用 JavaScript 语言编写,为 Elasticsearch 提供分析和可视化的 Web 平台。它可以在 Elasticsearch 的索引中查找,交互数据,并生成各种维度的表图。类别:中间件2. 部署环境Packet NameVersion备注EulerEuler 2.8与Centos二选一CentOSCentOS 7.5 with ARM与Euler二选一Elasticsearch6.2.3Logstash6.2.3Kibana6.2.3整个环境在一台服务器部署 3. 安装部署 3.1 约束说明 & 配置华为官方镜像源Kibana 的版本需要和 Elasticsearch 的版本一致,这是官网的配置要求,可参考网址:https://www.elastic.co/guide/cn/kibana/current/setup.html 配置华为官方镜像源Centos7.5 mkdir -p /etc/yum.repos.d/repo_bak/ mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/repo_bak/ curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.myhuaweicloud.com/repo/Centos-altarch-7.repo yum makecacheEuler2.8 wget http://mirrors.myhuaweicloud.com/repo/mirrors_source.sh && sh mirrors_source.sh 3.2 JDK安装Centos7.5 yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-develEuler2.8#Euler2.8 没有找到java-1.8.0-openjdk-devel, yum search openjdk yum -y install java-1.8.0-openjdk源码安装java(option)#下载tar包wget http://openjdk.linaro.org/releases/jdk8u-server-release-1803.tar.xz#解压tar -jxvf jdk8u-server-release-1803.tar.xz -C /usr/lib/jvm#创建软连接ln -sf /usr/lib/jvm/jdk8u-server-release-1803/bin/java /etc/alternative/java #配置环境变量vi /etc/profile.d/java.sh-------------------java.sh---------------#JAVA_HOMEexport JAVA_HOME=/usr/lib/jvm/jdk8u-server-release-1803export JRE_HOME=$JAVA_HOME/jreexport JAVA=$JAVA_HOME/binexport CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jarexport PATH=$PATH:${JAVA_HOME}/bin--------------------------------------------source /etc/profile.d/java.sh#查看java版本java -version 3.3 安装部署Elasticsearch6.2.3 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.3.tar.gz tar xvf elasticsearch-6.2.3.tar.gz -C /opt && cd /opt# 添加用户,elasticsearch不允许使用root执行 groupadd elastic && useradd elastic -g elastic -p elastic chown -R elastic:elastic elasticsearch-6.2.3 su elastic cd elasticsearch-6.2.3# 后台启动elasticsearch ./bin/elasticsearch &# 验证 curl 127.0.0.1:9200{ "name" : "Surge", "cluster_name" : "elasticsearch", "version" : { "number" : "2.1.0", "build_hash" : "72cd1f1a3eee09505e036106146dc1949dc5dc87", "build_timestamp" : "2015-11-18T22:40:03Z", "build_snapshot" : false, "lucene_version" : "5.3.1" }, "tagline" : "You Know, for Search"}备注:如果遇到如下错误ERROR: [2] bootstrap checks failed[2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]# 切换至root用户,进行操作# 临时生效# elasticsearch需要在内存中保存索引,max_map_count文件包含限制一个进程可以拥有的VMA(虚拟内存区域)的数量. 防止elasticsearch抛出内存不足的异常。 sudo sysctl vm.max_map_count=262144 [1]: max file descriptors [65535] for elasticsearch process is too low, increase to at least [65536]# centos7.5 执行如下命令,退出ssh或者重启生效 vi /etc/security/limits.conf# 在文件末尾添加* soft nofile 65536 #限制(软)进程数量* hard nofile 131072 #限制(硬)进程数量# Euler2.8执行如下命令,退出ssh或者重启生效# 限制资源使用的配置文件是 /etc/security/limits.conf,和/etc/security/limits.d/目录,/etc/security/limits.d/里面配置会覆盖/etc/security/limits.conf的配置 vi /etc/security/limits.d/huawei-nofile.conf# 在文件末尾添加* soft nofile 65536* hard nofile 65536部署Kibana6.2.3 wget https://artifacts.elastic.co/downloads/kibana/kibana-6.2.3-linux-x86_64.tar.gz tar xvf kibana-6.2.3-linux-x86_64.tar.gz -C /opt rm -rf /opt/kibana-6.2.3-linux-x86_64/node# 直接下载的Kibana是x86的,需要将node组件换成arm版的运行 wget https://nodejs.org/dist/v8.11.3/node-v8.11.3-linux-arm64.tar.xz tar xvf /opt/node-v8.11.3-linux-arm64.tar.xz -C /opt/kibana-6.2.3-linux-x86_64 cd /opt/kibana-6.2.3-linux-x86_64 && mv node-v8.11.3-linux-arm64 node# 修改配置文件 vi config/kibana.yml# 配置成任意IP可以访问,生产环境建议为特定IPserver.host: "0.0.0.0"# 后台启动kibana ./bin/kibana &访问http://IP:5601部署Logstash6.2.3 wget https://artifacts.elastic.co/downloads/logstash/logstash-6.2.3.tar.gz tar xvf logstash-6.2.3.tar.gz && cd logstash-6.2.3# 解压完成,早config目录下新建一个logstash.conf# 然后做好input ,filter,output三大块, 其中input是吸取logs文件下的所有log后缀的日志文件,filter是一个过滤函数,这里不用配置,output配置了导入到# hosts为127.0.0.1:9200的elasticsearch中,每天一个索引。 vi config/logstash.confinput { file { type => "log" path => "/logs/*.log" start_position => "beginning" }} output { stdout { codec => rubydebug { } } elasticsearch { hosts => "127.0.0.1" index => "log-%{+YYYY.MM.dd}" }}# 启动logstash ./bin/logstash -f ./config/logstash.conf开启另一个ssh终端,往日志文件目录中写入数据 mkdir -p /logs cd /logs echo 'hello world' > 1.log 3.4 验证在浏览器中访问http://IP:/5601,可以打开kibana页面, 选择Management标签,在index-name-*框中输入log*,选择Time-field name 为@timestamp 点击Discover,就可以看见内容了3.5 参考信息[1] 通过ELK快速搭建一个你可能需要的集中化日志平台:https://www.cnblogs.com/huangxincheng/p/7918722.html4. FAQ4.1 点击Management标签时显示如下界面说明数据源不存在,在logs目录下增加相应日志 mkdir -p /logs cd /logs echo 'hello world' > 1.log
-
在windows平台上,官方给的projectQ安装C++的Simulator库的办法有两个,要么是安装msvc(体积大且没多线程加速,因为msvc只支持OpenMP2.0),要么是装mingw编译器,后者可以支持正常的OpenMP,编译出来的C++库是是支持多线程的。显然装mingw更好,不过projectQ没说清楚具体怎么玩,只好自己查命令去编译C++库。下面是具体的过程(每台机器上提前装的库都有差别,不保证一定没问题):1. 提前要装的软件Anaconda3 64位mingw-w64vcruntime140.dll 64位说明:mingw-w64是最新版的mingw编译器(还有个旧版的叫mingw32,只有32位版的,早就停止更新了),安装的时候可以选装32位的还是64位的,由于要用64位的Python,肯定装64位的(如果必须要用32位的Python,那就装32位的mingw,但是坑很多,最后会说)装完之后,把安装目录下的bin文件夹比如C:\MinGW\mingw64\bin加到Path环境变量中。然后把下载的vcruntime140.dll放到mingw安装目录下的lib文件夹中,比如C:\MinGW\mingw64\lib。可能需要代理才能装这个编译器,这有离线版的。2. 开装projectQ!右键管理员身份打开Anaconda Prompt(环境变量都加好了的话直接cmd也行)输入命令: pip install --global-option build_ext --global-option --compiler=mingw32 projectq一般来说,一通各种包安装之后会开始编译C++库,然后会直接出个Error,说缺lmsvcr140 :问题的原因是微软把这个库给移除了,导致编译程序找不着这个东西。这个时候之前下载的dll就要派上用场了,直接修改Anaconda安装目录下的C:\Application\Anaconda3\Lib\distutils\cygwinccompiler.py把87行改成这样(可能需要带管理员权限的编辑器)再跑一遍pip命令应该就能装好C++版的Simulator库了3. 并行效果在导入projectQ的库之前加上以下几行代码以启用多线程: import os os.environ["OMP_NUM_THREADS"] = '8' os.environ["OMP_PROC_BIND"] = "spread"线程数设置就看各自的电脑了。Linux貌似是用projectQ官方给的export命令,没用过就不多说了。运行官方示例shor算法,记得把high_level_gates里面的BasicMathGate置为False,强制模拟器去分解模幂运算对应的酉门,然后就可以开始愉快的数框框了!实际上它不是一开始就用上多核并行,而是代码跑到途中才开始,所以可能要等一会儿才能看到CPU占用率上去。官方说的是可以用当代笔记本电脑在3分钟内分解4028033这么大的数,其中的前提是把high_level_gates里面的BasicMathGate置为True,即不分解那个最耗时的模幂运算酉门,有点作弊的感觉,我实际这么跑了一下,发现程序根本就没用多核去跑,还是单线程运行,结果大概跑了10分钟才分解完,没搞清楚为什么会这样,群里哪位大佬知道的话劳烦告知。其实开了并行感觉shor算法并没有变快多少,实实在在去分解个529(貌似只用了十几个qubit)这种数都慢得要死,有点失望QAQ。4. 注意事项我的Anaconda是最新版64位的(2019.03),不知道低版本的会不会有问题。而且我之前电脑上就有全套Visual Studio 2017,不知道这个会不会对安装结果有影响(理论上有mingw了就不需要msvc)。32位的安装方法和以上步骤差不多(先把所有东西都换成32位的),但是更麻烦,32位的Anaconda的根目录下的include文件夹下的pyconfig.py里面如果有#define hypot _hypot这一行的话,要先注释掉再装projectQ,否则会报错。补一句,就算32位的装好了,实际跑比特数比较多的projectQ程序的时候也会有很大概率出MemoryError,所以不建议装32位的。貌似Linux或Mac上装带并行的projectQ没这么多幺蛾子。5. 最后一开始我是装的32位的projectQ,看到一堆报错信息一脸懵逼,折腾了好久才把这些安装问题给解决,希望能对大家有所帮助。可能大家按这个安装教程弄到最后还是会出新的Bug,到时候欢迎大家跟帖交流!
-
在云服务器的日常应用中,大家是不是也常常遇到响应速度变慢、服务器登录不上、突然出现网络断开的情况等问题,这些可能都是由于云服务器的带宽和CPU利用率过高导致。上次的课程我们跟大家分享了解决Windows云服务器带宽和CPU利用率高问题,今天小课和大家一起学习怎么解决Linux云服务器带宽和CPU利用率高问题。当您发现弹性云服务器的运行速度变慢或弹性云服务器实例突然出现网络断开现象,则可能是云服务器的带宽和CPU使用率过高导致。如果您已经通过云监控服务完成创建过告警任务,当CPU或带宽利用率高时,系统会自动发送告警给您。Linux弹性云服务器实例带宽流量过高或CPU使用率高,您可以按如下步骤进行排查:问题定位:定位影响云服务器带宽和CPU使用率高的进程。问题处理:排查进程是否正常,并分类进行处理。正常进程:优化程序,或变更云服务器的配置。异常进程:建议您手动关闭进程,或者借助第三方工具关闭进程。常用命令本文相关操作命令以CentOS 7.2 64 位操作系统为例。其它版本的Linux操作系统命令可能有所差异,具体情况请参阅相应操作系统的官方文档。Linux云服务器查看CPU使用率等性能相关问题时的常用命令如下:ps -auxps -eftopCPU占用率高问题定位使用VNC功能登录弹性云服务器,请参考Linux云服务器远程登录(VNC方式)。执行如下命令查看当前系统的运行状态。top系统回显样例如下:查看显示结果。命令回显第一行:20:56:02 up 37 days,1 user, load average: 0.00, 0.01, 0.05的每个字段含义如下:系统当前时间为20:56:02,该云服务器已运行37天,当前共有1个用户登录, 最近1分钟、最近5分钟和最近15分钟的CPU平均负载。命令回显第三行:CPU资源总体使用情况。命令回显第四行:内存资源总体使用情况。回显最下方显示各进程的资源占用情况。说明:在top页面,可以直接输入小写“q”或者在键盘上按“Ctrl+C”退出。除了直接输入命令,您还可以单击VNC登录页面屏幕右上角的“Input Command”,在弹n出的对话框中粘贴或者输入相应命令,单击“Send”。在top运行中常用的内容命令如下:s:改变画面更新频率。l:关闭或开启第一部分第一行 top 信息的表示。t:关闭或开启第一部分第二行 Tasks 和第三行 Cpus 信息的表示。m:关闭或开启第一部分第四行 Mem 和 第五行 Swap 信息的表示。N:以 PID 的大小的顺序排列进程列表。P:以 CPU 占用率大小的顺序排列进程列表。M:以内存占用率大小的顺序排列进程列表。h:显示命令帮助。n:设置在进程列表所显示进程的数量。通过ll /proc/PID/exe命令可以查看每个进程 ID 对应的程序文件。CPU使用率高问题处理对于导致CPU使用率高的具体进程,如果确认是异常进程,可以直接通过top命令终止进程。对于kswapd0进程导致的CPU使用率高的问题,则需要对应用程序进行优化,或者通过增加内存进行系统规格的升级。kswapd0是系统的虚拟内存管理程序,如果物理内存不够用,系统就会唤醒kswapd0进程,由kswapd0分配磁盘交换空间用作缓存,因而占用大量的CPU资源。使用top命令终止CPU占用率高的进程您可以直接在top运行界面快速终止相应的异常进程。操作步骤如下:在top命令运行的同时,按下小写的“k”键。输入要终止进程的PID。进程的PID为top命令回显的第一列数值。例如,要终止PID为52的进程,直接输入“52”后回车。操作成功后,会出现如下图所示类似信息,按回车确认。kswapd0进程占用导致CPU使用率高可通过以下步骤排查进程的内存占用情况。si:每秒从交换区写到内存的大小,由磁盘调入内存。so:每秒写入交换区的内存大小,由内存调入磁盘。通过top命令查看kswapd0进程的资源使用。如果kswapd0进程持续处于非睡眠状态,且运行时间较长,可以初步判定系统在持续的进行换页操作,可以将问题转向内存不足的原因来排查。通过vmstat命令进一步查看系统虚拟内存的使用情况。如果si和so的值也比较高,说明系统存在频繁的换页操作,系统物理内存不足。对于内存不足问题,可以通过free、ps等命令进一步查询系统及系统内进程的内存占用情况,做进一步排查分析。临时可通过在业务空闲期重启应用或者系统释放内存。如果要从根本上解决内存不足的问题,需要对服务器内存进行扩容,扩大内存空间。如果不具备扩容的条件,可通过优化应用程序,以及配置使用大页内存来进行缓解。带宽使用率高问题分析如果是正常业务访问以及正常应用进程导致的带宽使用率高,需要升级服务器的带宽进行解决。如果是非正常访问,如某些特定IP的恶意访问,或者服务器遭受到了CC攻击。或者异常进程导致的带宽使用率高。可以通过流量监控工具nethogs来实时监测统计各进程的带宽使用情况,并进行问题进程的定位。使用nethogs工具进行排查PID:进程 ID。USER:运行该进程的用户。PROGRAM:进程或连接双方的IP地址和端口,前面是服务器的IP和端口,后面是客户端的IP和端口。DEV:流量要去往的网络端口。SENT:进程每秒发送的数据量。RECEIVED:进程每秒接收的数据量。-d:设置刷新的时间间隔,默认为 1s。-t:开启跟踪模式。-c:设置更新次数。device:设置要监测的网卡,默认是eth0。q:退出nethogs工具。s:按发送流量大小的顺序排列进程列表。r:按接收流量大小的顺序排列进程列表。m:切换显示计量单位,切换顺序依次为KB/s、KB、B、MB。执行以下命令,安装nethogs工具。yum install nethogs -y安装成功后可以通过netgos命令查看网络带宽的使用情况。nethogs命令常用参数说明如下:运行时可以输入以下参数完成相应的操作:执行以下命令,查看指定的网络端口每个进程的网络带宽使用情况。nethogs eth1回显参数说明如下:终止恶意程序或者屏蔽恶意访问IP。如果确认大量占用网络带宽的进程是恶意进程,可以使用kill PID命令终止恶意进程。如果是某个IP恶意访问,可以使用iptables服务来对指定IP地址进行处理,如屏蔽 IP 地址或限速。使用Web应用防火墙防御CC攻击若服务遭受了CC攻击,请在Web应用防火墙控制台开启CC安全防护。Web应用防火墙的使用指导请参见配置CC防护策略。【往期回顾】【第一课】我该怎么选择云主机的规格?【第二课】云小课带你了解镜像家族!【第三课】云小课带你学习购买云硬盘,快速读懂云存储。【第四课】云服务器网络怎么选?安全组怎么配?云小课为你支招!【第五课】云小课带您大话安全组【第六课】你了解云服务器的远程登录吗?小课教你自助排查MSTSC远程登录问题!【第七课】 云小课带你快速实现主机的上云迁移【第八课】 云小课教你轻松切换操作系统【第九课】如何通过镜像实现跨可用区的业务迁移?【第十课】“VPC连接”知多少?【第十一课】项目与企业项目【第十二课】云计算小课之ECS实例:新一代计算增强型云服务器C6蓄势起航【第十三课】怎么解决Windows云服务器带宽和CPU利用率高问题【第十四课】云计算小课之:快速购买弹性云服务器
-
TensorFlow 队列与线程深度学习的模型训练过程往往需要大量的数据,而将这些数据一次性的读入和预处理需要大量的时间开销,所以通常采用队列与多线程的思想解决这个问题,而且TensorFlow为我们提供了完善的函数。本文介绍了TensorFlow的线程和队列。在使用TensorFlow进行异步计算时,队列是一种强大的机制。正如TensorFlow中的其他组件一样,队列就是TensorFlow图中的节点。这是一种有状态的节点,就像变量一样:其他节点可以修改它的内容。具体来说,其他节点可以把新元素**到队列后端(rear),也可以把队列前端(front)的元素删除。在Python中是没有提供直接实现队列的函数的,所以通常会使用列表模拟队列。而TensorFlow提供了整套实现队列的函数和方法,在TensorFlow中,队列和变量类似,都是计算图上有状态的节点。操作队列的函数主要有:l FIFOQueue():创建一个先入先出(FIFO)的队列 l RandomShuffleQueue():创建一个随机出队的队列 l enqueue_many():初始化队列中的元素 l dequeue():出队 enqueue():入队与队列Queue有关的有以下三个概念:l Queue是TF队列和缓存机制的实现l QueueRunner是TF中对操作Queue的线程的封装l Coordinator是TF中用来协调线程运行的工具虽然它们经常同时出现,但这三样东西在TensorFlow里面是可以单独使用的,不妨先分开来看待。1. Queue,队列根据实现的方式不同,分成具体的几种类型,例如:l tf.FIFOQueue 按入列顺序出列的队列l tf.RandomShuffleQueue 随机顺序出列的队列l tf.PaddingFIFOQueue 以固定长度批量出列的队列l tf.PriorityQueue 带优先级出列的队列l ...这些类型的Queue除了自身的性质不太一样外,创建、使用的方法基本是相同的,以下介绍两个最常用的1) tf.FIFOQueue(capacity, dtypes, name='fifo_queue') 创建一个以先进先出的顺序对元素进行排队的队列参数:capacity:整数。可能存储在此队列中的元素数量的上限dtypes:DType对象列表。长度dtypes必须等于每个队列元 素中的张量数,dtype的类型形状,决定了后面进队列元素形状方法:q.dequeue()获取队列的数据q.enqueue(值)将一个数据添加进队列q.enqueue_many(列表或者元组)将多个数据添加进队列q.size() 返回队列的大小2)、tf.RandomShuffleQueue() 随机出的队列Queue主要包含入列(enqueue)和出列(dequeue)两个操作。enqueue操作返回计算图中的一个Operation节点,dequeue操作返回一个Tensor值。Tensor在创建时同样只是一个定义(或称为“声明”),需要放在Session中运行才能获得真正的数值。下面是一个单独使用Queue的例子:#模拟同步操作 ''' 1.创建一个空的队列 2.向队列设置几个初始的值 3.从队列中取出一个数据,再将数据加1 4.数据加1之后的结果进队列 5.打印出队列中的数据 ''' def sync_test(): #创建一个空的队列 q = tf.FIFOQueue(3,tf.float32) #向队列设置几个初始的值 enq_many = q.enqueue_many(([0.1,0.2,0.3],)) #从队列中取出一个数据,再将数据加1 out_q = q.dequeue() data = out_q+1 #数据加1之后的结果进队列 en_q = q.enqueue(data) with tf.Session() as sess: sess.run(enq_many) #执行en_q op 99次 for i in range(99): sess.run(en_q) #打印出队列中的数据 for i in range(q.size().eval()): print(q.dequeue().eval()) return None 2. QueueRunner,队列管理器tf.train.QueueRunner(queue, enqueue_ops=None)参数:l queue:A Queuel enqueue_ops:添加线程的队列操作列表,[]*2,指定两个线程l create_threads(sess, coord=None,start=False) 创建线程来运行给定会话的入队操作l start:布尔值,如果True启动线程;如果为False调用者 必须调用start()启动线程l coord:线程协调器 用于线程的管理Tensorflow的计算主要在使用CPU/GPU和内存,而数据读取涉及磁盘操作,速度远低于前者操作。因此通常会使用多个线程读取数据,然后使用一个线程消费数据。QueueRunner就是来管理这些读写队列的线程的。QueueRunner需要与Queue一起使用(这名字已经注定了它和Queue脱不开干系),但并不一定必须使用Coordinator。看下面这个例子:import tensorflow as tf import sys q = tf.FIFOQueue(10, "float") counter = tf.Variable(0.0) #计数器 # 给计数器加一 increment_op = tf.assign_add(counter, 1.0) # 将计数器加入队列 enqueue_op = q.enqueue(counter) # 创建QueueRunner # 用多个线程向队列添加数据 # 这里实际创建了4个线程,两个增加计数,两个执行入队 qr = tf.train.QueueRunner(q, enqueue_ops=[increment_op, enqueue_op] * 2) # 主线程 sess = tf.InteractiveSession() tf.global_variables_initializer().run() # 启动入队线程 qr.create_threads(sess, start=True) for i in range(20): print (sess.run(q.dequeue()))增加计数的进程会不停的后台运行,执行入队的进程会先执行10次(因为队列长度只有10),然后主线程开始消费数据,当一部分数据消费被后,入队的进程又会开始执行。最终主线程消费完20个数据后停止,但其他线程继续运行,程序不会结束。3. Coordinator,线程协调器tf.train.Coordinator() 线程协调员,实现一个简单的机制来协调一 组线程的终止方法: 返回的是线程协调实例 request_stop() 请求停止 join(threads=None, stop_grace_period_secs=120) 等待线程终止Coordinator是个用来保存线程组运行状态的协调器对象,它和TensorFlow的Queue没有必然关系,是可以单独和Python线程使用的。例如:#模拟异步操作 ''' 通过队列管理器来实现变量加1,入队,主线程出队列的操作,观察效果? (异步操作) ''' def async_test(): # # 1、定义一个队列,1000 q = tf.FIFOQueue(300,tf.float32) # 2、定义要做的事情 循环值,+1, 放入队列当中 var = tf.Variable(0.0) # 实现一个自增 tf.assign_add data = tf.assign_add(var,tf.constant(1.0)) en_q = q.enqueue(data) # 3、定义队列管理器op, 指定多少个子线程,子线程该干什么事情 # 1,2,3,4,5,6,7,8,9,10 qr = tf.train.QueueRunner(q, enqueue_ops=[en_q] * 2) # 初始化变量的OP init_op = tf.global_variables_initializer() with tf.Session() as sess: #运行初始化op sess.run(init_op) # 开启线程管理器,coord线程协调器 coord = tf.train.Coordinator() # 真正开启子线程,读数据入队列,t1,t2 0.0001 10 threads = qr.create_threads(sess, coord=coord, start=True) # 主线程,不断读取数据训练 t0 for i in range(300): # print(sess.run(q.dequeue())) print("size==>",sess.run(q.size())) # 停止子线程,回收 coord.request_stop() coord.join(threads) return None 将这个程序运行起来,主线程会等待所有子线程都停止后结束,从而使整个程序结束。由此可见,只要有任何一个线程调用了Coordinator的request_stop方法,所有的线程都可以通过should_stop方法感知并停止当前线程。将QueueRunner和Coordinator一起使用,实际上就是封装了这个判断操作,从而使任何一个现成出现异常时,能够正常结束整个程序,同时主线程也可以直接调用request_stop方法来停止所有子线程的执行。 更多的技术内容,请访问腾科it教育集团网站 www.togogo.net
-
在云服务器的日常应用中,大家是不是也常常遇到响应速度变慢、服务器登录不上、突然出现网络断开的情况等问题,这些可能都是由于云服务器的带宽和CPU利用率过高导致。今天小课和大家一起学习怎么解决Windows云服务器带宽和CPU利用率高问题。温馨提示:如果您已经通过云监控服务完成创建过告警任务,当CPU或带宽利用率高时,系统会自动发送告警给您。排查思路:定位影响云服务器带宽和CPU利用率高的进程。Windows操作系统本身提供了较多工具可以定位问题,包括任务管理器、性能监视器(Performance Monitor)、资源监视器(Resource Monitor)、Process Explorer、Xperf (Windows server 2008 以后)和抓取系统Full Memory Dump检查。在流量大的情况下,您还可以使用Wireshark抓取一段时间的网络包,分析流量使用情况。问题处理:排查进程是否正常,并分类进行处理。正常进程:优化程序,或变更云服务器的配置。异常进程:建议您手动关闭进程,您也可以借助第三方工具关闭进程。问题定位步骤在云服务器桌面的左下角,单击“开始 > 运行”。在“打开”后的输入框中输入“perfmon -res”。在“资源监视器”中,单击“CPU”或“网络”,查看CPU占用或率带宽使用情况。查看CPU和带宽占用率较高的进程ID和进程名。同时按下Ctrl+Alt+Delete,打开“Windows任务管理器”。以下步骤为您介绍在任务管理器中打开PID,找到进程的具体位置,核对是否异常进程。选择“进程”选项卡。单击菜单栏中的“查看 > 选择列”。勾选“ PID(进程标识符)”。单击“确定”。任务管理器的“进程”选型卡中,将会增加 PID 这一项。单击PID进行排序。在查找到的CPU或带宽占用率高的进程上右键单击“打开文件位置”。定位进程是否是正常或是否为恶意程序。分析处理在您采取措施处理问题前,首先需要判断影响CPU或带宽占用率高的进程是正常进程还是异常进程。不同类型的进程状态需要做不同处理。正常进程分析处理建议如果您的操作系统是Windows 2008/Windows 2012,请检查内容大小,建议内存配置在2GB或以上。检查后台是否有执行Windows Update的行为。检查杀毒软件是否正在后台执行扫描操作。核对弹性云服务器运行的应用程序中是否有对网络和CPU要求高的需求,如果是,建议您变更云服务器的配置或修改带宽。如果云服务器配置已经比较高,建议考虑云服务器上应用场景的分离部署,例如将数据库和应用分开部署。异常进程分析处理建议如果CPU或带宽利用率高是由于病毒、木马入侵导致的,那么需要手动结束进程。建议的处理顺序如下:使用云服务器备份或云硬盘备份。使用云服务器进行整机备份,请参考创建云服务器备份。使用云硬盘备份进行磁盘备份,请参考创建云硬盘备份。使用商业版杀毒软件或安装微软安全工具Microsoft Safety Scanner,在安全模式下扫描病毒。安装Windows最新补丁。使用MSconfig禁用所有非微软自带服务驱动,检查问题是否再次发生,具体请参考:如何在 Windows 中执行干净启动。若服务器或站点遭受DDOS攻击或CC攻击等,短期内产生大量的访问需求。您可以登录管理控制台。查看Anti-DDOS攻击是否开启,并检查防护策略是否配置合适;如未配置,请参考:配置开启Anti-DDoS防护。查看CC防护策略是否开启,并检查防护策略是否配置合适;如未配置,请参考:配置CC防护策略。【往期回顾】【第一课】我该怎么选择云主机的规格?【第二课】云小课带你了解镜像家族!【第三课】云小课带你学习购买云硬盘,快速读懂云存储。【第四课】云服务器网络怎么选?安全组怎么配?云小课为你支招!【第五课】云小课带您大话安全组【第六课】你了解云服务器的远程登录吗?小课教你自助排查MSTSC远程登录问题!【第七课】 云小课带你快速实现主机的上云迁移【第八课】 云小课教你轻松切换操作系统【第九课】如何通过镜像实现跨可用区的业务迁移?【第十课】“VPC连接”知多少?【第十一课】项目与企业项目【第十二课】云计算小课之ECS实例:新一代计算增强型云服务器C6蓄势起航
上滑加载中
推荐直播
-
华为AI技术发展与挑战:集成需求分析的实战指南
2024/11/26 周二 18:20-20:20
Alex 华为云学堂技术讲师
本期直播将综合讨论华为AI技术的发展现状,技术挑战,并深入探讨华为AI应用开发过程中的需求分析过程,从理论到实践帮助开发者快速掌握华为AI应用集成需求的框架和方法。
去报名 -
华为云DataArts+DWS助力企业数据治理一站式解决方案及应用实践
2024/11/27 周三 16:30-18:00
Walter.chi 华为云数据治理DTSE技术布道师
想知道数据治理项目中,数据主题域如何合理划分?数据标准及主数据标准如何制定?数仓分层模型如何合理规划?华为云DataArts+DWS助力企业数据治理项目一站式解决方案和应用实践告诉您答案!本期将从数据趋势、数据治理方案、数据治理规划及落地,案例分享四个方面来助力企业数据治理项目合理咨询规划及顺利实施。
去报名
热门标签