多个 gen_esme 会话

Multiple gen_esme sessions

相信你们都做得很好。

我正在尝试使用 OSERL 应用程序与 SMSC 建立多个会话。 由于要创建 SMPP 客户端,您需要继承 gen_esme 行为。

我想知道是否可以在不编写多个 gen_esme 模块的情况下与 SMSC 建立多个连接?

使用相同的 gen_esme 模块启动多个进程有两种主要策略:

  1. gen_esme:start_link/4 - 基于命名或引用的服务器
  2. gen_esme:start_link/3 - 基于 pid 的服务器

我将引用 sample_esme file found under the examples for oserl

命名服务器

大多数示例来自 oserl show usage of gen_esme:start_link/4 which in turn is calling gen_server:start_link/4gen_server:start_link/4ServerName 变量具有 {local, Name::atom()} | {global, GlobalName::term()} | {via, Module::atom(), ViaName::term()}.

的类型规范

这意味着如果我们将 sample_esme:start_link/0,1,2 函数更改为如下所示:

start_link() ->
    start_link(?MODULE).

start_link(SrvName) ->
    start_link(SrvName, true).

start_link(SrvName, Silent) ->
    Opts = [{rps, 1}, {queue_file, "./sample_esme.dqueue"}],
    gen_esme:start_link({local, SrvName}, ?MODULE, [Silent], Opts).

我们可以使用以下方式启动多个服务器:

sample_esme:start_link().           %% SrvName = 'sample_esme'
sample_esme:start_link(my_client1). %% SrvName = 'my_client1'
sample_esme:start_link(my_client2). %% SrvName = 'my_client2'

为了使我们的 sample_esme 模块与此命名服务器策略一起正常工作,需要修改其大部分调用函数。我们以sample_esme:rps/0,1为例:

rps() ->
    rps(?MODULE).

rps(SrvName) ->
    gen_esme:rps(SrvName).

现在我们可以在任何 运行 服务器上调用 gen_esme:rps/1 函数:

sample_esme:rps().           %% calls 'sample_esme'
sample_esme:rps(my_client1). %% 'my_client1'
sample_esme:rps(my_client2). %% 'my_client2'

这类似于 pooler 等项目引用其创建的池成员的方式。

pid 服务器

这与命名服务器策略基本相同,但我们只是传递服务器的 pid 而不是注册的原子。

这意味着如果我们将 sample_esme:start_link/0,1 函数更改为如下所示:

start_link() ->
    start_link(true).

start_link(Silent) ->
    Opts = [{rps, 1}, {queue_file, "./sample_esme.dqueue"}],
    gen_esme:start_link(?MODULE, [Silent], Opts).

请注意,我们所做的只是删除 {local, SrvName} 参数,因此它不会使用服务器的 pid 注册 SrvName 原子。

这意味着我们需要捕获每个创建的服务器的 pid:

{ok, Pid0} = sample_esme:start_link().
{ok, Pid1} = sample_esme:start_link().
{ok, Pid2} = sample_esme:start_link().

使用命名服务器中相同的 sample_esme:rps/0,1 示例,我们需要删除 sample_esme:rps/0 并添加一个 sample_esme:rps/1 函数,该函数接受 pid:

rps(SrvPid) ->
    gen_esme:rps(SrvPid).

现在我们可以在任何 运行 服务器上调用 gen_esme:rps/1 函数:

sample_esme:rps(Pid0).
sample_esme:rps(Pid1).
sample_esme:rps(Pid2).

这类似于 poolboy 等项目引用其创建的池成员的方式。

建议

如果您只是想将连接集中在一起,我建议您使用像 poolerpoolboy.

这样的库

如果您想要按名称引用有限数量的特定命名的连接,我建议只为每个连接设置一个带有子规范的主管:

{my_client1,
    {sample_esme, start_link, [my_client1]},
    permanent, 5000, worker, [sample_esme]}