总结初用erlang 时的遇到一些问题
算起来接触erlang 快四个月来,从零开始看书写erlang代码、修改RabbitMQ、业务开发、系统调优,总算是有点入门了。
最难受的是边学边修改RabbitMQ,难受只是暂时的,憋过去就海阔天空,最后提交修改2000+行代码。
说到坑都是自己技术不过关造成,erlang 设计与一般语言很大不同,虽然简单但还是有不少需要注意点;erlang 是一门非常成熟语言,OTP 也特别稳定,不过要想用好,很不容易。
列举遇到的注意点:
1. 学习资料少
书:《programing erlang》erlang 作者写的,通俗简单 嗯 真的很简单。。看一遍就够写得都差不多
官方文档: 不够详细?凑合看吧,好歹有
博客推荐:(建议有空将他们博客通读一遍,助你绕过前人走过的弯路)
http://www.cnblogs.com/zhengsyao/ (强推)
http://blog.yufeng.info/
http://www.cnblogs.com/me-sa/
http://wqtn22.iteye.com/
2. error_logger
这是个坑货, 而且默认crashlog 用这玩意儿记,一旦进程批量crash,因为内部receive-match 写磁盘方式,越来越慢。
可以选用lager,不过lager 在message_queue_len 超过指定值(50)后采用同步方式,内部依然是receive-match 写磁盘 方式写磁盘,
建议实现自己的lager_backend,通过cast 到独立 gen_server2 写磁盘,或者cast 到网络写到日志服务器上去
3. gen_server receive-match 问题
避免在热点gen_server 中使用receive-match 方式,或者都使用如rabbitmq 中的gen_server2,一定要防止在message_queue_len可能
比较大的进程中做recieve-match,error_logger就存在这个问题。
4. 热点进程
erlang 是公平调度,热点进程在负载稍高时,就会没机会得到处理,注意设置priority high
5. 单进程处理瓶颈
erlang 中因为进程无法共享数据,往往使用单个gen_server 完成共享逻辑,但erlang CPU计算是很低效的,往往但进程无法完成业务处理。
这个时候需要拆分到多个进程处理,如:server_1, server_2 .... 。
6. ETS
4、5 另一个解决方案是使用ETS,ETS 可以作为全局表,所有进程都可以读写,不存在热点进程,而且减少了进程消息交互成本,效率要高很多。
但是,ETS 是表结构,能够适合的场景很少,能用那就尽量多使用吧。
7. rpc:call
成本较大:一次调用有3次网络往返
服务端单进程:服务端有rex 进程处理,容易产生瓶颈,测试最多处理 10w/s 消息
如有必要尽量多使用 Pid ! Msg - receive 方式
8. gen_server:call timeout
timeout 是给call 方返还的,而实际处理一定会被处理,而且reply 也会在timeout 后发回message_queue,要注意。。
9. Pid ! Msg
Pid 不存在时,消息丢失, gen_cast 也一样;就算is_process_alive 判断也会存在竞态,所有是无法判断是否send sucess ,只能reply 确认
10. 依赖supervisor
erlang 设计模式,一般不怎么处理异常,非常态错误依赖supervisor 重启。 但如果gen_server 存在数据,重启瞬间 就会丢失数据。