【问题标题】:Hystrix async methods within javanica not running inside spring-boot java applicationjavanica中的Hystrix异步方法不在spring-boot java应用程序中运行
【发布时间】: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 执行它真的不是我得到的执行它的方法。

【问题讨论】:

    标签: java spring-cloud hystrix


    【解决方案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 所做的类重写。一旦我开始直接调用原始注释方法,一切都很好。
    猜你喜欢
    • 1970-01-01
    • 2015-06-13
    • 2016-11-01
    • 2018-09-16
    • 2018-12-12
    • 2023-03-16
    • 2021-08-12
    • 2021-05-12
    • 2017-10-18
    相关资源
    最近更新 更多