Hystrix使用例子(二)

Reactive Commands

您可以创建一个HystrixObservableCommand,它是HystrixCommand的专用版本,用于包装Observables,而不是使用上述方法将HystrixCommand转换为Observable。HystrixObservableCommand能够包装发出多个项目的Observable,而普通的HystrixCommands,即使转换为Observables,也不会发出多个项目。

在这种情况下,不要使用命令逻辑覆盖run方法(就像使用普通的HystrixCommand一样),而是覆盖构造方法,以便返回要包装的Observable。

要获取HystrixObservableCommand的Observable表示,请使用以下两种方法之一:

  • observe() - 返回一个“热”的Observable,它立即订阅底层的Observable,但是因为它是通过ReplaySubject过滤的,所以在你有机会订阅生成的Observable之前,你不会丢失它发出的任何项目。
  • toObservable() - 返回一个“冷”Observable,在您订阅生成的Observable之前,它不会订阅底层的Observable。

Fallback

您可以通过添加Hystrix将调用的回退方法来支持Hystrix命令中的优雅降级,以便在主命令失败时获取默认值。您可能希望为大多数可能会失败的Hystrix命令实现回退,但有几个例外:

  1. 执行写操作的命令
  • 如果你的Hystrix命令被设计为执行写操作而不是返回一个值(这样的命令通常在HystrixCommand的情况下返回一个空格,或者在HystrixObservableCommand的情况下返回一个空的Observable),没有多少意义实施后备。如果写入失败,您可能希望失败传播回调用者。
  1. 批处理系统/离线计算
  • 如果您的Hystrix命令正在填充缓存,生成报告或进行任何类型的离线计算,通常更适合将错误传播回调用者,然后调用者可以稍后重试该命令,而不是将调用者发送给调用者。无声的退化反应。

无论您的命令是否具有回退,都会更新所有常见的Hystrix状态和断路器状态/指标,以指示命令失败。在普通的HystrixCommand中,您可以通过getFallback()实现实现回退。

Hystrix将针对所有类型的故障执行此回退,例如run()失败,超时,线程池或信号量拒绝以及断路器短路。

以下示例包含此类后备:

public class CommandHelloFailure extends HystrixCommand<String> {

    private final String name;

    public CommandHelloFailure(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }

    @Override
    protected String run() {
        throw new RuntimeException("this command always fails");
    }

    @Override
    protected String getFallback() {
        return "Hello Failure " + name + "!";
    }
}

每次执行时,此命令的run()方法都将失败。但是,调用者将始终接收命令的getFallback()方法返回的值,而不是接收异常:

@Test
    public void testSynchronous() {
        assertEquals("Hello Failure World!", new CommandHelloFailure("World").execute());
        assertEquals("Hello Failure Bob!", new CommandHelloFailure("Bob").execute());
    }

HystrixObservableCommand Equivalent

对于HystrixObservableCommand,您可以覆盖resumeWithFallback方法,以便它返回第二个Observable,如果它失败,它将从主Observable接管。请注意,因为Observable在已经发出一个或多个项目后可能会失败,所以您的回退不应该假设它将发出观察者将看到的唯一值。

在内部,Hystrix使用RxJava onErrorResumeNext运算符在发生错误时在主要和回退Observable之间无缝转换。

Error Propagation

从run()方法抛出的所有异常除了HystrixBadRequestException都计为失败并触发getFallback()和断路器逻辑。

您可以在HystrixBadRequestException中包装要抛出的异常,并通过getCause()检索它。HystrixBadRequestException适用于报告非法参数或非系统故障等用例,这些故障不应计入故障指标,也不应触发回退逻辑。

HystrixObservableCommand Equivalent

在HystrixObservableCommand的情况下,通过来自结果Observable的onError通知返回不可恢复的错误,并通过回退到Hystrix通过您实现的resumeWithFallback方法获得的第二个Observable来完成回退。

Execution Exception types

Failure TypeException classException.causesubject to fallback
FAILUREHystrixRuntimeExceptionunderlying exception (user-controlled)YES
TIMEOUTHystrixRuntimeExceptionj.u.c.TimeoutExceptionYES
SHORT_CIRCUITEDHystrixRuntimeExceptionj.l.RuntimeExceptionYES
THREAD_POOL_REJECTEDHystrixRuntimeExceptionj.u.c.RejectedExecutionExceptionYES
SEMAPHORE_REJECTEDHystrixRuntimeExceptionj.l.RuntimeExceptionYES
BAD_REQUESTHystrixBadRequestExceptionunderlying exception (user-controlled)NO

Command Name

默认情况下,命令名称是从类名派生的:

getClass().getSimpleName();

要显式定义名称,请通过HystrixCommand或HystrixObservableCommand构造函数传递它:

public CommandHelloWorld(String name) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld")));
        this.name = name;
    }

要保存每个命令分配的Setter分配,您也可以像这样缓存Setter:

private static final Setter cachedSetter = 
        Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
            .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld"));    

    public CommandHelloWorld(String name) {
        super(cachedSetter);
        this.name = name;
    }

HystrixCommandKey是一个接口,可以实现为枚举或常规类,但它也有辅助工具类来构造和实例实例,例如:

HystrixCommandKey.Factory.asKey("HelloWorld")

Command Group

Hystrix使用命令组密钥将命令组合在一起,例如报告,警报,仪表板或团队/库所有权。

默认情况下,Hystrix使用它来定义命令线程池,除非定义了单独的线程池。

HystrixCommandGroupKey是一个接口,可以实现为枚举或常规类,但它也有辅助工具类来构造和实例实例,例如:

HystrixCommandGroupKey.Factory.asKey("ExampleGroup")

Command Thread-Pool

线程池密钥表示用于监视,度量标准发布,缓存和其他此类用途的HystrixThreadPool。HystrixCommand与注入其中的HystrixThreadPoolKey检索的单个HystrixThreadPool相关联,或者默认为使用创建的HystrixCommandGroupKey创建的HystrixThreadPool。

要显式定义名称,请通过HystrixCommand或HystrixObservableCommand构造函数传递它:

public CommandHelloWorld(String name) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")));
        this.name = name;
    }

HystrixThreadPoolKey是一个接口,可以实现为枚举或常规类,但它也有辅助工具类来构造和实例实例,例如:

HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")

您可能使用HystrixThreadPoolKey而不仅仅是不同的HystrixCommandGroupKey的原因是多个命令可能属于相同的“所有权或逻辑功能”组,但某些命令可能需要彼此隔离。

这是一个简单的例子:

  • 用于访问视频元数据的两个命令
  • 组名是“VideoMetadata”
  • 命令A与资源#1相反
  • 命令B与资源#2相反

如果命令A变为潜在的并且使其线程池饱和,则它不应该阻止命令B执行请求,因为它们每个都命中不同的后端资源。

因此,我们逻辑上希望将这些命令组合在一起,但希望它们以不同方式隔离,并使用HystrixThreadPoolKey为它们中的每一个提供不同的线程池。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值