Apache Tribes - 简介

目录

快速入门

Apache Tribes 是一个组或点对点通信框架,它使您能够轻松地连接远程对象以相互通信。

  • 导入:org.apache.catalina.tribes.Channel
  • 导入:org.apache.catalina.tribes.Member
  • 导入:org.apache.catalina.tribes.MembershipListener
  • 导入:org.apache.catalina.tribes.ChannelListener
  • 导入:org.apache.catalina.tribes.group.GroupChannel
  • 创建一个实现以下接口的类:org.apache.catalina.tribes.ChannelListener
  • 创建一个实现以下接口的类:org.apache.catalina.tribes.MembershipListener
  • 演示如何发送消息的简单类
    //create a channel
    Channel myChannel = new GroupChannel();
    
    //create my listeners
    ChannelListener msgListener = new MyMessageListener();
    MembershipListener mbrListener = new MyMemberListener();
    
    //attach the listeners to the channel
    myChannel.addMembershipListener(mbrListener);
    myChannel.addChannelListener(msgListener);
    
    //start the channel
    myChannel.start(Channel.DEFAULT);
    
    //create a message to be sent, message must implement java.io.Serializable
    //for performance reasons you probably want them to implement java.io.Externalizable
    Serializable myMsg = new MyMessage();
    
    //retrieve my current members
    Member[] group = myChannel.getMembers();
    
    //send the message
    myChannel.send(group,myMsg,Channel.SEND_OPTIONS_DEFAULT);

很简单吧?Tribes 的功能远不止我们展示的这些,希望文档能为您解释更多。请记住,我们始终欢迎您的建议、改进、错误修复以及您认为对该项目有帮助的任何内容。

什么是 Tribes

Tribes 是一个具有组通信功能的消息框架。Tribes 允许您在网络上发送和接收消息,它还允许动态发现网络中的其他节点。
这就是简短的故事,它真的就这么简单。Tribes 的实用性和独特之处将在下面的部分中介绍。

Tribes 模块始于 2006 年初,其代码库的一部分来自 2003 或 2004 年开始的集群模块。当前的集群实现存在一些缺陷,由于组通信的复杂性,创建了许多解决方法。简而言之,原本应该很久以前就分开的两个模块,现在终于要分开了。Tribes 将消息传递的复杂性从复制模块中分离出来,成为一个完全独立且高度灵活的组通信模块。

在 Tomcat 中,旧的 modules/cluster 现在变成了 modules/groupcom (Tribes) 和 modules/ha (复制)。这将允许开发继续进行,并让开发人员专注于他们实际正在处理的问题,而不是陷入他们不感兴趣的模块的细节中。我们理解,通信和复制都足够复杂,当试图在同一个模块中开发它们时,就会变成一个“集群”。

Tribes 允许保证消息传递,并且可以以多种方式进行定制。为什么这很重要?
因为作为开发人员,您希望确保您发送的消息能够到达目的地。更重要的是,如果消息没有到达目的地,位于 Tribes 之上的应用程序将被通知消息从未发送,以及它在哪个节点上失败。

为什么需要另一个消息框架

我非常喜欢重用代码,如果其他人已经完成了某项工作,并且它对我和我试图服务的社区可用,我绝不会梦想着重新开发它。
当我进行研究以改进集群模块时,我不断遇到一些障碍。
1. 框架不够灵活。
2. 框架的许可方式既不适合我,也不适合社区使用。
3. 我需要的一些功能缺失。
4. 消息传递是保证的,但没有向我报告反馈。
5. 我的消息传递语义必须在运行时之前配置。
等等...

因此,我提出了 Tribes,以解决这些问题以及其他随之而来的问题。在设计 Tribes 时,我想确保我没有丢失现有框架已经提供的任何灵活性或传递语义。目标是创建一个能够完成其他框架已经完成的所有事情的框架,但为应用程序开发人员提供更多灵活性。在下一节中,我们将概述 Tribes 提供或将要提供的功能。

功能概述

为了让您了解功能集,我将在此列出。一些功能尚未完成,如果是这种情况,则会相应标记。

可插拔模块
Tribes 使用接口构建。任何作为 Tribes 一部分的模块或组件都可以被替换,以定制您自己的 Tribes 实现。

保证消息传递
在 Tribes 的默认实现中,使用 TCP 或 UDP 进行消息传递。TCP 已经内置了保证消息传递和流量控制。我相信 Java TCP 的性能将优于 Java/UDP/流量控制/消息保证的实现,因为逻辑发生在堆栈的更低层。UDP 消息传递已添加,用于在需要时通过 UDP 而不是 TCP 发送消息。下面描述的相同保证场景仍然适用于 UDP,但是,当 UDP 消息丢失时,它被认为是失败的。
Tribes 支持非阻塞和阻塞 IO 操作。推荐的设置是使用非阻塞,因为它在发送和接收消息时能更好地促进并行处理。阻塞实现适用于 NIO 仍然是问题儿童的平台。

不同的保证级别
发送消息时,有三种不同的传递保证级别。

  1. 基于 IO 的发送保证。 - 最快,最不可靠
    这意味着 Tribes 认为,如果消息已发送到套接字发送缓冲区并被接受,则消息传输成功。
    在阻塞 IO 上,这将是 socket.getOutputStream().write(msg)
    在非阻塞 IO 上,这将是 socketChannel.write(),缓冲区字节缓冲区被清空,然后是 socketChannel.read() 以确保通道仍然打开。read() 已添加,因为当使用 NIO 时,如果连接已“关闭”,则 write() 将成功。
  2. 基于 ACK。 - 推荐,保证传递
    当消息已在远程节点上接收时,将向发送方发送一个 ACK,表明消息已成功接收。
  3. 基于 SYNC_ACK。 - 保证传递,保证处理,最慢
    当消息已在远程节点上接收时,该节点将处理该消息,如果消息处理成功,则向发送方发送一个 ACK,表明消息已成功接收和处理。如果消息已接收,但处理失败,则会向发送方发送一个 ACK_FAIL。这是一个独特的功能,为应用程序开发人员增加了巨大的价值。大多数框架在这里会告诉你消息已传递,应用程序开发人员必须构建逻辑来判断消息是否真的被远程节点上的应用程序正确处理。如果配置了,当 Tribes 接收 ACK_FAIL 时,它会抛出一个异常,并将该异常与未处理消息的成员关联起来。

当然,您可以编写更复杂的保证级别,其中一些将在文档的后面部分提到。一个值得一提的级别是 2 阶段提交,其中远程应用程序只有在所有节点都收到消息后才会收到消息。有点像全有或全无协议。

每条消息传递属性
也许是让 Tribes 从众多群组通信框架中脱颖而出的功能。 Tribes 允许您在每条消息的基础上决定消息传递的语义。这意味着,您的消息不是基于启动消息框架后保持不变的静态配置进行传递的。
为了让您了解此功能的强大之处,我将尝试用一个简单的例子来说明。假设您需要发送 10 条不同的消息,您可以按以下方式发送它们

Message_1 - asynchronous and fast, no guarantee required, fire and forget
Message_2 - all-or-nothing, either all receivers get it, or none.
Message_3 - encrypted and SYNC_ACK based
Message_4 - asynchronous, SYNC_ACK and call back when the message is processed on the remote nodes
Message_5 - totally ordered, this message should be received in the same order on all nodes that have been
            send totally ordered
Message_6 - asynchronous and totally ordered
Message_7 - RPC message, send a message, wait for all remote nodes to reply before returning
Message_8 - RPC message, wait for the first reply
Message_9 - RPC message, asynchronous, don't wait for a reply, collect them via a callback
Message_10- sent to a member that is not part of this group

正如您现在可以想象的那样,这些只是示例。您可以在每条消息的基础上应用的不同语义数量几乎是无限的。 Tribes 允许您在一条消息上设置多达 28 个不同的标志,然后配置 Tribes 以确定哪个标志会导致对消息采取什么操作。
想象一个共享的事务缓存,可能超过 90% 是读取操作,脏读应该完全无序并尽快传递。但另一方面,事务写入必须是有序的,以防止缓存损坏。使用 Tribes,您可以完全有序地发送写入消息,而读取消息则简单地发送以实现最高吞吐量。
可能还有更好的例子来说明如何使用此强大功能,因此请发挥您的想象力和经验,思考这如何能为您在应用程序中带来益处。

基于拦截器的消息处理
Tribes 使用可定制的拦截器堆栈来处理发送和接收的消息。
所以呢,所有框架都有这个功能!
是的,但在 Tribes 中,拦截器可以根据运行时发送的每条消息属性对消息做出反应。这意味着,如果您添加一个加密拦截器来加密消息,您可以决定此拦截器是否加密所有消息,或者只加密由运行在 Tribes 之上的应用程序决定的某些消息。
这就是 Tribes 能够以完全有序的方式发送一些消息,而其他消息则像上面的示例一样采用“发送并忘记”的方式。
可用的拦截器数量将不断增加,我们欢迎您提供任何贡献。

无线程拦截器堆栈 拦截器不需要任何单独的线程来执行其消息操作。
发送的消息将 piggy back 在发送它们的线程上,一直到传输完成。唯一的例外是 MessageDispatchInterceptor,它会将消息排队并将其发送到另一个线程以进行异步消息传递。接收到的消息由 receiver 组件中的线程池控制。
通道对象可以通过拦截器堆栈发送 heartbeat(),以允许超时、清理和其他事件。
MessageDispatchInterceptor 是唯一默认配置的拦截器。

并行传递
Tribes 支持消息的并行传递。这意味着节点 A 可以并行向节点 B 发送三条消息。当发送具有不同传递语义的消息时,此功能变得有用。否则,如果 Message_1 是完全有序发送的,Message_2 必须等待该消息完成。
通过 NIO,Tribes 也可以在同一个线程上同时向多个接收者发送消息。

静默成员消息传递
使用 Tribes,您可以向不在您组中的成员发送消息。因此,默认情况下,您已经可以跨广域网发送消息,即使当前的动态发现模块仅限于使用多播进行动态节点发现的局域网。当然,成员资格组件将来会扩展以支持广域网成员资格。但这非常有用,当您想将成员隐藏在组的其余部分之外,并且只与他们通信时。

在哪里可以获取 Tribes

Tribes 作为 Tomcat 的一个模块发布,并作为 Apache Tomcat 版本的一部分发布。