Elixir 项目的一些经验教训
来自Dennis的知识库
2016年12月23日 (五) 07:47Dennis zhuang(讨论 | 贡献)的版本
目录 |
日志
config :logger, backends: [{LoggerFileBackend, :error_log}] config :logger, :error_log, path: "/mnt/avos/logs/pier/pier.log", level: :info
打包和部署
- 使用 exrm
- 启动使用:
trap exit TERM; $APP_HOME/bin/$APP foreground & wait
- 默认 vm.args 要求节点名称在每台机器唯一,如果想设置不同的节点名称,比如走 marathon 容器化部署,很可能部署在同一台机器,可以注释掉 exrm 生成的启动脚本里的检测 vm.args 有没有设置 name 的代码,然后 export ERL_OPTS 来自主设置。
内存消耗
- GenServer 适当做 hibernate。
- Ecto 连接池设置 sock_options 来减少内存占用,因为他的连接池是固定大小,参考issue1328:
pool_size: 20, socket_options: [recbuf: 8192, sndbuf: 8192]
- cowboy 可以适当缩减请求对象大小,如果你确定后面不再使用,来释放内存,参考 reducing-the-memory-footprint
new_req = :cowboy_req.compact(req).
优化
- 对于 docker 容器,开启 SMP 情况下应该设置调度器数量,因为虚拟化会导致容器内启动了过多调度器,
+S 4
设置为 4个。 - 增大 process 和 ets 上限:
-env ERL_MAX_PORTS 102400 -env ERL_MAX_ETS_TABLES 50000
- 通过
:erlang.system_info/1
来观察内存、进程等状况。 - GenServer 的消息处理应当尽量快,避免将 IO 操作放在其中,可以异步化,然后结果更新会 GenServer 即可。
- 定时器采用 :erlang.send_after 配合 GenServer.handle_info 来处理。
- 对于负载较高,或者较为核心的 process,可以配置 process,比如优先级,堆大小等:
GenServer.start_link(__MODULE__, :ok, name: @name, spawn_opt: [priority: :high, min_bin_vheap_size: 1024*1024, min_heap_size: 1024*1024])
- 测试来看, ibrowse 的性能比 hackney 更好。
其他
- tzdata 这个库会在发现有新版本的时候自动去更新,在国内经常超时,没有必要。关闭 tzdata 更新:
config :tzdata, :autoupdate, :disabled
- 使用
bin/$app remote_console
来连上正在运行的 erl 进程,不要使用 attach,在退出的时候会导致进程退出。而 remote_console 不会,可以用 ctrl +c 退出。