学习Spring Cloud 技术第四篇-服务调用

330 阅读5分钟

作者简介:程序员冈刀,目前就职于阿里,曾就职于美团,java开发工程师,研究生。2022年,毕业于北京邮电大学电子工程学院、电子与通信工程专业。个人公众号《代码废柴》欢迎关注。


相关阅读:

  1. 带你学习Spring Cloud 技术第一篇-总览
  2. 带你学习Spring Cloud 技术第二篇-技术介绍
  3. 带你学习Spring Cloud 技术第三篇-服务注册中心

1. 简介

微服务之间的服务调用指的是:在大型系统中,微服务成千上万,完成一个功能或许需要好几个微服务。服务调用就是服务于微服务之间的通信,是完成一整个功能的必要技术。服务之间的调用、通信,通常有2种实现方式:第一种是采用HTTP接口方式,服务消费者采用实现HTTP组件进行调用;另外一种是使用RPC调用方式实现。在本文中,介绍Spring Cloud所使用的的服务调用机制。

2. 代码中存在的问题

在之前的例子中,服务调用直接将IP地址写到了代码中(例如下面的代码中),这就造成了配置是非动态的,很不方便,造成了很多没有必要的维护成本。

github.com/zhaoligang5… 这个版本中,服务消费者的代码请求地址直接写在了项目里面了:

例如:

/**
 * @author :breakpoint/赵立刚
 * @date : 2020/07/25
 */
@RestController
public class EurekaConsumerController {
  	// 直接写的是我们的IP地址;
    private static final String REQUEST_URL = "http://localhost:8001/";
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/consumer/getServerPort")
    public String getServerPort() {
        return restTemplate.getForObject(REQUEST_URL + "/getServerPort", String.class);
    }

}

注意到,上面的代码,我们把服务额提供者的IP直接写在了代码里,很方便,但是,如果我们的IP变动了,我们要要修改好多这样的问题,增加了不必要的工作量。那么有没有其他的方式,来做到一次配置不用改变呢?答案是肯定的,我们可以利用下面的技术来进行调用我们的服务。

在Spring Cloud技术生态中,实现远程调用主要技术有:

Ribbon、loadblancer、feign、openfeign 这四种方式调用,下面主要围绕Ribbon、openfeign阐述服务调用技术。

3. ribbon远程服务调用

官网:github.com/Netflix/rib…

简介:

Ribbon is a client-side load balancer that gives you a lot of control over the behavior of HTTP and TCP clients. Feign already uses Ribbon, so, if you use @FeignClient, this section also applies.

Ribbon is a client side IPC library that is battle-tested in cloud. It provides the following features

  • Load balancing
  • Fault tolerance
  • Multiple protocol (HTTP, TCP, UDP) support in an asynchronous and reactive model
  • Caching and batching

{

上面的翻译:

Ribbon是一个客户端IPC库,在云中进行了战斗测试。它提供了以下特性

  • 负载平衡

  • 容错

  • 多协议(HTTP, TCP, UDP)支持异步和反应模型

  • 缓存和批处理

}

上面就是ribbon为大家提供的功能。

我们接下来就测试远程调用以及负载均衡

3.1 使用Ribbon实现远程调用

  1. 在我们的项目中引入Ribbon依赖:
<!--  netflix-ribbon  -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
  1. 修改我们的业务类:
/**
 * @author :breakpoint/赵立刚
 * @date : 2020/07/25
 */
@RestController
public class EurekaConsumerController {

    // CLOUD-EUREKA-CLIENT-PROVIDER 是我们的服务提供者的名字
    private static final String REQUEST_URL = "http://CLOUD-EUREKA-CLIENT-PROVIDER";
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/consumer/getServerPort")
    public String getServerPort() {
        return restTemplate.getForObject(REQUEST_URL + "/getServerPort", String.class);
    }

}
  1. 测试结果:

image.png

访问:http://localhost/consumer/getServerPort 也可以返回我们想要得到的数据。

这样集成我们的ribbon是成功的。

实质上,eureka默认就是使用ribbon来进行调用的。

3.2 实现负载均衡

点对点方式的调用在很多情况下是无法满足服务集群调用的,为了实现服务的稳定性以及服务的可扩产性,引入了负载均衡的策略,实现增加系统的容量,横向扩展的能力。

  1. 新建我们的服务提供者spring-cloud-eureka-client-provider-8002,过程与8001一致,之后启动我们新建的服务提供者

image.png

image.png

  1. 修改我们的ApplicationContextConfig :
@Configuration
public class ApplicationContextConfig {

    @LoadBalanced // 进行负载均衡
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
  1. 调用测试:

测试结果,发现采用的轮询的方式分别进行调用我们的服务提供者。

项目代码小结:github.com/zhaoligang5…

4. openfeign 远程服务调用

作为后起之秀,肯定有他的优点,openfeign的底层也是用ribbon来实现的。

通过刚刚的编码,我们或多或少感觉到,编码还是不太顺滑与简单,而且步骤很复杂,我们能不能用以往的service调用呢,答案是肯定的,我们可以利用 openfeign

openfeign 与feign实质上差不多是一样的,都是客户端的调用。

注意:所有的远程调用均是在服务的消费端进行调用的。

4. 1 在我们的项目中,引入关于openfeign的依赖

<!--  spring-cloud-starter-openfeign  -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

4. 2 修改主启动类

在我们的服务消费侧进行修改

/**
 * @author :breakpoint/赵立刚
 * @date : 2020/07/25
 */
@EnableFeignClients // 加上这个
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientConsumer80 {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientConsumer80.class, args);
    }

}

4.3 修改业务逻辑代码

/**
 * @author :breakpoint/赵立刚
 * @date : 2020/07/26
 */
@FeignClient(value = "CLOUD-EUREKA-CLIENT-PROVIDER") //服务的名字
public interface RemoteProviderService {

    // 远程服务的接口
    @GetMapping("/getServerPort")
    public String getServerPort();
}

4.4 修改接口

/**
 * @author :breakpoint/赵立刚
 * @date : 2020/07/25
 */
@RestController
public class EurekaFeignController {

  	// 注入我们刚才新建立的服务
    @Autowired
    private RemoteProviderService remoteProviderService;

    @GetMapping("/consumer/feign/getServerPort")
    public String getServerPort() {
        return remoteProviderService.getServerPort();
    }

}

4.5 整体的项目结构

image.png

4.6 运行测试

测试步骤与以前是相同的。通过测试,发现测试结果是满足预期的。

至此,完成了完成了openfeign的调用工作。

代码地址:github.com/zhaoligang5…

5. 其他知识

相关阅读:

  1. 带你学习Spring Cloud 技术第一篇-总览
  2. 带你学习Spring Cloud 技术第二篇-技术介绍
  3. 带你学习Spring Cloud 技术第三篇-服务注册中心

作者简介:程序员冈刀,目前就职于阿里,曾就职于美团,java开发工程师,研究生。2022年,毕业于北京邮电大学电子工程学院、电子与通信工程专业。个人公众号《代码废柴》欢迎关注。

个人公众号