Hystrix 命令的预期粒度?

Intended granularity of Hystrix commands?

我刚刚阅读了 Hystrix docs/wiki,但仍然遗漏了基本层面的内容:HystrixCommand impl 的预期粒度级别是多少?

例如,假设我有一个 DAO 对象来处理某些数据库实体的 CRUD 操作,例如 Widget:

class Widget {
    Long id
    Long typeId
    Long version
    String name
    Boolean isAlive
}

interface WidgetDao {
    Widget insertWidget(Long typeId, String name, Boolean isAlive)

    List<Widget> getAllWidgets()

    Widget getWidgetById(Long id)

    void updateWidget(Widget widget)

    void deleteWidget(Widget widget)
}

现在,如果这个 DAO 连接的数据库出现故障,所有 DAO 方法都将开始失败。但是我 假设 数据库也有可能在某些事务或维护模式下被绑定,比如允许读取,但不允许写入。在这种极端情况下,读取会成功(getX(...) 方法),但所有其他方法都会失败并显示 SqlExceptions.

所以我问:我应该在这里使用的预期粒度级别是多少?要么:

  1. 一个 HystrixCommand impl for every DAO 方法,看到在某些情况下命令可能 运行 成功,而在其他情况下,它们可能会失败;或
  2. 一个 HystrixCommand 以某种方式融入 DAO class,跨越 所有 DAO 方法(因此,如果一个命令失败,整个 DAO "goes down".)?

我认为前者代表了更灵活的工程,但作为库的使用者向我介绍了更多的代码。想法?想法?

我的想法是,粒度级别的解释非常开放,但我认为这一切都归结为错误 tolerance/recovery 和微调。我会考虑以下几点:

  1. 您的失败点是什么以及如何从中恢复?你能康复吗?

您提到过:

I suppose it is also possible for the DB to be tied up in some transaction or maintenance mode, where say, reads are permitted, but not writes

如果是这种情况,也许围绕此设计您的 Hystrix 命令是有意义的。您可以尝试更通用的 "read widget" 命令和 "write widget" 命令。

假设您处于读取有效而写入无效的情况下,您可以保持读取并断开写入命令的电路,从而有可能在此过程中为您节省一些数据库连接。您可以通过增加粒度并为每个 DAO 方法使用一个命令来实现相同的目的,但我不确定这是否真的能为您带来任何好处。

  1. 您是否need/want 微调您的应用程序?

Hystrix 为 thread pools and metrics 提供了一些非常好的配置,可以根据每个命令进行调整。将它们配置为一个,按读写分组是否有意义,或者您是否希望对每个 DAO 方法进行更有限的 control/reporting?

总的来说,我认为这取决于具体情况,我认为 Hystrix 的创建并未考虑到任何特定级别的粒度。根据我的经验(通过 Hystrix 命令使用 REST API),我倾向于更多地使用第一种方法并支持粒度。当然,我们通过这种方式生成了更多的代码,但是这些库的消费者(在我们的例子中)很少需要处理它,因为他们只使用最终调用这些 Hystrix 命令的接口,我们可以利用线程pooling/fallback 个选项。这可以派上用场,因为使用 REST API,只有一个端点开始失败的情况并不少见,因此我们可以快速失败。

当然,您的用例与我的有点不同,但我会查看错误 tolerance/recovery 并从那里开始。