akka introduce

什么是Akka,Akka主要用来编写分布式的,可扩展的,并发的应用程序,详见官方文档,官方文档真的好长啊,这里记了一些akka的helloworld程序,算是简单入门吧。

Akka总结

Actor模型基于一种通过消息进行通信的简单的actor实体结构,能够轻松地构建应用程序来实现高并发性和可伸缩性。

         用于并发计算的actor模型基于各种称为actor的原语来构建系统。Actor执行操作来响应称为消息的输入。这些操作包括更改actor自己的状态,以及发出其他消息和创建其他actor。所有消息都是异步交付的,因此将消息发送发与接收方分开。正是由于这种分离,导致actor系统具有内在的并发性:可以不受限制地并行执行任何拥有输入消息的actor。在Akka中的消息都是不可变对象(这个在之前已经了解过了,包括怎么创建一个不可变对象)。

         Akka的监督策略有OneForOneStrategy和AllForOneStrategy,对于OneForOneStrategy策略,子Actor只会对出问题的子Actor进行处理,比如重启或者停止,而对于AllForOneStrategy,父Actor会对出问题的子Actor以及它所有的兄弟都进行处理。很显然,对于AllForOneStratege,它更适合各个Actor联系非常紧密的场景,如果多个Actor间只有一个Actor出现故障,则宣告整个任务失败。

         选择Actor,主要是通过通配符(actor的名字)来进行Actor选择。


第一个例子,来自《实战Java高并发...》,重点是一个Actor WatchDog监督另一个Actor MyWorker,在被监督的Actor退出时,监督者会收到一个Terminated类型的消息,另外Actor也可以重写supervisorStrategy() 方法来指定监督策略。其他一些细节都在程序中说明了,代码如下:

Main类:

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

public class DeadMain {
	
	public static void main(String[] args) {
		
		//ActorSystem.create()的第一个参数为系统名称,第一个参数为配置文件,这里没有配置文件
		ActorSystem system = ActorSystem.create("deadwatch");
		
		//ActorSystem.actorOf是创建一个Actor的方式,第二个参数为 actor的名字
		final ActorRef worker = system.actorOf(new Props(MyWorker.class));
		
		//当创建的actor的构造方法有参数时,可以使用下的方式创建
		ActorRef watcher = system.actorOf(new Props(new UntypedActorFactory() {
			private static final long serialVersionUID = 1L;
			public UntypedActor create() {
				return new WatchActor(worker);
			}
		}),"awatcher");
		
		//前两种方式向worker发送消息,没有发送者,后一种方式的发送者为watcher。
		worker.tell(MyWorker.Msg.WORKING);
		worker.tell(MyWorker.Msg.DONE);
		worker.tell(MyWorker.Msg.CLOSE, watcher);
	}
}

一个监督Actor WatchActor:

import akka.actor.ActorRef;
import akka.actor.SupervisorStrategy;
import akka.actor.Terminated;
import akka.actor.UntypedActor;

//无类型的Actor UntpyedActor,继承了这个就不能继承其他类了,这个是不足
//还有一种有类型的Actor
public class WatchActor extends UntypedActor{

	//构造函数
	public WatchActor(ActorRef ref){
		getContext().watch(ref);
	}
	
	@Override
	public SupervisorStrategy supervisorStrategy() {
		//TODO 这里覆盖父类的 supervisorStrategy,可以指定自己的监督策略
		//这里为了示意,仅仅返回一个null,有两种策略,有AllForOneStrategy和OneForOneStrategy
		return null;
	};
	
	@Override
	public void onReceive(Object msg) throws Exception {
		
		//如果被监视的对象(即MyWorker)退出,WatchActor将会收到一条Terminated消息。
		//这个消息不是MyWorker显示发送的,系统发送的?
		if(msg instanceof Terminated){
			System.out.println(
					String.format("%s has terminated, shutdown system.", ((Terminated)msg).getActor().path()));
			getContext().system().shutdown();
		}
		else if(msg==MyWorker.Msg.CLOSE){ 	//这个消息是在MyWorker退出的时候显示发送的
			System.out.println("I receive a message from sub actor, he said close");
		}else{
			unhandled(msg);
		}
	}
}

一个工作actor:

import akka.actor.UntypedActor;

//一个重写了各个生命周期的actor
public class MyWorker extends UntypedActor{

	public static enum Msg{
		WORKING,DONE,CLOSE;
	}
	
	//actor创建以后,会调用preStart()方法,在这个方法里,会进行一些资源的初始化工作
	//另外还有一个preRestart和postRestart方法,是在Actor被重启后执行的
	@Override
	public void preStart(){
		System.out.println("I am going to work, in preStart method.");
	}
	
	//Actor停止时,postStop()方法会被调用,同时这个Actor的监视者会收到
	//一个Terminated消息。
	@Override
	public void postStop(){
		System.out.println("MyWorker is stoping.");
	}
	
	@Override
	public void onReceive(Object msg) throws Exception {
		if(msg==Msg.WORKING){
			
			//这里打印getSender()输出是 deadLetters
			//没有发送者 就是 deadLetters ?
			System.out.println(getSender());
			System.out.println("I am working");
		}
		if(msg==Msg.DONE){
			System.out.println("stop working");
		}
		if(msg==Msg.CLOSE){
			System.out.println("I will shutdown");
			
			//这里打印getSender()输出是awatcher,就是watcher actor的名字
			System.out.println(getSender());
			//向这个消息(Msg.CLOSE)的发送者再发一条消息,告诉自己即将死了
			getSender().tell(Msg.CLOSE,getSelf());
			
			//这里调用context().stop()方法来停止一个actor,停止一个
			//actor的方式很多。
			context().stop(getSelf());
		}else{
			unhandled(msg);
		}
	}

}


下面是另一个例子,来自官方文档,计算圆周率Pi的,几个worker actor并行工作,感觉也很经典。

import java.util.concurrent.TimeUnit;

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.actor.UntypedActorFactory;
import akka.routing.RoundRobinRouter;
import akka.util.Duration;

public class Pi {

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

	//下面这四个静态内部类是4中不同类型的消息
	//Calculate,发送到Master,以启动计算
	static class Calculate {}

	//从Master actor发送到 worker actor,并携带任务
	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;
		}
	}

	//从worker actor发送到 Master actor并携带结果
	static class Result {
		private final double value;

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

		public double getValue() {
			return value;
		}
	}

	//从master actor发送到 Listener actor并携带最终结果
	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;
		}
	}

	//工作节点,只从mater actor接受一种类型的参数
	public static class Worker extends UntypedActor {

		//执行具体的计算任务,在worker中定义,此方法被封起来了
		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消息,从master 发送到 worker
				Work work = (Work) message;
				double result = calculatePiFor(work.getStart(), work.getNrOfElements());
				getSender().tell(new Result(result), getSelf());
			} else {
				//这个方法是在父类中定义的
				unhandled(message);
			}
		}
	}

	//控制节点,接受两种类型的参数,从Listener发送的,从worker节点发送的
	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;

			//这里创建了一个actor,并为其指定了一个路由策略(轮询)
			workerRouter = this.getContext()
					.actorOf(new Props(Worker.class).withRouter(new RoundRobinRouter(nrOfWorkers)), "workerRouter");
		}

		//onReceive方法就是消息处理器
		@Override
		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);
			}
		}
	}

	//接收从master发来的最终结果,并打印输出
	//这个Actor的构造不需要构造参数
	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);
			}
		}
	}

	//这个方法是整个计算开始的方法,第一个参数表示worker进程的个数
	public void calculate(final int nrOfWorkers, final int nrOfElements, final int nrOfMessages) {
		// Create an Akka system,后面的名字随便起
		ActorSystem system = ActorSystem.create("PiSystem");

		// create the result listener, which will print the result and shutdown
		// the system
		final ActorRef listener = system.actorOf(new Props(Listener.class), "listener");

		// create the master
		ActorRef master = system.actorOf(new Props(new UntypedActorFactory() {
			private static final long serialVersionUID = 1L;

			public UntypedActor create() {
				return new Master(nrOfWorkers, nrOfMessages, nrOfElements, listener);
			}
		}), "master");

		// start the calculation
		//谁调用tell,就是向谁发送??
		master.tell(new Calculate());
	}
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Akka是一个基于Actor模型的并发编程框架,它提供了一种简单而强大的方式来处理并发编程和分布式系统。WebSocket是一种在客户端和服务器之间进行双向通信的协议。而wss是WebSocket***可以通过akka-http模块来实现。akka-http提供了一套灵活的工具和API来处理HTTP和WebSocket请求。 要在Akka中使用WebSocket over SSL(wss),你需要做以下几步: 1. 配置SSL证书:你需要生成和配置一个SSL证书,可以使用自签名证书或者购买一个由可信机构签名的证书。 2. 导入依赖:确保你的项目中导入了akka-http和akka-stream依赖。 3. 创建WebSocket路由:使用akka-http的路由DSL创建一个WebSocket路由。你可以定义处理WebSocket消息的逻辑,比如收到消息时的处理和发送消息给客户端等。 4. 启动HTTP服务:创建一个HTTP服务器,并将WebSocket路由添加到路由器中。 下面是一个简单示例,演示了如何在Akka中使用WebSocket over SSL: ```scala import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.model.ws.{Message, TextMessage} import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer import akka.stream.scaladsl.{Flow, Sink, Source} import scala.concurrent.ExecutionContext.Implicits.global object WebSocketServer { def main(args: Array[String]): Unit = { implicit val system = ActorSystem("websocket-system") implicit val materializer = ActorMaterializer() val route =

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值