通过继承HystrixCommand来创建请求命令遇到的问题

来源:互联网 发布:制作vpn客户端软件 编辑:程序博客网 时间:2024/06/06 22:06

   在《spring cloud 微服务实战》第151页到152页,作者向我们介绍了一些Hystrix命令的进阶用法,通过继承的方式来实现创建请求命令,比如:

public class UserCommand extends HystrixCommand<User>{    private RestTemplate restTemplate;    private Long id;    public UserCommand(Setter setter,RestTemplate restTemplate,Long id){        super(setter);        this.restTemplate=restTemplate;        this.id=id;    }    @Override    protected User run() throws Exception {        return restTemplate.getForObject("http://USER-SERVICE/users/{1}",User.class,id);    }}

     书上说通过上面实现的UserCommand,我们既可以实现请求的同步执行也可以实现异步执行。就拿同步执行来说吧,User u=new UserCommand(restTemplate,1L).execute();

你可以直接在main方法中运行这句代码,但是运行过程中你会发现书上的这句代码少了一个参数setter,我不知道作者是忘了?还是采用了封装的方法省略了一部分代码?反正我觉得书中内容不够仔细,少一个参数肯定会报错啦,所以得加上,后面会给出修正后的代码。其次restTemplate不能使用你在类中注入的实例传入,而应该new 一个,否则会报空指针。

   修正后代码为:

User u=new UserCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), new RestTemplate(),1L).execute();
  

    如上代码所示,setter其实是@HystrixCommand注解中的一些配置参数,是Hystrix命令的一些额外配置,这里是配置了一个空字符串的GroupKey,因为他也是一个setter,运行后你发现一切正常,唯独在getForObject时报了一个超时错误:Exception in thread "main" com.netflix.hystrix.exception.HystrixRuntimeException: UserCommand timed-out and no fallback available.

    因为我USER-SERVICE是启动状态,并且不应该访问不到,我在浏览器中测试都是正常的,唯独这种超时,原来默认超时时间是1秒,我就设置大一些看她会有什么结果,再次修改代码:

User u=new UserCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(        HystrixCommandGroupKey.Factory.asKey("")).andCommandPropertiesDefaults(                HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(5000)),        new RestTemplate(),0L).execute();
另外设置超时还有一个API是

withExecutionIsolationThreadTimeoutInMilliseconds
但是他已经被标注过时了,所以用
withExecutionTimeoutInMilliseconds

     设置好超时后,又报了一个错误:Caused by: java.net.UnknownHostException: USER-SERVICE,原来你通过new UserCommand()这种方式运行的话,如果你的Uri传的是USER-SERVICE这种服务名的话,程序就解析不了,必须写localhost:8082这种形式,书上真的不够仔细,初学者很容易陷入其中。而如果是通过将服务启动并注册到eureka中,然后通过ribbon调用,那么你Uri写http://USER-SERVICE/users/{1}就可以,因为都已经注册到eureka上了,微服务之间都可以互相解析服务名为相应的主机端口,不知道理解的对不对,希望知情者能给予帮助。

   

     关于超时那里可参考http://ju.outofmemory.cn/entry/68192