[comment]: # Spark集群 + Akka + Kafka + Scala 开发(3) : 开发一个Akka + Spark的应用

前言

Spark集群 + Akka + Kafka + Scala 开发(1) : 配置开发环境中,我们已经部署好了一个Spark的开发环境。

Spark集群 + Akka + Kafka + Scala 开发(2) : 开发一个Spark应用中,我们已经写好了一个Spark的应用。

本文的目标是写一个基于akka的scala工程,在一个spark standalone的集群环境中运行。

akka是什么?

akka的作用

akka的名字是action kernel的回文。根据官方定义:akka用于resilient elastic distributed real-time transaction processing。

个人理解是:

resilient:是指对需求和安全性等方面(来自于外部的)的一种适应力(弹性)。

elastic:是指对资源利用方面的弹性。

因此,akka是一个满足需求弹性、资源分配弹性的分布式实时事务处理系统。

akka只是一个类库,一个工具,并没有提供一个平台。

akka的运行模式和用例

  • akka有两种运行模式:

    • As a library: 一个使用于web应用,把akka作为一个普通的jar包放到classpath或者WEB-INF/lib
    • As an application: 也称为micro system。
  • akka的用例

    akka的用例很多,可以参照Examples of use-cases for Akka.

本文中的用例

在本文中,一个Spark + akka的环境里,akka被用于as an application模式下。

我们会创建一个akka工程,含有两个应用:

  • akka host application

    建立一个actor system, 定义了所有的任务(actors)。等待客户端的请求。

    部分actor使用了spark的云计算功能。

    这是一个spark的应用。
  • akka client application

    调用host application上特定的actor。

我们看出,这里我们把akka作为一个任务处理器,并通过spark来完成任务。

项目结构和文件说明

说明

这个工程包含了两个应用。

一个Consumer应用:CusomerApp:实现了通过Spark的Stream+Kafka的技术来实现处理消息的功能。

一个Producer应用:ProducerApp:实现了向Kafka集群发消息的功能。

文件结构

AkkaSampleApp    # 项目目录
|-- build.bat # build文件
|-- src
|-- main
|-- resources
|-- application.conf # Akka Server应用的配置文件
|-- client.conf # Akka Client应用的配置文件
|-- scala
|-- ClientActor.scala # Akka Client的Actor:提供了一种调用Server Actor的方式。
|-- ClientApp.scala # Akka Client应用
|-- ProductionReaper.scala # Akka Shutdown pattern的实现者
|-- Reaper.scala # Akka Shutdown pattern的Reaper抽象类
|-- ServerActor.scala # Akka Server的Actor,提供一个求1到n的MapReduce计算。使用了Spark。
|-- ServerApp.scala # Akka Server应用

构建工程目录

可以运行:

mkdir AkkaSampleApp
mkdir -p /AkkaSampleApp/src/main/resources
mkdir -p /AkkaSampleApp/src/main/scala

代码

build.sbt

name := "akka-sample-app"

version := "1.0"

scalaVersion := "2.11.8"

scalacOptions += "-feature"
scalacOptions += "-deprecation"
scalacOptions += "-language:postfixOps" libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % "2.4.10",
"com.typesafe.akka" %% "akka-remote" % "2.4.10",
"org.apache.spark" %% "spark-core" % "2.0.0"
) resolvers += "Akka Snapshots" at "http://repo.akka.io/snapshots/"

application.conf

akka {
#loglevel = "DEBUG"
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port = 2552
}
#log-sent-messages = on
#log-received-messages = on
}
}

cient.conf

akka {
#loglevel = "DEBUG"
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port = 0
}
#log-sent-messages = on
#log-received-messages = on
}
}

注:port = 0表示这个端口号会自动生成一个。

ClientActor.scala

import akka.actor._
import akka.event.Logging class ClientActor(serverPath: String) extends Actor {
val log = Logging(context.system, this)
val serverActor = context.actorSelection(serverPath) def receive = {
case msg: String =>
log.info(s"ClientActor received message '$msg'")
serverActor ! 10000L
}
}

ClientApp.scala

import com.typesafe.config.ConfigFactory
import akka.actor._
import akka.remote.RemoteScope
import akka.util._ import java.util.concurrent.TimeUnit import scala.concurrent._
import scala.concurrent.duration._ object ClientApp {
def main(args: Array[String]): Unit = {
val system = ActorSystem("LocalSystem", ConfigFactory.load("client")) // get the remote actor via the server actor system's address
val serverAddress = AddressFromURIString("akka.tcp://ServerActorSystem@127.0.0.1:2552")
val actor = system.actorOf(Props[ServerActor].withDeploy(Deploy(scope = RemoteScope(serverAddress)))) // invoke the remote actor via a client actor.
// val remotePath = "akka.tcp://ServerActorSystem@127.0.0.1:2552/user/serverActor"
// val actor = system.actorOf(Props(classOf[ClientActor], remotePath), "clientActor") buildReaper(system, actor) // tell
actor ! 10000L waitShutdown(system, actor)
} private def buildReaper(system: ActorSystem, actor: ActorRef): Unit = {
import Reaper._
val reaper = system.actorOf(Props(classOf[ProductionReaper])) // Watch the action
reaper ! WatchMe(actor)
} private def waitShutdown(system: ActorSystem, actor: ActorRef): Unit = {
// trigger the shutdown operation in ProductionReaper
system.stop(actor) // wait to shutdown
Await.result(system.whenTerminated, 60.seconds)
}
}

ProductionReaper.scala

当所有的Actor停止后,终止Actor System。

class ProductionReaper extends Reaper {
// Shutdown
def allSoulsReaped(): Unit = {
context.system.terminate()
}
}

Reaper.scala

import akka.actor.{Actor, ActorRef, Terminated}
import scala.collection.mutable.ArrayBuffer object Reaper {
// Used by others to register an Actor for watching
case class WatchMe(ref: ActorRef)
} abstract class Reaper extends Actor {
import Reaper._ // Keep track of what we're watching
val watched = ArrayBuffer.empty[ActorRef] // Derivations need to implement this method. It's the
// hook that's called when everything's dead
def allSoulsReaped(): Unit // Watch and check for termination
final def receive = {
case WatchMe(ref) =>
context.watch(ref)
watched += ref
case Terminated(ref) =>
watched -= ref
if (watched.isEmpty) allSoulsReaped()
}
}

ServerActor.scala

提供一个求1到n平方和的MapReduce计算。

import akka.actor.Actor
import akka.actor.Props
import akka.event.Logging import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._
import org.apache.spark.SparkConf class ServerActor extends Actor {
val log = Logging(context.system, this) def receive = {
case n: Long =>
squareSum(n)
} private def squareSum(n: Long): Long = {
val conf = new SparkConf().setAppName("Simple Application")
val sc = new SparkContext(conf) val squareSum = sc.parallelize(1L until n).map { i =>
i * i
}.reduce(_ + _) log.info(s"============== The square sum of $n is $squareSum. ==============") squareSum
}
}

ServerApp.scala

import scala.concurrent.duration._
import com.typesafe.config.ConfigFactory
import akka.actor.ActorSystem
import akka.actor.Props object ServerApp {
def main(args: Array[String]): Unit = {
val system = ActorSystem("ServerActorSystem")
val actor = system.actorOf(Props[ServerActor], name = "serverActor")
}
}

构建工程

进入目录AkkaSampleApp。运行:

sbt package

第一次运行时间会比较长。

测试应用

启动Spark服务

  • 启动spark集群master server
$SPARK_HOME/sbin/start-master.sh

master服务,默认会使用7077这个端口。可以通过其日志文件查看实际的端口号。

  • 启动spark集群slave server
$SPARK_HOME/sbin/start-slave.sh spark://$(hostname):7077

启动Akka Server应用

运行:

$SPARK_HOME/bin/spark-submit --master spark://$(hostname):7077 --class ServerApp target/scala-2.11/akka-sample-app_2.11-1.0.jar

如果出现java.lang.NoClassDefFoundError错误,

请参照Spark集群 + Akka + Kafka + Scala 开发(1) : 配置开发环境

确保akka的包在Spark中设置好了。

注:可以使用Ctrl+C来中断这个Server应用。

启动Akka Client应用

新启动一个终端,运行:

java -classpath ./target/scala-2.11/akka-sample-app_2.11-1.0.jar:$AKKA_HOME/lib/akka/*:$SCALA_HOME/lib/* ClientApp
# or
# $SPARK_HOME/bin/spark-submit --master spark://$(hostname):7077 --class ClientApp target/scala-2.11/akka-sample-app_2.11-1.0.jar

然后:看看Server应用是否开始处理了。

总结

Server应用需要Spark的技术,因此,是在Spark环境中运行。

Clinet应用,可以是一个普通的Java应用。

下面请看

至此,我们已经写好了一个spark集群+akka+scala的应用。下一步请看:

Spark集群 + Akka + Kafka + Scala 开发(4) : 开发一个Kafka + Spark的应用

参照

Spark集群 + Akka + Kafka + Scala 开发(3) : 开发一个Akka + Spark的应用的更多相关文章

  1. Spark入门:第2节 Spark集群安装:1 - 3;第3节 Spark HA高可用部署:1 - 2

    三. Spark集群安装 3.1 下载spark安装包 下载地址spark官网:http://spark.apache.org/downloads.html 这里我们使用 spark-2.1.3-bi ...

  2. 大数据技术之_19_Spark学习_01_Spark 基础解析 + Spark 概述 + Spark 集群安装 + 执行 Spark 程序

    第1章 Spark 概述1.1 什么是 Spark1.2 Spark 特点1.3 Spark 的用户和用途第2章 Spark 集群安装2.1 集群角色2.2 机器准备2.3 下载 Spark 安装包2 ...

  3. hadoop+spark集群搭建入门

    忽略元数据末尾 回到原数据开始处 Hadoop+spark集群搭建 说明: 本文档主要讲述hadoop+spark的集群搭建,linux环境是centos,本文档集群搭建使用两个节点作为集群环境:一个 ...

  4. CentOS7 安装spark集群

    Spark版本 1.6.0 Scala版本 2.11.7 Zookeeper版本 3.4.7 配置虚拟机 3台虚拟机,sm,sd1,sd2 1. 关闭防火墙 systemctl stop firewa ...

  5. spark集群搭建

    文中的所有操作都是在之前的文章scala的安装及使用文章基础上建立的,重复操作已经简写: 配置中使用了master01.slave01.slave02.slave03: 一.虚拟机中操作(启动网卡)s ...

  6. Spark学习笔记5:Spark集群架构

    Spark的一大好处就是可以通过增加机器数量并使用集群模式运行,来扩展计算能力.Spark可以在各种各样的集群管理器(Hadoop YARN , Apache Mesos , 还有Spark自带的独立 ...

  7. Spark集群新增节点方法

    Spark集群处理能力不足需要扩容,如何在现有spark集群中新增新节点?本文以一个实例介绍如何给Spark集群新增一个节点. 1. 集群环境 现有Spark集群包括3台机器,用户名都是cdahdp, ...

  8. Spark集群安装与配置

    一.Scala安装 1.https://www.scala-lang.org/download/2.11.12.html下载并复制到/home/jun下解压 [jun@master ~]$ cd sc ...

  9. Spark 个人实战系列(1)--Spark 集群安装

    前言: CDH4不带yarn和spark, 因此需要自己搭建spark集群. 这边简单描述spark集群的安装过程, 并讲述spark的standalone模式, 以及对相关的脚本进行简单的分析. s ...

  10. Spark集群术语

    Spark集群术语解析 1. Application Application是用户在Spark上构建(编写)的程序,包含driver program 和executors(分布在集群中多个节点上运行的 ...

随机推荐

  1. java 线程安全 Lock

    java.util.concurrent.locks 对于线程安全我们前面使用了synchronized关键字,对于线程的协作我们使用Object.wait()和Object.notify().在JD ...

  2. 学习ASP.NET MVC(三)——我的第一个ASP.NET MVC 视图

    今天我将对前一篇文章中的示例进行修改,前一篇文章中并没有用到视图,这次将用到视图.对于前一个示例中的HelloWorldController类进行修改,使用视图模板文件生成HTML响应给浏览器. 一. ...

  3. echart饼状图使用,打发时间。

    新公司,刚来几天,闲着没事,领导让我做些无关痛痒的活,优化报表统计!!!之前是用flash做的,现在要改成echart实现.好吧,之前没用过,抱着学习态度,研究了下.写点东西打发下时间,能帮到需要帮助 ...

  4. 【SQL】姗姗来迟的SQL Server 安装图解

     逆天今天被人拉过去装了个数据库...顺便就记录一下安装过程吧,一直想发一直没时间弄,今天就发下安装过程吧,2012和2008安装过程一样的 [注意安装细节]         安装过程中如果出现问题参 ...

  5. 【WP开发】使用磁倾仪

    磁倾仪,也叫倾斜仪,主要用来检测手机设备在各个轴上旋转的角度.注意,磁倾仪与陀螺仪的差异,陀螺仪的关注点是旋转的角速度,它并不关注角度,只注重速度.而磁倾仪的读数就是设备倾斜的角度. 不管是使用重力感 ...

  6. OpenCASCADE Application Framework Data Framework Services

    OpenCASCADE Application Framework Data Framework Services eryar@163.com 一.概述Overview OpenCASCADE的数据框 ...

  7. 拓扑排序(二)之 C++详解

    本章是通过C++实现拓扑排序. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑排序的代码说明 4. 拓扑排序的完整源码和测试程序 转载请注明出处:http://www.cnblogs. ...

  8. CSS SANS – 神奇!使用 CSS3 创建的字体

    在我们的认识中,CSS 所能做的就是改变网页的排版布局,调整字间距等.然而,这里我们要介绍的则是使用 CSS3 制作字体.CSS SANS 可以通过 CSS 技术创建的A-Z字体,一起来围观下. 在线 ...

  9. EasyUI笔记

    以下功能实现朋友们若有更好的思路办法,欢迎留言交流. 1.关闭其他标签页(右键菜单触发,保留左侧第一个欢迎tab) 问题:取到的数组tabs长度会随着tab的关闭而变化 思路:先遍历需要关闭的标签页t ...

  10. JavaScript中,提取子字符串方法:Slice、Substring、Substr的比较。

    在JavaScript中,提取子字符串主要是通过 Slice.Substring.Substr 三个方法之一. // slice // 语法: string.slice(beginSlice [, e ...