Akka自定义简单rpc

1. 消息的传递,从一个Actor到另一个Actor或者从自己到自己。

//网络通信需要序列化反序列化
trait RemoteMessage extends Serializable
//Woker-->Master
case class RegisterWoker(wokerId:String , momery:Int, cores:Int) extends  RemoteMessage
//Master-->Woker
case class RegisteredWoker(masterURL:String) extends  RemoteMessage
//Woker-->Woker
case object SendHeartbeat
//Woker-->Master
case class Heartbeat(wokerId:String) extends  RemoteMessage
//Master-->Master
case object CheckTimeOutWoker

2. WokeInfo

class WokerInfo(val wokerId:String,val memory:Int, val cores:Int){
  //上次一心跳的时间
  var lastHeartbeatTime:Long = _
}

3.Woker类

import java.util.UUID

import scala.concurrent.duration._
import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

class Woker(val host:String, val port:Int, val momery:Int, val cores:Int) extends  Actor{
    val wokerId:String = UUID.randomUUID().toString
    var master:ActorSelection = _
    var Time = 10000


  override def preStart(): Unit = {
    import context.dispatcher
    master = context.actorSelection(s"akka.tcp://MasterSystem@$host:$port/user/Master")
    master ! RegisterWoker(wokerId,momery,cores)
  }

  override def receive: Receive = {
    case RegisteredWoker(masterURL) =>{
      println("注册成功! 地址"+masterURL)
      import context.dispatcher
      context.system.scheduler.schedule(0 millis,Time millis,self,SendHeartbeat)
    }
    case SendHeartbeat => {
      //发送心跳
      println("发送心跳")
      master ! Heartbeat(wokerId)
    }
  }
}

object Woker {
  def main(args: Array[String]): Unit = {
    val host: String = args( 0 )
    val port: Int = args( 1 ).toInt
    val configString: String =
      s"""
         |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
         |akka.remote.netty.tcp.hostname = "$host"
         |akka.remote.netty.tcp.port = "$port"
    """.stripMargin
    val config = ConfigFactory.parseString( configString )
    val actorSystem = ActorSystem( "WokerSystem", config )
    actorSystem.actorOf( Props( new Woker( args( 2 ), args( 3 ).toInt, args( 4 ).toInt, args( 5 ).toInt ) ), "Woker" )
    actorSystem.awaitTermination()
  }
}

4. Master类

import java.util.UUID

import akka.actor

import scala.concurrent.duration._
import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import com.typesafe.config.ConfigFactory

import scala.collection.mutable

class Master(val host:String, val port:Int) extends  Actor{
   val idToWoker = new mutable.HashMap[String,WokerInfo]()
   val wokers = new mutable.HashSet[WokerInfo]()
   val Time = 15000

  override def preStart(): Unit = {
    import context.dispatcher
    context.system.scheduler.schedule(0 millis,Time millis,self,CheckTimeOutWoker)
  }

  override def receive: Receive = {
    case RegisterWoker(wokerId,momery,cores) =>{
      if(!idToWoker.contains(wokerId)){
        val wokerInfo = new WokerInfo(wokerId,momery,cores)
        idToWoker(wokerId) = wokerInfo
        wokers+=wokerInfo
      }
      println("一个Woker注册了")
      sender ! RegisteredWoker(s"akka.tcp://MasterSystem@$host:$port/user/Master")
    }
    case Heartbeat(wokerId) =>{
      val currentTime = System.currentTimeMillis()
      if(idToWoker.contains(wokerId)){
        val wokerInfo = idToWoker(wokerId)
        wokerInfo.lastHeartbeatTime = currentTime
      }

    }
    case CheckTimeOutWoker =>{

      val currentTime = System.currentTimeMillis()
      val remote = wokers.filter(t=>currentTime-t.lastHeartbeatTime>=15000)
      for(r<-remote){
        wokers-=r
        idToWoker-=r.wokerId
        println("一个Woker断开了")
      }
      println("现有Woker:"+wokers.size)
    }
   }
}
object Master{
  def main(args: Array[String]): Unit = {
    val host:String = args(0)
    val port:Int = args(1).toInt
    val configString:String =  s"""
                                  |akka.actor.provider = "akka.remote.RemoteActorRefProvider"
                                  |akka.remote.netty.tcp.hostname = "$host"
                                  |akka.remote.netty.tcp.port = "$port"
    """.stripMargin
    val config = ConfigFactory.parseString(configString)
    val actorSystem = ActorSystem("MasterSystem",config)
    actorSystem.actorOf(Props(new Master(host,port)),"Master")
    actorSystem.awaitTermination()
  }
}
//s"akka.tcp://MasterSystem@$host:$port/user/Master"

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个使用Akka.NET编写自定义邮箱的示例: 首先,我们需要定义一个Actor,这个Actor就是我们的自定义邮箱: ```csharp using Akka.Actor; using System.Collections.Generic; namespace MyCustomMailbox { public class CustomMailbox : MailboxType, IProducesMessageQueue<CustomMessageQueue> { public override IMessageQueue CreateQueue() { return new CustomMessageQueue(); } } public class CustomMessageQueue : IMessageQueue, IUnboundedDequeBasedMessageQueueSemantics { private readonly Queue<object> messages = new Queue<object>(); public void Enqueue(IActorRef receiver, Envelope envelope) { messages.Enqueue(envelope.Message); } public bool HasMessages { get { return messages.Count > 0; } } public int Count { get { return messages.Count; } } public bool TryDequeue(out Envelope envelope) { if (messages.Count > 0) { envelope = new Envelope(messages.Dequeue(), ActorRefs.NoSender); return true; } else { envelope = null; return false; } } public void CleanUp(IActorRef owner, IMessageQueue deadletters) { while (TryDequeue(out Envelope envelope)) { deadletters.Enqueue(owner, envelope); } } } } ``` 在这个示例中,我们定义了一个CustomMailbox类型的自定义邮箱,这个邮箱使用了一个CustomMessageQueue类型的消息队列。CustomMessageQueue实现了IMessageQueue接口,并且使用了一个Queue<object>来存储消息。它还实现了IUnboundedDequeBasedMessageQueueSemantics接口,这个接口允许我们在实现自定义邮箱时使用一些特定的优化。 接下来,我们需要使用这个自定义邮箱来创建ActorSystem和Actor: ```csharp using Akka.Actor; namespace MyCustomMailbox { class Program { static void Main(string[] args) { var system = ActorSystem.Create("CustomMailboxSystem"); var props = Props.Create<CustomMailboxActor>().WithMailbox("MyCustomMailbox"); var actor = system.ActorOf(props); actor.Tell("Hello, world!"); actor.Tell("How are you?"); actor.Tell("I'm fine, thank you."); actor.Tell("print"); system.Terminate().Wait(); } } [ActorOf(typeof(CustomMailbox))] class CustomMailboxActor : UntypedActor { private readonly List<object> messages = new List<object>(); protected override void OnReceive(object message) { if (message is string) { messages.Add(message); Console.WriteLine($"Added message: {message}"); } else if (message is string && (string)message == "print") { Console.WriteLine("All messages:"); foreach (var msg in messages) { Console.WriteLine(msg); } } else { Console.WriteLine("Invalid message!"); } } } } ``` 在这个示例中,我们创建了一个ActorSystem,并使用CustomMailbox类型的自定义邮箱来创建了一个Actor。我们向这个Actor发送了三条消息,然后发送了一个"print"消息。当Actor收到"print"消息时,它会将所有消息打印出来。 运行这个程序,你会看到以下输出: ``` Added message: Hello, world! Added message: How are you? Added message: I'm fine, thank you. All messages: Hello, world! How are you? I'm fine, thank you. ``` 这个示例展示了如何使用Akka.NET创建一个自定义邮箱,并将其应用到一个Actor中。你可以根据自己的需要扩展这个示例,例如添加删除消息的功能,或者添加更多类型的消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值