Akka学习

Akka

Akka中文文档:https://zhan-ge.gitbooks.io/akka-scala/content/

Akka文档

简介

特点

Akka提供可拓展的实时事务处理。
Akka是一个运行时与编程模型一致的系统。为以下目标设计
垂直拓展(并发)
水平拓展(远程调用)
高容错
在Akka的世界里,只有一个内容需要学习和管理,具有高内聚和高一致的语义。

优势

AKKA提供一种Actor并发模型,其粒度比线程小很多,这意味着你可以在项目中使用大量的Actor。
Akka提供了一套容错机制,允许在Actor出错时进行一些恢复或者重置操作。
AKKA不仅可以在单击上构建高并发程序,也可以在网络中构建分布式程序,并提供位置透明的Actor定位服务。

#Actor System

一个ActorSystem是一个非常重量级的结构,它会创建多个线程,因此每个逻辑应用中仅创建一个。

层次结构

1、如果一个 Actor 负责管理另一个 Actor 要做的工作,比如通过传递子任务,管理者则能够监起管子 Actor。原因在于管理者知道预期都有哪些类型的错误并如何处理这些错误。2、如果一个 Actor 持有非常重要的数据(比如避免状态丢失)x0010,该 Actor 需要为所有子 Actor 找出任务可能的危险,对他们监管并处理他们的错误。根据请求的性质,最好为每个请求创建一个新的子 Actor,从而简化用户收集回复的状态管理。这也就是 Erlang 中著名的“Error Kernel Pattern”。
3、如果一个 Actor 依赖另一个 Actor 来履行其职责,则它需要监视该 Actor 的活跃性并在接收到终止提示后采取行动。这种方式与监管不同,因为监视的部分感受不到监管策略的影响,另外需要注意的是,仅基于函数依赖并不能作为决定将子 Actor 放置在层级中哪个位置的标准。

创建一个ActorSystem
implicit val system: ActorSystem = ActorSystem("report-system")
implicit val materializer: ActorMaterializer = ActorMaterializer()
//report-system是ActorSystem名
配置容器

Actor 系统作为 Actor 的协作组合,是用于管理共享设施的自然单元,比如调度服务、配置中心、日志服务等。拥有不同配置的多个 Actor 系统可以在用一个 JVM 共存,在 Akka 本身内也没有公共的共享状态。这与 Actor 系统之间的透明通信——即在一个节点内部或跨网络连接——可以发现 Actor 系统本身也可以作为一个层次结构的功能块。

阻塞问题

1、在 Actor 中(或由 Router 管理的一组 Actor)进行阻塞调用时,确保配置一个专用的线程池或给线程池设置足够的大小。
2、在 Future 中进行阻塞调用时,确保在同一时间点该类操作的数量有一个上界。
3、在 Future 中进行阻塞调用时,提供一个带有线程数量上界的线程池,而改数量要与应用所运行的硬件属性匹配。
4、奉献一个单独的线程来管理阻塞资源(比如 NIO 选择器同时驱动多个 Channel)并通过发送 Actor 消息来分发事件。
配置线程池的工作最好交个 Akka,通过application.conf进行简单的配置并由 ActorSystem[Java, Scala] 进行实例化。

//由ActorSystem创建Actor
val statisticsActor = system.actorOf(Props[StatisticsActor])
val controlAppActor = system.actorOf(Props[ControlAppActor])
val controlServiceActor = system.actorOf(Props[ControlServiceActor])
val cacheActor = system.actorOf(Props[CacheActor].withRouter(new  RoundRobinPool(cache_RoundRobinPool)), "cacheActor")
// 配置文件中描述的各Actor的RoundRobinPool的大小
  val cache_RoundRobinPool: Int =  conf.getString("akka.cache_RoundRobinPool").toInt
Actor

Actor模型是一个并行计算(Concurrent Computation)模型,它把actor作为并行计算的基本元素来对待:为响应一个接收到的消息,一个actor能够自己做出一些决策,如创建更多的actor,或发送更多的消息,或者确定如何去响应接收到的下一个消息。
在这里插入图片描述
一个Actor是一个包含状态、行为、Mailbox、子Actor及应对监管策略的容器,所有这些都被封装在一个Actor引用中。
一个Actor拥有清晰的生命周期,在不被引用后并不会自动销毁,引用之后要关闭释放资源。

Futures

可以将一个actor的返回结果重定向到另一个actor中进行处理,主actor或者进程无需等待actor的返回结果。
在Akka中, 一个Future是用来获取某个并发操作的结果的数据结构。这个操作通常是由Actor执行或由Dispatcher直接执行的. 这个结果可以以同步(阻塞)或异步(非阻塞)的方式访问。
Future提供了一种简单的方式来执行并行算法。

Future直接使用

Future有两种使用方式:
1、阻塞方式(Blocking):该方式下,父actor或主程序停止执行知道所有future完成各自任务。通过scala.concurrent.Await使用。
2、非阻塞方式(Non-Blocking),也称为回调方式(Callback):父actor或主程序在执行期间启动future,future任务和父actor并行执行,当每个future完成任务,将通知父actor。通过onComplete、onSuccess、onFailure方式使用。

执行上下文(ExecutionContext)

为了运行回调和操作,Futures需要有一个ExecutionContext。
如果你在作用域内有一个ActorSystem,它会它自己派发器用作ExecutionContext,你也可以用ExecutionContext伴生对象提供的工厂方法来将Executors和ExecutorServices进行包裹,或者甚至创建自己的实例。
通过导入ExecutionContext.Implicits.global来导入默认的全局执行上下文。你可以把该执行上下文看做是一个线程池,ExecutionContext是在某个线程池执行任务的抽象。
如果在代码中没有导入该执行上下文,代码将无法编译。

Actor示例代码

创建一个HelloActor接收消息
package com.eliande.test1
import akka.actor.Actor
 
object HelloActorTest  {
 
  case class ClientMessagesList(key: String, value: List[String])
 
  class HelloActorTest1 extends Actor{
    override def receive: Receive = {
      case msg: ClientMessages => {
        RedisSet.getRedis1(msg.key, msg.value)
      }
      case msg: ClientMessagesList => {
        RedisSet.getRedisList(msg.key, msg.value)
      }
 
    }
  }
创建一个Actor发送消息
package com.eliande.test1
 
import java.util.concurrent.TimeUnit
import akka.actor.{ActorSystem, Props}
import akka.pattern._
import akka.stream.ActorMaterializer
import akka.util.Timeout
import com.eliande.test1.HelloActorTest.ClientMessagesList
import scala.collection.immutable.{List, Map}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success}
import scala.concurrent.duration._
 
object ActorTest extends App {
 
  implicit val system1: ActorSystem = ActorSystem("system1")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec = ExecutionContext.global
 
  var helloActorTest = system1.actorOf(Props[HelloTest])
  implicit val timeOut: Timeout = Timeout(15 seconds)
  //直接发送Actor
  helloActorTest ! ClientMessages("123", "abc")
  helloActorTest ! ClientMessagesList("aaa", List("123", "456", "789"))
  helloActorTest ! ClientMessagesMap("haha", Map("123" -> "456", "456" -> "def"))
  helloActorTest ! ClientMessagesSet("myset", "123", "wer")
 
  /*Future写法,要返回执行结果*/
  val furturn: Future[String] = (helloActorTest ? ClientMessages("qwe", "abc")).mapTo[String]
 
  //Await写法,阻塞
  // val resuit = Await.result(furturn, timeOut.duration).asInstanceOf[String]
  // println(resuit)
 
  furturn onComplete ({
    case Success(x) => {
      val msg = x
      println(x + "xxx")
    }
    case Failure(x) => {
      println("Failure")
    }
  })
  println("01234567890")
}

Akka-http

配置文件
akka-http-host = "127.0.0.1"
  akka-http-port = 8000testtest
  web-path = "test"
  web-parameter = "testParam"
路由选择
lazy val reportRoutes: Route =
    pathPrefix(webPathPrefix) {
      get {
        parameter(parameter) {
          params => {
            val commandDesc: Future[String] = (httpActor ? ReportCondition(params)).mapTo[String]
            complete(commandDesc)
          }
        }
      } ~ post {
        entity(as[String]) {
          params => {
            val commandDesc: Future[String] = (httpActor ? ReportCondition(params)).mapTo[String]
            complete(commandDesc)
          }
        }
      }
    }
起路由
Http().bindAndHandle(routes, host, port)
路由选择格式
val route =
  a {
    b {
      c {
        ... // route 1
      } ~
      d {
        ... // route 2
      } ~
      ... // route 3
    } ~
    e {
      ... // route 4
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值