通过SpringCloud高可用,我们已经搭建起微服务架构中的核心组件--服务注册中心(包括单节点模式和高可用模式)。同时,还将一个简单的hello-service通过简单的配置使得该程序注册到Eureka注册中心上,称为该服务治理体系下的一个服务。
现在我们已经有了服务注册中心和服务提供者,下面就来尝试构建一个服务消费者。
服务消费者
这个服务消费者,主要完成两个目标:发现服务以及消费服务
其中,服务的发现任务是由Eureka客户端完成,而服务消费的任务是由Ribbon完成,Ribbon是一个基于HTTP和TCP的客户端负载均衡器,它可以在通过客户端中配置的ribbonServerList服务端列表去轮询访问以达到负载均衡的作用。当Ribbon与Eureka联合使用时,Ribbon的服务实例清单ribbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务端列表。同时它也会用NIWSServerPing来取代IPing,它将职责委托给Eureka来确定服务端是否已经启动。本质就是它在Eureka服务发现的基础上实现了一套对服务实例的选择策略,从而实现对服务的消费。+
编码实现
1.准备工作
启动之前高可用的服务注册中心eureka-server以及hello-service服务,为了试实验Ribbon的客户端负载均衡的功能,通过java -jar命令行的方式来启动不同端口的hello-service
但是在打包之前,如果hello-service中有测试类,需要将测试类跳过,否则敲入命令mvn:install会报错,因此打包的时候要使用这个命令:
mvn install -Dmaven.test.skip=true
然后在target目录下,敲入命令:
java -jar springboot-01-1.0-SNAPSHOT.jar --server.port=8081
java -jar springboot-01-1.0-SNAPSHOT.jar --server.port=8082
在启动成功之后,如下图所示,从Eureka信息面板可以看到名为HELLO-SERVICE的服务中出现了两个实例单元,分别是通过命令启动的8081端口和8082端口的服务
两个端口的服务
2.新建Consumer
创建一个SpringBoot的基础工程来实现消费服务者,取名为ribbon-consumer,并在pom中引入如下的依赖,新增了spring-cloud-starter-ribbon
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
</dependencies>
然后创建应用主类ConsumerApplication,通过@EnableDiscoveryClient注解让该应用注册为Eureka客户端应用,以获得服务发现的能力。同时,在该主类中创建RestTemplate的SpringBean实例,并通过@LoadBalanced注解开启客户端负载均衡。
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
创建ConsumerController类并实现/ribbon-consumer接口。在该接口中,通过在上面创建的RestTemplate来实现对HELLO-SERVICE服务提供的/hello接口进行调用。可以看到在这里访问的地址是服务名HELLO-SERVICE,而不是一个具体的地址,在服务治理框架中,这是一个重要的特性。
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/ribbon-consumer")
public String helloConsumer(){
return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
}
}
在application.properties中配置Eureka服务注册中心的位置,需要与hello-service一样,不然是发现不了服务的。
spring.application.name=ribbon-consumer
server.port=9000
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka
3.启动服务
启动服务,然后在注册中心的面板中我们可以看到有两个服务。
然后在地址栏中输入http://localhost:9000/ribbon-consumer发起get请求,成功返回了“Hello world”,此时我们可以在ribbon-consumer应用的控制台中看到如下信息,Ribbon输出了当前客户端维护的HELLO-SERVICE的服务列表情况。其中包含了各个实例的位置,Ribbon就是按照此信息进行轮询访问,以实现基于客户端的负载均衡。
DynamicServerListLoadBalancer
for client HELLO - SERVICE initialized: DynamicServerListLoadBalancer: {
NFLoadBalancer: name = HELLO - SERVICE,
current list of Servers = [192.168 .31 .142: 8081, 192.168 .31 .142: 8082],
Load balancer stats = Zone stats: {
defaultzone = [Zone: defaultzone;Instance count: 2;Active connections count: 0;Circuit breaker tripped count: 0;Active connections per server: 0.0;]
},
Server stats: [
[Server: 192.168 .31 .142: 8081;Zone: defaultZone;Total Requests: 0;Successive connection failure: 0;Total blackout seconds: 0;Last connection made: Thu Jan 01 08: 00: 00 CST 1970;First connection made: Thu Jan 01 08: 00: 00 CST 1970;Active Connections: 0;total failure count in last(1000) msecs: 0;average resp time: 0.0;90 percentile resp time: 0.0;95 percentile resp time: 0.0;min resp time: 0.0;max resp time: 0.0;stddev resp time: 0.0],
[Server: 192.168 .31 .142: 8082;Zone: defaultZone;Total Requests: 0;Successive connection failure: 0;Total blackout seconds: 0;Last connection made: Thu Jan 01 08: 00: 00 CST 1970;First connection made: Thu Jan 01 08: 00: 00 CST 1970;Active Connections: 0;total failure count in last(1000) msecs: 0;average resp time: 0.0;90 percentile resp time: 0.0;95 percentile resp time: 0.0;min resp time: 0.0;max resp time: 0.0;stddev resp time: 0.0]
]
}
ServerList: org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList @673b1fae
再尝试发送几次请求,并观察两个HELLO-SERVICE的控制台,可以看到两个控制台会交替打印下面的日志,可以用来判断当前的ribbon-consumer对HELLO-SERVICE的调用是否是负载均衡的。
c.tinner.web.controller.HelloController : /add, host:192.168.31.142, service_id:hello-service
网友评论