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<Eric>
,而应返回 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
的公共版本。我制作了EricComponent
public static
,它成功了。自己文件中的***类可以工作。上面链接的我的代码有效(假设 restTemplate 调用有效)并返回 n OK
。
【讨论】:
感谢@spencergibb 为您花在这方面的时间。我确实有@EnableHystrix.. 并且能够根据您将Observable<Eric>
从默认值替换为Eric
的建议避免ClassCastException。有人应该更新 Javanica 文档来说明这一点。但是,当我运行它时,我会得到所有“呼叫轰炸”的 println。加上返回的ObservableResult<Eric>
上的invoke()
方法仍然永远不会被执行。
根据您的更新 #3,结果证明将 EricComponent 分离到自己的文件中效果很好。现在一切都在运行。此外,通过 BlockingObservables 切换到阻塞和通过常规 Observables 切换到非阻塞也很有效,并为我提供了 POC 所需的东西。再次感谢@spencergibb。
我在单元测试中遇到了与异步方法(Future@EnableAspectJAutoProxy
等)不起作用:(this.myHystrixMethod
)。这显然不适合 AspectJ 所做的类重写。一旦我开始直接调用原始注释方法,一切都很好。以上是关于javanica中的Hystrix异步方法不在spring-boot java应用程序中运行的主要内容,如果未能解决你的问题,请参考以下文章
hystrix进阶-注解hystrix-javanica使用
Hystrix Javanica 后备在 Spring Cloud 1.0 中不起作用