文章参考自:
https://www.cnblogs.com/tudou008/p/5484911.html
https://www.cnblogs.com/fvsfvs123/p/4178117.html
https://blog.csdn.net/eeeggghit/article/details/83507563
https://blog.csdn.net/huang1196/article/details/38401197

version: release 1.3.2

Part 1: 进程结构和启动流程

作为独立application启动后,进程结构图如下:
Ranch浅析

未命名进程标识:

  1. <0.97.0>: ranch_app
  2. <0.103.0>: ranch_listerner_sup
  3. <0.104.0>: ranch_conn_sup
  4. <0.105.0>: ranch_acceptors_sup

作为独立application启动流程:

Created with Raphaël 2.2.0ranch_app:start()ranch_app:start()ranch_supranch_app:start()ranch_server:start_link()ranch_server

然后在自己的application中调用

Created with Raphaël 2.2.0ranch:start_listener()ranch_sup:start_child(ranch_acceptor)supervisor:start_child(ranch_sup, ranch_listener_sup)ranch_listener_sup:start_child(ranch_conns_sup, ranch_acceptors_sup)ranch_acceptors_sup(启动NumAcceptors个ranch_acceptors监听listen_socket).

需要了解的api:

  1. supervisor:start_link() 启动一个监督进程
  2. supervisor:start_child() 在指定监督进程下,启动一个子进程
  3. gen_tcp:controlling_process() 将指定socket的控制权转移给指定的进程

Part2: 代码细节

  1. gen_tcp:accept 得到socket的active 属性是 {active, false}, 这种情况下要接收socket的消息, 方法只有手动调用 gen_tcp:recv 阻塞等待消息到来. (tcp_echo例子), 要么 inet:setopt(Socket, [{active, once}]. 这样每当有消息到来,就会通知进程(仅一次, 处理完消息后,下次仍需手动设置为 [{active,once}]).

  2. tcp_reverse例子中,ProtocolProc是gen_server行为, gen_server:start_link需要把Mod:init调用完毕后,才算启动完成,返回{ok, Pid}, 那么在Mod:init中调用了 ranch:accept_ack, 会处于一直等待shoot消息,而shoot消息需要ProtocolProc进程启动者,ranch_conn_sup发送,但ranch_conn_sup又无法获取到ProtocolProcPid,所以不能发送消息,两个进程处于互相等待状态 . 所以官方给出解决方法是 Mod:start_link函数体内,使用 proc_lib:spawn_link 启动ProcotolProc,马上返回Pid到ranch_conn_sup, 然后调用Mod:init函数,等待shoot消息到来,之后再调用 gen_server:enter_loop , 状态进入gen_server:loop函数中,表现与正常的gen_server一样.

  3. tcp_reverse例子中, 消息处理完毕后,返回结果第三个参数传入超时时间,这样5秒后进程无消息到达则会收到 timeout 消息,返回 {stop, normal, State} 进入关闭进程处理.

  4. ranch_server进程本质上是一个管理各个连接实例Ref的角色,拥有一张Ets表,存储的信息有
    ①. {conns_sup, Ref}: 实例的ranch_conns_sup进程Pid
    ②. {addr, Ref}: 实例的inet:sockname(ListenSocket)信息
    ③. {max_conns, Ref}: 实例的最大连接数
    ④. {opts, Ref}: 实例的传输层参数(TransOpt}.
    实例启动和停止都会涉及ranch_server信息修改, 有了ranch_server这些基础工作,ranch才能实现多实例管理.

  5. 应用到自己的项目,注意要修改Opts参数,主要是 {port,max_connections} 这两个参数.
    ranch_tcp的opt的所有可选参数在 ranch_tcp文件头部可见,ranch_ssl的opt则在ranch_ssl文件头部可见.

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-02-09
  • 2022-12-23
  • 2022-12-23
  • 2021-12-05
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-20
相关资源
相似解决方案