一、为什么要打包Erlang代码
当你写完一个Erlang应用后,总不能每次都手动启动虚拟机、加载模块吧?我们需要一种标准化的方式,把代码、依赖和配置打包成一个完整的发布包,方便部署到任何环境。这就是Relx的用武之地——它能把你的Erlang项目变成开箱即用的独立包。
举个例子,假设你开发了一个简单的TCP服务器:
%% 技术栈:Erlang/OTP 25 + Relx 4.0
-module(my_tcp_server).
-behaviour(gen_server).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init(_Args) ->
{ok, Port} = application:get_env(my_app, tcp_port),
{ok, ListenSocket} = gen_tcp:listen(Port, [binary, {reuseaddr, true}]),
spawn_link(fun() -> acceptor(ListenSocket) end),
{ok, #{socket => ListenSocket}}.
acceptor(ListenSocket) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn(fun() -> handle_client(Socket) end),
acceptor(ListenSocket).
这样的代码如果直接扔到服务器上运行,光是处理依赖就会让人头疼。
二、Relx基础配置
Relx通过relx.config文件定义打包规则。先看一个最小化配置:
%% relx.config
{release, {my_app, "1.0.0"}, [my_app, sasl]}. % 包含主应用和SASL工具库
{dev_mode, false}. % 生产环境模式
{include_erts, true}. % 嵌入Erlang运行时
关键参数说明:
include_erts:打包时带上Erlang虚拟机,这样目标机器就不需要预装Erlangextended_start_script:生成高级启动脚本,支持热升级等操作sys_config:指定系统配置文件路径
进阶示例添加依赖管理:
{release, {my_app, "1.0.0"}, [
my_app,
cowboy, % HTTP服务依赖
jsone % JSON处理库
]}.
{overlay_vars, "vars.config"}. % 动态变量文件
三、实战打包流程
假设项目结构如下:
my_app/
├── ebin/
├── src/
├── priv/
└── rel/ # Relx输出目录
具体操作步骤:
- 编译项目:
rebar3 compile
- 生成发布包:
rebar3 release
- 打包成tar.gz(适合服务器部署):
rebar3 tar
生成的发布包包含完整目录结构:
_build/prod/rel/my_app/
├── bin/ # 启动脚本
├── erts-12.3/ # Erlang运行时
├── lib/ # 所有依赖库
└── releases/ # 版本元数据
四、高级技巧与陷阱规避
4.1 环境变量注入
通过vm.args和sys.config实现多环境配置:
%% vm.args(JVM参数风格)
-name my_app@127.0.0.1
-setcookie secret
-kernel inet_dist_listen_min 9100
%% sys.config(Erlang术语格式)
[
{my_app, [
{tcp_port, 5566},
{max_connections, 1000}
]},
{kernel, [
{start_timer, true}
]}
].
4.2 常见问题处理
- 依赖冲突:用
rebar3 tree查看依赖树 - 路径问题:
{lib_dirs, ["../deps"]}指定非标准路径 - 版本锁定:在
rebar.lock中固定依赖版本
4.3 热升级实战
假设要从1.0升级到1.1:
# 生成升级包
rebar3 release -n my_app -v 1.1.0 --upfrom 1.0.0
# 部署命令
_build/prod/rel/my_app/bin/my_app upgrade "1.1.0"
五、为什么选择Relx
优势亮点:
- 零配置依赖:自动解析rebar.config中的依赖
- 跨平台:Windows/Linux/macOS输出一致
- 轻量化:基础包通常小于30MB
对比其他工具:
| 工具 | 优点 | 缺点 |
|---|---|---|
| Rebar2 | 兼容老项目 | 已停止维护 |
| Mix | Elixir生态原生支持 | 纯Erlang项目支持有限 |
适用场景:
- 需要交付给客户的闭源项目
- 容器化部署(配合Docker更佳)
- 嵌入式设备等无网络环境
六、总结与最佳实践
- 版本控制:始终在relx.config中指定版本号
- 安全隔离:生产环境务必禁用dev_mode
- 备份策略:保留旧版本包以便回滚
- 监控集成:通过
-config sys.config加载监控配置
完整生产级配置示例:
{release, {my_app, "1.0.0"}, [
my_app,
sasl,
observer % 监控工具
]}.
{include_erts, true}.
{extended_start_script, true}.
{overlay, [
{mkdir, "log"},
{copy, "config/custom.vm.args", "releases/{{release_version}}/vm.args"}
]}.
记住:好的发布包应该像家电一样——插电即用,不需要用户看说明书。
评论