作者简介:程序员冈刀,目前就职于阿里,曾就职于美团,java开发工程师,研究生。2022年,毕业于北京邮电大学电子工程学院、电子与通信工程专业。个人公众号《代码废柴》欢迎关注。
相关阅读:
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远程服务调用
简介:
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实现远程调用
- 在我们的项目中引入Ribbon依赖:
<!-- netflix-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- 修改我们的业务类:
/**
* @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);
}
}
- 测试结果:
访问:http://localhost/consumer/getServerPort 也可以返回我们想要得到的数据。
这样集成我们的ribbon是成功的。
实质上,eureka默认就是使用ribbon来进行调用的。
3.2 实现负载均衡
点对点方式的调用在很多情况下是无法满足服务集群调用的,为了实现服务的稳定性以及服务的可扩产性,引入了负载均衡的策略,实现增加系统的容量,横向扩展的能力。
- 新建我们的服务提供者spring-cloud-eureka-client-provider-8002,过程与8001一致,之后启动我们新建的服务提供者
- 修改我们的ApplicationContextConfig :
@Configuration
public class ApplicationContextConfig {
@LoadBalanced // 进行负载均衡
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
- 调用测试:
测试结果,发现采用的轮询的方式分别进行调用我们的服务提供者。
项目代码小结: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 整体的项目结构
4.6 运行测试
测试步骤与以前是相同的。通过测试,发现测试结果是满足预期的。
至此,完成了完成了openfeign的调用工作。
5. 其他知识
相关阅读:
作者简介:程序员冈刀,目前就职于阿里,曾就职于美团,java开发工程师,研究生。2022年,毕业于北京邮电大学电子工程学院、电子与通信工程专业。个人公众号《代码废柴》欢迎关注。