上次讲到了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个模块(未完待续...)