一、概述

  1.什么是akka

    

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

  更多入门的基础与介绍,参考https://www.iteblog.com/archives/1154.html

  入门系列推荐http://www.cnblogs.com/tiger-xc/p/6785575.html

  akka官网https://akka.io/

  2.Actor模型

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

  

  

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

  1.提供了一种高级抽象,能够简化在并发(Concurrency)/并行(Parallelism)应用场景下的编程开发

  2.提供了异步非阻塞的、高性能的事件驱动编程模型

  3.超级轻量级事件处理(每GB堆内存几百万Actor)

  3.Actor角色

  Akka中角色主要分为ActorSystem和Actor,这和Hadoop中有点儿类似。一个老大负责监管,下面小弟负责干活

  ActorSystem

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

  Actor 

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

    1.preStart()方法:该方法在Actor对象构造方法执行后执行,整个Actor生命周期中仅执行一次。

    2.receive()方法:该方法在Actor的preStart方法执行完成后执行,用于接收消息,会被反复执行。

二、使用akka实现简单的RPC框架

  1.使用maven创建工程(或者SBT)

    使用maven创建工程:https://www.cnblogs.com/hd-zg/p/5951185.html

    引入akka依赖

  1. <!-- akka依赖-->
  2. <dependency>
  3. <groupId>com.typesafe.akka</groupId>
  4. <artifactId>akka-actor_2.10</artifactId>
  5. <version>2.3.14</version>
  6. </dependency>
  7.  
  8. <dependency>
  9. <groupId>com.typesafe.akka</groupId>
  10. <artifactId>akka-remote_2.10</artifactId>
  11. <version>2.3.14</version>
  12. </dependency>

 pom如下:(build等可以修改)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6.  
  7. <groupId>cn.itcast.akka</groupId>
  8. <artifactId>my-rpc</artifactId>
  9. <version>1.0</version>
  10.  
  11. <properties>
  12. <maven.compiler.source>1.7</maven.compiler.source>
  13. <maven.compiler.target>1.7</maven.compiler.target>
  14. <encoding>UTF-8</encoding>
  15. <scala.version>2.10.6</scala.version>
  16. <scala.compat.version>2.10</scala.compat.version>
  17. </properties>
  18.  
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.scala-lang</groupId>
  22. <artifactId>scala-library</artifactId>
  23. <version>${scala.version}</version>
  24. </dependency>
  25.  
  26. <dependency>
  27. <groupId>com.typesafe.akka</groupId>
  28. <artifactId>akka-actor_2.10</artifactId>
  29. <version>2.3.14</version>
  30. </dependency>
  31.  
  32. <dependency>
  33. <groupId>com.typesafe.akka</groupId>
  34. <artifactId>akka-remote_2.10</artifactId>
  35. <version>2.3.14</version>
  36. </dependency>
  37.  
  38. </dependencies>
  39.  
  40. <build>
  41. <sourceDirectory>src/main/scala</sourceDirectory>
  42. <testSourceDirectory>src/test/scala</testSourceDirectory>
  43. <plugins>
  44. <plugin>
  45. <groupId>net.alchim31.maven</groupId>
  46. <artifactId>scala-maven-plugin</artifactId>
  47. <version>3.2.2</version>
  48. <executions>
  49. <execution>
  50. <goals>
  51. <goal>compile</goal>
  52. <goal>testCompile</goal>
  53. </goals>
  54. <configuration>
  55. <args>
  56. <arg>-make:transitive</arg>
  57. <arg>-dependencyfile</arg>
  58. <arg>${project.build.directory}/.scala_dependencies</arg>
  59. </args>
  60. </configuration>
  61. </execution>
  62. </executions>
  63. </plugin>
  64.  
  65. <plugin>
  66. <groupId>org.apache.maven.plugins</groupId>
  67. <artifactId>maven-shade-plugin</artifactId>
  68. <version>2.4.3</version>
  69. <executions>
  70. <execution>
  71. <phase>package</phase>
  72. <goals>
  73. <goal>shade</goal>
  74. </goals>
  75. <configuration>
  76. <filters>
  77. <filter>
  78. <artifact>*:*</artifact>
  79. <excludes>
  80. <exclude>META-INF/*.SF</exclude>
  81. <exclude>META-INF/*.DSA</exclude>
  82. <exclude>META-INF/*.RSA</exclude>
  83. </excludes>
  84. </filter>
  85. </filters>
  86. <transformers>
  87. <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  88. <resource>reference.conf</resource>
  89. </transformer>
  90. <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  91. <mainClass>cn.itcast.akkk.Master</mainClass>
  92. </transformer>
  93. </transformers>
  94. </configuration>
  95. </execution>
  96. </executions>
  97. </plugin>
  98. </plugins>
  99. </build>
  100.  
  101. </project>

 打包可以使用shade这个插件

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-shade-plugin</artifactId>
  4. <version>2.4.3</version>
  5. <executions>
  6. <execution>
  7. <phase>package</phase>
  8. <goals>
  9. <goal>shade</goal>
  10. </goals>
  11. <configuration>
  12. <filters>
  13. <filter>
  14. <artifact>*:*</artifact>
  15. <excludes>
  16. <exclude>META-INF/*.SF</exclude>
  17. <exclude>META-INF/*.DSA</exclude>
  18. <exclude>META-INF/*.RSA</exclude>
  19. </excludes>
  20. </filter>
  21. </filters>
  22. <transformers>
  23. <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
  24. <resource>reference.conf</resource>
  25. </transformer>
  26. <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
  27. <mainClass>cn.itcast.akkk.Master</mainClass>
  28. </transformer>
  29. </transformers>
  30. </configuration>
  31. </execution>
  32. </executions>
  33. </plugin>

  2.架构

  

  3.master程序示例

  1. package cn.jiangbei.akka
  2.  
  3. import java.io.FileInputStream
  4. import java.util.Properties
  5.  
  6. import akka.actor.{Actor, ActorSystem, Props}
  7. import com.typesafe.config.ConfigFactory
  8.  
  9. class Master extends Actor {
  10.  
  11. println("构造器被调用!")
  12.  
  13. // 生命周期方法(类似的还有postStop)
  14. override def preStart(): Unit = {
  15. println("preStart生命周期方法被调用!")
  16. }
  17.  
  18. // 用于接收消息
  19. override def receive: Receive = {
  20. case "connect" => println("已连接!")
  21. case "hello" => println("hello!")
  22. }
  23. }
  24.  
  25. object Master {
  26. def main(args: Array[String]): Unit = {
  27. val properties = new Properties()
  28. val path = Thread.currentThread().getContextClassLoader.getResource("master.properties").getPath //文件要放到resource文件夹下
  29. properties.load(new FileInputStream(path))
  30. val config = ConfigFactory.parseProperties(properties)
  31. // 准备配置
  32. /* val host = args(0)
  33. val port = args(1).toInt
  34. val configStr =
  35. s"""
  36. |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
  37. |akka.remote.netty.tcp.hostname = "$host"
  38. |akka.remote.netty.tcp.port = "$port"
  39. """.stripMargin
  40. val config = ConfigFactory.parseString(configStr)*/
  41. // 创建和监控
  42. val actorSystem = ActorSystem("MasterSystem", config)
  43. // 创建Actor(以后Actor可以发送消息了)
  44. val master = actorSystem.actorOf(Props(new Master), "Master")
  45. master ! "hello"
  46. actorSystem.awaitTermination()
  47. }
  48. }

  4.worker和master通信

  1. package cn.jiangbei.akka
  2.  
  3. import java.io.FileInputStream
  4. import java.util.Properties
  5.  
  6. import akka.actor.{Actor, ActorSystem, Props}
  7. import com.typesafe.config.ConfigFactory
  8.  
  9. class Master extends Actor {
  10.  
  11. // 生命周期方法(类似的还有postStop)
  12. override def preStart(): Unit = {
  13. println("preStart生命周期方法被调用!")
  14. }
  15.  
  16. // 用于接收消息
  17. override def receive: Receive = {
  18. case "connect" => {
  19. println("已连接!")
  20. // 使用sender发送消息给worker
  21. sender ! "reply"
  22. }
  23. case "hello" => println("hello!")
  24. }
  25. }
  26.  
  27. object Master {
  28. def main(args: Array[String]): Unit = {
  29. val properties = new Properties()
  30. val path = Thread.currentThread().getContextClassLoader.getResource("master.properties").getPath //文件要放到resource文件夹下
  31. properties.load(new FileInputStream(path))
  32. val config = ConfigFactory.parseProperties(properties)
  33. // 准备配置
  34. /* val host = args(0)
  35. val port = args(1).toInt
  36. val configStr =
  37. s"""
  38. |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
  39. |akka.remote.netty.tcp.hostname = "$host"
  40. |akka.remote.netty.tcp.port = "$port"
  41. """.stripMargin
  42. val config = ConfigFactory.parseString(configStr)*/
  43. // 创建和监控
  44. val actorSystem = ActorSystem("MasterSystem", config)
  45. // 创建Actor(以后Actor可以发送消息了)
  46. val master = actorSystem.actorOf(Props(new Master), "Master")
  47. actorSystem.awaitTermination()
  48. }
  49. }

Master

  1. akka.actor.provider=akka.remote.RemoteActorRefProvider
  2. akka.remote.netty.tcp.hostname=127.0.0.1
  3. akka.remote.netty.tcp.port=8888

master.properties

  1. package cn.jiangbei.akka
  2.  
  3. import java.io.FileInputStream
  4. import java.util.Properties
  5.  
  6. import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
  7. import com.typesafe.config.ConfigFactory
  8.  
  9. class Worker extends Actor {
  10.  
  11. var master: ActorSelection = _
  12.  
  13. override def preStart(): Unit = {
  14. // 先与master建立连接(参数在Master运行时会打印在日志),context为继承Actor所提供
  15. // 同样,下面的地址端口也可以分离出来
  16. val masterHost = "127.0.0.1"
  17. val masterPort = 8888
  18. // /user/Master进行指定与哪个master通信
  19. master = context.actorSelection(s"akka.tcp://MasterSystem@$masterHost:$masterPort/user/Master")
  20. // 得到master引用后即可发送消息
  21. master ! "connect"
  22. }
  23.  
  24. override def receive: Receive = { // 返回的是一个偏函数
  25. case "reply" => println("收到master的回复!")
  26.  
  27. }
  28. }
  29.  
  30. object Worker {
  31. def main(args: Array[String]): Unit = {
  32. // 以下与Master类似
  33. val properties = new Properties()
  34. val path = Thread.currentThread().getContextClassLoader.getResource("worker.properties").getPath //文件要放到resource文件夹下
  35. properties.load(new FileInputStream(path))
  36. val config = ConfigFactory.parseProperties(properties)
  37. val actorSystem = ActorSystem("MasterSystem", config)
  38. // 创建Actor,再进行new Worker后会调用preStart()进行消息的发送
  39. actorSystem.actorOf(Props(new Worker), "Worker")
  40. actorSystem.awaitTermination()
  41. }
  42.  
  43. }

Worker

  1. akka.actor.provider=akka.remote.RemoteActorRefProvider
  2. akka.remote.netty.tcp.hostname=127.0.0.1
  3. akka.remote.netty.tcp.port=8889

worker.properties

大数据入门第二十一天——scala入门(二)并发编程Akka的更多相关文章

  1. 大数据入门第二十一天——scala入门(一)并发编程Actor

    注:我们现在学的Scala Actor是scala 2.10.x版本及以前版本的Actor. Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃 一. ...

  2. 大数据入门第二十天——scala入门(一)入门与配置

    一.概述 1.什么是scala  Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性.Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序. ...

  3. 大数据入门第二十天——scala入门(二)scala基础01

    一.基础语法 1.变量类型 // 上表中列出的数据类型都是对象,也就是说scala没有java中的原生类型.在scala是可以对数字等基础类型调用方法的. 2.变量声明——能用val的尽量使用val! ...

  4. 大数据入门第二十天——scala入门(二)scala基础02

    一. 类.对象.继承.特质 1.类 Scala的类与Java.C++的类比起来更简洁 定义: package com.jiangbei //在Scala中,类并不用声明为public. //Scala ...

  5. 大数据入门第十二天——sqoop入门

    一.概述 1.sqoop是什么 从其官网:http://sqoop.apache.org/ Apache Sqoop(TM) is a tool designed for efficiently tr ...

  6. 大数据入门第十二天——azkaban入门

    一.概述 1.azkaban是什么 通过官方文档:https://azkaban.github.io/ Azkaban is a batch workflow job scheduler create ...

  7. 大数据入门第十二天——flume入门

    一.概述 1.什么是flume 官网的介绍:http://flume.apache.org/ Flume is a distributed, reliable, and available servi ...

  8. 大数据入门第十九天——推荐系统与mahout(一)入门与概述

    一.推荐系统概述 为了解决信息过载和用户无明确需求的问题,找到用户感兴趣的物品,才有了个性化推荐系统.其实,解决信息过载的问题,代表性的解决方案是分类目录和搜索引擎,如hao123,电商首页的分类目录 ...

  9. 大数据入门第十七天——storm上游数据源 之kafka详解(一)入门与集群安装

    一.概述 1.kafka是什么 根据标题可以有个概念:kafka是storm的上游数据源之一,也是一对经典的组合,就像郭德纲和于谦 根据官网:http://kafka.apache.org/intro ...

随机推荐

  1. 手把手在MyEclipse中搭建Hibernate开发环境

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/53414303冷血之心的博客) 在MyEclipse中如何搭建Hib ...

  2. NodeJS配置TaoBao源

    npm install -g cnpm --registry=https://registry.npm.taobao.org

  3. R中的空间数据分析

    > library(sp) > library(maptools) > library(raster) > library(rgeos) > maxd3 = readAs ...

  4. CSS 实例之打开大门

    本个实例主要的效果如下图所示 本案例主要运用到了3D旋转和定位技术.具体步骤如下: 1.首先在页面主体加三个很简单的div标签: <div class="door"> ...

  5. 如何配置Linux的服务设置为自动启动或崩溃重新启动后

    介绍 在本教程中,自动启动 Linux 服务,我们将退后一步,更详细地解释 init 进程. 你应该很好地了解它们如何控制守护进程的启动行为. 在第一部分本系列教程我们分享使用 MySQL 的如何崩溃 ...

  6. ulimit linux文件配置

    文件描述符在形式上是一个非负整数.实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表.当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符.在程序设计中,一 ...

  7. git 学习汇总

    生成gitignore 文件: https://gitignore.io/ git 版本回退 git reset --hard HEAD^ 上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然 ...

  8. Spring Boot 集成 thymeleaf 模版引擎

    Spring Boot 建议使用 HTML 来完成动态页面.Spring Boot 提供了大量的模版引擎,包括 Thymeleaf.FreeMarker.Velocity等. Spring Boot ...

  9. [BUG]自己的bug自己解,记一次在变量使用过程引发的bug

    [实现的功能要求]在短信编辑界面,将所有的emoji表情全部插入到编辑区域,其中表情共有5页,每遍历完一页时需要自动翻页重新获取表情并插入,在第5页中只有10个表情 下面先看看这段代码,大家能否看出有 ...

  10. 1.数据结构&算法的引言+时间复杂度

    一.什么是计算机科学? 首先明确的一点就是计算机科学不仅仅是对计算机的研究,虽然计算机在科学发展的过程中发挥了重大的作用,但是它只是一个工具,一个没有灵魂的工具而已.所谓的计算机科学实际上是对问题.解 ...