用Java调度系统设计的消息

时间:2014-11-24 09:53:10

标签: java multithreading performance akka

我正在寻找针对以下用例的轻量级高效解决方案:

  • 网关模块接收为不同接受者提供的资源。
  • 每个接受者排队的资源(按到达顺序排列)。
  • 清除过程扫描这些队列,如果资源可用于某些接受者,则他将它们捆绑在某个标记(唯一ID)下,并发送新捆绑可用的通知。

系统特征:

  • 接受者的数量是动态的。
  • 对一个捆绑包中的资源数量没有限制。

Message Dispatching System

该模块将在Java 7(非集群)下的Tomcat 7中使用。

我考虑了以下解决方案:

  1. JMS - 每个接受者的dymanic队列配置,是否可以使用队列中的所有可用消息?每个队列的线程配置(不可扩展)?
  2. AKKA演员。没有找到合适的使用模式。
  3. 天真的纯Java实现,其中队列将由一个线程(循环)扫描。
  4. 我认为这是讨论此问题的可用解决方案的正确位置。 请在考虑以下几点时分享您的想法:

    • 合适的第三方框架。
    • 资源队列可扩展扫描。

    先谢谢。

3 个答案:

答案 0 :(得分:5)

您可以使用各种技术,例如:

但是从高可用性可伸缩性的原因,你应该使用 Akka

<强>阿卡

实现的起点是Akka内置的Consistent Hashing路由算法 - 简单来说,这种类型的路由逻辑根据提供的密钥选择一致的路由。与您的问题描述相比,路线接受者

路由器actor有两种不同的风格,它为您提供了在基础架构中部署新接受器的灵活机制。

  • 池 - 路由器创建路由器作为子actor,如果它们终止则将它们从路由器中删除。

  • Group - 在路由器外部创建routee actor,路由器使用actor选择将消息发送到指定路径,而不会看到终止。

首先,请阅读Akka路由文档,以便更好地了解Akka框架中的路由实现:

您还可以查看有关可扩展和高可用系统设计的文章:

Q1 Actor是否可以知道他的路线(他的哈希键)?

Actor可能知道当前处理的是什么键,因为它可能只是消息的一部分 - 但是您不应该基于此键构建交叉消息逻辑/状态。

消息:

import akka.routing.ConsistentHashingRouter.ConsistentHashable
  class Message(key : String) extends ConsistentHashable with Serializable {
      override def consistentHashKey(): AnyRef = key
  }

演员:

  import akka.actor.{Actor, ActorLogging}

  class EchoActor extends Actor with ActorLogging {

    log.info("Actor created {}", self.path.name)

    def receive = {
      case message: Message =>
        log.info("Received message {} in actor {}", message.consistentHashKey(),             self.path.name)
      case _ => log.error("Received unsupported message");
    }
  }

Q2玩家可以管理除邮箱之外的州吗?

演员状态只能通过他们之间发送的消息进行更改。

如果要初始化包含对经典java / spring / .. bean的引用的actor,它将能够与非actor的世界/状态进行交互,例如。 dao层,但这种类型的集成应该尽可能地限制并作为反模式处理。

Q3有没有办法使用抗冲突的配置?

作为API使用者,您需要自己定义collision resistant模型,但Akka再次提供了执行此操作所需的基础结构。

  1. 在大多数情况下,密钥将成为域的一部分,例如。拍卖ID,客户ID

  2. 如果需要按需生成密钥,您可以使用ClusterSingleton Persistence扩展名。

  3. Generator可能是Actor负责生成唯一ID,其他参与者可能会使用ask模式获取新ID。

    ClusterSingleton使用ClusterSingletonManager进行初始化,并使用ClusterSingletonProxy

    获取
    system.actorOf(ClusterSingletonManager.props(
    singletonProps = Props(classOf[Generator]),
    singletonName = "gnerator",
    terminationMessage = End,
    role = Some("generator")),
    name = "singleton")
    
    
    system.actorOf(ClusterSingletonProxy.props(
    singletonPath = "/user/singleton/generator",
    role = Some("generator")),
    name = "generatorProxy")
    

答案 1 :(得分:0)

我认为对于您的问题,JMS将是正确的解决方案。您可以使用RabbitMQ,它具有根据密钥将消息路由到不同队列的路由器,并为消息流和消息确认机制提供内置解决方案。

答案 2 :(得分:0)

你可以使用Apache Camel。它轻巧,支持很多enterprise integration patternsParticularly Content Based Router是一种可能的解决方案。