SpringCloud之OpenFeign简单使用

发布于:2024-04-25 ⋅ 阅读:(23) ⋅ 点赞:(0)

SpringCloud之OpenFeign简单使用

OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡调用其他服务。

一、远程调用功能

  1. 创建提供服务的模块remote-feign-provider
  • 引入依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>

版本信息如下

<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot.version>2.4.2</spring-boot.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
        <nacos.version>2021.1</nacos.version>
        <spring-cloud.version>2020.0.1</spring-cloud.version>
        <spring-cloud-bootstrap.version>3.0.3</spring-cloud-bootstrap.version>
        <spring-cloud-loadbalancer.version>3.0.1</spring-cloud-loadbalancer.version>
        <spring-cloud-openfeign.version>3.0.1</spring-cloud-openfeign.version>
</properties>
  • 创建主类
@EnableDiscoveryClient
@SpringBootApplication
public class RemoteFeignProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(RemoteFeignProviderApplication.class, args);
    }
}
  • 创建bootstrap.yml
spring:
  application:
    name: remote-feign-provider
  cloud:
    nacos:
      discovery:
        group: remote-group
        namespace: remoteinvoke
        server-addr: 192.168.56.102:8848
        weight: 5

server:
  port: 8082

注意nacos面板中需要新建相应的命名空间

  • 创建TestController,提供相应的调用服务
@RestController
public class TestController {

    @Value("${server.port}")
    private int port;

    @GetMapping("/service")
    public String test(){
        return "provicer servvice: [from port]:" + port;
    }
}

开启8081,8082两个端口的remote-feign-provider服务集群

  1. 下面开始创建调用模块,consumer模块
  • 创建remote-feign-service模块
  • 引入依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>
  • 主类
@SpringBootApplication
@EnableFeignClients(basePackages = "cn.axj.remote.feign.feign")
@EnableDiscoveryClient
public class FeignServiceApplication {

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

@EnableDiscoveryClient默认要注册到注册中心,这个注解可加可不加。

@EnableFeignClients : basePackages 用于OpenFeign扫描定义的FeignClient包路径

  • bootstrap.yml
spring:
  application:
    name: remote-feign-service
  cloud:
    nacos:
      discovery:
        group: remote-group
        namespace: remoteinvoke
        server-addr: 192.168.56.102:8848
        weight: 5

server:
  port: 8080
使用url形式的方式
  • 创建LoadBalanceProviderOriginalFeignClient的接口,并利用SpringMvc的特性,将provider提供的服务/service声明成springmvc形式
@FeignClient(url = "http://localhost:8082",name = "remoteFeignSerivce")
public interface LoadBalanceProviderOriginalFeignClient {

    @GetMapping("/service")
    String service();

}

定义一个url为http://localhost:8082的服务ip/端口的服务,指定该类访问的基础ip地址和端口固定

关于@FeignClient注解,参数释义如下

参数名称 释义 示例
name/value 指定远程服务的名称,用于服务发现和调用。 @FeignClient(name = "user-service")
url 直接指定远程服务的 URL 地址。当提供了 url 时,name 将被忽略。 @FeignClient(url = "http://localhost:8080")
configuration 用于自定义 Feign 客户端的配置,可以包含自定义的 Encoder、Decoder、LoggerLevel 等。 @FeignClient(name = "user-service", configuration = MyFeignConfiguration.class)
fallback 用于指定熔断降级类,当远程服务调用失败时,会调用这个降级类中的方法。 @FeignClient(name = "user-service", fallback = UserServiceClientFallback.class)
fallbackFactory 用于创建熔断降级类的工厂,允许在创建降级类时注入其他依赖。 @FeignClient(name = "user-service", fallbackFactory = UserServiceClientFallbackFactory.class)
path 定义所有请求的基础路径,会添加到每个请求的前面。 @FeignClient(name = "user-service", path = "/api/v1")
decode404 当服务器返回 404 时,是否应该解码响应体。默认为 false @FeignClient(name = "user-service", decode404 = true)
loggerLevel 设置 Feign 客户端的日志级别,可选值包括 NONE, BASIC, HEADERS, FULL @FeignClient(name = "user-service", loggerLevel = Logger.Level.FULL)
primary 当在 Spring 上下文中存在多个同名的 Feign 客户端时,标记哪个作为主要的 bean。 @FeignClient(name = "user-service", primary = true)
qualifier 当需要区分多个同类型的 Feign 客户端时,用于指定一个唯一的名称,以便在注入时区分。 @FeignClient(name = "user-service", qualifier = "myFeignClient")
  • 创建入口类Controller
@RestController
public class TestController {

    @Resource
    private LoadBalanceProviderOriginalFeignClient loadBalanceProviderOriginalFeignClient;

    @GetMapping("/test")
    public String test(){
        return loadBalanceProviderOriginalFeignClient.service();
    }
}

将FeignClient用组件的形式注入到Spring中,类似于Mybatis的Mapper类,OpenFeign会生产代理对象注入到Spring容器中

测试

启动remote-feign-service模块,访问localhost:8080/test,返回

provicer servvice: [from port]:8082

反复刷新,观察返回情况,可以看到返回信息一直是8082服务器返回的。

二、负载功能

OpenFeign默认开启负载,使用注册到注册中心的服务名称定义FeignClient。

  • 在remote-feign-service模块中增加loadBalancer依赖
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
  • 创建负载类的LoadBalanceProviderFeignClient接口
@FeignClient(name = "remote-feign-provider") 
public interface LoadBalanceProviderFeignClient {

    @GetMapping("/service")
    String service();
}

name: 在注册中心中注册的调用服务名称

  • 在TestController中注入该FeignClient
@RestController
public class TestController {

    @Resource
    private LoadBalanceProviderOriginalFeignClient loadBalanceProviderOriginalFeignClient;

    @Resource
    private LoadBalanceProviderFeignClient loadBalanceProviderFeignClient;

    @GetMapping("/test")
    public String test(){
        return loadBalanceProviderOriginalFeignClient.service();
    }

    @GetMapping("/test2")
    public String test2(){
        return loadBalanceProviderFeignClient.service();
    }
}
测试

重启remote-feign-service模块,访问localhost:8080/test2,观察返回

provicer servvice: [from port]:8082
provicer servvice: [from port]:8081
provicer servvice: [from port]:8082
provicer servvice: [from port]:8081
provicer servvice: [from port]:8082
....

此时已默认加入负载功能

三、熔断降级

当远程服务调用失败时,会采用熔断降级策略,调用熔断降级的方法返回。

熔断降级需要搭配熔断降级组件使用,这里使用hystrix进行熔断

由于springcloud高版本openFeign已经默认移除了hystrix组件,这里需要手动加上hystrix依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
  • bootstrap.yml中增加配置
feign:
  circuitbreaker:
    enabled: true
  • 新建LoadBalanceProviderFeignClientFallback熔断类
@Component
public class LoadBalanceProviderFeignClientFallback implements LoadBalanceProviderFeignClient{
    
    @Override
    public String service() {
        return "error fall back";
    }
}

tips: 必须将熔断类放入Spring容器中

  • 配置FeignClient的熔断类,配置FeignClient fallback属性
@FeignClient(name = "remote-feign-provider",fallback = LoadBalanceProviderFeignClientFallback.class)
public interface LoadBalanceProviderFeignClient {

    @GetMapping("/service")
    String service();
}

重启remote-feign-service模块,并将remote-feign-provider服务全部关掉。模拟熔断现象产生,访问localhost:8080/test2,观察返回

error fall back

返回结果是有熔断类逻辑返回


网站公告

今日签到

点亮在社区的每一天
去签到