Scala系列——Akka并发编程

打个广告,帮朋友卖点东西,东西超便宜的哟,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

Scala系列——Akka并发编程_第1张图片 微信

一、Akka简介

1、基本介绍

        Akka基于Actor模型,提供了一个用于构建可扩展的(Scalable)、弹性的(Resilient)、快速响应的(Responsive)应用程序的平台。

        Actor模型:在计算机科学领域,Actor模型是一个并行计算(Concurrent Computation)模型,它把actor作为并行计算的基本元素来对待:为响应一个接收到的消息,一个actor能够自己做出一些决策,如创建更多的actor,或发送更多的消息,或者确定如何去响应接收到的下一个消息。

Scala系列——Akka并发编程_第2张图片

        Actor是Akka中最核心的概念,它是一个封装了状态和行为的对象,Actor之间可以通过交换消息的方式进行通信,每个Actor都有自己的收件箱(Mailbox)。通过Actor能够简化锁及线程管理,可以非常容易地开发出正确地并发程序和并行系统,Actor具有如下特性:

  • 提供了一种高级抽象,能够简化在并发(Concurrency)/并行(Parallelism)应用场景下的编程开发
  • 提供了异步非阻塞的、高性能的事件驱动编程模型
  • 超级轻量级事件处理(每GB堆内存几百万Actor)

2、重要类介绍

1.ActorSystem

        在Akka中,ActorSystem是一个重量级的结构,他需要分配多个线程,所以在实际应用中,ActorSystem通常是一个单例对象,我们可以使用这个ActorSystem创建很多Actor。

2.Actor

        在Akka中,Actor负责通信,在Actor中有一些重要的生命周期方法。

  • preStart()方法:该方法在Actor对象构造方法执行后执行,整个Actor生命周期中仅执行一次。
  • receive()方法:该方法在Actor的preStart方法执行完成后执行,用于接收消息,会被反复执行。

二、RPC项目搭建

1、需求

        目前大多数的分布式架构底层通信都是通过RPC实现的,RPC框架非常多,比如前我们学过的Hadoop项目的RPC通信框架,但是Hadoop在设计之初就是为了运行长达数小时的批量而设计的,在某些极端的情况下,任务提交的延迟很高,所有Hadoop的RPC显得有些笨重。

        Spark 的RPC是通过Akka类库实现的,Akka用Scala语言开发,基于Actor并发模型实现,Akka具有高可靠、高性能、可扩展等特点,使用Akka可以轻松实现分布式RPC功能。

2、架构图

Scala系列——Akka并发编程_第3张图片

3、代码实现

首先maven构建如下:



    4.0.0
​
    com.scala
    my_rpc
    1.0-SNAPSHOT
​
    
        1.7
        1.7
        UTF-8
        2.10.6
        2.10
    
​
    
        
            org.scala-lang
            scala-library
            ${scala.version}
        
​
        
            com.typesafe.akka
            akka-actor_2.10
            2.3.14
        
​
        
            com.typesafe.akka
            akka-remote_2.10
            2.3.14
        
​
    
​
    
        
        src/main/scala
        src/test/scala
        
            
                net.alchim31.maven
                scala-maven-plugin
                3.2.2
                
                    
                        
                            compile
                            testCompile
                        
                        
                            
                                -make:transitive
                                -dependencyfile
                                ${project.build.directory}/.scala_dependencies
                            
                        
                    
                
            
​
            
                org.apache.maven.plugins
                maven-shade-plugin
                2.4.3
                
                    
                        package
                        
                            shade
                        
                        
                            
                                
                                    *:*
                                    
                                        META-INF/*.SF
                                        META-INF/*.DSA
                                        META-INF/*.RSA
                                    
                                
                            
                            
                                
                                    reference.conf
                                
                                
                                    com.scala.rpc.Worker
                                
                            
                        
                    
                
            
        
    

然后Master如下:

class Master extends Actor{
  println("constructor invoked")
​
  override def preStart(): Unit = {
    println("preStart invoked")
  }
​
  // 用于接收消息
  override def receive: Receive = {
    case "connect" => {
      println("a client connected")
      sender ! "reply"
    }
​
    case "hello" => {
      println("hello")
    }
  }
}
​
object Master {
  def main(args: Array[String]) {
​
    val host = args(0)
    val port = args(1).toInt
    // 准备配置
    val configStr =
      s"""
         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
         |akka.remote.netty.tcp.hostname = "$host"
         |akka.remote.netty.tcp.port = "$port"
       """.stripMargin
    val config = ConfigFactory.parseString(configStr)
    //ActorSystem老大,辅助创建和监控下面的Actor,他是单例的
    val actorSystem = ActorSystem("MasterSystem", config)
    //创建Actor, 起个名字
    val master = actorSystem.actorOf(Props[Master], "Master")//Master主构造器会执行
    master ! "hello"  //发送信息
    actorSystem.awaitTermination()  //让进程等待着, 先别结束
  }
}

Worker如下:

class Worker(val masterHost: String, val masterPort: Int) extends Actor{
​
  var master : ActorSelection = _
  //建立连接
  override def preStart(): Unit = {
    //在master启动时会打印下面的那个协议, 可以先用这个做一个标志, 连接哪个master
    //继承actor后会有一个context, 可以通过它来连接
    //需要有/user, Master要和master那边创建的名字保持一致(val master = actorSystem.actorOf(Props[Master], "Master"))
    master = context.actorSelection(s"akka.tcp://MasterSystem@$masterHost:$masterPort/user/Master")
    master ! "connect"
  }
​
  override def receive: Receive = {
    case "reply" => {
      println("a reply form master")
    }
  }
}
​
object Worker {
  def main(args: Array[String]) {
    val host = args(0)
    val port = args(1).toInt
    val masterHost = args(2)
    val masterPort = args(3).toInt
    // 准备配置
    val configStr =
      s"""
         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
         |akka.remote.netty.tcp.hostname = "$host"
         |akka.remote.netty.tcp.port = "$port"
       """.stripMargin
    val config = ConfigFactory.parseString(configStr)
    //ActorSystem老大,辅助创建和监控下面的Actor,他是单例的
    val actorSystem = ActorSystem("WorkerSystem", config)
    actorSystem.actorOf(Props(new Worker(masterHost, masterPort)), "Worker")
    actorSystem.awaitTermination()
  }
}

 

你可能感兴趣的:(Scala系列)