ranch 源码分析(二)

接上ranch 源码分析(一)

上次讲到了ranch.erl的start_listener函数,下面我们详细分析下这个函数

-module(ranch).

%...... 省略若干行

-spec start_listener(ref(), non_neg_integer(), module(), any(), module(), any())
    -> supervisor:startchild_ret().
start_listener(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts)
        when is_integer(NbAcceptors) andalso is_atom(Transport)
        andalso is_atom(Protocol) ->
    _ = code:ensure_loaded(Transport),
    %% @todo Remove in Ranch 2.0 and simply require ssl.
    _ = ensure_ssl(Transport),
    case erlang:function_exported(Transport, name, 0) of
        false ->
            {error, badarg};
        true ->
            Res = supervisor:start_child(ranch_sup, child_spec(Ref, NbAcceptors,
                    Transport, TransOpts, Protocol, ProtoOpts)),
            Socket = proplists:get_value(socket, TransOpts),
            case Res of
                {ok, Pid} when Socket =/= undefined ->
                    %% Give ownership of the socket to ranch_acceptors_sup
                    %% to make sure the socket stays open as long as the
                    %% listener is alive. If the socket closes however there
                    %% will be no way to recover because we don't know how
                    %% to open it again.
                    Children = supervisor:which_children(Pid),
                    {_, AcceptorsSup, _, _}
                        = lists:keyfind(ranch_acceptors_sup, 1, Children),
                    %%% Note: the catch is here because SSL crashes when you change
                    %%% the controlling process of a listen socket because of a bug.
                    %%% The bug will be fixed in R16.
                    catch Transport:controlling_process(Socket, AcceptorsSup);
                _ ->
                    ok
            end,
            Res
    end.


%...... 省略若干行

-spec child_spec(ref(), non_neg_integer(), module(), any(), module(), any())
    -> supervisor:child_spec().
child_spec(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts)
        when is_integer(NbAcceptors) andalso is_atom(Transport)
        andalso is_atom(Protocol) ->
    %% @todo Remove in Ranch 2.0 and simply require ssl.
    _ = ensure_ssl(Transport),
    {{ranch_listener_sup, Ref}, {ranch_listener_sup, start_link, [
        Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts
    ]}, permanent, infinity, supervisor, [ranch_listener_sup]}.

%...... 省略若干行

可以看到在ranch的start_listener中,首先查看Transport模块(传输层模块,这里是ranch_tcp)是否载入,

如果正常载入就启动ranch_listener_sup:start_link/6为ranch_sup的子进程

supervisor:start_child不明白的可以参考 [Erlang 0030] 理解Erlang/OTP Supervisor

 

下面我们查看ranch_listener_sup.erl

-module(ranch_listener_sup).
-behaviour(supervisor).

-export([start_link/6]).
-export([init/1]).

-spec start_link(ranch:ref(), non_neg_integer(), module(), any(), module(), any())
    -> {ok, pid()}.
start_link(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) ->
    MaxConns = proplists:get_value(max_connections, TransOpts, 1024),
    ranch_server:set_new_listener_opts(Ref, MaxConns, ProtoOpts),
    supervisor:start_link(?MODULE, {
        Ref, NbAcceptors, Transport, TransOpts, Protocol
    }).

init({Ref, NbAcceptors, Transport, TransOpts, Protocol}) ->
    AckTimeout = proplists:get_value(ack_timeout, TransOpts, 5000),
    ConnType = proplists:get_value(connection_type, TransOpts, worker),
    Shutdown = proplists:get_value(shutdown, TransOpts, 5000),
    ChildSpecs = [
        {ranch_conns_sup, {ranch_conns_sup, start_link,
                [Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol]},
            permanent, infinity, supervisor, [ranch_conns_sup]},
        {ranch_acceptors_sup, {ranch_acceptors_sup, start_link,
                [Ref, NbAcceptors, Transport, TransOpts]},
            permanent, infinity, supervisor, [ranch_acceptors_sup]}
    ],
    {ok, {{rest_for_one, 1, 5}, ChildSpecs}}.

这里-behaviour(supervisor),就是典型的supervisor类型模块

启动了ranch_conns_sup和ranch_acceptors_sup 2个进程

这是ranch的主要工作模块才慢慢显露出来,下次我们重点分析这2个模块(未完待续...)

 

posted @ 2016-05-09 13:33  土豆008  阅读(579)  评论(0编辑  收藏  举报