这里说一下我自己犯的一个错误。我有三个项目eureka-server,provide-service,consumer-service,以下我统称为ABC三个项目。现在的步骤是这样的,先访问C项目的一个接口,接口里面用restTemplate发送的一个请求,具体看下面

@RestController
public class TestController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/test")
    public void test() {
        //template.getForEntity("http://localhost:8000/test",String.class);
        restTemplate.getForEntity("http://provide-serivce/test",String.class);
    }
}

然后B的test这个接口代码如下

 @RequestMapping(value = "/test")
    public String test(HttpServletResponse resp) {
        System.out.println("provide-service is provides services");
        return "redirect:/page";
    }

这里ABC的配置是正常的,并且BC项目都注册到A上了,当我们访问C的test接口时显示如下错误

java.net.UnknownHostException: provide-serivce
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) ~[na:1.8.0_144]
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_144]
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_144]
	at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_144]
	at java.net.Socket.connect(Socket.java:538) ~[na:1.8.0_144]

这里显示的错误很明显,就是不知道的域名。然后我就一直纳闷了,按我自己的逻辑,我的消费者已经拥有的从注册中心拉取服务名实例的权限,已经拥有服务名列表(服务名就是包含元元素,其中包含ip,port),为什么显示不知道的域名呢?当然了这就是我想当然的问题了。是的C项目确实有从注册中心拿的服务实例列表,但是我错的点resttemplate只是类似于httpclient的一个发送rest风格的请求,它这里是没有办法去识别所谓的服务名的,不识别服务名当然就会报那个错误咯。在《spring Cloud 微服务实战》这本书上写的,一定要@loadBalance注解修饰的restTemplate才能实现服务名的调用,没有修饰的restTemplate是没有该功能的。@loadBalance是Netflix的ribbon中的一个负载均衡的注解,当我项目加了loadbalacnce的时候,就可以了。


至于为什么一定要该注解修饰,这里我大概讲一下。loadBalance这个注解加上之后,这个注解有3件事情要处理。

    第一件就是从负载均衡器中选一个对应的服务实例,那有的人就会问为什么从负载均衡器中挑选,原因很明显就是,所有的服务名实例都放在负载均衡器中的serverlist。

    第二件事情就是从第一件事情挑选的实例中去请求内容。

    第三件事情就是由服务名转为真正使用的ip地址


讲到这里大概应该清楚了吧。哎,之前也是百思不得其解,现在终于明白了

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐