大數據開發-從Scala到Akka併發編程_jDW32G3c87fjEBtYNE7Z7f

大數據開發-從Scala到Akka併發編程

大數據開發-從Scala到Akka併發編程

[4-1 Scala作業.pdf](file/4-1 Scala作業_UVqqJLwoIp.pdf)

1.遞歸實現瓶蓋,瓶子換酒瓶的算法

1.1 需求描述

每瓶啤酒2元,3個空酒瓶或者5個瓶蓋可換1瓶啤酒。100元最多可喝多少瓶啤酒?(不允許借啤酒)
思路:利用遞歸算法,一次性買完,然後遞歸算出瓶蓋和空瓶能換的啤酒數

1.2 代碼實現

  def extralPeer(bot: Int, cap: Int): Int = {
    val count = bot / 3 + cap / 5
    if (count <= 0)
      return 0

    val modBot = bot % 3
    val modCap = cap % 5
    count + extralPeer(count + modBot, count + modCap)
  }

2.Scala實現猜拳遊戲

2.1 需求如下

  1. 選取對戰角色
  2. 開始對戰,用戶出拳,與對手進行比較,提示勝負信息
  3. 猜拳結束算分,平局都加一分,獲勝加二分,失敗不加分
  4. 循環對戰,當輸入“n”時,終止對戰,並顯示對戰結果
  5. 遊戲結束後顯示得分

2.2 實現邏輯和主要代碼

  1. 創建用戶類User,定義類的屬性(name,score)和類的方法(showFist())
  2. 創建計算機類Computer,定義類的屬性(name,score)和類的方法(showFist())
  3. 實現計算機隨機出拳
  4. 創建遊戲類Game,定義類的屬性(甲方玩家、乙方玩家、對戰次數)
  5. 編寫初始化方法、遊戲開始方法

主要代碼:

2.3 效果演示

代碼:https://github.com/hulichao/bigdata-code/tree/master/src/main/scala/com/hoult/scala/job/game

def extralPeer(bot: Int, cap: Int): Int = {
  val count = bot / 3 + cap / 5
  
  if (count <= 0)
  
    return 0
  
  val modBot = bot % 3
  
  val modCap = cap % 5
  
  count + extralPeer(count + modBot, count + modCap) 
  } 

3.用戶位置時長統計sql

3.1 需求描述

現有如下數據需要處理: 字段:用戶ID,位置ID,開始時間,停留時長(分鐘)
4行樣例數據:​ UserA,LocationA,8,60 UserA,LocationA,9,60 UserB,LocationB,10,60 UserB,LocationB,11,80 樣例
數據中的數據含義是: 用戶UserA,在LocationA位置,從8點開始,停留了60鍾
處理要求: 1、對同一個用戶,在同一個位置,連續的多條記錄進行合併 2、合併原則:開始時間取最早時間,停留
時長累計求和

3.2 Sql實現

select user_id, location_id, min(start_time) as start_time, sum(stay_time) as stay_time from t1 group by user_id, location_id

4.Actor間通訊

編寫兩個Actor, 分別是AActor和BActor,兩個Actor之間可以互相發送消息

4.1主要實現

先用一個start命令啓動AActor,然後給自己發 一個消息,啓動go後面的流程,然後A,B互相循環發送消息

主要代碼:https://github.com/hulichao/bigdata-code/tree/master/src/main/scala/com/hoult/scala/job/actor

object Demo {
  private val MyFactory = ActorSystem("myFactory")
  // 通過MyFactory.actorOf方法來創建一個actor;
  //只給A發消息,讓他們兩個Actor開始對話
  private val bActorRef = MyFactory.actorOf(Props[BActor], "bAcator")
  private val aActorRef = MyFactory.actorOf(Props(new AActor(bActorRef)), "aAcator")
  def main(args: Array[String]): Unit = {
    var flag = true
    while (flag) {
      val consoleLine: String = StdIn.readLine()
      //通過!來發送消息
      aActorRef ! consoleLine
      if (consoleLine.equals("拜拜")) {
        flag = false
        println("程序即將結束!")
      }
      // 休眠100毫秒
      Thread.sleep(100)
    }
  }
}

5.模擬Spark中Master與Worker進程通訊

https://www.jianshu.com/p/43cf21b424ec

爲了加深對主從服務心跳檢測機制(HeartBeat)的理解,模擬master與slave之間的通信。

  1. Worker 註冊到 Master,Master 完成註冊,並回復 Worker 註冊成功(註冊功能)
  2. Worker 定時發送心跳,並在 Master 接收到
  3. Master 接收到 Worker 心跳後,要更新該 Worker 的最近一次發送心跳的時間
  4. 給 Master 啓動定時任務,定時檢測註冊的 Worker 有哪些沒有更新心跳,並將其從 hashmap 中刪除

5.1 代碼實現

關鍵點:Worker 和 Master的啓動方式都是 通過發送start來啓動的,協議使用模板類來實現,故增加幾個case class,處理邏輯注意 客戶端要發送哪幾類消息,服務端要接受那幾類消息,兩者結合使用即可,代碼:https://github.com/hulichao/bigdata-code/tree/master/src/main/scala/com/hoult/scala/job/spark

主要實現:

//master消息處理
val workers = mutable.Map[String, WorkerInfo]()
  override def receive: Receive = {
    case "start" => {
      println("master running....")
      // 檢查超時worker
      self ! StartTimeOutWorker
    }

    case StartTimeOutWorker => {
      println("start check timeout worker...")
      // 定義定時器,每隔一段時間檢查worker心跳是否超時
      import context.dispatcher
      context.system.scheduler.schedule(0 millis, 9000 millis, self, RemoveTimeOutWorker)
    }
    case RemoveTimeOutWorker => {
      // 獲取workers中所有workerInfo
      val workerInfos = workers.values
      // 獲取當前時間
      val currentTime = System.currentTimeMillis()
      // 找出超時6秒的worker
      workerInfos.filter(info => (currentTime - info.lastHeartBeatTime) > 6000)
        .foreach(workers -= _.id)
      println(s"===> workers.size = ${workers.size}")
    }

    case RegisterWorkerInfo(id, cpu, ram) => {
      //判斷是否已註冊
      if (!workers.contains(id)) {
        val info =
        // 添加數據
        workers += (id -> new WorkerInfo(id, cpu, ram)) //worker列表添加
        println("workers => 註冊:" + workers)
        //註冊成功回覆消息
        sender() ! RegisteredWorkerInfo
      }

    }
    case HeartBeat(id) => {
      // 更新對應workinfo的心跳時間
      // 從workers中取出workerinfo
      val workerInfo = workers(id)
      // 更新最後心跳時間
      workerInfo.lastHeartBeatTime = System.currentTimeMillis()
      println(s"master updated worker ${id}'s heartbeat")
    }
//worker消息處理
override def receive: Receive = {

    case "start" => {
      println("worker running...")
      // 發送註冊信息
      masterProxy ! RegisterWorkerInfo(id, 16, 16 * 1024)
    }
    case RegisteredWorkerInfo => {
      println(s"worker ${id} registered!")

      // 定義定時器,每隔一段時間告訴自己發送心跳
      import context.dispatcher
      // 0 millis:立即執行
      // 3000 millis:每隔3秒執行
      // self:接收對象,發給自己
      // SendHeartBeat:發送內容
      context.system.scheduler.schedule(0 millis, 3000 millis, self, SendHeartBeat)
    }
    //發送心跳
    case SendHeartBeat => {
      println(s"worker ${id} send heartbeat to master")
      masterProxy ! HeartBeat(id)
    } 

5.3 演示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章