Eureka的消费
在上文我们进行了 Eureka 的服务注册中心单机与高可用搭建,也对服务提供者进行了搭建。通过讲解,我们知道客户端有两个部分,服务提供者与服务消费者。那么,我们应该如何让一个客户对服务端提供的服务进行消费?
RestTemplate直接调用
我们再搭建一个项目 eurekaconsumer,这个项目与搭建服务提供者的步骤相同,都是客户端,所以这里不再重复。首先,启动类比较普通,在后面我们会对启动类做一些修改,代码如下所示。
package com.cloudtest.eurekaconsumer;
@SpringBootApplication
@EnableEurekaClient
public class EurekaconsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaconsumerApplication.class, args);
}
@Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
}
然后为了方便消费 “/hello” 应用,我们在这里也写一个应用,用来消费服务提供者提供的服务,新建类,代码如下所示。
package com.cloudtest.eurekaconsumer.controller;
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/consumer")
public String consumer(){
return restTemplate.getForEntity("http://HELLOSERVICE/hello",String.class). getBody();
//第一种方式
return restTemplate.getForEntity("http://localhost:8090/hello",String.class). getBody();
}
}
在上面的程序中,RestTemplate 在进行应用间的调用时,需要配置 URL。因为 “/hello” 服务在 8090 上,所以直接将 URL 写在这里即可。同样需要修改配置文件,配置文件如下。
server.port=8070
spring.application.name=consumerService
eureka.client.service-url.defaultZone=http://localhost:8764/eureka/
在上面的程序中,将应用名定义为 ConsumerService,并将服务注册。进入 http://localhost:8765/ 信息面板进行观察,根据预期,在配置高可用的情况下,会在这个服务注册中心上查询到这个应用,结果如图10.14所示。

启动新建的服务。在页面上访问 http://localhost:8070/consumer 链接,结果如图10.15所示。

同时,进入服务提供者的控制台,可以看到如下的日志。
2019-01-06 18:07:10.463 INFO 17300 --- [nio-8090-exec-7]
c.c.e.controller.HelloController :
host:port=http://DESKTOP-TQ4OD79:8090, service_id:HELLOSERVICE
看到日志说明调用成功。
LoadBalancerClient调用
学完10.2.1节,可以完成应用之间的直接调用,但是这种直接调用是有问题的。其一,没有走服务注册中心;其二,如果有多台服务器,URL 被固定,明显不会存在负载均衡,而且,如果 URL 没有写进来,服务器是一种空闲状态。
因此可以使用 LoadBalancerClient 方式进行负载均衡。相对于第一种方式,程序启动的地方不需要进行修改,只修改控制类,控制类的代码如下所示。
package com.cloudtest.eurekaconsumer.controller;
@RestController
public class ConsumerController {
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/consumer")
public String consumer(){
//第二种方式
ServiceInstance serviceInstance=loadBalancerClient.choose("HELLOSERVICE");
String url=String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance. getPort())+"/hello";
return restTemplate.getForEntity(url,String.class).getBody();
}
}
在代码中,使用 LoadBalancerClient 的 choose 方法,选择服务 ID 获取实例。然后,从实例中,取出主机、端口,最后拼接服务,这样就形成一个 URL。通过变化的 URL,我们可以继续使用 RestTemplate。
@LoadBalanced注解
上面的第二种方式,用来实现应用间调用完全没有问题,唯一的缺点就是每次都要写,特别浪费时间,而且都是重复代码。此时,我们使用第三种方式,会更加方便。
首先修改启动类,在 RestTemplate 上添加注解 @LoadBalanced,将 RestTemplate 注册到 Bean。在这里也可以使用配置类,不过在启动类中演示更加方便。启动类代码如下所示。
package com.cloudtest.eurekaconsumer;
@SpringBootApplication
@EnableEurekaClient
public class EurekaconsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaconsumerApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
在上面的代码中,可以看到注解 @LoadBalanced 被添加了。现在,我们修改前文的控制类,控制类代码如下所示。
package com.cloudtest.eurekaconsumer.controller;
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/consumer")
public String consumer(){
//第三种方式
return restTemplate.getForEntity("http://HELLOSERVICE/hello",String.class).getBody();
}
}
上面的代码,相较前面两种方式而言更加简洁了,URL 上直接将应用名写进去。不过需要注意的是,程序中需要依赖注入 RestTemplate。启动程序,并进行调用,在服务提供者的控制台上日志如下所示。
2019-01-06 18:53:16.001 INFO 17300 --- [io-8090-exec-10] c.c.e.controller. HelloController : host:port=http://DESKTOP-TQ4OD79:8090, service_id:HELLOSERVICE