大数据入门第二十一天——scala入门(二)并发编程Akka
一、概述
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依赖
- <!-- akka依赖-->
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-actor_2.10</artifactId>
- <version>2.3.14</version>
- </dependency>
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-remote_2.10</artifactId>
- <version>2.3.14</version>
- </dependency>
pom如下:(build等可以修改)
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>cn.itcast.akka</groupId>
- <artifactId>my-rpc</artifactId>
- <version>1.0</version>
- <properties>
- <maven.compiler.source>1.7</maven.compiler.source>
- <maven.compiler.target>1.7</maven.compiler.target>
- <encoding>UTF-8</encoding>
- <scala.version>2.10.6</scala.version>
- <scala.compat.version>2.10</scala.compat.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.scala-lang</groupId>
- <artifactId>scala-library</artifactId>
- <version>${scala.version}</version>
- </dependency>
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-actor_2.10</artifactId>
- <version>2.3.14</version>
- </dependency>
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-remote_2.10</artifactId>
- <version>2.3.14</version>
- </dependency>
- </dependencies>
- <build>
- <sourceDirectory>src/main/scala</sourceDirectory>
- <testSourceDirectory>src/test/scala</testSourceDirectory>
- <plugins>
- <plugin>
- <groupId>net.alchim31.maven</groupId>
- <artifactId>scala-maven-plugin</artifactId>
- <version>3.2.2</version>
- <executions>
- <execution>
- <goals>
- <goal>compile</goal>
- <goal>testCompile</goal>
- </goals>
- <configuration>
- <args>
- <arg>-make:transitive</arg>
- <arg>-dependencyfile</arg>
- <arg>${project.build.directory}/.scala_dependencies</arg>
- </args>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <version>2.4.3</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>shade</goal>
- </goals>
- <configuration>
- <filters>
- <filter>
- <artifact>*:*</artifact>
- <excludes>
- <exclude>META-INF/*.SF</exclude>
- <exclude>META-INF/*.DSA</exclude>
- <exclude>META-INF/*.RSA</exclude>
- </excludes>
- </filter>
- </filters>
- <transformers>
- <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>reference.conf</resource>
- </transformer>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
- <mainClass>cn.itcast.akkk.Master</mainClass>
- </transformer>
- </transformers>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </project>
打包可以使用shade这个插件
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <version>2.4.3</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>shade</goal>
- </goals>
- <configuration>
- <filters>
- <filter>
- <artifact>*:*</artifact>
- <excludes>
- <exclude>META-INF/*.SF</exclude>
- <exclude>META-INF/*.DSA</exclude>
- <exclude>META-INF/*.RSA</exclude>
- </excludes>
- </filter>
- </filters>
- <transformers>
- <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>reference.conf</resource>
- </transformer>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
- <mainClass>cn.itcast.akkk.Master</mainClass>
- </transformer>
- </transformers>
- </configuration>
- </execution>
- </executions>
- </plugin>
2.架构
3.master程序示例
- package cn.jiangbei.akka
- import java.io.FileInputStream
- import java.util.Properties
- import akka.actor.{Actor, ActorSystem, Props}
- import com.typesafe.config.ConfigFactory
- class Master extends Actor {
- println("构造器被调用!")
- // 生命周期方法(类似的还有postStop)
- override def preStart(): Unit = {
- println("preStart生命周期方法被调用!")
- }
- // 用于接收消息
- override def receive: Receive = {
- case "connect" => println("已连接!")
- case "hello" => println("hello!")
- }
- }
- object Master {
- def main(args: Array[String]): Unit = {
- val properties = new Properties()
- val path = Thread.currentThread().getContextClassLoader.getResource("master.properties").getPath //文件要放到resource文件夹下
- properties.load(new FileInputStream(path))
- val config = ConfigFactory.parseProperties(properties)
- // 准备配置
- /* 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)*/
- // 创建和监控
- val actorSystem = ActorSystem("MasterSystem", config)
- // 创建Actor(以后Actor可以发送消息了)
- val master = actorSystem.actorOf(Props(new Master), "Master")
- master ! "hello"
- actorSystem.awaitTermination()
- }
- }
4.worker和master通信
- package cn.jiangbei.akka
- import java.io.FileInputStream
- import java.util.Properties
- import akka.actor.{Actor, ActorSystem, Props}
- import com.typesafe.config.ConfigFactory
- class Master extends Actor {
- // 生命周期方法(类似的还有postStop)
- override def preStart(): Unit = {
- println("preStart生命周期方法被调用!")
- }
- // 用于接收消息
- override def receive: Receive = {
- case "connect" => {
- println("已连接!")
- // 使用sender发送消息给worker
- sender ! "reply"
- }
- case "hello" => println("hello!")
- }
- }
- object Master {
- def main(args: Array[String]): Unit = {
- val properties = new Properties()
- val path = Thread.currentThread().getContextClassLoader.getResource("master.properties").getPath //文件要放到resource文件夹下
- properties.load(new FileInputStream(path))
- val config = ConfigFactory.parseProperties(properties)
- // 准备配置
- /* 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)*/
- // 创建和监控
- val actorSystem = ActorSystem("MasterSystem", config)
- // 创建Actor(以后Actor可以发送消息了)
- val master = actorSystem.actorOf(Props(new Master), "Master")
- actorSystem.awaitTermination()
- }
- }
Master
- akka.actor.provider=akka.remote.RemoteActorRefProvider
- akka.remote.netty.tcp.hostname=127.0.0.1
- akka.remote.netty.tcp.port=8888
master.properties
- package cn.jiangbei.akka
- import java.io.FileInputStream
- import java.util.Properties
- import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
- import com.typesafe.config.ConfigFactory
- class Worker extends Actor {
- var master: ActorSelection = _
- override def preStart(): Unit = {
- // 先与master建立连接(参数在Master运行时会打印在日志),context为继承Actor所提供
- // 同样,下面的地址端口也可以分离出来
- val masterHost = "127.0.0.1"
- val masterPort = 8888
- // /user/Master进行指定与哪个master通信
- master = context.actorSelection(s"akka.tcp://MasterSystem@$masterHost:$masterPort/user/Master")
- // 得到master引用后即可发送消息
- master ! "connect"
- }
- override def receive: Receive = { // 返回的是一个偏函数
- case "reply" => println("收到master的回复!")
- }
- }
- object Worker {
- def main(args: Array[String]): Unit = {
- // 以下与Master类似
- val properties = new Properties()
- val path = Thread.currentThread().getContextClassLoader.getResource("worker.properties").getPath //文件要放到resource文件夹下
- properties.load(new FileInputStream(path))
- val config = ConfigFactory.parseProperties(properties)
- val actorSystem = ActorSystem("MasterSystem", config)
- // 创建Actor,再进行new Worker后会调用preStart()进行消息的发送
- actorSystem.actorOf(Props(new Worker), "Worker")
- actorSystem.awaitTermination()
- }
- }
Worker
- akka.actor.provider=akka.remote.RemoteActorRefProvider
- akka.remote.netty.tcp.hostname=127.0.0.1
- akka.remote.netty.tcp.port=8889
worker.properties
大数据入门第二十一天——scala入门(二)并发编程Akka的更多相关文章
- 大数据入门第二十一天——scala入门(一)并发编程Actor
注:我们现在学的Scala Actor是scala 2.10.x版本及以前版本的Actor. Scala在2.11.x版本中将Akka加入其中,作为其默认的Actor,老版本的Actor已经废弃 一. ...
- 大数据入门第二十天——scala入门(一)入门与配置
一.概述 1.什么是scala Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性.Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序. ...
- 大数据入门第二十天——scala入门(二)scala基础01
一.基础语法 1.变量类型 // 上表中列出的数据类型都是对象,也就是说scala没有java中的原生类型.在scala是可以对数字等基础类型调用方法的. 2.变量声明——能用val的尽量使用val! ...
- 大数据入门第二十天——scala入门(二)scala基础02
一. 类.对象.继承.特质 1.类 Scala的类与Java.C++的类比起来更简洁 定义: package com.jiangbei //在Scala中,类并不用声明为public. //Scala ...
- 大数据入门第十二天——sqoop入门
一.概述 1.sqoop是什么 从其官网:http://sqoop.apache.org/ Apache Sqoop(TM) is a tool designed for efficiently tr ...
- 大数据入门第十二天——azkaban入门
一.概述 1.azkaban是什么 通过官方文档:https://azkaban.github.io/ Azkaban is a batch workflow job scheduler create ...
- 大数据入门第十二天——flume入门
一.概述 1.什么是flume 官网的介绍:http://flume.apache.org/ Flume is a distributed, reliable, and available servi ...
- 大数据入门第十九天——推荐系统与mahout(一)入门与概述
一.推荐系统概述 为了解决信息过载和用户无明确需求的问题,找到用户感兴趣的物品,才有了个性化推荐系统.其实,解决信息过载的问题,代表性的解决方案是分类目录和搜索引擎,如hao123,电商首页的分类目录 ...
- 大数据入门第十七天——storm上游数据源 之kafka详解(一)入门与集群安装
一.概述 1.kafka是什么 根据标题可以有个概念:kafka是storm的上游数据源之一,也是一对经典的组合,就像郭德纲和于谦 根据官网:http://kafka.apache.org/intro ...
随机推荐
- 手把手在MyEclipse中搭建Hibernate开发环境
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/53414303冷血之心的博客) 在MyEclipse中如何搭建Hib ...
- NodeJS配置TaoBao源
npm install -g cnpm --registry=https://registry.npm.taobao.org
- R中的空间数据分析
> library(sp) > library(maptools) > library(raster) > library(rgeos) > maxd3 = readAs ...
- CSS 实例之打开大门
本个实例主要的效果如下图所示 本案例主要运用到了3D旋转和定位技术.具体步骤如下: 1.首先在页面主体加三个很简单的div标签: <div class="door"> ...
- 如何配置Linux的服务设置为自动启动或崩溃重新启动后
介绍 在本教程中,自动启动 Linux 服务,我们将退后一步,更详细地解释 init 进程. 你应该很好地了解它们如何控制守护进程的启动行为. 在第一部分本系列教程我们分享使用 MySQL 的如何崩溃 ...
- ulimit linux文件配置
文件描述符在形式上是一个非负整数.实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表.当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符.在程序设计中,一 ...
- git 学习汇总
生成gitignore 文件: https://gitignore.io/ git 版本回退 git reset --hard HEAD^ 上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然 ...
- Spring Boot 集成 thymeleaf 模版引擎
Spring Boot 建议使用 HTML 来完成动态页面.Spring Boot 提供了大量的模版引擎,包括 Thymeleaf.FreeMarker.Velocity等. Spring Boot ...
- [BUG]自己的bug自己解,记一次在变量使用过程引发的bug
[实现的功能要求]在短信编辑界面,将所有的emoji表情全部插入到编辑区域,其中表情共有5页,每遍历完一页时需要自动翻页重新获取表情并插入,在第5页中只有10个表情 下面先看看这段代码,大家能否看出有 ...
- 1.数据结构&算法的引言+时间复杂度
一.什么是计算机科学? 首先明确的一点就是计算机科学不仅仅是对计算机的研究,虽然计算机在科学发展的过程中发挥了重大的作用,但是它只是一个工具,一个没有灵魂的工具而已.所谓的计算机科学实际上是对问题.解 ...