转载

SpringCloud构建微服务架构:服务消费

在Spring Cloud Commons中提供了大量的与服务治理相关的抽象接口,包括 DiscoveryClient 、这里我们即将介绍的 LoadBalancerClient 等。对于这些接口的定义我们在上一篇介绍服务注册与发现时已经说过,Spring Cloud做这一层抽象,很好的解耦了服务治理体系,使得我们可以轻易的替换不同的服务治理设施。

LoadBalancerClient 接口的命名中,我们就知道这是一个负载均衡客户端的抽象定义,下面我们就看看如何使用Spring Cloud提供的负载均衡器客户端接口来实现服务的消费。

下面的例子,我们将利用上一篇中构建的eureka-server作为服务注册中心、eureka-client作为服务提供者作为基础。

  • 我们先来创建一个服务消费者工程,命名为: eureka-consumer 。并在 pom.xml 中引入依赖(这里省略了parent和dependencyManagement的配置):
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>
复制代码
  • 配置 application.properties ,指定eureka注册中心的地址:

    spring.application.name=eureka-consumer
    server.port=2101
    
    eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
    复制代码
  • 创建应用主类。初始化 RestTemplate ,用来真正发起REST请求。 @EnableDiscoveryClient 注解用来将当前应用加入到服务治理体系中。

    @EnableDiscoveryClient
    @SpringBootApplication
    public class Application {
    
    	@Bean
    	public RestTemplate restTemplate() {
    		return new RestTemplate();
    	}
    
    	public static void main(String[] args) {
    		new SpringApplicationBuilder(Application.class).web(true).run(args);
    	}
    }
    复制代码
  • 创建一个接口用来消费eureka-client提供的接口:

    @RestController
    public class DcController {
    
        @Autowired
        LoadBalancerClient loadBalancerClient;
        @Autowired
        RestTemplate restTemplate;
    
        @GetMapping("/consumer")
        public String dc() {
            ServiceInstance serviceInstance = loadBalancerClient.choose("eureka-client");
            String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/dc";
            System.out.println(url);
            return restTemplate.getForObject(url, String.class);
        }
    }
    复制代码

可以看到这里,我们注入了 LoadBalancerClientRestTemplate ,并在 /consumer 接口的实现中,先通过 loadBalancerClientchoose 函数来负载均衡的选出一个 eureka-client 的服务实例,这个服务实例的基本信息存储在 ServiceInstance 中,然后通过这些对象中的信息拼接出访问 /dc 接口的详细地址,最后再利用 RestTemplate 对象实现对服务提供者接口的调用。

在完成了上面你的代码编写之后,读者可以将eureka-server、eureka-client、eureka-consumer都启动起来,然后访问 http://localhost:2101/consumer ,来跟踪观察eureka-consumer服务是如何消费eureka-client服务的 /dc 接口的。

SpringCloud构建微服务架构:服务消费

2. 服务消费(Ribbon)

通过上面的学习,我们已经学会如何通过 LoadBalancerClient 接口来获取某个服务的具体实例,并根据实例信息来发起服务接口消费请求。但是这样的做法需要我们手工的去编写服务选取、链接拼接等繁琐的工作,对于开发人员来说非常的不友好。所以,下来我们看看Spring Cloud中针对客户端负载均衡的工具包:Spring Cloud Ribbon。

2.1 Spring Cloud Ribbon

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP和TCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。

当Ribbon与Eureka联合使用时,ribbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务实例列表。同时它也会用NIWSDiscoveryPing来取代IPing,它将职责委托给Eureka来确定服务端是否已经启动。

而当Ribbon与Consul联合使用时,ribbonServerList会被ConsulServerList来扩展成从Consul获取服务实例列表。同时由ConsulPing来作为IPing接口的实现。

我们在使用Spring Cloud Ribbon的时候,不论是与Eureka还是Consul结合,都会在引入Spring Cloud Eureka或Spring Cloud Consul依赖的时候通过自动化配置来加载上述所说的配置内容,所以我们可以快速在Spring Cloud中实现服务间调用的负载均衡。

下面我们通过具体的例子来看看如何使用Spring Cloud Ribbon来实现服务的调用以及客户端均衡负载。

2.2 搭建

下面的例子,我们将利用之前构建的 eureka-server 作为服务注册中心、 eureka-client 作为服务提供者作为基础。而基于Spring Cloud Ribbon实现的消费者,我们可以根据 eureka-consumer 实现的内容进行简单改在就能完成,具体步骤如下:

  • 根据 eureka-consumer 复制一个服务消费者工程,命名为: eureka-consumer-ribbon 。在 pom.xml 中增加下面的依赖:

    <dependencies>
        ...
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
    </dependencies>
    复制代码
  • 修改应用主类。为 RestTemplate 增加 @LoadBalanced 注解:

    @SpringBootApplication
    @EnableDiscoveryClient
    public class EurekaConsumerApplication {
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaConsumerApplication.class, args);
        }
    }
    复制代码
  • 修改Controller。去掉原来通过 LoadBalancerClient 选取实例和拼接URL的步骤,直接通过RestTemplate发起请求。

    @RestController
    public class DcController {
    
        @Autowired
        RestTemplate restTemplate;
    
        @GetMapping("/consumer")
        public String dc() {
            return restTemplate.getForObject("http://eureka-client/dc", String.class);
        }
    
    }
    复制代码

    可以看到这里,我们除了去掉了原来与 LoadBalancerClient 相关的逻辑之外,对于 RestTemplate 的使用,我们的第一个url参数有一些特别。这里请求的host位置并没有使用一个具体的IP地址和端口的形式,而是采用了服务名的方式组成。那么这样的请求为什么可以调用成功呢?因为Spring Cloud Ribbon有一个拦截器,它能够在这里进行实际调用的时候,自动的去选取服务实例,并将实际要请求的IP地址和端口替换这里的服务名,从而完成服务接口的调用。

    在完成了上面你的代码编写之后,读者可以将eureka-server、eureka-client、eureka-consumer-ribbon都启动起来,然后访问 http://localhost:2101/consumer ,来跟踪观察eureka-consumer-ribbon服务是如何消费eureka-client服务的 /dc 接口的,并且也可以通过启动多个eureka-client服务来观察其负载均衡的效果。

3. 服务消费(Feign)

3.1 Spring Cloud Feign

Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端。它使得编写Web服务客户端变得更加简单。我们只需要通过创建接口并用注解来配置它既可完成对Web服务接口的绑定。它具备可插拔的注解支持,包括Feign注解、JAX-RS注解。它也支持可插拔的编码器和解码器。Spring Cloud Feign还扩展了对Spring MVC注解的支持,同时还整合了Ribbon和Eureka来提供均衡负载的HTTP客户端实现。

下面,我们通过一个例子来展现Feign如何方便的声明对eureka-client服务的定义和调用。

3.2 搭建

下面的例子,我们将利用之前构建的 eureka-server 作为服务注册中心、 eureka-client 作为服务提供者作为基础。而基于Spring Cloud Ribbon实现的消费者,我们可以根据 eureka-consumer 实现的内容进行简单改在就能完成,具体步骤如下:

  • 根据 eureka-consumer 复制一个服务消费者工程,命名为: eureka-consumer-feign 。在 pom.xml 中增加下面的依赖:

    <dependencies>
        ...
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
    </dependencies>
    复制代码
  • 修改应用主类。通过 @EnableFeignClients 注解开启扫描Spring Cloud Feign客户端的功能:

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		new SpringApplicationBuilder(Application.class).web(true).run(args);
	}
}
复制代码
  • 创建一个Feign的客户端接口定义。使用 @FeignClient 注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用Spring MVC的注解就可以来绑定服务提供方的REST接口,比如下面就是绑定 eureka-client 服务的 /dc 接口的例子:

    @FeignClient("eureka-client")
    public interface DcClient {
    
        @GetMapping("/dc")
        String consumer();
    
    }
    复制代码
  • 修改Controller。通过定义的feign客户端来调用服务提供方的接口:

    @RestController
    public class DcController {
    
        @Autowired
        DcClient dcClient;
    
        @GetMapping("/consumer")
        public String dc() {
            return dcClient.consumer();
        }
    
    }
    复制代码

通过Spring Cloud Feign来实现服务调用的方式更加简单了,通过 @FeignClient 定义的接口来统一的生命我们需要依赖的微服务接口。而在具体使用的时候就跟调用本地方法一点的进行调用即可。由于Feign是基于Ribbon实现的,所以它自带了客户端负载均衡功能,也可以通过Ribbon的IRule进行策略扩展。另外,Feign还整合的Hystrix来实现服务的容错保护,在Dalston版本中,Feign的Hystrix默认是关闭的。

在完成了上面你的代码编写之后,读者可以将eureka-server、eureka-client、eureka-consumer-feign都启动起来,然后访问 http://localhost:2101/consumer ,来跟踪观察eureka-consumer-feign服务是如何消费eureka-client服务的 /dc 接口的,并且也可以通过启动多个eureka-client服务来观察其负载均衡的效果。

还可参考spring cloud

原文  https://juejin.im/post/5ce75b6ef265da1bb96fb73b
正文到此结束
Loading...