第5章 微服务之间如何交互

在第3章讲解Eureka时,我们提到了Eureka会保存各个服务的元数据,元数据中包含了各个服务的地址等信息。那么服务之间到底是怎样通过这些信息进行交互的呢?

Spring Cloud服务间的调用默认支持两种方式:Ribbon和Feign,具体来说就是使用RestTemplate和FeignClient来调用。不管使用什么方式,本质上都是通过REST接口调用服务的HTTP接口,参数和结果默认都是通过jackson序列化和反序列化的。

前面我们已经创建了customer微服务,这里我们再新建一个order微服务。使用两个服务来进行服务间调用的学习。

order微服务的端口号设置为8002。order微服务的pom.xml引入了如下包:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

其中spring-cloud-starter-netflix-ribbon 引入了Ribbon支持。

为了使用Ribbon访问customer服务的接口,我们在order的启动类中加入了如下代码,加载RestTemplate。

@Bean
@LoadBalanced
public RestTemplate restTemplate(){
    return new RestTemplate();
}

注意:这里使用的注解@Loadbalanced是用来开启Ribbon负载均衡的。如果没有添加此注解,那么得到的restTemplate就不具备Ribbon的负载均衡功能,也不会识别微服务的实例名,只能当作传统的http访问工具类来使用。

编写测试controller。

@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/users/{userId}")
    public String getUserInfo(@PathVariable Long userId) {
        System.out.printf("这里要使用Ribbon来远程调用customer服务获取用户信息");
        String userInfoStr = restTemplate.getForObject("http://customer/users/" +
                userId, String.class);
        return userInfoStr;
    }

}

通过这样,就可以访问customer服务中的接口,customer中的接口代码如下:

@GetMapping("/users/{userId}")
public String getUserInfoByUserId(@PathVariable Long userId){
    return "userInfo with userId = " + userId;
}

在浏览器中访问http://localhost:8002/users/1001,可以得到如5.1的结果。

27ec2c0cc65c44b7698ef39807d56c2e.png
图5.1 Ribbon方式

通过上面的例子,我们通过RestTemplate在order和customer之间进行了服务间的http请求,内部请求过程中使用了http://customer/users/这个地址,并没有涉及到域名端口之类的东西。这里的customer就是我们之前提到的实例名。也就是这个服务在整个系统中的唯一名称。

5.1 Ribbon

Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP的客户端的行为。为Ribbon配置服务提供者地址后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。当然,我们也可为Ribbon实现自定义的负载均衡算法。

在Spring Cloud中,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。在本章刚开始,我们新建的order服务使用RestTemplate调用customer接口的实例就是使用了带有Ribbon功能的RestTemplate。

RestTemplate提供了若干方便我们使用的工具方法,通过这些方法可以很方便地实现网络访问/服务间调用。

接下来我们介绍几个常见的方法。

  • delete():在特定的URL上对资源执行HTTP DELETE操作。
  • getForEntity():发送一个HTTP

    GET请求,返回的ResponseEntity包含了响应体所映射成的对象。
    
  • getForObject():发送一个HTTP GET请求,返回的请求体将映射为一个自定义对象。
  • postForEntity():POST

    数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的。
    
  • postForObject():POST 数据到一个URL,返回根据响应体匹配形成的对象。
  • headForHeaders():发送HTTP HEAD请求,返回包含特定资源URL的HTTP头。
  • optionsForAllow():发送HTTP OPTIONS请求,返回对特定URL的Allow头信息。
  • postForLocation():POST 数据到一个URL,返回新创建资源的URL。
  • put():PUT 资源到特定的URL。
  • execute():在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象。
  • exchange():在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中。

5.2 Feign

Feign 是一个声明web服务客户端,它使编写web服务客户端更容易,使用Feign
创建一个接口并对它进行注解,它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持可插拔的编码器与解码器,Spring
Cloud 增加了对 Spring MVC的注解,Spring Web 默认使用了HttpMessageConverters,
Spring Cloud 集成 Ribbon 和 Eureka 提供的负载均衡的HTTP客户端 Feign。

为order服务添加feign支持。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-feign</artifactId>
</dependency>

为启动类添加注解@EnableFeignClients,开启Feign扫描。

新建service接口类,代码如下:

@FeignClient("customer")
public interface UserService {

    @GetMapping("/users/{userId}")
    String getUserInfoByUserId(@PathVariable Long userId);

}

在UserController中添加接口方法。

@GetMapping("/feign/users/{userId}")
public String getUserInfoWithFeign(@PathVariable Long userId){

    System.out.printf("这里要使用Feign来远程调用customer服务获取用户信息");
    String userInfoStr = userService.getUserInfoByUserId(userId);
    return userInfoStr;

}

启动order服务,浏览器访问http://localhost:8002/feign/users/100112。得到如图5.2的结果。

6e3f4c20d3e2479bd0275bbf300fda51.png
图5.2 feign方式

5.3 小结

本章主要了解了如何使用Ribbon和Feign通过Eureka的实例来进行服务间的接口调用。到本文为止,我们已经可以构建一些简单的微服务,并可以让它们注册到同一个注册中心,连接到同一个配置中心,并且可以在不需要url的情况下进行服务间交互。

原文地址:https://www.cnblogs.com/hanbin/p/14224668.html