- 浏览: 268083 次
- 性别:
- 来自: 杭州
最新评论
-
pjsong3101:
引用 public static void main ...
JVM中可生成的最大Thread数量 -
lzp459260276:
RabbitMQ源码分析 – 消息生命周期 -
huotianjun:
关于:为什么要每个操作写一个信息,而不是在publish时写一 ...
RabbitMQ源码分析 – 持久化机制 -
puyongjun_1989:
楼主你好, (256 * 1024) / 64 = 409 ...
JVM中可生成的最大Thread数量 -
chuqingq:
很不错,学习!
Erlang并发机制 –进程调度
文章列表
(注:分析代码基于RabbitMQ 2.8.2)
当消息需要持久化(相应队列首先必须是durable)或者因为内存吃紧,需要把消息转移到磁盘的时候就会触发持久化操作。Rabbit中两部分信息涉及到持久化操作:一个是消息本身,由msg_store模块 ...
这篇文章主要总结下这几个概念,前几天看到微博里在讨论,当时也有点搞不清楚,昨天在看到Reactor和Proactor模式的时候,又提到相关概念,索性搞搞清楚,写个总结。
《Unix网络编程卷1:套接字联网API》(下面称为卷1)第6章对Unix I/O模型有5种划分:阻塞式I/O模型,非阻塞式I/O模型,I/O复用模型,信号驱动式I/O,异步I/O模型。这里我们只关心跟我们主题相关的四类:
阻塞式I/O模型:应用进程调用I/O操作时阻塞,只有等待要操作的数据准备好,并复制到应用进程的缓冲区中才返回。
非阻塞式I/O模型:当应用进程要调用的I/O操作会导致该进程进入阻塞状态时,该 ...
(注:分析代码基于RabbitMQ 2.8.2)
当rabbit无法直接将消息投递到消费者时,需要暂时将消息入队列,以便重新投递。但是,将消息入队列并不意味着,就是将消息扔在一个队列中就不管了,rabbit提供了一套状态转换的机制来管理消息。
在rabbit中,队列中的消息可能会处理以下四种状态:
alpha:消息内容以及消息在队列中的位置(消息索引)都保存在内存中;
beta:消息内容只在磁盘上,消息索引只在内存中;
gamma:消息内容只在磁盘上,消息索引在内存和磁盘上都存在;
delta:消息的内容和索引都在磁盘上。
注意:对于持久化消息,消息内容和消息索引都必须 ...
(注:分析代码基于RabbitMQ 2.8.2)
当客户端通过basic.publish命令(AMQP定义)发布一个消息时,rabbit需要经过以下几个步骤处理消息:
1) 根据客户端传来的消息内容及相关属性(目标exchange,routing keys,mandatory及immediate属性)构造 ...
(注:分析代码基于RabbitMQ 2.8.2)
Connection
在上篇文章中提到,客户端连上rabbit后,需要向rabbit发送AMQP协议头,rabbit在收到协议头后,开始在0号channel 上跟客户端进行交互(AMQP中一个连接可以多路复用,1~65535为可用的channel编号,0号channel,也就是frame中channel的索引为0,被认为是全局于整个连接)。
根据AMQP协议,经过connection.start -> connection.start_ok -> connection.secure -> connection.se ...
(注:分析代码基于RabbitMQ 2.8.2)
网络层的启动也是作为上一篇文章中提到的一个启动步骤来启动的,入口为[$RABBIT_SRC/src/rabbit_networking.erl -->
boot/0],代码如下:
boot() ->
ok = start(),
ok = boot_tcp(),
ok = boot_ssl().
[ ...
RabbitMQ是一个消息队列的实现,基于AMQP(Advanced Message
Queuing Protocol)。最近因为工作需要,打算深入了解RabbitMQ的架构以实现,后续会出一系列文章记录分析过程。这篇总结RabbitMQ的启动过程。
(注:分析代码基于RabbitMQ 2.8.2)
RabbitMQ的启动入口在[$RABBIT_SRC/src/rabbit.erl
--> start/2]。主要代码如下:
start(normal, []) ->
case erts_version_check() of
...
Erlang的热部署做的很完善,参见Release
Handling,这篇文章只关心最基本的模块更新。模块是Erlang程序组织的最基本单元。如下代码就是一个最简单的hello模块(为了说明问题,我们添加了一个init函数):
-module(hello).
-export([init/0, hello/1]).
init() ->
Db = dict:new(),
dict:store(name, "jzh", Db).
hello(Db) ->
Value = dict:fetch(name, Db),
...
Erlang中每个进程都有独立的堆内存,默认的大小是233个words(可配置),并以Fibonacci序列的顺序增长(233对应fib(11))。不过,当堆内存增大到一定程序时,增长速度减缓,比如内存大于fib(35)=14M的时候,堆内存开始不以Fibonacci序列增长(具体参见[$R15B_OTP_SRC/erts/emulator/beam/erl_gc.c --> erts_init_gc]里的说明)。一般情况下,进程所用到的数据都放在各自的堆内存中。
Erlang的GC机制跟其它语言(比如Java)相比,很重要的一点是,它的GC是以进程为单位进 ...
Erlang系统中,进程之间的通信是通过消息传递来完成的。消息使用Pid ! Message的形式发送,通过receive语句获取。每个Erlang进程都有用来存储传入消息的信箱。当一个消息发送的时候,它会从发送进程中拷贝到接收进程的信箱,并以它们到达的时间次序存储。消息的传递是异步的,一个发送进程不会在发送消息后被暂停。
上面提到发送消息时,会在两个进程之间存在消息复制,为什么需要复制呢?这就跟进程的堆内存有关。虽然在Erlang的文档(heap_type)中说明堆内存有三种类型:private,shared,hybrid,但是在实际的代码中,只有两种priva ...
一般情况下,在SMP环境中,每个调度器都会绑定到一个CPU核心,为了保证调度器可以充分的利用CPU资源,那么就必要确保每个调度器任务队列的长度大致相同,Erlang通过任务迁移算法来完成这个功能。Characterizing
the Scalability o ...
OpenStack中的Nova各个服务之间以松耦合的方式使用AMQP进行通信(RPC)。使用AMQP的发布/订阅模式来进行RPC有如下优势:
1)
客户端及服务端之间解耦:客户端不需要知道有哪些服务端以及服务端的地址;
2)
客户端与服务端之间完全的同步性:客户端的RPC不需要服务端正好在运行;
3)
远程调用的随机均衡:如果有多个服务端在运行,单向RPC会透明的分发到最一个可用的服务端。
Nova用到了direct,fanout,topic三种类型的交换器(Exchange),整个架构图如下: ...
自己做的一个小东西,欢迎有兴趣的同学试用:https://github.com/onlychoice/ganger
Ganger - A simple automate tool.
==================================================
What is Ganger
--------------------------------------
Ganger is a simple automate tool. It can automate deploy packages, launch
target processe ...
Erlang调度器主要完成对Erlang进程的调度,它是Erlang实现软件实时和进程之间公平使用CPU的关键。Erlang运行时,有4种任务需要被调度:进程,Port,Linked-in driver,Erlang虚拟机的系统级活动。
Erlang调度器主要有以下特点:
1. 进程调度运行在用户空间 :Erlang进程不同于操作系统进程,Erlang的进程调度也跟操作系统完全没有关系,是由Erlang虚拟机来完成的;
2. 调度是抢占式的:每一个进程在创建时,都会分配一个固定数目的reduction(R15B中,这个数量默认值是2000),每一次操作(函数调用),reduct ...
在了解Erlang的并发机制之前,我们先来看一下Erlang与Java的并发性能对比,一个是并发单元的创建时间,一个是并发单元之间的消息通讯时间(纵坐标代表时间,横坐标代表并发数量):
(测试程序及说明见这里,原测试时间比较早了,于是在自己的虚拟机上重新跑了下(CenterOS 6,3G内存);JVM生成线程数量控制,可见这里,)
从上面的测试结果来看,Erlang的并发效率要比Java好很多,不在一个数量级上,Erlang是Java的1000倍左右(这不能说明在所有场景下