erlang 原生支持rpc

erlang 原生支持rpc(rex)

1.rex 是什么?

rexkernrl进程树第2个启动的进程
主要提供rpc服务,系统的所有rpc远程调用,都会经过rex

2.rex 创建

% kernel.erl
 Rpc = #{id => rex,
                    start => {rpc, start_link, []},
                    restart => permanent,
                    shutdown => 2000,
                    type => worker,
                    modules => [rpc]},
...

3.rex是否是热点?

所有的rpc请求都要经过rex进程,很容易形成热点,
而且是以节点(node)为单位的堵塞,换句话说,如果N个Node同时向同一个Node发起rpc请求,那么所有的消息都在同一个rex进程堆积。
是否有替代方案?有,请参照https://github.com/discordapp/gen_rpc.git

4.rpc:callrpc:block_call的区别

# rpc:call

do_call(Node, Request, infinity) ->
    rpc_check(catch gen_server:call({?NAME,Node}, Request, infinity));
do_call(Node, Request, Timeout) ->
    Tag = make_ref(),
    {Receiver,Mref} =
    erlang:spawn_monitor(
      fun() ->
          %% Middleman process. Should be unsensitive to regular
          %% exit signals.
          process_flag(trap_exit, true),
          Result = gen_server:call({?NAME,Node}, Request, Timeout),
          exit({self(),Tag,Result})
      end),
      % 这里不直接使用 gen_server:call 是因为gen_server:call可能让调用线程崩溃(exit)
      % 但是换句话来说,可以使用catch语句捕获异常,防止错误
      % 这样子还可以节约一个调度
      
    receive
    {'DOWN',Mref,_,_,{Receiver,Tag,Result}} ->
        rpc_check(Result);
    {'DOWN',Mref,_,_,Reason} ->
        %% The middleman code failed. Or someone did 
        %% exit(_, kill) on the middleman process => Reason==killed
        rpc_check_t({'EXIT',Reason})
    end.

handle_call({call, Mod, Fun, Args, Gleader}, To, S) ->
    handle_call_call(Mod, Fun, Args, Gleader, To, S);
...
handle_call_call(Mod, Fun, Args, Gleader, To, S) ->
    %% Spawn not to block the rpc server.
    {Caller,_} =
    erlang:spawn_monitor(
      fun () ->
          set_group_leader(Gleader),
          Reply = 
              %% in case some sucker rex'es 
              %% something that throws
              case catch apply(Mod, Fun, Args) of
              {'EXIT', _} = Exit ->
                  {badrpc, Exit};
              Result ->
                  Result
              end,
          gen_server:reply(To, Reply)
      end),
     % 在目标Node上新开一个proc来处理rpc请求
    {noreply, maps:put(Caller, To, S)}.

% rpc:block_call
handle_call({block_call, Mod, Fun, Args, Gleader}, _To, S) ->
    MyGL = group_leader(),
    set_group_leader(Gleader),
    Reply = 
    case catch apply(Mod,Fun,Args) of
        {'EXIT', _} = Exit ->
        {badrpc, Exit};
        Other ->
        Other
    end,
    group_leader(MyGL, self()), % restore
    % 这个会真正堵塞rex,所以尽量不要使用
    {reply, Reply, S};

所以rpc:call其实算是异步调用,切记不要使用rpc:block_call,除非遇到特殊情况

5.如何减少rpc的热点?

  • 尽量使用 gen_server:call({PID,Node}, Request, Timeout)来代替rpc:call(M,F,A)
  • 尽量自己建立类似于rex的进程,然后使用负载
  • 如果使用的是cast,请尽量合并请求,减少消息数量

6. 总结

虽然系统提供了rpc的原始支持,但是确带来了另外一个热点问题。

但是反观erlangActor思想,我们会发现,我们在日常的使用中,rpc是一种不符合Actor思想的做法。
个人认为真正纯粹的Actor,就是给对面Node上的proc发送一个消息,然后等到消息回执就可以了,直接使用gen_server:call就可以满足,而且不会有任何的热点问题。

7.参考

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容

  • erlang常规面试题 基础 消息发送 基础相关 OTP相关 gen_server:cast和erlang:sen...
    randyjia阅读 4,143评论 1 3
  • 世界是并行的,Erlang程序反应了我们思考和交流的方式,人作为个体通过发送消息进行交流,如果有人死亡,其他人会注...
    abel_cao阅读 2,755评论 1 4
  • 分布式 Erlang Erlang 自带分布式功能,并且 Erlang 语言的消息发送也完全适应分布式环境。我们称...
    Shawn_xiaoyu阅读 8,430评论 6 12
  • erlang应用脚本stop分析 其实这篇文章的名字应该是如何安全关闭erlang应用更加科学。 erlang应用...
    randyjiawenjie阅读 1,397评论 0 1
  • 并发 创建进程 使用 erlang:spawn/1,2,3,4 用来创建一个 erlang 进程。Erlang 进...
    Shawn_xiaoyu阅读 13,847评论 9 22