【问题标题】:how to use gun:open in a gen_server module如何使用 gun:open 在 gen_server 模块中
【发布时间】:2019-02-24 15:26:59
【问题描述】:

我有一个 gen_server 模块,我使用 gun 作为 http 客户端与 http 服务器建立长拉连接,所以我在模块的 init 中调用 gun:open,但是如果 gun:open 失败,我的模块失败,所以我的应用程序无法启动。这样做的正确方法是什么。以下是我的代码:

init() ->
    lager:debug("http_api_client: connecting to admin server...~n"),
    {ok, ConnPid} = gun:open("localhost", 5001),
    {ok, Protocol} = gun:await_up(ConnPid),
    {ok, #state{conn_pid = ConnPid, streams = #{},protocol =  Protocol}}.

【问题讨论】:

  • 具体错误是什么?你的代码看起来不错。我也使用 gun 编写了一个 http 客户端。也许这个例子会有所帮助:) github.com/zhongwencool/eetcd/blob/master/src/…
  • 嘿,我是github.com/amark/gun的作者,我很困惑,这和我们有关吗?列出的几个命令与我们的 API 匹配,有人将 GUN 移植到 erlang 吗?或者有没有一个名为 gun 的 Erlang 项目?
  • @marknadal 这是一个无关的 Erlang 项目,一个 HTTP 客户端 :) github.com/ninenines/gun

标签: erlang erlang-otp gun


【解决方案1】:

基本上,您有两个选择:您的进程需要 HTTP 服务器可用(您当前的解决方案),或者它不可用,并在与 HTTP 服务器的连接正常关闭时处理请求(通过返回错误响应) .这篇博文更雄辩地展示了这个想法:https://ferd.ca/it-s-about-the-guarantees.html

您可以通过将此代码分离到一个单独的函数中来做到这一点,如果连接失败,该函数也不会崩溃:

try_connect(State) ->
    lager:debug("http_api_client: connecting to admin server...~n"),
    case gun:open("localhost", 5001) of
        {ok, ConnPid} ->
            {ok, Protocol} = gun:await_up(ConnPid),
            State#state{conn_pid = ConnPid, streams = #{},protocol =  Protocol};
        {error, _} ->
            State#state{conn_pid = undefined}
    end.

并从init 调用此函数。也就是不管你能不能连接,你的gen_server都会启动。

init(_) ->
    {ok, try_connect(#state{})}.

然后,当你向这个 gen_server 发出要求连接存在的请求时,检查它是否是undefined

handle_call(foo, _, State = #state{conn_pid = undefined}) ->
    {reply, {error, not_connected}, State};
handle_call(foo, _, State = #state{conn_pid = ConnPid}) ->
    %% make a request through ConnPid here
    {reply, ok, State};

当然,这意味着如果启动时连接失败,您的 gen_server 将永远不会尝试再次连接。您可以添加一个计时器,也可以添加一个显式的reconnect 命令:

handle_call(reconnect, _, State = #state{conn_pid = undefined}) ->
    NewState = try_connect(State),
    Result = case NewState of
                 #state{conn_pid = undefined} ->
                     reconnect_failed;
                 _ ->
                     ok
             end,
    {reply, Result, NewState};
handle_call(reconnect, _, State) ->
    {reply, already_connected, State}.

上面的代码没有处理 gen_server 运行时连接断开的情况。你可以明确地处理它,或者你可以让你的 gen_server 进程在这种情况下崩溃,以便它重新启动到“未连接”状态。

【讨论】:

  • 它有效。我还需要检查 gun:await_up 的返回值,其他代码都可以。
猜你喜欢
  • 2016-08-21
  • 2017-01-28
  • 2018-10-17
  • 2013-01-22
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多