Ranch模块的作用是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。 ranch_listener_sup模块介绍此模块是ranch调用的一个模块,用来处理所有的监听和网络连接中心。 该模块的创建时由ranch:start_listener函数启动的基于监督者进程ranch_sup的子进程 功能函数介绍erlang的map结构 #{},#{name =>"test"} 注意区分两种表达式: =>(可以用来更新映射和创建新的映射) :=(只能更新映射,在键不存在时会抛出异常) start_link:创建supervisor进程,并且将创建这个进程的参数保存到ranch_server中。 1.Ref 监听者实例别名 2.Transport socket进程的创建者 3.protocol 实际的功能执行者 init:ranch_listener_sup进程创建成功的调用函数。 主要做了下面的事情: 1.创建子进程ranch_conns_sup,传入的参数有Ref,Transport,Protocol三个。这个进程的功能是管理所有的外部连接。 2.创建子进程ranch_acceptors_sup,传入参数是Ref,Transport(可选两种:tcp,ssl).这个进程就是实际的对外端口监听者 3.将该进程的{Ref,self()(自己的进程pid)}存入到ranch_server 4.进程是以reset_for_one的方式启动这两个进程,则表明这两个进程是有依赖关系的。如果ranch_conns_sup挂了,则一定也会挂掉ranch_acceptors_sup,然后重新一次重启这两个进程 5.实际中,ranch_acceptors_sup的启动是依赖ranch_conns_sup进程的,所以,必须ranch_conns_sup进程必须先启动
ranch_conns_sup模块介绍接受socket连接的进程,创建Protocol进程,并且监控这些进程的退出 功能函数介绍start_link:这个进程必须的,因为该进程是以supervisor创建的子进程,必须有此函数。 该进程不是gen_server的标准,而是采用原始的proc_lib:start_link创建的进程,传入的参数包括 父进程id,Ref,Transport,Protocol init:通过start_link函数调用本模块的init函数。 该函数做了一下的功能: 1.设置process_flag(trap_exit,true),标识是可以接受link模块的退出信息 2.设置{Ref,self()}到ranch_server保存数据 3.从ranch_server和TransOpts中获取相应的初始化信息,并保存到loop循环的#state中 4.proc_lib:init_ack(Parent, {ok, self()}) 这是是内部的proc_lib的实现,标识告诉父进程,进程创建成功了,并会返回给父进程一个{ok,Pid(当前创建进程的pid)} loop:执行主要的逻辑 1.{?MODULE,start_protocol, To, Socket}:socket收到连接,发送该进程,创建Protocol进程。在此进程创建的时候需要注意,实例进程创建进程的返回值一定要注意,{ok, Pid}表示自己对自己进程关闭负责,而{ok,SupPid,ProtocolPid}则表示,该进程是有一个conns_sup进程来管理这些启动的进程。此处ranch是提供了两种方法来处理。 2.{?MODULE,active_connections,To,Tag}:获取该进程激活的连接数 3.{remove_connection, Ref,Pid}:移除连接,此处注意,当前只是计数减一,并没有真正的关闭进程 4.{set_max_conns}:重新设置最大的连接数,如果sleeper里面有数据,则会将这些链接重新启用 5.{‘EXIT’,Parent,Reason}:此处Parent指的是ranch_listener_sup进程,如果父进程关闭,则无条件的关闭启动的所有连接进程 6.{'EXIT',Pid,Reason}:link的进程关闭了,则清理pid.此处要注意,该进程link的pid不能设置process_flag(trap_exit,true),负责就不会收到此断开信息。如果有睡眠的连接进程等待,则激活这些连接进程。 7.{system,From,Request}:调用系统的指令.gen_server的terminate,code_change函数都和此有关系。目前看到的支持3中大类,1.suspended 挂起 2.running 获取一些模块的信息 3.terminating 关闭进程 8.{'$gen_call', {To, Tag}, Request(which_children,count_children)}:To:标识是From,即发起者的进程pid,Tag=erlang:monitor(process,Process)即发起者监听接受方的MRef信息,在收到信息后,取消monitor,并返回信息。并且此种请求时通过同步的方式请求。具体的调用方法是:gen_server:call(SupPid,which_children)的方式请求 start_protocol:此方法由socket进程发起,同步创建实例,执行loop的第一种情况 active_connections:同步请求活跃的连接数,和loop的第8中情况相似,也可以已第8种情况替代 handshake:此方法大调用于loop的第1中情况,将启动的实例进程pid和socket进行绑定。并且验证,启动实例。如果当前的连接数已满,则阻塞住socket进程。如果条件满足,则确认绑定成功。 terminate(#stat{shutdown=brutal_kill},Reason,):关闭此进程,此函数是有system触发的,system_terminate()函数调用terminate,直接结束。brutal_kill标识是直接kill掉。 terminate(#state{shutdown=integer()}):表示是非直接关闭,等待进程的自我了断。 kill_children:直接杀死进程,杀死前unlinke(Pid),避免收到进程杀死的信息 shutdown_children,wait_children:这两个函数时相互配合使用的,在exit(P,shutdown)成功时,会收到wait_children的{‘DOWN,,process,Pid,’}的信息,显示的知道有多少个进程被中断。 system_continue,system_terminate,system_code_change:这三个函数,是配合system的命令在sys模块默认调用的,目前来看,主要有3个功能,system_continue:用来获取一些进程的信息;system_terminate:用来系统中断进程;system_code_change:用来进程一些数据的更新处理 report_error:对错误写日志记录
ranch_acceptors_sup 连接接受监督者模块介绍设置监听socket,将此socket同时分发给ranch_accpetor 接受者,监听连接 函数分析%% 通过设置receive after 0,优先处理{alarm,X}的消息。因为在超时时间为0的receive中,会立即触发一个超时,但是在此之前,
系统会尝试对邮箱进行模式匹配,所以此方法,可以对消息优先处理,可以用于清空邮箱中的所有消息。
1.优先匹配例子
priority_receive()->
receive
{alarm,X}->
after 0->
receive
Any->
Any
end
end.
2.清空邮箱所有消息
flush(Logger) ->
receive Msg ->
ranch:log(warning,
"Ranch acceptor received unexpected message: ~p~n",
[Msg], Logger),
flush(Logger)
after 0 ->
ok
end. 节选自gen.erl
do_call(Process, Label, Request, Timeout) ->
try erlang:monitor(process, Process) of
Mref ->
%% If the monitor/2 call failed to set up a connection to a
%% remote node, we don't want the '!' operator to attempt
%% to set up the connection again. (If the monitor/2 call
%% failed due to an expired timeout, '!' too would probably
%% have to wait for the timeout to expire.) Therefore,
%% use erlang:send/3 with the 'noconnect' option so that it
%% will fail immediately if there is no connection to the
%% remote node.
catch erlang:send(Process, {Label, {self(), Mref}, Request},
[noconnect]),
receive
{Mref, Reply} ->
erlang:demonitor(Mref, [flush]),
{ok, Reply};
{'DOWN', Mref, _, _, noconnection} ->
Node = get_node(Process),
exit({nodedown, Node});
{'DOWN', Mref, _, _, Reason} ->
exit(Reason)
after Timeout ->
erlang:demonitor(Mref, [flush]),
exit(timeout)
end
catch
error:_ ->
%% Node (C/Java?) is not supporting the monitor.
%% The other possible case -- this node is not distributed
%% -- should have been handled earlier.
%% Do the best possible with monitor_node/2.
%% This code may hang indefinitely if the Process
%% does not exist. It is only used for featureweak remote nodes.
Node = get_node(Process),
monitor_node(Node, true),
receive
{nodedown, Node} ->
monitor_node(Node, false),
exit({nodedown, Node})
after 0 ->
Tag = make_ref(),
Process ! {Label, {self(), Tag}, Request},
wait_resp(Node, Tag, Timeout)
end
end. 从上面代码中可以看到,是在本地进程monitor了被call的进程,并且erlang:send的方式发送信息,此时再receive一个阻塞等待结果返回,然后再TimeOut的时候,如果还没有返回,则返回给进程exit(timeout)的错误信息。所以,就会出现,虽然timeout了,被调的进程还是会处理完,而不能当作被调进程没有收到处理。 如何避免?:1,从源头避免,确保call的进程处理信息足够简单,不超时 2.采用cast,或 ! 替代处理 参考网址:Erlang中带超时的receive ranch_acceptor模块简介此模块用来接收外部的socket连接。并通知ranch_conns_sup通知业务进程启动并且绑定到该socket进程 函数介绍start_link:次数采用原始的spawn_link函数启动一个进程,返回{ok, Pid} loop:1.通过Transport:accept阻塞进程,直到接收到一个连接进来,然后绑定该连接的socket先到connsSup上,然后调用ranch_conns_sup:start_protocol启动一个实例进程,进行绑定。 {ok, CSocket}:标识连接成功,并且创建了一个连接的socket,进行启动和绑定操作 {error,emfile}:大量的并发操作调用,导致操作系统的文件描述符数量被瞬间用完,抛出emfile.此处应为会同时创建多个连接进程,和多个外部的socket连接,则必然会出现此种情况。在晚上看到过,有人在使用了1024个连接,https之后,就会出现问题,导致连接不成功。贴上网址如下:http://erlang.org/pipermail/erlang-questions/2015-January/082446.html {error,closed}:表明listening socket 关闭了 ?MODULE:loop(_):此方法是可以保证,在版本更新时,总是调用到最新的模块函数 flush:每一次循环是,都清空掉该进程接收到的其他非accepotr消息 关于连接出现{error,emfile}的问题: 1.此错误标识同时创建了多个链接进程,导致操作系统的文件描述符数量被瞬间用完导致。 2.有两种I/O处理,一个异步和一个同步。异步I/O下,这个会比较容易实现,需要给予一定的过载保护,防止过分压榨底层系统的性能。 3.两种方式:1、设置 ulimit -n 10480 2.修改 /etc/security/limit.conf文件的句柄数量 limit.conf
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
* soft nproc 65535
* hard nproc 65535
* soft nofile 65535
* hard nofile 65535
# End of file
4.参考网址: [erlang-questions] {error,emfile} 从EMFILE和ENFILE说起,fd limit的问题(一) EMFILE,too many open files的解决方案 此处记录问题:看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注天达云行业资讯频道,感谢您对天达云的支持。
|