Spring Cloud Eureka 服务治理--服务发现与消费
这篇文章主要介绍如何使用Spring Cloud Eureka来实现服务治理--服务消费 ,是一个总结 记录 方便自己记忆。
文章知识 均来自以下系列文章,请参考原文
Spring Cloud构建微服务架构:服务消费(基础)【Dalston版】
Spring Cloud构建微服务架构:服务消费(Ribbon)【Dalston版】
Spring Cloud构建微服务架构:服务消费(Feign)【Dalston版】
使用Spring Cloud Eureka来实现服务治理
2.服务注册与发现 : 创建 服务提供者 ---创建提供服务的客户端,并向服务注册中心注册自己
Step1:创建一个Spring Boot项目eureka-client,添加起步依赖 spring-cloud-starter-netflix-eureka-client ,spring-boot-starter-web
Step2:在项目入口添加 @EnableDiscoveryClient 注解,该注解能激活Eureka中的DiscoveryClient实现,这样才能实现Controller中对服务信息的输出。
Step3:在application.properties文件中配置一下
#微服务的名称:后续在调用的时候只需要使用该名称就可以进行服务的访问
spring.application.name=eureka-client
#微服务端口
server.port=2001
#指定服务注册中心的位置
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
Step4:添加一个 该微服务可以提供的功能,例如 通过 DiscoveryClient对象,在日志中打印出服务实例的相关内容
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DiscoveryClientController { @Autowired private DiscoveryClient discoveryClient; @GetMapping("/discoveryClient") public String discoveryClient() { // 服务实例相关内容 String service = "Services: " + discoveryClient.getServices(); // 打印出服务实例相关内容 System.out.println(service); // 返回服务实例相关内容 return service; } }
Step5:启动 eureka-client项目,再访问http://localhost:1001/就会在Instances currently registered with Eureka列表看到刚刚注册的eureka-client服务
Step6:如果要访问eureka-client微服务提供的discoveryClient 服务,可以访问http://localhost:2001/discoveryClient。
待解决:那么我们其实需要的是 如何在其它微服务 访问 eureka-client eureka-client微服务提供的discoveryClient 服务。也就是 如何去消费服务提供者的接口 ,接着看
3.1 服务消费 :创建服务消费者 并消费 eureka-client提供的服务--基础版
使用Spring Cloud提供的负载均衡器客户端接口 LoadBalancerClient
接口 实现服务的消费。通过LoadBalancerClient
接口来获取某个服务的具体实例,并根据实例信息来发起服务接口消费请求。
Step1:创建一个Spring Boot项目 eureka-consumer(服务消费者工程),添加起步依赖 spring-cloud-starter-netflix-eureka-client ,spring-boot-starter-web
Step2:在项目入口类添加@EnableDiscoveryClient 注解,激活Eureka中的DiscoveryClient实现,将当前应用加入到服务治理体系中。
Step3:在application.properties文件添加配置
#微服务的名称:后续在调用的时候只需要使用该名称就可以进行服务的访问
spring.application.name=eureka-consumer
#微服务端口
server.port=2101
#指定服务注册中心的位置
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
Step4:在配置类中初始化RestTemplate,用来真正发起REST请求。
@Bean public RestTemplate restTemplate() { return new RestTemplate(); }
Step5: 创建一个接口用来消费eureka-client提供的接口
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class DiscoveryClientController { @Autowired private LoadBalancerClient loadBalancerClient; @Autowired private RestTemplate restTemplate; @GetMapping("/consumer") public String discoveryClient() { // LoadBalancerClient负载均衡的选出一个eureka-client的服务实例,把这个服务实例的基本信息存储在ServiceInstance中 ServiceInstance serviceInstance = loadBalancerClient.choose("eureka-client"); // 拼接出访问eureka-client微服务 /discoveryClient接口的详细地址 String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "discoveryClient"; System.out.println("url==" + url); // 利用RestTemplate对象实现对服务提供者接口的调用。 String services = restTemplate.getForObject(url, String.class); return services; } }
Step6:启动eureka-server,eureka-client,eureka-consumer。并访问http://localhost:2101/consumer 。就会看到eureka-consumer服务是如何消费eureka-client服务的/discoveryClient
接口的
3.2 服务消费 :创建服务消费者 并消费 eureka-client提供的服务--Ribbon
基础版 通过LoadBalancerClient接口实现服务的消费,需要我们手工编写服务的选择,链接拼接等操作,对于开发人员不友好。所以Spring Cloud针对客户端负载均衡提供了工具包Spring Cloud Ribbon。
Spring Cloud Ribbon
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP和TCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。
当Ribbon与Eureka联合使用时,ribbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务实例列表。同时它也会用NIWSDiscoveryPing来取代IPing,它将职责委托给Eureka来确定服务端是否已经启动。
我们在使用Spring Cloud Ribbon的时候,不论是与Eureka还是Consul结合,都会在引入Spring Cloud Eureka或Spring Cloud Consul依赖的时候通过自动化配置来加载上述所说的配置内容,所以我们可以快速在Spring Cloud中实现服务间调用的负载均衡。
使用Spring Cloud Ribbon来实现服务的调用以及客户端均衡负载。
Step1:创建Spring Boot项目eureka-consumer-ribbon,添加起步依赖 spring-cloud-starter-netflix-eureka-client ,spring-boot-starter-web,spring-cloud-starter-netflix-ribbon。
Step2:在项目入口类添加@EnableDiscoveryClient注解,将当前应用 添加到 服务治理体系中。
Step3:在application.properties文件中配置微服务
#微服务的名称:后续在调用的时候只需要使用该名称就可以进行服务的访问
spring.application.name=eureka-consumer-ribbon
#微服务端口
server.port=2201
#指定服务注册中心的位置
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
Step4:在配置类中初始化RestTemplate,用来真正发起REST请求。并增加@LoadBalanced注解
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
Step5: 创建一个接口用来消费eureka-client提供的接口
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class DiscoveryClientController { @Autowired private RestTemplate restTemplate; @GetMapping("/consumer") public String discoveryClient() { String services = restTemplate.getForObject("http://eureka-client/discoveryClient", String.class); return services; } }
Step6:启动eureka-server,eureka-client,eureka-consumer-ribbon。并访问http://localhost:2201/consumer 。就会看到eureka-consumer-ribbon服务是如何消费eureka-client服务的/discoveryClient
接口的
总结:使用 Spring Cloud Ribbon 的@LoadBalanced 注解 ,就可以使用 服务名和接口url 去调用服务。 因为Spring Cloud Ribbon有一个拦截器,它能够在这里进行实际调用的时候,自动的去选取服务实例,并将实际要请求的IP地址和端口替换这里的服务名,从而完成服务接口的调用。
3.3 服务消费 :创建服务消费者 并消费 eureka-client提供的服务--Feign
Spring Cloud Feign
Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端。它使得编写Web服务客户端变得更加简单。
我们只需要通过创建接口并用注解来配置它既可完成对Web服务接口的绑定。它具备可插拔的注解支持,包括Feign注解、JAX-RS注解。它也支持可插拔的编码器和解码器。
Spring Cloud Feign还扩展了对Spring MVC注解的支持,同时还整合了Ribbon和Eureka来提供均衡负载的HTTP客户端实现。
使用Feign方便的声明对eureka-client服务的定义和调用
Step1:创建Spring Boot项目eureka-consumer-feign,添加起步依赖 spring-cloud-starter-netflix-eureka-client ,spring-boot-starter-web,spring-cloud-starter-openfeign
Step2:在项目入口类添加@EnableDiscoveryClient注解,将当前应用 添加到 服务治理体系中。
Step3:在application.properties文件中配置微服务
#微服务的名称:后续在调用的时候只需要使用该名称就可以进行服务的访问
spring.application.name=eureka-consumer-feign
#微服务端口
server.port=2301
#指定服务注册中心的位置
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
Step4:在配置类 添加 @EnableFeignClients注解,开启扫名Spring Cloud Feign客户端功能。
Step5:创建一个Feign的客户端接口定义。使用@FeignClient
注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用Spring MVC的注解就可以来绑定服务提供方的REST接口,比如下面就是绑定eureka-client
服务的/discoveryClient
接口的例子:
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.GetMapping; @Service @FeignClient("eureka-client") public interface DiscoveryClientService { @GetMapping("/discoveryClient") public String consumer(); }
Step6:创建controller ,通过定义的feign客户端来调用服务提供方的接口
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DiscoveryClientController { @Autowired private DiscoveryClientService discoveryClientService; @GetMapping("/consumer") public String comsumer() { String services = discoveryClientService.consumer(); return services; } }
Step7:启动eureka-server,eureka-client,eureka-consumer-feign。并访问http://localhost:2301/consumer 。就会看到eureka-consumer-feign服务是如何消费eureka-client服务的/discoveryClient
接口的
总结:通过Spring Cloud Feign来实现服务调用的方式更加简单了。通过@FeignClient定义的接口来统一的声明我们需要依赖的微服务接口,而在具体使用的时候就跟调用本地方法一点的进行调用即可。
由于Feign是基于Ribbon实现的,所以它自带了客户端负载均衡功能,也可以通过Ribbon的IRule进行策略扩展。
另外,Feign还整合的Hystrix来实现服务的容错保护,在Dalston版本中,Feign的Hystrix默认是关闭的。待后文介绍Hystrix带领大家入门之后,我们再结合介绍Feign中的Hystrix以及配置方式。
3种方式总结对比:
基础版:用Spring Cloud的LoadBalancerClient
接口 获取获取某个服务的具体实例,链接拼接。并通过RestTemplate发起REST请求。
Ribbon版:用Spring Cloud的@LoadBalanced注解 通过服务提供者的服务名 ,并通过RestTemplate发起REST请求。和基础版相比 不再需要拼接服务url
Feign版:把服务提供者 通过@FeignClient注解 定义成 服务消费者的一个接口。服务提供者的方法 可以定义成接口中的方法。在服务消费者方 通过调用接口的方式 调用其它微服务的方法。
3种方式可以互为替代。
4.几台服务提供相同服务来做均衡负载
我们可以准备多个微服务,来提供相同的服务。这样当消费者调用服务时,Eureka Server 会随机调用某个微服务。
创建微服务eureka-client-1,提供和eureka-client微服务一样的服务,共消费方调用。
Step1:创建一个Spring Boot项目eureka-client-1,添加起步依赖 spring-cloud-starter-netflix-eureka-client ,spring-boot-starter-web
Step2:在项目入口添加 @EnableDiscoveryClient 注解,该注解能激活Eureka中的DiscoveryClient实现,这样才能实现Controller中对服务信息的输出。
Step3:在application.properties文件中配置一下
#微服务的名称:后续在调用的时候只需要使用该名称就可以进行服务的访问
spring.application.name=eureka-client
#微服务端口
server.port=2002
#指定服务注册中心的位置
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
- spring.application.name 和 微服务eureka-client 保持一致
Step4:添加一个 该微服务可以提供的功能,例如 通过 DiscoveryClient对象,在日志中打印出服务实例的相关内容
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DiscoveryClientController { @Autowired private DiscoveryClient discoveryClient; @GetMapping("/discoveryClient") public String discoveryClient() { // 服务实例相关内容 String service = "this is client 2 Services: " + discoveryClient.getServices(); // 打印出服务实例相关内容 System.out.println(service); // 返回服务实例相关内容 return service; } }
- eureka-client 提供的服务的url 和 微服务eureka-client 保持一致。但输出内容不同
Step5:启动 eureka-client-1项目,再访问http://localhost:1001/就会在Instances currently registered with Eureka列表看到刚刚注册的eureka-client-1服务
Step6:如果要访问eureka-client-1微服务提供的discoveryClient 服务,可以访问http://localhost:2002/discoveryClient。
Step7:启动eureka-consumer,并多次访问http://localhost:2101/consumer 。就会看到eureka-client 和 eureka-client-1 返回的两种结果交替出现,说明两个服务中心自动提供了服务均衡负载的功能。