《Java高并发程序设计》学习 --7.2 Akka之有关消息投递的一些说明

45 篇文章 0 订阅
整个Akka应用是由消息驱动的。消息是除了Actor之外最重要的核心组件。作为在并发程序中的核心组件,在Actor之间传递的消息应该满足不可变性,也就是不变模式。因为可变的消息无法高效的在并发环境中使用。理论上Akka中的消息可以使用任何对象实例,但实际使用中,强烈推荐使用不可变对象。一个典型的不可变对象的实现如下:
public final class ImmutableMessage {
	private final int sequenceNumber;
	private final List<String> values;
	
	public ImmutableMessage(int sequenceNumber, List<String> values) {
		this.sequenceNumber = sequenceNumber;
		this.values = Collections.unmodifiableList(new ArrayList<String>(values));
	}
	
	public int getSequenceNumber() {
		return sequenceNumber;
	}
	
	public List<String> getValues() {
		return values;
	}
}
上述代码实现了一个不可变的消息。注意代码中对final的使用,它申明了当前消息中的几个字段都是常量,在消息构造完成后,就不能再发生改变了。更加需要注意的是,对于values字段,final关键字只能保证values引用的不可变性,并无法保证values对象的不可变性。为了实现彻底的不可变性,代码构造了一个不可变的List对象。
对于消息投递,大家可能有一个疑问,那就是消息投递究竟是以何种策略进行的呢?也就是发出去的消息一定会被对方接收到吗?如果接收不到会重发吗?有没有可能重复接收消息呢?
实际上,对于消息投递,可以有3中不同的策略:
第一种,称为至多一次投递。在这种策略中,每一条消息最多会被投递一次。在这种情况下,可能偶尔会出现消息投递失败,而导致消息丢失。
第二种,称为至少一次投递。在这种策略中,每一条消息至少会被投递一次,直到成功为止。因此在一些偶然的场合,接受者可能会收到重复的消息,但不会发生消息丢失。
第三张,称为精确的消息投递。也就是所有的消息保证被精确地投递并成功接收一次,既不会有丢失,也不会有重复接收。
很明显,第一种策略是最高性能,最低成本的。因为系统只要负责把消息送出去就可以了,不需要关注是否成功。第二种策略则需要保存消息投递的状态并不断重试。而第三种策略则是成本最高且最不容易实现的。
那我们是否真的需要保证消息投递的可靠性呢?
答案是否定的。实际上,我们没有必要在Akka层保证消息的可靠性。这样做,成本太高了,也是没有必要的。消息的可靠性更应该在应用的业务层去维护,因为也许在有些时候,丢失一些消息完全是符合应用要求的。因此,在使用Akka时,需要在业务层对此进行保证。
此外,对于消息投递的Akka可以在一定程度上保证顺序性。比如:Actor A1向A2顺序发送了M1、M2和M3三条消息。Actor A3向A2顺序发送了M4、M5和M6三条消息。那么系统可以保证:
(1)如果M1没有丢失,那它一定先于M2和M3被A2收到。
(2)如果M2没有丢失,那它一定先于M3被A2收到。
(3)如果M4没有丢失,那它一定先于M5和M6被A2收到。
(4)如果M5没有丢失,那它一先于M6被A2收到。
(5)对于A2来说,来自A1和A3的消息可能交织在一起,没有顺序保证。
在这里,值得注意的一点是,这种消息投递规则不具备可传递性,比如:
Actor A向C发送了M1,接着,ActorA向B发送了M2,B将M2转发给Actor C。那么在这种情况下,C收到M1和M2的先后顺序是没有保证的。

注:本篇博客内容总结自《 Java 高并发程序设计》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值