如何对占据服务器大量cpu资源的用户进行限制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何对占据服务器大量cpu资源的用户进行限制相关的知识,希望对你有一定的参考价值。

参考技术A 研究生工作过程中遇到有学生无视linux服务器实际的CPU核心数,开出几十上百个运算密集型进程,其他用户登陆困难或无响应等异常情况,需要对占用大头(CPU老虎?)的CPU资源做出限制。
使用cgroup可以实现用户组级别的限制,把老虎们扔进限制组就能解决问题,如果需要分别限制用户那就每个老虎一个组(前提是老虎属于少数,如果多数人都是老虎那就得考虑加CPU甚至加服务器了,组里穷,提买服务器基本属于说废话)。
注意linux中创建用户时默认会创建同名的组,所以按用户限制时不需要额外建组,直接限制用户的名字即可。

1.安装cgroup
服务器环境为centos7,使用yum安装cgroup:

2.配置cgroup
设置cgroup服务开机启动:

编辑/etc/cgconfig.conf:

编辑/etc/cgrules.conf:

第一列为用户(组)名,第二列为限制类型,第三列为限制器名,即前述/etc/cgconfig.conf中的限制器

注:同一个限制器下建议只放置一个用户,如果放置多个用户(或者含多个用户的组)会导致组内争抢限制器的资源,组内一个人高占用会使得其他人卡住,违背了使用限制器的初衷“限制少数高占用用户,使得低占用用户体验流畅”。

重启服务:

完成

面对这种CPU老虎,服务器终于重新丝滑流畅了起来

写代码如何合理使用和优化我们的机器资源(CPU内存网络磁盘)

写代码脑子一定要绷紧一根弦,认知到我们所在的机器资源是有限的。机器资源有哪些?CPU、内存、网络、磁盘等,如果不做好保护控制工作,一旦某一资源满负荷,很容易导致出现线上问题。

1 CPU 资源怎么限制

* 
计算算法优化。如果服务需要进行大量的计算,比如推荐排序服务,那么务必对你的计算算法进行优化,比如笔者曾经对地理空间距离计算这一重度使用的算法进行了优化,取得了较好的效果,详见《地理空间距离计算优化》一文。
* 
锁。对于很多服务而言,没有那么多耗费计算资源的算法,但 CPU 使用率也很高,这个时候需要看看锁的使用情况,我的建议是如无必要,尽量不用显式使用锁。
* 
习惯问题。比如写循环的时候,千万要检查看看是否能正确退出,有些时候一不小心,在某些条件下就成为死循环,很著名的案例就是《多线程下HashMap的死循环问题》。比如集合遍历时候使用性能较差的遍历方式、String + 检查,如果有超过多个 String 相加,是否使用 StringBuffer.append?
* 
尽量使用线程池。通过线程池来限制线程的数目,避免线程过多造成的线程上下文切换的开销。
* 
JVM 参数调优。JVM 参数也会影响 CPU 的使用,如《发布或重启线上服务时抖动问题解决方案》。

2 内存资源怎么限制

* 
JVM 参数设置。通过 JVM 参数的设置来限制内存使用,JVM 参数调优比较靠经验,有一篇朋友写的好文可以参考《Linux 与 JVM 的内存关系分析》。
* 
初始化 Java 集合类大小。使用 Java 集合类的时候尽量初始化大小,在长连接服务等耗费内存资源的服务中这种优化非常重要。
* 
使用内存池/对象池
* 
使用线程池的时候一定要设置队列的最大长度。之前看过好多起故障都是由于队列最大长度没有限制最后导致内存溢出。
* 
如果数据较大避免使用本地缓存。如果数据量较大,可以考虑放置到分布式缓存如 Redis、Tair 等,不然 gc 都可能把自己服务卡死。
* 
对缓存数据进行压缩。比如之前做推荐相关服务时,需要保存用户偏好数据,如果直接保存可能有 12G,后来采用短文本压缩算法直接压缩到 6G,不过这时一定要考虑好压缩解压缩算法的 cpu 使用率、效率与压缩率的平衡,一些压缩率很高但是性能很差的算法,也不适合线上实时调用。有些时候直接使用 probuf 来序列化之后保存,这样也能节省内存空间。
* 
清楚第三方软件实现细节,精确调优。在使用第三方软件时,只有清楚细节后才知道怎么节约内存,这点我在实际工作中深有体会,比如之前在阅读过lucene的源码后发现我们的索引文件原来是可以压缩的,而这在说明文档中都找不到,具体参考《lucene索引文件大小优化小结》一文。

3 网络资源怎么限制

* 
减少调用的次数。经常看到有同学在循环里用 redis/tair 的 get,如果意识到这里面的网络开销的话就应该使用批量处理;又如在推荐服务中经常遇到要去多个地方去取数据,一般采用多线程并行去取数据,这个时候不仅耗费cpu资源,也耗费网络资源,一种在实际中常常采用的方法就是先将很多数据离线存储到一块 ,这时候线上服务只要一个请求就能将所有数据获取。
* 
减少传输的数据量。一种方法是压缩后传输,还有一种就是按需传输,比如经常遇到的 getData(int id),如果我们返回该 id 对应的 Data 所有信息,一来人家不需要,二来数据量传输太大,这个时候可以改为 getData(int id, Listfields),使用方传输相应的字段过来,服务端只返回使用方需要的字段即可。

4 磁盘资源怎么限制

打日志要控制量,并定期清理。1)只打印关键的异常日志;2)对日志大小进行监控报警。我有一次就遇到了第三方服务挂了,然后我这边就不断打印调用该第三方服务异常的日志,本来我的服务有降级方案,如果第三方服务挂了会自动使用其它服务,但是突然收到报警说我服务挂了,登上机器一看才知道是磁盘不够导致的崩溃;3)定期对日志进行清理,比如用 crontab,每隔几天对日志进行清理;4)打印日志到远端,对于一些比较重要的日志可以直接将日志打印到远端HDFS文件系统里;
备注
基础原则……控制资源的使用









































以上是关于如何对占据服务器大量cpu资源的用户进行限制的主要内容,如果未能解决你的问题,请参考以下文章

W3wp.exe占用CPU及内存资源

cgroup实现cpu绑定和资源使用比例限制

CC攻击原理及防范方法和如何防范CC攻击

kvm如何让一个vcpu占用一个物理cpu

nexus 消耗大量cpu资源,启动一堆僵尸进程

win10服务主机本地系统占用大量CPU怎么解决