在erlang杀手级应用rabbitmq中,不难发现,有一个gen_server2.erl模块。而在rabbitmq中,gen_server2.erl是对gen_server.erl模块的重写。

RabbitMQ重新实现了gen_server -> gen_server2。 很多Module都是用了这个behavior。

我们首先来看下OTP里gen_server 的实现:

gen_server的启动入口是gen_server:start_link,一个以gen_server为behavior的Module,例如frontend call gen_server:start_link( node_manager)来启动node_manager这个gen_server.

gen_server:start_link启动一个进程,执行gen_server:init_it。

gen_server:init_it做了三件事:

1.  调用node_manager:init

2.  send ack to frontend

3.  start loop

loop

先比较gen_server和gen_server2的loop

gen_server loop是receive一个message,处理这个message,再去receive下一个message,没有message时就block在那里。

message一般是三种来源:

1. frontend 的gen_server:call 由 node_manager: handle_call来处理, 会有reply send to frontend

2. frontend 的gen_server:cast 有 node_manager : handle_cast来处理

3.  其他由 node_manager : handle_info来处理

而gen_server2的loop与其不同:

1. receive所有message, 加到Queue里。

2. 如果Queue不空,从Queue里取出一个处理,再step1

3. 如果Queue为空:

3.1 如果没有hibernate, 直接去receive,然后加到Queue。如果timeout, 就由handle_info来处理

3.2 如果有hibernate,没有backoff, 将timeout设成 infinity, 在那一直去receive(边睡边等)

3.3 如果有hibernate,也有backoff, 直接去receive,然后加到Queue,如果timeout,去call pre_hibernate, hibernate,wake 以后重新调整timeout。

gen_server的message box可能非常大,而gen_server2使用了一个额外的Queue来解决这个问题,注释显示这样避免了selective receives in callbacks 去scan一个巨大的MessageBox, selective receives in callbacks例如multi_call,mcall

hibernate

node_manager的init和所有callback function 都可以返回一个hibernate,使loop进入休眠,直到有下个message进来。进入休眠会比较省cpu资源,一般对于下一个message需要很久后才come in的scenario

gen_server2提供了两个新的callback function: pre_hibernate and post_hibernate。

这里看下gen_server和gen_server2的 hibernate实现:

gen_server的每轮loop一旦收到一个hibernate, 就立刻调用proc_lib:hibernate, 当醒来时直接receive,然后处理message。

gen_server2的每轮loop一旦收到一个hibernate,先调用pre_hibernate ,再调用proc_lib:hibernate,醒来时receive所有message, 加到Queue里,再调用post_hibernate,然后处理Queue里的message

timeout

gen_server和gen_server2里的timeout不太一样

gen_server里,timeout是针对一个request处理,node_manager的init, handle_call, handle_cast, handle_info都可以返回一个timeout,  这样当下一次 receive timeout了以后,由handle_info(timeout)来处理。如果不设timeout, 默认是infinity,就是receive会block在那里。gen_server的timeout和hibernate没有什么关系,当有hibernate时就没有timeout,因为直到有request来才会wake, 这样就直接receive即可。

gen_server2里,timeout是在Queue空的时候使用,Queue空的时候需要receive messages,此时有三种情况:

1. 没有hibernate,就和gen_server一样,如果timeout由handle_info处理

2. 有hibernate没有backoff, timeout就没用了,跟gen_server一样,直接进入hibernate。

3. 当有hibernate又有backoff时,receive会等待timeout的时间再进入hibernate,而timeout时间是不断调整的。

backoff

gen_server2 的backoff 有这个几个参数:InitialTimeout, MinimumTimeout, DesiredHibernatePeriod。当一次hibernate的时间很长,超过DesiredHibernatePeriod,就会将下次timeout设置的时间短一点,这样可以尽快hibernate;如果当一次hibernate的时间很短,就会将下次timeout设置的时间长一点,这样在request来的很频繁的时候避免去hibernate。

mcall

gen_server2 增加了一个mcall接口,可以一次并行call gen_server2

gen_server2 与gen_server的对比的更多相关文章

  1. gen_server port 调用receive_match 问题

    问题由来 前些天对系统做了一个优化,将原来从queue 轮询刷出数据后每条消息一个 spawn 进程单独处理,修改为批量刷出.一条一条刷轮询刷 queue 存在问题:刷queue 进程太多时,占用CP ...

  2. Erlang generic standard behaviours -- gen_server hibernate

    hibernate 主要用于在内存空闲时,通过整理进程的stack,回收进程的heap 来达到回收内存节省资源的效果. hibernate 可用于OTP 进程以及普通进程, hibernate 的官方 ...

  3. Ignite性能测试以及对redis的对比

    测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...

  4. IIC驱动移植在linux3.14.78上的实现和在linux2.6.29上实现对比(deep dive)

    首先说明下为什么写这篇文章,网上有许多博客也是介绍I2C驱动在linux上移植的实现,但是笔者认为他们相当一部分没有分清所写的驱动时的驱动模型,是基于device tree, 还是基于传统的Platf ...

  5. [原] KVM 环境下MySQL性能对比

    KVM 环境下MySQL性能对比 标签(空格分隔): Cloud2.0 [TOC] 测试目的 对比MySQL在物理机和KVM环境下性能情况 压测标准 压测遵循单一变量原则,所有的对比都是只改变一个变量 ...

  6. arcgis api for js入门开发系列六地图分屏对比(含源代码)

    上一篇实现了demo的地图标绘模块,本篇新增地图地图分屏对比模块,截图如下(源代码见文章底部): 对效果图的简单介绍一下,在demo只采用了两分屏对比,感兴趣的话,可以在两分屏的基础上拓展,修改css ...

  7. 嵌入式&iOS:回调函数(C)与block(OC)回调对比

    学了OC的block,再写C的回调函数有点别扭,对比下区别,回忆记录下. C的回调函数: callBack.h 1).定义一个回调函数的参数数量.类型. typedef void (*CallBack ...

  8. C#跨平台手机应用开发工具Xamarin尝试 与Eclipse简单对比

    Xamarin 支持使用C#开发基于Android.IOS.WindowsPhone应用开发,最大特点C#+跨平台,详细说明问度娘. 安装 研究 想体验研究的点击查看页面 Xamarin For Vi ...

  9. 几款主流 NoSql 数据库的对比

    最近小组准备启动一个 node 开源项目,从前端亲和力.大数据下的IO性能.可扩展性几点入手挑选了 NoSql 数据库,但具体使用哪一款产品还需要做一次选型. 我们最终把选项范围缩窄在 HBase.R ...

随机推荐

  1. RTU模式与ASCII模式有什么不同

    所有设备必须必须实现 RTU 模式.ASCII 传输模式是选项,即默认设置必须为 RTU 模式. 当设备使用RTU (Remote Terminal Unit) 模式在 Modbus 串行链路通信, ...

  2. VUE -- 安装新模块

  3. Http标准协议Android网络框架——NoHttp

    NoHttp详细文档:http://doc.nohttp.net NoHttp公益测试接口:http://api.nohttp.net 支持与RxJava完美结合.支持一句话切换底层为OkHttp,支 ...

  4. C++之类成员所占内存大小问题总结

    1.空类所占字节数为1,可见代码如下 #include <iostream> using namespace std; class Parent { }; class Child:publ ...

  5. 《Linux性能及调优指南》----1.1 Linux进程管理

    翻译:飞哥 ( http://hi.baidu.com/imlidapeng ) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance ...

  6. Java的身份证号码工具类

    /** * Copyright (C) 2009-2010 Yichuan, Fuchun All rights reserved. * Licensed to the Apache Software ...

  7. HTML5游戏实战(1):50行代码实现正面跑酷游戏

    前段时间看到一个"熊来了"的HTML5跑酷游戏,它是一个典型的正面2D跑酷游戏,这里借用它来介绍一下用Gamebuilder+CanTK开发正面跑酷游戏的基本方法. CanTK(C ...

  8. 2017.6.29 java读取.properties配置文件的几种方法

    参考来自:http://www.cnblogs.com/s3189454231s/p/5626557.html 关于路径的解释:http://blog.csdn.net/bluishglc/artic ...

  9. Gizmos 辅助线框

    Gizmos are used to give visual debugging or setup aids in the scene view. Gizmos是用于在场景视图可视化调试或辅助设置. ...

  10. Android学习(十) SQLite 基于SQLiteOpenHelper的操作方式

    main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...