gen_server 相关的片段分析得也差不多了, 这篇作为一个简要的总结.这一系列相关的分析暂且告一段落(之后如有必要,还会回来的 ^^ ),下一个系列主要是以pool 相关, 包括但不仅限于开源项目pooler, poolboy, emysql 中的pool 的管理, rabbitmq-server 中的worker_pool 角色等.
lapse request
对于gen_server handle_call callback, 主要处理同步请求,如果gen_server 进程在Timeout 时间内无法处理完成或根本来不及处理,这个时候就会出现失效的请求. 也就是当handle_call 在开始处理某请求时, 该请求的调用者早已经不再需要此次处理.
这样的需求并不一定是需要的,需要还是根据需求场景的不同定. 而避免此种情形出现的方式也比较简单,不着急,慢慢分析:
判断调用者alive
在gen module 处理call 请求的函数 do_call/4, 在将请求发送给目标gen_server 进程后, 请求调用者就会同步receive 目标gen_server 进程的返回, 超时Timeout 之后, 调用进程以exit(timeout) 退出.是的,等gen_server 进程在Timeout 时间内无法完成或根本来不及处理请求, 请求的调用者按照默认的方式, 就会exit. 也就是说,在没有try catch 的情况下,借助erlang:is_alive/0 API , 是可以判断当前handle_call 处理的请求是否是有效的.
但是, 如果使用了try catch 或者是catch 请求的调用进程就很有可能不按照预先的期望exit 退出了,这个时候, 这种方式就已经没有效果了.
monitored_by
还是在gen module 处理call 请求的函数 do_call/4,在发送给目标gen_server 进程请求之前, 请求的调用进程会首先monitor gen_server 进程,并在Timeout 之后demonitor. 也就是, 某请求如果还是有效的话, 在gen_server 进程的 monitored_by lists 中,应该还有请求的调用进程存在.
long-lived
通常情况下,Erlang process 更被期望于以short-lived 的方式存在.
An Erlang process starts with a small stack and heap in order to support a huge number of processes in a system. The size is configurable and the default value is 233 words. In general, Erlang processes are expected to short-lived and have small amounts of live data. When there is not enough free memory in the heap for a pro- cess, it is garbage collected, and if less memory can be freed than required it grows.
但是对于gen_server 来说,一般都是作为long-lived 的进程角色.对于long-lived 的进程角色,需要对其资源利用谨慎处理(通常情况下,是对于GC).
而优化的方案,需要根据应用场景的不同而不同,可供选的大致有:
1, hibernation
2, fullsweep_after
A non-negative integer which indicates how many times generational garbage collections can be done without forcing a fullsweep collection. In low-memory systems (especially without virtual memory), setting the value to
0
can help to conserve memory.
Riak 的官方文档中,对fullsweep_after 的参数设置为0.
3, min_heap_size
4, erlang:garbage_collect/1
参见RabbitMQ-server 中的background_gc module.
当然,最为理想的方案, 是尽可能将long-lived 的进程角色改为 short-lived . 参见riak_client 对gen_fsm 的使用.
参考
1, http://erlang.org/pipermail/erlang-questions/2011-October/061871.html
2, http://docs.basho.com/riak/latest/ops/advanced/configs/configuration-files/
3, http://www.erlang.org/doc/man/erlang.html#system_flag-2
4, Characterizing the Scalability of Erlang VM
5, Exploring Alternative Memory Architectures for Erlang- Implementation and Performance Evaluation (A How does the initial heap size affect the runtime? )
6, https://github.com/Eonblast/Emysql/pull/101