Erlang虽然号称N个9的稳定性,但是在实际使用中还是有很多机会看到Erlang Crash了的,其中和VM相关的Crash 十有八九是由于内存使用过量,导致系统服务分配内存导致的。Erlang的内存分配测量是集中批发,零售给各个VM部件,包括用户进程和ETS数据库等内存消费大户。VM的内存增长是以fib方式上升的,一旦你的内存使用到G级别,那么之后的大量内存分配会以超过你预想的速度消费。
    其中用户进程的消息队列是其中的罪魁祸首。 Erlang的虚拟机实现和设计上都没有阻止用户往一个进程的消息队里面扔消息,当消息的生产速度过快,超过进程的处理能力,这些消息就堆积起来,占用越来愈多的内存,最终导致VM崩溃。
    那么我们如何来避免这种事情呢?既然不能阻止,那我们绕着走,通过监控来避免:
     1. 监控消息队列的增长。
     2. 监控VM整个内存的使用量。
     
    一旦发现上面的二个情况的发生,我们可以采用的措施有以下几种:
     1. 收紧内存。 在模块编写的时候,对于内存消费大户的模块,比如说cache等,注册接收内存紧张的信息。一旦收到此类威胁信号,马上释放掉不必要的内存,保命要紧。
    2. 切断或者限制输入源,大部分的服务器程序都是网络服务,输入都是从用户的请求开始。 那我们可以暂时不接收或者减半处理用户的网络封包请求,使得工作进程能够及时处理滞留的消息。
    3. 重新审视设计,为什么会有工作进程处理不过来的情况?是不是设计上服务有单点,能不能scale来处理。
    这里重点看下如何发现内存紧张。Erts本事提供很多的信息源让用户来知道目前VM内部模块的内存使用情况,但是经常身在此山中,无法从更高的角度来看这个问题。
    Erlang提供了memsup模块来让用户从操作系统的角度了解整个VM占用的VM情况。文档参看这里
    memsup is a process which supervises the memory usage for the system and for individual processes. It is part of the OS_Mon application, see os_mon(6). Available for Unix, Windows and VxWorks.
    Periodically performs a memory check:
     *If more than a certain amount of available system memory is allocated, as reported by the underlying operating system, the alarm {system_memory_high_watermark, []} is set.
     *If any Erlang process Pid in the system has allocated more than a certain amount of total system memory, the alarm {process_memory_high_watermark, Pid} is set.
    通过预设内存使用的上限,当使用过度的时候,我们就可以收到这种报警消息,我们的应用就有了进一步处理的依据了。
     这方面 rabbitmq 处理的非常好,所以rabbitmq很稳健,代码也写得很清爽,各位可以参考下。
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐