Spring Cloud Feign 的远程服务调用

本文介绍了如何在Spring Boot项目中利用Spring Cloud Feign进行远程服务调用。项目依赖包括Spring Cloud Consul、Spring Cloud Gateway、Hystrix和OpenFeign。文章详细阐述了创建项目的过程,包括配置信息、启动类、控制器类、接口类和服务熔断类的设置。通过Feign客户端,项目提供了一个接口,当远程调用服务正常时返回响应,异常时则通过服务熔断类返回默认信息。

说明

简介

  • 首先,这是一个标准的 Spring Boot 项目
  • 其次,它实现基于 Spring Cloud Consul的服务注册功能
  • 最后,它支持 Spring Cloud Feign远程调用
    • 如果Feign 客户端远程调用异常,则返回 fallback 信息(通过 Spring Cloud Netflix Hystrix实现)
  • 当前实现的功能:
    • 提供一个接口,接收 uri 为 /api/user/{id}的 HTTP GET 请求
    • 这个接口通过 Feign 客户端远程调用 awesome-user-server服务中匹配 /api/user/{id}的接口

创建项目

  • 博主使用的开发工具是 Intellij IDEA,创建的项目结构如下所示:
    • 在这里插入图片描述
    • 主要包含六部分内容(其他部分请参考 Spring Cloud Gateway 网关)
      • 依赖信息:pom.xml
      • 配置信息:application.yml
      • 启动类: AwesomeUserApiApplication.java
      • 控制器类:UserController.java
      • 接口类:UserService.java
      • 接口对应的服务熔断类:UserServiceFallback.java

依赖

  • 主要引入依赖:
    • spring-cloud-starter-consul-all:注册服务到 Consul
    • spring-cloud-starter-gateway :支持网关服务。(用于实现网关功能直接转发某些请求,和当前博客主要介绍的内容关系不大,但由于本博客属于 Spring Cloud 微服务化(精简完整版)的一部分,由于整体设计的原因,所以这里引入这个依赖)
    • spring-cloud-starter-netflix-hystrix :支持熔断服务
    • spring-cloud-starter-openfeign:支持 Feign 客户端远程调用
  • 完整 pom.xml
  • <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>andy.wanna.sing</groupId>
      <artifactId>awesome-user-api</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>awesome-user-api</name>
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <java.version>1.8</java.version>
      </properties>
    
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
      </parent>
    
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Greenwich.SR1</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
    
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-all</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <finalName>awesome-gateway</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
          <plugins>
            <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
              <artifactId>maven-clean-plugin</artifactId>
              <version>3.1.0</version>
            </plugin>
           <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
            <plugin>
              <artifactId>maven-resources-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.22.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-war-plugin</artifactId>
              <version>3.2.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-install-plugin</artifactId>
              <version>2.5.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-deploy-plugin</artifactId>
              <version>2.8.2</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>
    
    

配置信息

  • 主要配置内容:

    • 服务注册中心(Spring Cloud Consul 配置)
    • 启动 Feign Hystrix
    • 运行的端口号
    • 健康检查暴露的端点
  • application.yml
  • spring:
        application:
            name: awesome-gateway
        cloud:
            consul:
                host: localhost
                port: 8500
                discovery:
                    enabled: true
                    register: true
                    healthCheckInterval: 10s
                    instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
    feign:
      hystrix:
        enabled: true   
    server:
        port: 9201
    management:
        endpoints:
            web:
                exposure:
                    include: metrics,env,beans,mappings,health
    

启动类

  • 标准的 Spring Boot 项目启动类
  • 注意:需要添加 @EnableFeignClients
  • package awesome.user.api;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * 启动类
     *
     *
     * @author: Andy
     * @time: 2019/4/15 15:39
     * @since
     */
    @SpringBootApplication
    @EnableFeignClients
    public class AwesomeUserApiApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(AwesomeUserApiApplication.class, args);
        }
    
    }
    
    

控制器类

  • 提供一个用户接口,
    • 匹配 uri : /api/user/{id}
    • 接口调用 UserService的接口(UserService中实现了 Feign客户端远程调用和服务降级,下面会介绍)
    • package awesome.user.api.controller.user;
      
      import awesome.user.api.bean.User;
      import awesome.user.api.service.UserService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.http.HttpStatus;
      import org.springframework.http.ResponseEntity;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RestController;
      
      /**
       * 用户控制器
       *
       * @author: Andy
       * @time: 2019/4/16 21:36
       * @since
       */
      @RestController
      public class UserController {
      
          @Autowired
          private UserService userService;
      
          /**
           * 获取用户信息
           *
           *
           * @param id 用户ID
           * @return: {@link ResponseEntity<User> }
           * @author: Andy
           * @time: 2019/4/16 22:02
           */
          @GetMapping("/api/user/{id}")
          public ResponseEntity<?> getUser(@PathVariable("id") Integer id){
          try {
              return userService.getUser(id);
          }catch (Exception e){
              //todo: do something
              e.printStackTrace();
              return new ResponseEntity<>("请求失败!", HttpStatus.INTERNAL_SERVER_ERROR);
          }
      }
      }
      
      

接口类

  • 这个类是本博客的核心类
    • 它实现了 FeignClient远程调用和 Hystrix服务降级
      • 类上有注解 @FeignClient(name = "awesome-user-server", fallback = UserServiceFallback.class),它的作用是把请求转发到 awesome-user-server服务,并且当请求出现异常时,返回 UserService的实现类 UserServiceFallback对应的方法的返回值。
      • 方法上有注解 @GetMapping("/api/user/{id}"),表示这个方法的调用匹配的远程服务的 uri,在本例中,即匹配 awesome-user-server服务中 uri 为 /api/user/{id}的接口。
    • package awesome.user.api.service;
      
      import awesome.user.api.bean.User;
      import awesome.user.api.fallback.UserServiceFallback;
      import org.springframework.cloud.openfeign.FeignClient;
      import org.springframework.http.ResponseEntity;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      
      @FeignClient(name = "awesome-user-server", fallback = UserServiceFallback.class)
      public interface UserService {
      
          /**
           * 获取用户信息
           *
           *
           * @param id 用户ID
           * @return: {@link <User> }
           * @author: Andy
           * @time: 2019/4/16 22:02
           */
          @GetMapping("/api/user/{id}")
          ResponseEntity<?> getUser(@PathVariable("id") Integer id);
      }
      
      
      

接口对应的服务熔断类

  • 即实现服务降级的类
    • 这个类必须需要有 @FeignClient注解的接口,并为每个方法定义默认返回值。
    • 这个类需要被注册成 Bean,以便注入。所以,博主给它添加注解@Component
    • package awesome.user.api.fallback;
      
      import awesome.user.api.bean.User;
      import awesome.user.api.service.UserService;
      import org.springframework.http.HttpStatus;
      import org.springframework.http.ResponseEntity;
      import org.springframework.stereotype.Component;
      
      /**
       * user 服务降级类
       *
       * @author: Andy
       * @time: 2019/4/16 21:47
       * @since
       */
      @Component
      public class UserServiceFallback implements UserService {
          @Override
          public ResponseEntity<?> getUser(Integer id) {
              return new ResponseEntity<>("Server 请求失败!" ,HttpStatus.INTERNAL_SERVER_ERROR);
          }
      }
      

测试

  • 上面我们构建了一下 API 项目。它的作用是:
    • 提供一个接口,接受匹配 /api/user/{id}的请求,并通过 FeignClient远程调用 awesome-user-server服务的接口获取相关信息,最后返回响应。
      • FeignClient远程调用服务不可用时,返回接口对应的服务熔断类对应方法的返回值。
    • 为了完成这个测试,我们需要要 awesome-user-server服务。
      • awesome-user-server必须是 Web 项目,并且注册到服务注册中心。实现基于 Spring Cloud Consul 的服务注册与发现,博主写在下面的博客:

服务正常可用

服务异常不可用

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值