Akka示例Scala代码| 青训营笔记

148 阅读6分钟

[toc]

Akka特性

下面是一些Akka的其他重要特性:

分布式计算:Akka提供了强大的分布式计算支持,可以构建分布式系统。它包括分布式Actor模型、远程Actor、集群和容错机制等功能,使得在分布式环境下构建可伸缩和容错的应用程序变得更加容易。

持久性:Akka提供了事件溯源(Event Sourcing)和快照(Snapshot)机制,可以将Actor的状态持久化到存储系统中,以便在重启后恢复状态。这对于需要持久化和回溯数据的应用程序非常有用。

流处理:Akka Stream是Akka的一个模块,用于构建高吞吐量和低延迟的流处理应用程序。它提供了一种声明性的API,用于处理连续的数据流,支持各种操作符和模式,如过滤、转换、聚合、缓冲等。

路由策略:除了基本的消息路由功能之外,Akka还提供了各种路由策略,如负载均衡、故障转移、一致性哈希等。这些路由策略可以根据应用程序的需求和负载情况,动态地选择和管理消息的路由路径。

高级监控和诊断:Akka提供了丰富的监控和诊断工具,帮助开发人员监视和分析应用程序的运行状态。这包括监控Actor的邮箱和邮箱队列长度、处理时间等指标,以及记录和分析应用程序的日志。

集群管理:Akka Cluster模块提供了用于构建分布式集群的工具和机制。它支持动态加入和离开集群的节点,以及在集群中分配和管理Actor实例。它还提供了一致性哈希算法和故障检测机制,以确保集群的可用性和可靠性。

网络通信:Akka提供了高性能的网络通信库,用于在Actor之间进行消息传递。它支持多种传输协议和编解码器,可以在不同的网络环境中进行可靠的通信。

状态管理:Akka提供了一种称为FSM(有限状态机)的模型,用于管理Actor的状态。FSM模型使得状态转换和事件处理变得更加清晰和可控,对于需要复杂状态管理的应用程序非常有用。

跨语言支持:Akka的核心是用Scala编写的,但它也提供了对Java和其他JVM语言的支持。这使得开发人员可以使用自己熟悉的编程语言和工具来构建Akka应用程序。

插件生态系统:Akka具有丰富的插件生态系统,可以扩展和增强其功能。这些插件包括监控和诊断工具、持久性插件、流处理插件、序列化插件等,可以根据应用程序的需求选择和集成。

高级容错机制:Akka的容错机制非常强大,可以处理各种故障和异常情况。它通过监督机制和失败恢复策略,使得系统能够自动从故障中恢复,并保持运行状态。

高性能:Akka的设计注重高性能和低延迟。它通过异步、非阻塞的消息传递机制和基于事件驱动的模型,实现了高吞吐量和低延迟的处理能力。

总之,Akka是一个强大的开发工具包,提供了丰富的特性和功能,用于构建可伸缩、容错和高性能的分布式应用程序。无论是构建实时数据处理系统、分布式计算平台还是可靠性要求高的应用程序,Akka都可以提供可靠的基础设施和抽象层。它的特性和功能使得开发人员能够轻松构建高度并发、分布式的应用程序,并具备容错、弹性和可伸缩性。

Akka FSM有限状态机

import akka.actor._

object UserStorageFSM {
  //定义Actor的状态
  sealed trait State
  case object Connected extends State
  case object Disconnected extends State

  //定义状态转移事件
  sealed trait Data
  case object EmptyData extends Data
  case class User(name: String, email: String) extends Data

  //定义消息
  case class Connect()
  case class Disconnect()
  case class CreateUser(user: User)
  case class GetUser(name: String)

  class UserStorageFSM extends FSM[State, Data] {
    startWith(Disconnected, EmptyData)

    //定义状态转移
    when(Disconnected) {
      case Event(Connect(), _) =>
        println("UserStorage connected to DB")
        goto(Connected) using EmptyData
    }

    //定义状态转移和处理消息
    when(Connected) {
      case Event(Disconnect(), _) =>
        println("UserStorage disconnected from DB")
        goto(Disconnected) using EmptyData

      case Event(CreateUser(user), _) =>
        println(s"User ${user.name} created")
        stay using User(user.name, user.email)

      case Event(GetUser(name), data) =>
        data match {
          case User(`name`, email) =>
            println(s"User $name retrieved, email=$email")
            stay
          case_ =>
            println(s"User $name not found")
            stay
        }
    }

    //定义Actor启动时的初始状态
    initialize()
  }

  def main(args: Array[String]) {
    val system = ActorSystem("UserStorage")
    val userStorage = system.actorOf(Props[UserStorageFSM], "userStorage")

    //发送消息,测试状态转移和消息处理
    userStorage ! Connect()
    userStorage ! CreateUser(User("John", "john@example.com"))
    userStorage ! GetUser("John")
    userStorage ! GetUser("Bob")
    userStorage ! Disconnect()

    //停止ActorSystem
    system.terminate()
  }
}

Akka stream

import akka.actor.ActorSystem
import akka.stream.scaladsl._
import akka.stream._

object AkkaStreamExample {
  def main(args: Array[String]): Unit = {
    // 创建ActorSystem和材料化的流
    implicit val system = ActorSystem("AkkaStreamExample")
    implicit val materializer = ActorMaterializer()

    // 创建一个Source,它从1到10生成一个整数序列
    val source = Source(1 to 10)

    // 创建一个Flow,它将整数加倍
    val doubleFlow = Flow[Int].map(_ * 2)

    // 创建一个Sink,它将结果打印到控制台
    val consoleSink = Sink.foreach(println)

    // 将Source、Flow和Sink组合在一起形成一个流水线
    val pipeline = source.via(doubleFlow).to(consoleSink)

    // 运行流水线
    pipeline.run()

    // 停止ActorSystem
    system.terminate()
  }
}

Akka路由策略

import akka.actor._
import akka.routing._

object RouterExample {
  //定义消息
  case class Work(message: String)

  //定义Worker Actor
  class Worker extends Actor {
    def receive = {
      case Work(message) =>
        println(s"${self.path.name} received message: $message")
    }
  }

  def main(args: Array[String]): Unit = {
    //创建ActorSystem和Router Actor
    val system = ActorSystem("RouterExample")
    val router = system.actorOf(FromConfig.props(Props[Worker]), "router")  //路由器将使用配置文件中指定的路由策略来管理消息路由。

    //发送一些消息到Router
    router ! Work("message 1")
    router ! Work("message 2")
    router ! Work("message 3")
    router ! Work("message 4")

    //停止ActorSystem
    system.terminate()
  }
}
//路由配置文件

akka.actor.deployment {
  /router {
    router = round-robin-pool
    nr-of-instances = 5
  }
}

Akka持久性

import akka.actor._
import akka.persistence._

object UserStorageExample {
  //定义消息
  case class AddUser(user: User)
  case class GetUser(name: String)
  case class User(name: String, email: String)

  //定义Actor状态
  case class UserStorage(users: List[User] = Nil)

  //定义事件
  case class UserAdded(user: User)

  //定义Actor
  class UserStorageActor extends PersistentActor {
    override def persistenceId = "user-storage-actor"

    //Actor状态和处理事件
    var state = UserStorage()

    def updateState(event: UserAdded): Unit = {
      state = UserStorage(event.user :: state.users)
    }

    //处理消息
    def receiveCommand: Receive = {
      case AddUser(user) =>
        persist(UserAdded(user)) { event =>
          updateState(event)
          println(s"User ${user.name} added")
        }

      case GetUser(name) =>
        val user = state.users.find(_.name == name)
        sender() ! user
    }

    //恢复状态
    def receiveRecover: Receive = {
      case event: UserAdded =>
        updateState(event)
    }
  }

  def main(args: Array[String]): Unit = {
    //创建ActorSystem和UserStorageActor
    val system= ActorSystem("UserStorageExample")
    val userStorage = system.actorOf(Props[UserStorageActor], "userStorage")

    //发送一些消息到Actor
    userStorage ! AddUser(User("John", "john@example.com"))
    userStorage ! AddUser(User("Bob", "bob@example.com"))
    userStorage ! AddUser(User("Alice", "alice@example.com"))
    userStorage ! GetUser("John")
    userStorage ! GetUser("Bob")
    userStorage ! GetUser("Charlie")

    //停止ActorSystem
    system.terminate()
  }
}

Akka集群和集群事件

import akka.actor._
import akka.cluster.Cluster
import akka.cluster.ClusterEvent._

object ClusterExample {
  //定义消息
  case class Greet(message: String)

  //定义Actor
  class SimpleClusterActor extends Actor {
    val cluster = Cluster(context.system)

    //订阅集群事件
    override def preStart(): Unit = {
      cluster.subscribe(self, initialStateMode = InitialStateAsEvents,
        classOf[MemberEvent], classOf[UnreachableMember])
    }

    //取消订阅集群事件
    override def postStop(): Unit = {
      cluster.unsubscribe(self)
    }

    //处理消息
    def receive = {
      case Greet(message) =>
        println(s"${self.path.name} received message: $message")
    }
  }

  def main(args: Array[String]): Unit = {
    //创建ActorSystem和SimpleClusterActor
    val system = ActorSystem("ClusterSystem")
    val simpleClusterActor = system.actorOf(Props[SimpleClusterActor], "simpleClusterActor")

    //发送一些消息到Actor
    simpleClusterActor ! Greet("Hello, Akka Cluster!")

    //停止ActorSystem
    system.terminate()
  }
}

Akka 监控和诊断工具

import akka.actor._
import akka.pattern._
import akka.util.Timeout
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

object MonitoringExample {
  //定义消息
  case class Greet(message: String)

  //定义Actor
  class SimpleActor extends Actor {
    def receive = {
      case Greet(message) =>
        println(s"${self.path.name} received message: $message")
        Thread.sleep(1000)
    }
  }

  def main(args: Array[String]): Unit = {
    //创建ActorSystem和SimpleActor
    val system = ActorSystem("MonitoringSystem")
    val simpleActor = system.actorOf(Props[SimpleActor], "simpleActor")

    //发送一些消息到Actor
    simpleActor ! Greet("Hello, Akka Monitoring!")

    //监视Actor邮箱和邮箱队列长度
    val mailboxSizeFuture = simpleActor ? CurrentMessageCount
    implicit val timeout = Timeout(5.seconds)
    val mailboxSize = mailboxSizeFuture.mapTo[Int].futureValue

    //输出邮箱和邮箱队列长度
    println(s"Mailbox size: $mailboxSize")

    //停止ActorSystem
    system.terminate()
  }
}

Akka 网络通信

以下是一个使用Akka网络通信的Scala代码示例,我们使用了TCP协议进行通信

import akka.actor._
import akka.io._
import akka.util.ByteString

object TcpExample {
  //定义消息
  case class SendMessage(message: String)

  //定义Actor
  class TcpClient(remote: InetSocketAddress) extends Actor {
    import context.system
    IO(Tcp) ! Connect(remote)

    def receive = {
      case CommandFailed(_: Connect) =>
        println("Connection failed")
        context stop self

      case Connected(remote, local) =>
        println(s"Connected to $remote")
        val connection = sender()
        connection ! Register(self)

        context.become {
          case SendMessage(message) =>
            connection ! Write(ByteString(message))
          case Received(data) =>
            println(s"Received message: ${data.utf8String}")
          case _: ConnectionClosed =>
            println("Connection closed")
            context stop self
        }
    }
  }

  def main(args: Array[String]): Unit = {
    //创建ActorSystem和TcpClient
    val system = ActorSystem("TcpSystem")
    val remote = new InetSocketAddress("localhost", 8080)
    val tcpClient = system.actorOf(Props(new TcpClient(remote)), "tcpClient")

    //发送一些消息到Actor
    tcpClient ! SendMessage("Hello, Akka TCP!")

    //停止ActorSystem
    system.terminate()
  }
}