“Elixir 项目的一些经验教训”的版本间的差异
来自Dennis的知识库
Dennis zhuang(讨论 | 贡献) |
Dennis zhuang(讨论 | 贡献) |
||
(未显示1个用户的5个中间版本) | |||
第15行: | 第15行: | ||
== 打包和部署 == | == 打包和部署 == | ||
+ | * 生产环境记得开启: config :phoenix, :serve_endpoints, true | ||
* 使用 exrm | * 使用 exrm | ||
* 启动使用: | * 启动使用: | ||
第35行: | 第36行: | ||
</pre> | </pre> | ||
− | * cowboy 可以适当缩减请求对象大小,如果你确定后面不再使用,来释放内存,参考 [https://github.com/YuyaYumoto/cowboy/blob/master/guide/req.md#reducing-the-memory-footprint | + | * cowboy 可以适当缩减请求对象大小,如果你确定后面不再使用,来释放内存,参考 [https://github.com/YuyaYumoto/cowboy/blob/master/guide/req.md#reducing-the-memory-footprint reducing-the-memory-footprint ] |
<pre> | <pre> | ||
第43行: | 第44行: | ||
== 优化 == | == 优化 == | ||
− | * 对于 docker 容器,开启 SMP 情况下应该设置调度器数量,因为虚拟化会导致容器内启动了过多调度器, | + | * 对于 docker 容器,开启 SMP 情况下应该设置调度器数量,因为虚拟化会导致容器内启动了过多调度器, <pre>+S 4 </pre> 设置为 4个。 |
* 增大 process 和 ets 上限: | * 增大 process 和 ets 上限: | ||
第51行: | 第52行: | ||
</pre> | </pre> | ||
− | * 通过 | + | * 通过 <pre>:erlang.system_info/1</pre> 来观察内存、进程等状况。 |
− | * GenServer 的消息处理应当尽量快,避免将 IO | + | * GenServer 的消息处理应当尽量快,避免将 IO 操作放在其中,可以异步化,然后将请求结果更新回去 GenServer 即可。 |
* 定时器采用 :erlang.send_after 配合 GenServer.handle_info 来处理。 | * 定时器采用 :erlang.send_after 配合 GenServer.handle_info 来处理。 | ||
* 对于负载较高,或者较为核心的 process,可以配置 process,比如优先级,堆大小等: | * 对于负载较高,或者较为核心的 process,可以配置 process,比如优先级,堆大小等: | ||
第62行: | 第63行: | ||
min_heap_size: 1024*1024]) | min_heap_size: 1024*1024]) | ||
</pre> | </pre> | ||
− | * | + | |
+ | 当然也可以采用 poolboy 都池化方案。 | ||
+ | |||
+ | * 测试来看,HTTP 库 ibrowse 的性能比 hackney 更好,也就是 HTTPotion 比 HTTPoison 表现更为优秀,两者都需要设置连接池大小: | ||
+ | |||
+ | <pre> | ||
+ | :ibrowse.set_dest(host, port, [{:max_sessions, 750}, | ||
+ | {:max_pipeline_size, 1}]) | ||
+ | |||
+ | :hackney_pool.start_pool(:pool, | ||
+ | [timeout: 15000, | ||
+ | max_connections: 1000]) | ||
+ | </pre> | ||
+ | |||
+ | * 日志对性能的影响很大,生产环境一定不要开启 debug,至少 INFO 级别。如果不想输出 phoenix 的 route 访问日志,可以从 lib 里的 Endpoint 移除 plug Plug.Logger,在想要输出的 scope 里再加回去。 | ||
== 其他 == | == 其他 == | ||
第72行: | 第87行: | ||
</pre> | </pre> | ||
− | * 使用 | + | * 使用 <pre>bin/$app remote_console </pre> 来连上正在运行的 erl 进程,不要使用 attach,在退出的时候会导致进程退出。而 remote_console 不会,可以用 ctrl +c 退出。 |
2016年12月23日 (五) 07:58的最后版本
目录 |
[编辑] 日志
config :logger, backends: [{LoggerFileBackend, :error_log}] config :logger, :error_log, path: "/mnt/avos/logs/pier/pier.log", level: :info
[编辑] 打包和部署
- 生产环境记得开启: config :phoenix, :serve_endpoints, true
- 使用 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])
当然也可以采用 poolboy 都池化方案。
- 测试来看,HTTP 库 ibrowse 的性能比 hackney 更好,也就是 HTTPotion 比 HTTPoison 表现更为优秀,两者都需要设置连接池大小:
:ibrowse.set_dest(host, port, [{:max_sessions, 750}, {:max_pipeline_size, 1}]) :hackney_pool.start_pool(:pool, [timeout: 15000, max_connections: 1000])
- 日志对性能的影响很大,生产环境一定不要开启 debug,至少 INFO 级别。如果不想输出 phoenix 的 route 访问日志,可以从 lib 里的 Endpoint 移除 plug Plug.Logger,在想要输出的 scope 里再加回去。
[编辑] 其他
- tzdata 这个库会在发现有新版本的时候自动去更新,在国内经常超时,没有必要。关闭 tzdata 更新:
config :tzdata, :autoupdate, :disabled
- 使用
bin/$app remote_console
来连上正在运行的 erl 进程,不要使用 attach,在退出的时候会导致进程退出。而 remote_console 不会,可以用 ctrl +c 退出。