zoukankan      html  css  js  c++  java
  • 第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的情况下进行服务间交互。

  • 相关阅读:
    JAVA-初步认识-第十二章-多线程创建方式一继承
    JAVA-初步认识-第十二章-主线程运行示例
    JAVA-初步认识-第十二章-JVM中的多线程分析
    JAVA-初步认识-第十二章-面向对象(Jar包)
    JAVA-初步认识-第十二章-面向对象(导入import)
    ecstore-kvcache里表结构
    ecstore-app接口
    ecstore与淘宝sdk的autoload加载顺序问题
    正则匹配<{$vcode}>变量
    电子面单纸打印时固定高度18cm,到底是多少px
  • 原文地址:https://www.cnblogs.com/hanbin/p/14224668.html
Copyright © 2011-2022 走看看