akka基本使用

1.Akka介绍

Akka是JVM平台上构建高并发,分布式应用的编程框架。它采用scala语言编写,同时提供了scala和java开发接口。Akka主要解决的问题是:可以轻松的写出高效稳定的并发程序,程序员不需要过多的考虑线程,锁和资源竞争等细节。

2.Akka Actor模型

Akka框架采用Actor模型,如下图所示。
在这里插入图片描述
Actor与Actor之间用消息进行通信,当某一个Actor给另外一个Actor发消息,消息是有序的,当消息投寄到相应的邮箱后,对方Actor怎么处理是异步的,当然也可以等待它的回复。

JVM中的Actor有以下几个特点:

  • 每个Actor都有对应一个邮箱

  • Actor是串行处理消息的

  • Actor中的消息是不可变的

优势:

  • 简化并发编程:每个Actor都是相互独立的,因此没有共享资源,这也就避免了并发编程中锁的问题。
3.案例
import akka.actor.{Actor, ActorRef, ActorSystem, Props}

class SelfActor extends  Actor{
  override def receive: Receive = {
    case "hello" =>  { println("收到hello,回应 hello too") }
    case "ok" => { println("收到ok,回应 ok too") }
    case "exit" => { context.stop(self)}
    case _ =>  { println("匹配不到") }
  }
}

object SelfActor {
  def main(args: Array[String]): Unit = {
    // 创建一个ActorSystem
    val actorSystem = ActorSystem("actorsystem")
    // 创建一个actor
    val actor01:ActorRef = actorSystem.actorOf(Props[SelfActor], "actor01")
    actor01 ! "hello"
    
    actorSystem.shutdown()
  }
}

maven依赖

<dependency>
	<groupId>com.typesafe.akka</groupId>
	<artifactId>akka-actor_2.11</artifactId>
	<version>2.3.11</version>
</dependency>

运行结果

收到hello,回应 hello too

Akka实现跨进程通信
本例实现了一个echo服务器,服务器将从客户端收到的消息返回给客户端。

服务端 AkkaServer.scala

import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import com.typesafe.config.ConfigFactory


class AkkaServer extends Actor {

  override def receive: Receive = {
    case "start" => println("服务器开始工作了....")

    case msg:ClientMessage => {
      println("客户端id: " + msg.clientId + ", 客户端name: " + msg.clientName
       + ",消息: " + msg.msg)
      // 返回服务端的消息
      sender() ! ServerMessage(msg.msg)
    }
  }
}


object AkkaServer  {
  def main(args: Array[String]): Unit = {
    val host = "127.0.0.1"
    val port = 9999

    // 创建 config 对象,指定协议类型、监听的ip和端口
    val config = ConfigFactory.parseString(
      s"""
         |akka.actor.provider="akka.remote.RemoteActorRefProvider"
         |akka.remote.netty.tcp.hostname=$host
         |akka.remote.netty.tcp.port=$port
        """.stripMargin)


    val actorSystem = ActorSystem("server", config)
    // 创建一个actor
    val serverActor:ActorRef = actorSystem.actorOf(Props[AkkaServer], "server-actor")
    serverActor ! "start"
  }
}

客户端 AkkaClient.scala

import akka.actor.{Actor, ActorRef, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

import scala.io.StdIn


class AkkaClient(clientID:String, clientName:String, host: String, port: Int) extends Actor{

  var serverActorRef: ActorSelection = _

  override def preStart(): Unit = {
    serverActorRef = context.actorSelection(s"akka.tcp://server@${host}:${port}/user/server-actor")
    println("this.serverActorRefer=" + this.serverActorRef)
  }


  override def receive: Receive = {
    case "start" => println("客户端开始工作...")

    case msg:String => {
      serverActorRef ! ClientMessage(clientID, clientName, msg)
    }

    case msg:ServerMessage => {
      println("收到服务器消息:" + msg.toString )
    }
  }
}


object AkkaClient {
  def main(args: Array[String]): Unit = {

    val (host, port, serverHost, serverPort) = ("127.0.0.1", 9990, "127.0.0.1", 9999)
    val config = ConfigFactory.parseString(
      s"""
         |akka.actor.provider="akka.remote.RemoteActorRefProvider"
         |akka.remote.netty.tcp.hostname=$host
         |akka.remote.netty.tcp.port=$port
        """.stripMargin)

    // 创建 ActorSystem
    val actorSystem = ActorSystem("client-actorsystem", config)
    // 创建 clientActor 的 Actor 和 ActorRef
    val clientActor: ActorRef = actorSystem.actorOf(Props(new AkkaClient("01", "client-01", serverHost, serverPort)), "client-01")

    // 启动客户端
    clientActor ! "start"


    while (true) {
      val mes = StdIn.readLine()
      clientActor ! mes
    }
  }
}

maven依赖

<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-remote_2.11</artifactId>
    <version>2.3.11</version>
</dependency>

运行结果:

server

[INFO] [07/08/2020 11:13:04.385] [main] [Remoting] Starting remoting
[INFO] [07/08/2020 11:13:05.091] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://server@127.0.0.1:9999]
[INFO] [07/08/2020 11:13:05.092] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://server@127.0.0.1:9999]
服务器开始工作了....
客户端id: 01, 客户端name: client-01,消息: hello world

client

[INFO] [07/08/2020 11:13:06.549] [main] [Remoting] Starting remoting
[INFO] [07/08/2020 11:13:07.249] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://client-actorsystem@127.0.0.1:9990]
[INFO] [07/08/2020 11:13:07.250] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://client-actorsystem@127.0.0.1:9990]
this.serverActorRefer=ActorSelection[Anchor(akka.tcp://server@127.0.0.1:9999/), Path(/user/server-actor)]
客户端开始工作...
hello world
收到服务器消息:ServerMessage(hello world)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值