javanica中的Hystrix异步方法不在spring-boot java应用程序中运行

Posted

技术标签:

【中文标题】javanica中的Hystrix异步方法不在spring-boot java应用程序中运行【英文标题】:Hystrix async methods within javanica not running inside spring-boot java application 【发布时间】:2014-12-09 22:13:55 【问题描述】:

我正在使用 spring-cloud-starter(即具有所有微服务功能的 spring boot)。当我在使用 javanica @HystrixCommand 注释的组件中创建 hystrix 方法时,请按照 javanica github 站点 (https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica) 上的说明使该方法异步运行,无论我使用它们的“Future”还是“响应式执行” Observable',没有任何东西运行/执行,每当我尝试提取结果(在 Future 的情况下)或获取回调(在反应式执行的情况下 .. 并且 println 的不触发时,我都会得到java.lang.ClassCastException: springbootdemo.EricComponent$1 cannot be cast to springbootdemo.Eric所以它真的没有运行)。

public class Application  ...

@RestController
@RequestMapping(value = "/makebunchofcalls/num")
class EricController  ..

    @RequestMapping(method=RequestMethod.POST)
    ArrayList<Eric> doCalls(@PathVariable Integer num) throws IOException 
        ArrayList<Eric> ale = new ArrayList<Eric>(num);
        for (int i =0; i<num; i++) 
            rx.Observable<Eric> oe = this.ericComponent.doRestTemplateCallAsync(i);
            oe.subscribe(new Action1<Eric>() 
                @Override
                public void call(Eric e)   // AT RUNTIME, ClassCastException
                    ale.add(e);
                
            );
        

        return ale;
    

@Component
class EricComponent  ...

    // async version =========== using reactive execution via rx library from netflix ==============

    @HystrixCommand(fallbackMethod = "defaultRestTemplateCallAsync", commandKey = "dogeAsync")
    public rx.Observable<Eric> doRestTemplateCallAsync(int callNum) 
        return new ObservableResult<Eric>() 
            @Override
            public Eric invoke()   // NEVER CALLED
                try 
                    ResponseEntity<String> result = restTemplate.getForEntity("http://doges/doges/24232/photos", String.class);  // actually make a call
                    System.out.println("*************** call successfull: " + new Integer(callNum).toString() + " *************");
                 catch (Exception ex) 
                    System.out.println("=============== call " + new Integer(callNum).toString() + " not successfull: " + ex.getMessage() + " =============");
                
                return new Eric(new Integer(callNum).toString(), "ok");
            
        ;
    

    public rx.Observable<Eric> defaultRestTemplateCallAsync(int callNum) 
        return new ObservableResult<Eric>() 
            @Override
            public Eric invoke() 
                System.out.println("!!!!!!!!!!!!! call bombed " + new Integer(callNum).toString() + "!!!!!!!!!!!!!");
                return new Eric(new Integer(callNum).toString(), "bomb");
            
        ;
    

为什么我会返回 EricComponent$1 而不是 Eric?顺便说一句,Eric 只是一个带有 2 个字符串的简单类......它被省略了。

我认为我必须明确执行,但这暗示了我,因为:1)使用 Future 执行它,queue() 方法不可用,因为文档声称和 2)使用 Observable 执行它真的不是我得到的执行它的方法。

【问题讨论】:

【参考方案1】:

您的应用程序类上有@EnableHystrix 注释吗?

subscribe 方法是异步的,您正在尝试在同步控制器方法中填充列表,因此那里可能存在问题。你能把subscribe改成toBlockingObservable().forEach()看看有没有帮助?

更新 #1 我能够复制。您的默认方法不应返回 Observable&lt;Eric&gt;,而应返回 Eric

public Eric defaultRestTemplateCallAsync(final int callNum) 
    System.out.println("!!!!!!!!!!!!! call bombed " + new Integer(callNum) + "!!!!!!!!!!!!!");
    return new Eric(new Integer(callNum).toString(), "bomb");

更新 #2 在这里查看我的代码https://github.com/spencergibb/communityanswers/tree/so26372319

更新 #3 当我注释掉fallbackMethod 属性时,它抱怨找不到用于AOP 的EricComponent 的公共版本。我制作了EricComponentpublic static,它成功了。自己文件中的***类可以工作。上面链接的我的代码有效(假设 restTemplate 调用有效)并返回 n OK

【讨论】:

感谢@spencergibb 为您花在这方面的时间。我确实有@EnableHystrix.. 并且能够根据您将Observable&lt;Eric&gt; 从默认值替换为Eric 的建议避免ClassCastException。有人应该更新 Javanica 文档来说明这一点。但是,当我运行它时,我会得到所有“呼叫轰炸”的 println。加上返回的ObservableResult&lt;Eric&gt; 上的invoke() 方法仍然永远不会被执行。 根据您的更新 #3,结果证明将 EricComponent 分离到自己的文件中效果很好。现在一切都在运行。此外,通过 BlockingObservables 切换到阻塞和通过常规 Observables 切换到非阻塞也很有效,并为我提供了 POC 所需的东西。再次感谢@spencergibb。 我在单元测试中遇到了与异步方法(Future)相同的问题。不幸的是,我的正常策略(@EnableAspectJAutoProxy 等)不起作用:( 我终于找到了问题所在——我试图从类本身中调用一个带注释的方法(例如this.myHystrixMethod)。这显然不适合 AspectJ 所做的类重写。一旦我开始直接调用原始注释方法,一切都很好。

以上是关于javanica中的Hystrix异步方法不在spring-boot java应用程序中运行的主要内容,如果未能解决你的问题,请参考以下文章

hystrix进阶-注解hystrix-javanica使用

hystrix实战只javanica

Hystrix Javanica 后备在 Spring Cloud 1.0 中不起作用

如何对 javanica @HystrixCommand 注释方法进行单元测试?

Hystrix 配置

Hystrix 命令不在 Hystrix 环境中运行