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-Phase-Commit),在这种情况下,远程应用程序直到所有节点都收到消息后才接收消息。有点像全有或全无协议。

每消息交付属性
这也许是 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 能够像上面的例子那样,发送一些完全有序的消息,而另一些则采用“即发即弃”模式的原因。
可用的拦截器数量将持续增长,我们非常感谢您的任何贡献。
无线程拦截器栈 拦截器不需要任何单独的线程来执行其消息操作。

发送的消息将附着在发送它们的线程上,一路完成传输。例外是 MessageDispatchInterceptor,它将消息排队并在单独的线程上发送,以实现异步消息交付。接收到的消息由 receiver 组件中的线程池控制。
通道对象可以通过拦截器栈发送 heartbeat(),以允许超时、清理和其他事件。
MessageDispatchInterceptor 是唯一默认配置的拦截器。
并行交付

Tribes 支持消息的并行交付。这意味着节点 A 可以并行地向节点 B 发送三条消息。当发送具有不同交付语义的消息时,此功能变得非常有用。否则,如果消息 1 是完全有序发送的,消息 2 将不得不等待该消息完成。
通过 NIO,Tribes 还能够在同一个线程上同时向多个接收者发送消息。
静默成员消息传递

使用 Tribes,您可以向不在您组中的成员发送消息。因此,默认情况下,您已经可以在广域网上发送消息,尽管目前动态发现模块通过使用多播进行动态节点发现仅限于局域网。当然,成员关系组件未来将扩展以支持广域网成员关系。但这在您希望向组内其他成员隐藏某些成员并仅与他们通信时非常有用。
Tribes 作为 Tomcat 的一个模块发布,并作为 Apache Tomcat 发布的一部分。

如何获取 Tribes

版权所有 © 1999-2025,Apache 软件基金会