KivaKit 是一个基于 Apache 许可证的开源 Java 框架,用于实现微服务。KivaKit 需要一个 Java 11+虚拟机,但与 Java 8 和 9 项目源代码兼容。KivaKit 由一组精心集成的迷你框架组成。每个迷你框架都有一致的设计和自己的关注点,可以单独使用,也可与其他迷你框架协同使用。下图是这些框架的依赖网络简图,这是一张很直观的 KivaKit 高级架构图:
每个微型框架都解决了开发微服务时经常遇到的某个问题。本文将简要介绍上图中的各个微型框架及它们的使用方法。
消息传递
正如我们在上图中所见,消息传递(Messaging)是 KivaKit 的核心。消息传递在构建状态可观察的组件时很有用,这在基于云的世界中是一项好用的特性。KivaKit 中的许多对象会广播或收听状态消息,例如 Alert、Problem、Warning 或 Trace。它们大多数是中继器(Repeater),侦听来自其他对象的状态消息并将它们重新广播给下游感兴趣的侦听器(listener)。这形成了一个带有终端侦听器的侦听器链:
C->B->A
复制代码
通常,链中的最后一个侦听器是某种日志记录器(Logger),但链的末端也可以有多个侦听器,可以是任何实现侦听器的对象。例如,在验证(Validation)迷你框架中,状态消息由 ValidationIssues 类捕获,然后用于确定验证是否成功,还能在验证失败时向用户展示特定问题。给定上面的侦听器链,C 和 B 实现了中继器,最终的对象 A 实现了侦听器。在链中的每个类中,侦听器链扩展为:
listener.listenTo(broadcaster)
复制代码
为了向感兴趣的侦听器传输消息,这里从 Broadcaster 继承了一些针对常见消息类型的便利方法:
消息 | 含义 |
---|---|
problem() | 出了点问题,需要解决,但这对当前的操作来说并不致命。 |
glitch() | 出现了一个小问题。与Warning不同,Glitch表示出现了验证失败或发生数据丢失的问题。与Problem不同,Glitch表示操作肯定会恢复并继续。<br> |
warning() | 出现了一个小问题,应该更正,但不一定需要注意。 |
quibble() | 发生了一个不需要更正的小问题。 |
announcement() | 宣布一项操作的一个重要阶段。 |
narration() | 某个操作中的一个步骤已经开始或完成。 |
infromation() | 不代表任何问题的常用信息。 |
trace() | 调试时使用的诊断信息。 |
广播器(Broadcaster)还提供了一种机制,可以通过对类和包的模式匹配,从命令行打开和关闭 Trace 消息。
Mixin
在 KivaKit 中有两种方法可以实现中继器。第一种方法是简单地扩展 BaseRepeater。第二种是使用有状态的 trait 或 Mixin。实现 RepeaterMixin 接口与扩展 BaseRepeater 是一样的,但是 mixin 中继器可以在已经有基类的类中使用。请注意,下面讨论的 Component 接口使用了相同的模式。如果无法扩展 BaseComponent,则可以实现 ComponentMixin。
Mixin 接口 Java 语言缺少的一项特性提供了一种解决方法。它的工作原理是将状态查找委托给一个包私有类,MixinState;该类使用实现 Mixin 的类的 this 引用,在身份哈希映射中查找关联的状态对象。Mixin 界面如下所示:
public interface Mixin
{
default <T> T state(Class<? extends Mixin> type, Factory<T> factory)
{
return MixinState.get(this, type, factory);
}
}
复制代码
如果 state()没有找到 this 的 state 对象,将使用给定的工厂方法创建一个新的 state 对象,然后该对象将与 statemap 中的 mixin 相关联。例如,我们的 RepeaterMixin 接口大致如下所示(为简洁起见,省略了大部分方法):
public interface RepeaterMixin extends Repeater, Mixin
{
@Override
default void addListener(Listener listener, Filter<Transmittable> filter)
{
repeater().addListener(listener, filter);
}
@Override
default void removeListener(Listener listener)
{
repeater().removeListener(listener);
}
[...]
default Repeater repeater()
{
return state(RepeaterMixin.class, BaseRepeater::new);
}
}
复制代码
在这里,addListener()和 removeListener()方法分别通过 repeater()检索它们的 BaseRepeater 状态对象,并将方法调用委托给该对象。正如我们所见,在 KivaKit 中实现一个 mixin 并不是很复杂。应该注意的是,每次调用 mixin 中的方法都需要在状态映射中查找。身份哈希映射一般来说很好用,但对于一些组件来说,这可能会带来性能问题。与大多数性能问题一样,我们最好做最简单的事情,直到我们的分析器另有说明为止。
组件
KivaKit 组件(Component)往往会是微服务的关键部分。组件可以通过扩展 BaseComponent(最常见的情况)或通过实现 ComponentMixin 来轻松访问消息。除了从中继器继承的侦听器列表之外,从 Component 继承根本不会向对象添加任何状态。这样组件就变得非常轻量级。实例化大量组件也不是什么问题。由于组件都是中