中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Ranch模塊的作用是什么

發布時間:2021-07-30 15:18:12 來源:億速云 閱讀:258 作者:Leah 欄目:大數據

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 接受者,監聽連接

函數分析

  • start_link:啟動進程的入口,使用supervisor的模式啟動進程

  • init:1.獲取連接監督者,獲取Transport的配置信息,更具配置的監聽連接數,通過one_for_one的方式創建一定數量的監聽連接進程,來監聽外部連接

  • recevie 的機制

%% 通過設置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.
  • 拓展:為什么在call一個進程時,timeout了,但是call 的進程也會執行完消息處理?

節選自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的解決方案

此處記錄問題:

  • 1.如果設置cert密匙,客戶端是如何發送的,并且服務器又是如何驗證的

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

盐源县| 江山市| 高碑店市| 阳泉市| 大丰市| 土默特右旗| 察哈| 云梦县| 安庆市| 深泽县| 图们市| 武川县| 龙州县| 民乐县| 资中县| 镇安县| 普兰店市| 南漳县| 岳池县| 嘉义县| 东海县| 宜宾市| 洛隆县| 镇雄县| 牙克石市| 马山县| 滨州市| 富阳市| 铁岭市| 深泽县| 永善县| 商丘市| 常州市| 昌黎县| 石阡县| 监利县| 沽源县| 景泰县| 沈丘县| 卢龙县| 青冈县|