Akka学习笔记-简介与API简单操作

 Akka 是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和 Scala 的 Actor 模型应用。Akka是一个开发库和运行环境,可以用于构建高并发、分布式、可容错、事件驱动的基于JVM的应用。使构建高并发的分布式应用更加容易。


Akka可以以两种不同的方式来使用

  • 以库的形式:在web应用中使用,放到 WEB-INF/lib 中或者作为一个普通的Jar包放进classpath。
  • 以微内核的形式:你可以将应用放进一个独立的内核。自己有一个main类来初始化Actor系统。


Akka平台竞争力

Akka提供可扩展的实时事务处理。

Akka是一个运行时与编程模型一致的系统,为以下目标设计:

    - 垂直扩展(并发)
    - 水平扩展(远程调用)
    - 高容错
Akka的几大特性:
1)易于构建并行和分布式应用 (Simple Concurrency & Distribution)
Akka在设计时采用了异步通讯和分布式架构,并对上层进行抽象,如Actors、Futures ,STM等。

2)可靠性(Resilient by Design)

系统具备自愈能力,在本地/远程都有监护。

3)高性能(High Performance)

在单机中每秒可发送50000000个消息。内存占用小,1GB内存中可保存2500000个actors。

4)弹性,无中心(Elastic — Decentralized)

自适应的负责均衡,路由,分区,配置

5)可扩展(Extensible)

可以使用Akka 扩展包进行扩展。

        在Akka的世界里,只有一个内容需要学习和管理,具有高内聚和高一致的语义。Akka是一种高度可扩展的软件,这不仅仅表现在性能方面,也表现在它所适用的应用的大小。Akka的核心,Akka-actor是非常小的,可以非常方便地放进你的应用中,提供你需要的异步无锁并行功能,不会有任何困扰。你可以任意选择Akka的某些部分集成到你的应用中,也可以使用完整的包——Akka 微内核,它是一个独立的容器,可以直接部署你的Akka应用。随着CPU核数越来越多,即使你只使用一台电脑,Akka也可作为一种提供卓越性能的选择。Akka还同时提供多种并发范型,允许用户选择正确的工具来完成工作。


Akka使用场景

我们看到Akka被成功运用在众多行业的众多大企业,从投资业到商业银行、从零售业到社会媒体、仿真、游戏和赌

博、汽车和交通系统、数据分析等等等等。任何需要高吞吐率和低延迟的系统都是使用Akka的候选。

Actor使你能够进行服务失败管理(监管者),负载管理(缓和策略、超时和隔离),水平和垂直方向上的可扩展性

(增加cpu核数和/或增加更多的机器)管理。

下面的链接中有一些Akka用户关于他们如何使用Akka的描述:

http://stackoverflow.com/questions/4493001/good-use-case-for-akka

所有以上这些都在这个Apache2许可的开源软件中。


Actors模型

Actor模型是由Carl Hewitt于上世纪70年代早期提出的,目的是为了解决分布式编程中一系列的编程问题。 其特点如下: 系统中的所有事物都可以扮演一个Actor,Actor之间是完全独立的,在收到消息时Actor所采取的所有动作都是并行的。 Actor是封装状态和行为的对象,他们的唯一通讯方式是交换消息,消息的类型可以是任意的,消息的内容也可以是任意的,交换的消息存放在接收方的邮箱里。 在一个方法中的动作没有明确的顺序。很多开发语言都提供了原生的Actor模型,例如erlang、scala等。


先看一个简单实例:
<dependency>
	<groupId>com.typesafe.akka</groupId>
	<artifactId>akka-actor_2.11</artifactId>
	<version>2.3.11</version>
</dependency>

import java.util.concurrent.TimeUnit;

import scala.concurrent.duration.Duration;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;

public class Bootstrap {

	public static void main(String[] args) {
		ActorSystem actorSystem = ActorSystem.create("CaculateSystem");
		final ActorRef master = actorSystem.actorOf(Props.create(Master.class), "Master");
		actorSystem.scheduler().schedule(
				Duration.create(1, TimeUnit.SECONDS), 
				Duration.create(1, TimeUnit.SECONDS), 
				new Runnable() {
					@Override
					public void run() {
						master.tell(new Operation(1, 2, OperationSymbol.ADD), null);
						master.tell(new Operation(3, 2, OperationSymbol.SUB), null);
						master.tell(new Operation(2, 2, OperationSymbol.MUL), null);
						master.tell(new Operation(8, 2, OperationSymbol.DEV), null);
					}
				}, 
				actorSystem.dispatcher());
	}
}

import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;

public class Master extends UntypedActor {
	
	@Override
	public void onReceive(Object message) throws Exception {
		if (message instanceof Operation) {
			ActorRef worker = getContext().actorOf(Props.create(Worker.class));
			worker.tell(message, getSelf());
		} else if (message instanceof OperationResult) {
			OperationResult operationResult = (OperationResult) message;
			System.out.println(operationResult.toString());
			getContext().stop(getSender());
		} else {
			unhandled(message);
		}
	}

}

import akka.actor.UntypedActor;

public class Worker extends UntypedActor {

	@Override
	public void onReceive(Object message) throws Exception {
		if (message instanceof Operation) {
			Operation operation = (Operation) message;
			int result = operation.execute();
			getSender().tell(new OperationResult(operation, result), getSelf());
		} else {
			unhandled(message);
		}
	}

}

public class Operation {
	
	private final int param1;
	private final int param2;
	private final OperationSymbol symbol;
	
	public Operation(int param1, int param2, OperationSymbol symbol) {
		this.param1 = param1;
		this.param2 = param2;
		this.symbol = symbol;
	}
	
	public int getParam1() {
		return param1;
	}
	
	public int getParam2() {
		return param2;
	}
	
	public OperationSymbol getOperationSymbol() {
		return symbol;
	}
	
	public int execute() {
		int result = 0;
		String name = symbol.getName();
		if (name.equalsIgnoreCase(OperationSymbol.ADD.getName())) {
			result = this.param1 + this.param2;
		} else if (name.equalsIgnoreCase(OperationSymbol.SUB.getName())) {
			result = this.param1 - this.param2;
		} else if (name.equalsIgnoreCase(OperationSymbol.MUL.getName())) {
			result = this.param1 * this.param2;
		} else {
			result = this.param1 / this.param2;
		}
		return result;
	}

}

public enum OperationSymbol {

	ADD("+"), SUB("-"), MUL("*"), DEV("/");
	
	private String name = null;
	
	private OperationSymbol(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	
}

public class OperationResult {

	private final Operation operation;
	private final int result;
	
	public OperationResult(Operation operation, int result) {
		this.operation = operation;
		this.result = result;
	}
	
	@Override
	public String toString() {
		return operation.getParam1() + operation.getOperationSymbol().getName() 
				+ operation.getParam2() + "=" + result;
	}
	
}

再看一个官方的实例:
import java.util.concurrent.TimeUnit;

import scala.concurrent.duration.Duration;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.routing.RoundRobinRouter;

public class Pi {

	public static void main(String[] args) {
		Pi pi = new Pi();
		pi.calculate(4, 10000, 10000);
	}

	static class Calculate {
	}

	static class Work {
		private final int start;
		private final int nrOfElements;

		public Work(int start, int nrOfElements) {
			this.start = start;
			this.nrOfElements = nrOfElements;
		}

		public int getStart() {
			return start;
		}

		public int getNrOfElements() {
			return nrOfElements;
		}
	}

	static class Result {
		private final double value;

		public Result(double value) {
			this.value = value;
		}

		public double getValue() {
			return value;
		}
	}

	static class PiApproximation {
		private final double pi;
		private final Duration duration;

		public PiApproximation(double pi, Duration duration) {
			this.pi = pi;
			this.duration = duration;
		}

		public double getPi() {
			return pi;
		}

		public Duration getDuration() {
			return duration;
		}
	}

	public static class Worker extends UntypedActor {

		private double calculatePiFor(int start, int nrOfElements) {
			double acc = 0.0;
			for (int i = start * nrOfElements; i <= ((start + 1) * nrOfElements - 1); i++) {
				acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1);
			}
			return acc;
		}

		public void onReceive(Object message) {
			if (message instanceof Work) {
				Work work = (Work) message;
				double result = calculatePiFor(work.getStart(), work.getNrOfElements());
				getSender().tell(new Result(result), getSelf());
			} else {
				unhandled(message);
			}
		}
	}

	public static class Master extends UntypedActor {
		private final int nrOfMessages;
		private final int nrOfElements;

		private double pi;
		private int nrOfResults;
		private final long start = System.currentTimeMillis();

		private final ActorRef listener;
		private final ActorRef workerRouter;

		public Master(final int nrOfWorkers, int nrOfMessages, int nrOfElements, ActorRef listener) {
			this.nrOfMessages = nrOfMessages;
			this.nrOfElements = nrOfElements;
			this.listener = listener;
			this.workerRouter = this.getContext().actorOf(Props.create(Worker.class).withRouter(
					new RoundRobinRouter(nrOfWorkers)), "workerRouter");
		}

		public void onReceive(Object message) {
			if (message instanceof Calculate) {
				for (int start = 0; start < nrOfMessages; start++) {
					workerRouter.tell(new Work(start, nrOfElements), getSelf());
				}
			} else if (message instanceof Result) {
				Result result = (Result) message;
				pi += result.getValue();
				nrOfResults += 1;
				if (nrOfResults == nrOfMessages) {
					// Send the result to the listener
					Duration duration = Duration.create(System.currentTimeMillis() - start,
							TimeUnit.MILLISECONDS);
					listener.tell(new PiApproximation(pi, duration), getSelf());
					// Stops this actor and all its supervised children
					getContext().stop(getSelf());
				}
			} else {
				unhandled(message);
			}
		}
	}

	public static class Listener extends UntypedActor {
		public void onReceive(Object message) {
			if (message instanceof PiApproximation) {
				PiApproximation approximation = (PiApproximation) message;
				System.out.println(String.format("\n\tPi approximation: \t\t%s\n\tCalculation time: \t%s",
										approximation.getPi(), approximation.getDuration()));
				getContext().system().shutdown();
			} else {
				unhandled(message);
			}
		}
	}

	public void calculate(final int nrOfWorkers, final int nrOfElements, final int nrOfMessages) {
		ActorSystem system = ActorSystem.create("PiSystem");
		final ActorRef listener = system.actorOf(Props.create(Listener.class), "listener");
		ActorRef master = system.actorOf(Props.create(Master.class, 
				nrOfWorkers, nrOfMessages, nrOfElements, listener), "master");
//		ActorRef master = system.actorOf(new Props(new UntypedActorFactory() {
//		      public UntypedActor create() {
//		        return new Master(nrOfWorkers, nrOfMessages, nrOfElements, listener);
//		      }
//		    }), "master");
		master.tell(new Calculate(), null);
	}

}

实例都比较简单,主要流程大致如下:
Master角色接收Client角色发来的请求,然后将请求并发交给Worker角色处理,Worker角色负责处理具体的业务,Worker角色处理业务完成之后将处理结果发回给Master角色,Master角色收集并处理Worker返回的结果,最后将最终结果返回给Client角色。 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值