浅谈Spring Cloud OpenFeign

举报
QGS 发表于 2023/06/07 22:03:08 2023/06/07
【摘要】 浅谈Spring Cloud OpenFeign

OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。
Spring Cloud OpenFeign
以将OpenFeign集成到Spring Boot应用中的方式。首先利用了OpenFeign的声明式方式定义Web服务客户端;其次还更进一步,通过集成RibbonEureka实现负载均衡的HTTP客户端。

Feign底层是ribbon

Openfeign快速入门

Provider


.yml

server:
  port: 8080  
spring:
  application:
    name: provider-server #应用名称

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka


User(消费端)


server:
  port: 8081
spring:
  application:
    name: user-server #应用名称

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

#设置超时时间
ribbon:
  ReadTimeout: 3000 # 3秒
  ConnectTimeout: 3000 #连接服务的超时时间



OpenFeign调用参数处理(重点)

@PathVariable注解:获取url中的数据

解决映射名称不一致问题(提交请求参数的action的形参名称不一致,使用@RequestParam注解解析)


Feign传参确保消费者和提供者的参数列表一致包括返回值方法签名要一致

1.通过URL传参数,GET请求,参数列表使用@PathVariable (“”)

2.如果是GET请求,每个基本参数必须加回 @Requestparam(“”)

3.如果是posT请求,而且是对象集合等参数,必须加@ Requestbody或者@ Requestparam

 

provider-service


@RestController

public class ParamController {

    //url传参
    @GetMapping("param/{name}/{age}")
    public String param(@PathVariable("name") String name,@PathVariable("age") int age){
        System.out.println("姓名: "+name+" 年龄 "+age);
    return "姓名: "+name+" 年龄 "+age;
    }



    @GetMapping("getParam")
    public String getParam(@RequestParam(required = false) String name){
        System.out.println("姓名: "+name);
        return "姓名: "+name;
    }



    @GetMapping("twoParam")
    public String twoParam(@RequestParam(required = false) String name,@RequestParam(required = false)int age){
        System.out.println("姓名: "+name+" 年龄 "+age);
        return "姓名: "+name+" 年龄 "+age;
    }



    @PostMapping("oneObject")
    public String oneObject(@RequestBody User user){
        System.out.println(user.toString());
        return user + "";
    }

}

 

User-service

 

@FeignClient(value = "provider-server") //提供者的应用名称
public interface UserProviderFeign {

    @GetMapping("provider")
    public String provider();

    @GetMapping("param/{name}/{age}")
    public String paramUrl(@PathVariable("name") String name, @PathVariable("age") int age);

    @GetMapping("getParam")
    public String getParam(@RequestParam(required = false) String name);

    @GetMapping("twoParam")
    public String twoParam(@RequestParam(required = false) String name,@RequestParam(required = false)int age);

    @PostMapping("oneObject")
    public String oneObject(@RequestBody User user);

}

 

@GetMapping("paramTest")

public String paramTest(){

    userProviderFeign.paramUrl("张三",20);
    userProviderFeign.getParam("李四");
    userProviderFeign.twoParam("小红",18);
    User user = User.builder()
            .name("小冰")
            .age(18)
            .time(new Date()).build();
    userProviderFeign.oneObject(user);
    return "provider";

}



Feign传递时间

@GetMapping("testTime")
public String testTime(@RequestParam Date date){
    return date +"";
}

@GetMapping("time")
public String time(){
Date date =new Date();
    System.out.println(date);
    String s = userProviderFeign.testTime(date);
    return s;

}





Feign日志处理

Feign提供了日志打印功能,我们在项目中可以通过配置来调整日志级别,从而了解Feignhttp请求的细节 ,也就是说feign提供的日志功能可以对接口的调用情况进行监控和输出。

 

日志级别:

NONE: 默认的,不显示任何日志

BASIC:仅记录请求方法、URL、响应状态码以及执行时间

HEADERS:除了BASIC中定义的信息以外,还有请求和响应的头信息

FULL: 除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据


public Logger.Level level(){

    return Logger.Level.FULL;

}


logging:
  level:
    com.example.feign.UserProviderFeign : debug

Hystrix介绍

Hystrix是一个用于处理分布式系统的延迟和容错的一个开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能保证在一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的稳定性。断路器本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的,可处理的备选响应,而不是长时间等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

provider-service

application.yml

server:

  port: 8080

spring:

  application:

    name: provider-service01

eureka:

  client:

    service-url:

      defaultZone: http://localhost:8761/eureka

  instance:

    hostname: localhost

    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

Customer-service

添加Hystrix依赖

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

application.yml

server:
  port: 8081
spring:
  application:
    name: c-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

feign:
  hystrix:
    enabled: true 

Feign接口

@FeignClient(value = "provider-service01") //provider服务名
public interface CustomerToProviderFeign {

    @GetMapping("Provider")
    public String pro();
}

@Component
public class CustomerToProviderFeignHystrix implements CustomerToProviderFeign {

    @Override
    public String pro() {
        return "熔断后备选方案";
    }
}

controller

Hystrix常用配置

server:
  port: 8081
spring:
  application:
    name: c-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

feign:
  hystrix:
    enabled: true
hystrix:  #hysrix全局控制
  command:
    default:
      circuitBreaker:
        enabled: true #开启断路器
        requestVolumeThreshold: 10 #失败次数
        sleepWindowInMilliseconds: 20000 #窗口时间
        errorThresholdPercentage: 60 #失败率
      execution:
        isolation:
          Strategy: thread #隔离方式 thread线程格里尼集合和SEMAPHORE信号量隔离级别
          thread:
            timeoutInMilliseconds: 3000 #调用超时时长
      fallback:
        isolation:
          semaphore:
            maxConcurrentRequests: 1000  #信号量隔离级别最大并发数
ribbon:
  ReadTimeout: 5000   #结合feign底层ribbon调用时长
  ConnectTimeout: 5000

OpenFeign项目

eign-project01

Pom.xml

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>8</maven.compiler.source>
  <maven.compiler.target>8</maven.compiler.target>
  <java.version>1.8</java.version>
  <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
</dependencies>


<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>${spring-cloud.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

pojo

api

Pom.xml

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>pojo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</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-zipkin</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

UserOrderFeign

@FeignClient(value = "order-service",fallback = UserOrderFeignHystrix.class)
public interface UserOrderFeign {


    @GetMapping("getOrderByUserId")
    Order getOrderByUserId(@RequestParam int ID);

}

@Component
public class UserOrderFeignHystrix implements UserOrderFeign {

    @Override
    public Order getOrderByUserId(int ID) {
        return null;
    }

}

Order-center 提供者

Pom.xml

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>project-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <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-zipkin</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

@RestController
public class OrederController implements UserOrderFeign {

    @Override
    public Order getOrderByUserId(int ID) {
        Order egg = Order.builder().ID(101).name("炸蛋").price(1.5).build();
        return egg;
    }

}

application.yml

server:
  port: 8080
spring:
  application:
    name: order-service
    zipkin:
      base-url: http://localhost:9411
    sleuth:
      sampler:
        probability: 1 #取值0-1  ,1为100%采集
        rate: 10  #每秒间隔接受的trace量

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

User-center

Pom.xml

<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>project-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <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-zipkin</artifactId>
    </dependency>
</dependencies>

@RestController
public class UserController {

    @Resource
    public UserOrderFeign userOrderFeign;

    @GetMapping("seek")
    public Order seekOrder(){
        Order orderByUserId = userOrderFeign.getOrderByUserId(101);
        return orderByUserId;
    }

}

application.yml

server:
  port: 8081
spring:
  application:
    name: user-service
    zipkin:
      base-url: http://localhost:9411
    sleuth:
      sampler:
        probability: 1 #取值0-1  ,1为100%采集
        rate: 10  #每秒间隔接受的trace量

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}


feign:
  hystrix:
    enabled: true #开启熔断

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。