ranch 源码分析(二)

摘要:
接上ranch源码分析(一)上次讲到了ranch.erl的start_listener函数,下面我们详细分析下这个函数-module(ranch).%......省略若干行-specstart_listener(ref(),non_neg_integer(),module(),any(),module(),any())-˃supervisor:startchild_ret().start_list

接上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) andalsois_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.
                    catchTransport: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) andalsois_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个模块(未完待续...)

免责声明:文章转载自《ranch 源码分析(二)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇python基础 时间和日期的处理EF里一对一、一对多、多对多关系的配置和级联删除下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

RF(一)RF的安装步骤

7.安装Appium 8,安装最新版本的nodeJS:node-v6.9.49,在命令行上执行Appium命令,您应该能够启动Appium服务器~~~~...

tabsSwiper 全屏选项卡(uniapp-uView)

完整代码˂swiper:current="swiperCurrent"@transitio...

NodeJs使用jwt生成token以及使用express-jwt校验和解密token

=0){//当数据库有当前用户时,它返回tokenlettoken=jwt.sign;res.send}else{res.send}}catch{//p抛出异常并将其发送到错误中间件以处理console.log;next;}})//注册接口路由器。post('/register',异步(req,res,next)=˃{let{用户名,密码,昵称}=req-b...

ArcGIS Server服务状态正在停止。。。问题BUG解决

1、 ArcGISServer服务器存在服务问题:ArcGISServerManager的所有服务都显示为“正在停止…”。N个解决方案1)港口占用问题。端口4000-4002已被其他程序占用,导致服务无法正常启动。您可以通过CMD找到相关PID占用的端口,停止它,然后启动GIS服务。您也可以在安装目录中将其手动更改为D:ProgramFiles ArcGIS...

easyExcel自动合并单元格

importcom.alibaba.excel.write.handler.CellWriteHandler;importorg.apache.poi.ss.usermodel.Sheet;importorg.apache.poi.ss.util.CellRangeAddress;int[]mergeColumnIndex){this.mergeRowInd...

最新版Swagger 3升级指南和新功能体验!

因此,本期将为您带来一篇关于Swagger最新版本的文章。本文将向您展示Swagger最新版本的变化?如何将旧版本的Swagger升级到新版本?Swagger是一个用于生成、描述和调用RESTful接口的Web服务。Swagger 2.9.2的使用分为以下四个步骤:添加依赖项、启用Swagger功能、配置Swagger文档摘要信息和调用接口访问。让我们分别来...