应用 | Application
应用行为
用于处理应用程序和定义应用程序回调的模块。
在Elixir中(实际上,在Erlang/OTP中),应用程序是实现某些特定功能的组件,可以作为一个单元启动和停止,并且可以在其他系统中重用。
应用程序使用名为APP.app
where APP
的应用程序文件来定义,通常位于应用程序名称中underscore_case
。应用程序文件必须ebin
与应用程序的已编译模块位于同一个目录中。在Elixir中,Mix构建工具负责编译您的源代码并生成您的应用程序.app
文件。您可以.app
通过输入来了解更多关于文件生成的信息mix help compile.app
。
编译完应用程序后,运行系统就是启动当前应用程序及其依赖关系的问题。与其他语言不同,Elixir没有main
负责启动系统的程序。相反,您启动一个或多个应用程序,每个应用程序都有自己的初始化和终止逻辑。
启动应用程序是通过“应用程序模块回调”完成的,该应用程序模块回调是定义该start/2
功能的模块。start/2
然后该功能应该启动一个主管,这个主管通常被称为顶级主管,因为它位于可能长的监督树的根部。当系统关闭时,所有应用程序都会关闭其顶级主管,这会按照与启动顺序相反的顺序终止子级。
我们已经提到Mix构建工具负责编译应用程序,但它也能够运行应用程序。例如,mix test
在测试运行之前,自动启动您的应用程序依赖项和您的应用程序本身。mix run --no-halt
也引导您当前的项目,并可用于启动长时间运行的系统。看mix help run
。
开发人员也可以使用Distillery等构建版本的
工具。发行版能够将所有源代码以及Erlang虚拟机打包到一个目录中。发布还可以明确控制每个应用程序的启动顺序和顺序。它们还提供了更简化的机制,用于启动和停止系统,调试,记录以及系统监视。
最后,Elixir提供了诸如escript和archives等工具,这些工具是打包应用程序的不同机制。这些通常用于工具必须在开发人员之间共享而不是部署选项。请参阅mix help archive.build
并mix help escript.build
了解更多细节。
干净地关闭一个实时系统可以通过调用来完成System.stop/1
。它将以与启动相反的顺序关闭所有应用程序。然后,每个应用程序将关闭其顶级主管(如果有),然后关闭其子级。
从Erlang/OTP 19.1开始,操作系统中的SIGTERM将自动转换为System.stop/0
。Erlang / OTP 20通过该:os.set_signal/2
功能为用户提供了更加明确的操作系统信号控制。
应用程序还提供了一个“应用程序环境”,这就是应用程序的配置方式。应用程序环境可以静态设置,也可以通过配置文件设置,也可以通过put_env/3
和朋友动态设置。
在接下来的部分中,我们将更详细地介绍“应用程序环境”和“应用程序模块回调”。
应用环境
一旦应用程序启动,OTP提供了一个可用于配置应用程序的应用程序环境。
假设您在Mix项目中,可以application/0
将该mix.exs
文件中的函数编辑为以下内容:
def application do
[env: [hello: :world]]
end
在应用程序功能中,我们可以为我们的应用程序定义默认环境值。通过启动您的应用程序iex -S mix
,您可以访问默认值:
Application.get_env(:APP_NAME, :hello)
#=> :world
Mix项目中的应用程序和依赖项通常通过config/config.exs
文件进行配置。例如,使用您的应用程序的人可以:hello
按如下方式配置密钥:
config :APP_NAME, hello: :brand_new_world
也可以通过动态配置应用程序put_env/3
。
请记住,每个应用程序都对其环境负责。不要使用本模块中的函数来直接访问或修改其他应用程序的环境(因为它可能会导致应用程序环境中的数据不一致)。
应用模块回调
很多时候,应用程序定义了一个监督树,当应用程序启动和停止时,监督树必须启动和停止。为此,我们需要定义一个应用程序模块回调。第一步是在mix.exs
文件的应用程序定义中定义模块回调:
def application do
[mod: {MyApp, []}]
end
我们的应用程序现在需要MyApp
模块提供应用程序回调。这可以通过use Application
在该模块中调用并定义start/2
回调来完成,例如:
defmodule MyApp do
use Application
def start(_type, _args) do
MyApp.Supervisor.start_link()
end
end
start/2
通常返回{:ok, pid}
或{:ok, pid, state}
何地pid
标识监督树和state
是应用程序状态。args
元组的第二个元素。:mod
选择。
type
传递给的参数start/2
通常是:normal
除非在分布式设置中配置了应用程序接管和故障转移。分布式应用程序超出了本文档的范围。对于那些对这个主题感兴趣的人,请访问OTP文档:
:application
模块
开发人员也可以实现stop/1
回调(由自动定义use Application
)来完成任何应用程序清理。它接收应用程序状态并可以返回任何值。请注意,关闭管理员由虚拟机自动处理。
没有监督树的应用程序不会在mix.exs
文件中的应用程序定义中定义应用程序模块回调。即使没有模块带有应用程序回调,例如start/2
和stop/1
,应用程序也可以像使用监督树的应用程序一样启动和停止。
摘要
类型
app()key()start_type()state()value()
函数
app_dir(app)
获取app的目录。
app_dir(app, path)
返回里面的给定路径 app_dir/1
delete_env(app, key, opts \ [])
key
从给定的app
环境中删除
ensure_all_started(app, type \ :temporary)
确保给定app
及其应用程序已启动
ensure_started(app, type \ :temporary)
确保给定app
已启动
fetch_env(app, key)
返回值key
的app
元组中的环境
fetch_env!(app, key)
返回key
in app
环境中的值
format_error(reason)
格式错误原因被返回start/2
,ensure_started/2
,stop/1
,load/1
和unload/1
,返回一个字符串
get_all_env(app)
返回所有的键值对 app
get_application(module)
获取给定模块的应用程序
get_env(app, key, default \ nil)
返回key
in app
环境中的值
load(app)
加载给定的 app
loaded_applications()
返回一个包含已加载应用程序信息的列表
put_env(app, key, value, opts \ [])
把value
在key
对于给定的app
spec(app)
返回规格 app
spec(app, key)
返回值key
中app
的规范
start(app, type \ :temporary)
启动给定的app
started_applications(timeout \ 5000)
返回包含当前正在运行的应用程序的信息的列表。
stop(app)
停止给定的app
unload(app)
卸载给定的app
回调
start(start_type, start_args)
在启动应用程序时调用
start_phase(phase, start_type, phase_args)
在同步阶段启动应用程序
stop(state)
在应用程序停止时调用
类型
app()
app() :: atom
key()
key() :: atom
start_type()
start_type() :: :permanent | :transient | :temporary
state()
state() :: term
value()
value() :: term
函数
app_dir(app)
app_dir(app) :: String.t
获取应用程序的目录。
该信息基于代码路径返回。这里是一个例子:
File.mkdir_p!("foo/ebin")
Code.prepend_path("foo/ebin")
Application.app_dir(:foo)
#=> "foo"
即使目录是空的并且没有.app
文件,它也被认为是基于名称“foo / ebin”的应用程序目录。该名称可能包含一个-
被认为是应用程序版本的短划线,并且为了查找目的将其删除:
File.mkdir_p!("bar-123/ebin")
Code.prepend_path("bar-123/ebin")
Application.app_dir(:bar)
#=> "bar-123"
有关代码路径的更多信息,请查看Code
Elixir中的:code
模块以及Erlang的模块。
app_dir(app, path)
app_dir(app, String.t | [String.t]) :: String.t
返回里面的给定路径app_dir/1
。
delete_env(app, key, opts \ [])
delete_env(app, key, [timeout: timeout, persistent: boolean]) :: :ok
key
从给定的app
环境中删除。
请参阅有关put_env/4
选项的说明。
ensure_all_started(app, type \ :temporary)
ensure_all_started(app, start_type) ::
{:ok, [app]} |
{:error, {app, term}}
确保给定app
及其应用程序已启动。
同start/2
也开始在列出的应用程序:applications
中.app
的文件的情况下,他们以前都没有启动。
ensure_started(app, type \ :temporary)
ensure_started(app, start_type) :: :ok | {:error, term}
确保给定app
已经开始了。
与应用程序已启动时相同,start/2
但返回:ok
。这在测试应用程序需要明确启动的脚本和测试设置中非常有用:
:ok = Application.ensure_started(:my_test_dep)
fetch_env(app, key)
fetch_env(app, key) :: {:ok, value} | :error
返回值key
中app
的环境中的元组。
如果配置参数不存在,则函数返回:error
。
fetch_env!(app, key)
fetch_env!(app, key) :: value | no_return
返回key
在app
环境。
如果配置参数不存在,则引发ArgumentError
。
format_error(reason)
format_error(any) :: String.t
格式化返回的错误原因start/2
,ensure_started/2
,stop/1
,load/1
和unload/1
,返回一个字符串。
get_all_env(app)
get_all_env(app) :: [{key, value}]
返回所有的键值对app
。
get_application(module)
get_application(atom) :: atom | nil
获取给定模块的应用程序。
该应用程序通过分析所有加载的应用程序的规格来定位。如果模块未在任何应用程序规范中列出,则返回nil
。
get_env(app, key, default \ nil)
get_env(app, key, value) :: value
返回key
in app
环境中的值。
如果配置参数不存在,则该函数返回default
值。
load(app)
load(app) :: :ok | {:error, term}
加载给定的app
。
为了加载,.app
文件必须位于加载路径中。所有:included_applications
也将被加载。
加载应用程序不会启动,也不会加载它的模块,但它会加载它的环境。
loaded_applications()
loaded_applications() :: [tuple]
返回一个包含已加载应用程序信息的列表。
put_env(app, key, value, opts \ [])
put_env(app, key, value, [timeout: timeout, persistent: boolean]) :: :ok
放value
中key
对于给定的app
。
备选方案
:timeout
- 更改超时(默认为5_000
毫秒)
:persistent
- 在应用程序加载和重新加载时保持给定的值
如果put_env/4
在加载应用程序之前调用,则.app
文件中指定的应用程序环境值将覆盖先前设置的应用程序环境值。
如果true
需要保证使用此函数设置的参数不会被加载时应用程序资源文件中定义的参数覆盖,则可以将持久性选项设置为。这意味着在加载应用程序和应用程序重新加载之后,持久值将保持不变。
spec(app)
spec(app) :: [{key, value}] | nil
返回规格app
。
以下键被返回:
- :description
- :id
- :vsn
- :modules
- :maxP
- :maxT
- :registered
- :included_applications
- :applications
- :mod
- :start_phases
注意环境不会被返回,因为它可以通过访问fetch_env/2
。nil
如果应用程序未加载,则返回。
spec(app, key)
spec(app, key) :: value | nil
返回key
在app
的规格。
请参阅spec/1
支持的键。如果给定的规格参数不存在,则此函数将会升起。nil
如果应用程序未加载,则返回。
start(app, type \ :temporary)
start(app, start_type) :: :ok | {:error, term}
开始给定app
。
如果app
未加载,应用程序将首先使用加载load/1
。任何包含:included_applications
在.app
文件的关键字中的应用程序也将被加载,但它们不会被启动。
此外,:applications
密钥中列出的所有应用程序必须在此应用程序之前明确启动。如果不是,{:error, {:not_started, app}}
则返回,app
缺失应用程序的名称在哪里。
如果您想自动加载并启动
所有app
的依赖关系,请参阅ensure_all_started/2
。
type
参数指定应用程序的类型:
:permanent
- 如果app
终止,所有其他应用程序和整个节点也终止。
:transient
- 如果app
以:normal
理由终止,则会被报告,但不会终止其他应用程序。如果临时应用程序异常终止,则所有其他应用程序和整个节点也终止。
:temporary
- 如果app
终止,则会报告,但不会终止其他应用程序(默认)。请注意,始终可以通过调用明确停止应用程序stop/1
。无论应用程序的类型如何,其他应用程序都不会受到影响。请注意,该:transient
类型实际使用很少,因为监督树终止时,原因设置为:shutdown
,而不是:normal
.started_app
lications(timeout \ 5000)started_app
lications(timeout ):: [tuple]返回一个列表,其中包含当前正在运行的应用程序的信息.stop(app
)stop(app
):::ok | {:error,term}停止给定app
。当停止时,应用程序仍然是被加载的。unload(app
)unload(app
):::ok | {:错误,术语}卸载给定的。app
它也将卸载所有:included_applications
。请注意,函数不会清除应用程序模块.Callbacksstart(start_type
,start_args)start(start_type
,start_args :: term):: {:ok,pid} | {:ok,pid,state} | {:error,reason :: term}当应用程序启动时调用。当一个应用程序开始使用Application.start/2
(以及其他功能)时调用此函数Application.ensure_started/2
。这个功能应该启动应用程序的顶层过程(如果应用程序遵循监督的OTP设计原则,应该是应用程序监督树的最高管理者)。start_type
定义应用程序的启动方式:
:normal
- 如果启动是正常启动,或者由于从另一个节点和应用程序规范密钥进行故障转移而分发并在当前节点上启动应用程序,:start_phases
则使用此选项:undefined
。
{:takeover, node}
- 如果由于节点上的故障转移而分发应用程序并在当前节点上启动应用程序时使用node
。
{:failover, node}
- 如果应用程序是分布式的,并且由于节点上的故障转移而在当前节点上启动node
,并且应用程序规范密钥:start_phases
不是,则使用它:undefined
。
start_args
是在:mod
规范键(例如,mod: {MyApp, [:my_args]}
)中传递给应用程序的参数。
这个函数应该返回,{:ok, pid}
或者{:ok, pid, state}
如果启动成功。pid
应该是最高管理者的PID。state
可以是任意的,如果省略则默认为[]
; 如果应用程序稍后停止,state
则传递给stop/1
回调函数(stop/1
有关更多信息,请参阅回调文档)。
use Application
没有提供start/2
回调的默认实现。
start_phase(phase, start_type, phase_args) (optional)
start_phase(phase :: term, start_type, phase_args :: term) ::
:ok |
{:error, reason :: term}
以同步阶段启动应用程序。
此函数在start/2
完成后但在Application.start/2
返回之前调用。它将在应用程序(和任何包含的应用程序)规范中定义的每个开始阶段被调用一次,按其列出的顺序。
stop(state)
stop(state) :: term
当应用程序停止时调用。
该功能在应用程序停止时调用,即其监控树已停止。它应该与start/2
回调所做的相反,并且应该执行任何必要的清理。此回调的返回值将被忽略。
state
是应用程序模块定义这种函数时start/2
回调的返回值或prep_stop/1
函数的返回值。
use Application
定义了这个函数的默认实现,它什么都不做,只是返回:ok
。